libc: Prevent FCSEL instruction from being used to avoid raising an unintended exception #24185
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
closes #24184
According to the comment, this line of the current
sin
function evaluatesx + 0x1p120
and raises anINEXACT
exception ifx
is not zero.It also evaluates
x / 0x1p120
and raises anUNDERFLOW
exception ifx
is a non-normalized number.This is the disassembly results of the
sin
function test built in #24184.FCSEL
instruction selects one of the two registers according to the condition and copies its value.The
FCSEL
instruction is preceded by theFMUL
andFADD
instructions, indicating that bothx / 0x1p120
andx + 0x1p120
are evaluated.It selects one or the other based on the result of
ix < 0x00100000
, but if a floating point exception occurs in the calculation of the one not selected, the exception is reflected in the final result.In other words, it is effective in reducing branching, but both the
FMUL
andFADD
instructions can have the side effect of raising a floating point exception, which may cause an exception that the programmer does not intend.To prevent
FCSEL
instruction from being used here, this PR splitsdoNotOptimizeAway
in two.This change adds a branch instruction, but since this code path only passes if
x
is very small (|x| < 2^-26
insin
), I believe this change is acceptable.In fact, after this PR, unintended exceptions no longer occur.
Several other functions are similarly changed to prevent from raising unintended exceptions.