Convert "denormal-fp-math" and "denormal-fp-math-f32" into a first
class denormal_fpenv attribute. Previously the query for the effective
denormal mode involved two string attribute queries with parsing. I'm
introducing more uses of this, so it makes sense to convert this
to a more efficient encoding. The old representation was also awkward
since it was split across two separate attributes. The new encoding
just stores the default and float modes as bitfields, largely avoiding
the need to consider if the other mode is set.
The syntax in the common cases looks like this:
`denormal_fpenv(preservesign,preservesign)`
`denormal_fpenv(float: preservesign,preservesign)`
`denormal_fpenv(dynamic,dynamic float: preservesign,preservesign)`
I wasn't sure about reusing the float type name instead of adding a
new keyword. It's parsed as a type but only accepts float. I'm also
debating switching the name to subnormal to match the current
preferred IEEE terminology (also used by nofpclass and other
contexts).
This has a behavior change when using the command flag debug
options to set the denormal mode. The behavior of the flag
ignored functions with an explicit attribute set, per
the default and f32 version. Now that these are one attribute,
the flag logic can't distinguish which of the two components
were explicitly set on the function. Only one test appeared to
rely on this behavior, so I just avoided using the flags in it.
This also does not perform all the code cleanups this enables.
In particular the attributor handling could be cleaned up.
I also guessed at how to support this in MLIR. I followed
MemoryEffects as a reference; it appears bitfields are expanded
into arguments to attributes, so the representation there is
a bit uglier with the 2 2-element fields flattened into 4 arguments.
Switch to using computeKnownBits instead of computeConstantRange
in computeKnownFPClass's ldexp handling. This is preparation to
move the handling into KnownFPClass. Since KnownFPClass is in Support,
it can make use of KnownBits as the input argument. ConstantRange is in
IR, so it cannot be used from Support.
This functionally reverts fd5cfcc41311c6287e9dc408b8aae499501660e1 and
35ce17b6f6ca5dd321af8e6763554b10824e4ac4.
This was correct and necessary, but is causing performance regressions
since isGuaranteedNotToBeUndef is apparently not smart enough to detect
through recurrences. Revert this for the release branch.
Also the test coverage was inadequate for the fma case, so add a new
case which changes with and without the check.
The handling for fma was very basic and only handled the
repeated input case. Re-use the fmul and fadd handling for more
accurate sign bit and nan handling.
In the case where both operands have the same sign,
as long as one of the operands is normal or infinity,
the result cannot underflow to a zero.
Pre-committing for #175614
This adds the analogous metadata to the nofpclass attribute
to assert values are not a certain set of floating-point classes.
This allows the same information to be expressed if a function
argument is passed indirectly. This matches the bitmask encoding
of nofpclass.
I also think this should be allowed for stores to symmetrically handle
sret, but leave that for later.
Alternatively we could add a more expressive !fprange metadata,
but that would be much more complex. It's useful to match the attribute,
and more annotations can always be added.
Fixes#133560
This enables assumes to work. Somehow the most obvious example
I could think of does not work (return of assumed argument).
The context instruction for the return seems to be off by one.
Match the structure of ComputeKnownBits. Expose the condition
handling as a utility function so SimplifyDemanedFPClass can make
use of this. Avoids some redundant code and improves accuracy in
at least one case.
Reapply the zero handling, reverted in
108a22ed5fa1836b4cfcd05e9d96f98a533068d5
The failing libc test should have been fixed by
e25eacf10c0d6718bad4e18e63757f97be9f9596
This partially reverts commit 108a22ed5fa1836b4cfcd05e9d96f98a533068d5.
Restore the sign-bit tracking for both inputs known-negative case,
and leave the 0 handling for later. There is a libc test improperly
relying on running code compiled for IEEE behavior that changed
the output denormal mode.
Reverts llvm/llvm-project#174123
This caused test failures within LLVM libc. They can be reproduced by
doing a libc build against a clang with this commit included and running
`ninja -k 0 libc.test.src.math.smoke.log1p_test.__unit__
libc.test.src.math.smoke.log1p_test.__unit__.__NO_FMA_OPT`.
This already recognized that if both inputs are positive, the
result is positive. Extend this to the mirror situation with
negative inputs.
Also special case fadd x, x. Canonically, fmul x, 2 is fadd x, x.
We can tell the sign bit won't change, and 0 will propagate.
Improve known non-nan sign bit tracking. Handle cases with
a known 0 or inf input of indeterminate sign.
The tails of some library functions have sign management
for special cases.
Multiply by large constant can be used to scale denormal inputs into
a normal range. This pattern appears frequently in math function library
implementations to make use of hardware instructions that do not support
denormals. We already handle this case for ldexp, but now canonicalize
ldexp by a constant to an fmul.
The test cases are mostly the existing nofpclass test for ldexp,
run through the new instcombine to replace ldexp with fmul.
Calculating alignment for `make.buffer.rsrc` intrinsic. The logic is the
alignment on use of return value of `make.buffer.rsrc` should be capped
by the base operand's alignment of `make.buffer.rsrc`.
For example:
```ll
define float @foo(ptr addrspace(1) align X %ptr) {
%fat.ptr = call ptr addrspace(7) @llvm.amdgcn.make.buffer.rsrc.p7.p1(ptr addrspace(1) %ptr, i16 0, i32 C, i32 0)
%y = load float, ptr addrspace(7) %fat.ptr, align Y
ret float %y
}
```
We hopes that `Y = min(X, Y)`
---
After discussion, it seems improper for letting `Y = min(X, Y)` since it
contradict with the semantic of align on load.
So we would apply the origin behavior of align, which is letting `X` and
`Y` both equal to `max(X, Y)`
---------
Co-authored-by: Shilei Tian <i@tianshilei.me>