688 Commits

Author SHA1 Message Date
Nikita Popov
a654a27fcd
[InstCombine] Fold min/max(fpext x, C) to fpext(min/max(x, fptrunc C)) (#179968)
Fold `min/max(fpext x, C)` to `fpext(min/max(x, fptrunc C))` in cases
where the truncation of the constant is lossless.

This helps eliminate fpext/fptrunc pairs around min/max and addresses
the regression from https://github.com/llvm/llvm-project/pull/177988.

Proof: https://alive2.llvm.org/ce/z/y_Bcdd
2026-02-09 09:13:26 +00:00
Matt Arsenault
0d4a35d560
IR: Remove llvm.convert.to.fp16 and llvm.convert.from.fp16 intrinsics (#174484)
These are long overdue for removal. These were originally a hack
to support loading half values before there was any / decent support
for the half type through the backend. There's no reason to continue
supporting these, they're equivalent to fpext/fptrunc with a bitcast.

SelectionDAG stopped translating these directly, and used the
bitcast + fp cast since f7a02c17628e825, so there's been no reason
to use these since 2014.
2026-01-21 09:50:28 +00:00
Nikita Popov
4996e3be34 [ConstantFolding] Allow truncation when folding wasm.dot
Changes this to getSigned() to match the signedness of the calculation.
However, we still need to allow truncation because the addition
result may overflow, and the operation is specified to truncate
in that case.

Fixes https://github.com/llvm/llvm-project/issues/175159.
2026-01-09 17:15:31 +01:00
Stefan Weigl-Bosker
575d200d64
[ConstantFolding] Add edge cases for llvm.log{,2,10} (#173304)
Addresses https://github.com/llvm/llvm-project/issues/173267.

- folds log(-x) -> NaN
- folds log(0) -> -inf
- also folds log(1) -> 0.0 without host libm

> note: log(inf) is also doable but it causes some other tests to fail
so I avoided it for now
2025-12-24 00:39:46 +01:00
Paul Walker
2c02e4c790
[NFC][LLVM][ConstantFolding] Use Type* variant of ConstantFP::get when folding scalar intrinsics. (#172709)
This gives peace of mind the code paths will remain valid if enabled for vector types and -use-constant-fp-for-*-splat enabled.
2025-12-23 12:10:57 +00:00
Nikita Popov
6a25e454d6
[ConstantFolding] Support ptrtoaddr in ConstantFoldCompareInstOperands (#162653)
This folds `icmp (ptrtoaddr x, ptrtoaddr y)` to `icmp (x, y)`, matching
the existing ptrtoint fold. Restrict both folds to only the case where
the result type matches the address type.
    
I think that all folds this can do in practice end up actually being
valid for ptrtoint to a type large than the address size as well, but I
don't really see a way to justify this generically without making
assumptions about what kind of folding the recursive calls may do.

This is based on the icmp semantics specified in
https://github.com/llvm/llvm-project/pull/163936.
2025-12-11 08:14:44 +01:00
valadaptive
352b901828
[ConstantFolding] Handle roundeven libcalls (#170692)
Basically identical to nearbyint and rint, which we already treat as
rounding to nearest with ties to even during constant folding.
2025-12-05 12:07:28 +01:00
Lewis Crawford
ea3fdc5972
Avoid maxnum(sNaN, x) optimizations / folds (#170181)
The behaviour of constant-folding `maxnum(sNaN, x)` and `minnum(sNaN,
x)` has become controversial, and there are ongoing discussions about
which behaviour we want to specify in the LLVM IR LangRef.

See:
  - https://github.com/llvm/llvm-project/issues/170082
  - https://github.com/llvm/llvm-project/pull/168838
  - https://github.com/llvm/llvm-project/pull/138451
  - https://github.com/llvm/llvm-project/pull/170067
-
https://discourse.llvm.org/t/rfc-a-consistent-set-of-semantics-for-the-floating-point-minimum-and-maximum-operations/89006

This patch removes optimizations and constant-folding support for
`maxnum(sNaN, x)` but keeps it folded/optimized for `qNaN`. This should
allow for some more flexibility so the implementation can conform to
either the old or new version of the semantics specified without any
changes.

As far as I am aware, optimizations involving constant `sNaN` should
generally be edge-cases that rarely occur, so here should hopefully be
very little real-world performance impact from disabling these
optimizations.
2025-12-02 12:43:03 +00:00
Craig Topper
88305251fe
[ConstantFolding] Add constant folding for scalable vector interleave intrinsics. (#168668)
We can constant fold interleave of identical splat vectors to a larger
splat vector.
2025-11-19 15:50:36 -08:00
Craig Topper
90ea49a9d1
[ConstantFolding] Generalize constant folding for vector_deinterleave2 to deinterleave3-8. (#168640) 2025-11-19 14:27:34 -08:00
Craig Topper
4ab24235cb
[ConstantFolding] Generalize constant folding for vector_interleave2 to interleave3-8. (#168473) 2025-11-18 11:13:15 -08:00
Paul Walker
96c6fd36c1
[LLVM][ConstantFolding] Extend constantFoldVectorReduce to include scalable vectors. (#165437) 2025-10-31 11:14:08 +00:00
Nikita Popov
573ca36753
[IR] Replace alignment argument with attribute on masked intrinsics (#163802)
The `masked.load`, `masked.store`, `masked.gather` and `masked.scatter`
intrinsics currently accept a separate alignment immarg. Replace this
with an `align` attribute on the pointer / vector of pointers argument.

This is the standard representation for alignment information on
intrinsics, and is already used by all other memory intrinsics. This
means the signatures now match llvm.expandload, llvm.vp.load, etc.
(Things like llvm.memcpy used to have a separate alignment argument as
well, but were already migrated a long time ago.)

It's worth noting that the masked.gather and masked.scatter intrinsics
previously accepted a zero alignment to indicate the ABI type alignment
of the element type. This special case is gone now: If the align
attribute is omitted, the implied alignment is 1, as usual. If ABI
alignment is desired, it needs to be explicitly emitted (which the
IRBuilder API already requires anyway).
2025-10-20 08:50:09 +00:00
Paul Walker
d17d32a6cb
[LLVM][ConstProp] Enable intrinsic simplifications for vector ConstantInt based operands. (#159358)
Simplifcation of vector.reduce intrinsics are prevented by an early
bailout for ConstantInt base operands. This PR removes the bailout and
updates the tests to show matching output when
-use-constant-int-for-*-splat is used.
2025-10-17 13:43:00 +01:00
Nikita Popov
5841319aca [ConstantFolding] Support ptrtoadd in IsConstantOffsetFromGlobal()
Handle ptrtoaddr the same way as ptrtoint. This code is already
working on the index size (= address size) of the pointer only.
2025-10-09 14:59:23 +02:00
Nikita Popov
3e64db583d
[ConstantFolding] Support ptrtoaddr in cast folds (#162480)
We can support the same folds for as for ptrtoint. For the cast pair
fold we just need to use the address type instead. The gep based folds
were already operating on the address (aka index) width anyway.
2025-10-09 08:22:31 +00:00
Nikita Popov
7e5bb1e58a
[IR] Require DataLayout for pointer cast elimination (#162279)
isEliminableCastPair() currently tries to support elimination of
ptrtoint/inttoptr cast pairs by assuming that the maximum possible
pointer size is 64 bits. Of course, this is no longer the case nowadays.

This PR changes isEliminableCastPair() to accept an optional DataLayout
argument, which is required to eliminate pointer casts.

This means that we no longer eliminate these cast pairs during ConstExpr
construction, and instead only do it during DL-aware constant folding.
This had a lot of annoying fallout on tests, most of which I've
addressed in advance of this change.
2025-10-07 17:19:48 +02:00
Lewis Crawford
25c0da8b0d
[NVPTX] Fix NaN + overflow semantics of f2ll/d2i (#159530)
Fix the NaN-handling semantics of various NVVM intrinsics converting
from fp types to integer types.

Previously in ConstantFolding, NaN inputs would be constant-folded to 0.
However, v9.0 of the PTX spec states that:

In float-to-integer conversions, depending upon conversion types, NaN
input results in following value:
 * Zero if source is not `.f64` and destination is not `.s64`, .`u64`.
* Otherwise `1 << (BitWidth(dst) - 1)` corresponding to the value of
`(MAXINT >> 1) + 1` for unsigned type or `MININT` for signed type.

Also, support for constant-folding +/-Inf and values which
overflow/underflow the integer output type has been added (they clamp to
min/max int).

Because of this NaN-handling semantic difference, we also need to
disable transforming several intrinsics to FPToSI/FPToUI, as the LLVM
intstruction will return poison, but the intrinsics have defined
behaviour for these edge-cases like NaN/Inf/overflow.
2025-09-25 16:19:11 +01:00
Alexander Richardson
fd81bd8b3e
[ConstantFolding] Avoid use of isNonIntegralPointerType()
Avoiding any new inttoptr is unnecessarily restrictive for "plain"
non-integral pointers, but it is important for unstable pointers and
pointers with external state. Fixes another test codegen regression
from https://github.com/llvm/llvm-project/pull/105735.

Reviewed By: nikic

Pull Request: https://github.com/llvm/llvm-project/pull/159959
2025-09-23 15:29:33 -07:00
Florian Hahn
607a813029
[ConstFold] Don't crash on ConstantExprs when folding get_active_lane_m.
Check if operands are ConstantInt to avoid crashing on constant
expression after https://github.com/llvm/llvm-project/pull/156659.
2025-09-11 23:17:56 +01:00
Matthew Devereau
75099c2246
[ConstantFolding] Fold scalable get_active_lane_masks (#156659)
Scalable get_active_lane_mask intrinsics with a range of 0 can be
lowered to zeroinitializer. This helps remove no-op scalable masked
stores and loads.
2025-09-11 10:53:18 +01:00
Aaditya
bdebbd9015
[AMDGPU] Propagate Constants for Wave Reduction Intrinsics (#150395) 2025-09-10 20:13:30 +05:30
Hongyu Chen
75b0c89e62
[InstCombine][VectorCombine][NFC] Unify uses of lossless inverse cast (#156597)
This patch addresses
https://github.com/llvm/llvm-project/pull/155216#discussion_r2297724663.
This patch adds a helper function to put the inverse cast on constants,
with cast flags preserved(optional).
Follow-up patches will add trunc/ext handling on VectorCombine and flags
preservation on InstCombine.
2025-09-08 13:30:06 +00:00
Lewis Crawford
729701b885
[NVPTX] Constant fold NVVM add/mul/div/fma (#152544)
Constant fold the NVVM intrinsics for add, mul, div, fma with specific
rounding modes.
2025-08-22 17:33:00 +01:00
Jasmine Tang
10d9e7b1b7
Reapply "[WebAssembly] Constant fold wasm.dot" (#153070)
In #149619, for the test of `@dot_follow_modulo_spec_2`, constant
folding the addition of two i32 1073741824 causes an overflow from 2^32
to -2^32=-2147483648, which triggers the UB sanitizer. This PR reapplies
the previous PR, explicitly casting the addition operand to int64_t
first before performing the addition before producing a int32 number via
`Constant *C = get(cast<IntegerType>(Ty->getScalarType()), V, isSigned)`
2025-08-14 18:52:35 -07:00
Alexander Richardson
3a4b351ba1
[IR] Introduce the ptrtoaddr instruction
This introduces a new `ptrtoaddr` instruction which is similar to
`ptrtoint` but has two differences:

1) Unlike `ptrtoint`, `ptrtoaddr` does not capture provenance
2) `ptrtoaddr` only extracts (and then extends/truncates) the low
   index-width bits of the pointer

For most architectures, difference 2) does not matter since index (address)
width and pointer representation width are the same, but this does make a
difference for architectures that have pointers that aren't just plain
integer addresses such as AMDGPU fat pointers or CHERI capabilities.

This commit introduces textual and bitcode IR support as well as basic code
generation, but optimization passes do not handle the new instruction yet
so it may result in worse code than using ptrtoint. Follow-up changes will
update capture tracking, etc. for the new instruction.

RFC: https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/54

Reviewed By: nikic

Pull Request: https://github.com/llvm/llvm-project/pull/139357
2025-08-08 10:12:39 -07:00
Andrew Lazarev
f61526971f
Revert "[WebAssembly] Constant fold wasm.dot" (#152382)
Reverts llvm/llvm-project#149619

It breaks ubsan bot:
https://lab.llvm.org/buildbot/#/builders/25/builds/10523

Earlier today the failure was hidden by another breakage that is fixed
now.
2025-08-06 15:16:19 -07:00
Jasmine Tang
9c6bb18040
[WebAssembly] Constant fold wasm.dot (#149619)
Constant fold wasm.dot of constant vectors/splats.

Test case added in
`llvm/test/Transforms/InstSimplify/ConstProp/WebAssembly/dot.ll`

Related to https://github.com/llvm/llvm-project/issues/55933
2025-08-05 15:22:37 -07:00
Lewis Crawford
5146917407
[ConstantFolding] Fix incorrect nvvm_round folding (#151563)
The `nvvm_round` intrinsic should round to the nearest even number in
the case of ties. It lowers to PTX `cvt.rni`, which will "round to
nearest integer, choosing even integer if source is equidistant between
two integers", so it matches the semantics of `rint` (and not `round` as
the name suggests).
2025-08-01 10:31:43 +01:00
Lewis Crawford
c5327b935b
[ConstantFolding] Fix typo in GetNVVMDenormMode (#151297)
Fix typo in function name of GetNVVMDenormMode
(Denrom vs Denorm).
2025-07-30 10:48:09 +01:00
Paul Walker
1528ddbe76
[ConstantFolding][SVE] Do not fold fcmp of denormal without known mode. (#150614)
This is a follow on to
https://github.com/llvm/llvm-project/pull/115407 that introduced code
which bypasses the splat handling for scalable vectors. To maintain
existing tests I have moved the early return until after the splat
handling so all vector types are treated equally.
2025-07-29 12:37:59 +01:00
Pedro Lobo
67658af1cc
[ConstantFolding] Merge constant gep inrange attributes (#150546)
When folding a gep+gep into a single gep, intersect their `inrange`
attributes.
2025-07-25 20:02:06 +01:00
Kazu Hirata
31281da34b
[Analysis] Drop const from return types (NFC) (#150258)
We don't need const on APFloat.
2025-07-23 15:18:38 -07:00
Lewis Crawford
0823f4ff08
[ConstantFolding] Fix nvvm_round folding on PPC (#149837)
Fix a failing test for constant-folding the nvvm_round intrinsic. The
original implementation added in #141233 used a native libm call to the
"round" function, but on PPC this produces +0.0 if the input is -0.0,
which caused a test failure.

This patch updates it to use APFloat functions instead of native libm
calls to ensure cross-platform consistency.
2025-07-21 17:48:45 +01:00
Lewis Crawford
fd8ae2cb76
Add constant-folding for unary NVVM intrinsics (#141233)
Add support for constant-folding numerous NVVM unary arithmetic
intrinsics (including f, d, and ftz_f variants):
  - nvvm.ceil.*
  - nvvm.fabs.*
  - nvvm.floor.*
  - nvvm.rcp.*
  - nvvm.round.*
  - nvvm.saturate.*
  - nvvm.sqrt.f
  - nvvm.sqrt.rn.*
2025-07-21 11:32:09 +01:00
jjasmine
18286e0c2a
[WebAssembly] Constant fold SIMD intrinsics: any/alltrue (#148074)
Constant fold  SIMD wasm intrinsics: any/alltrue

Added test in `llvm/test/Transforms/InstSimplify`
2025-07-15 02:13:22 +08:00
Kazu Hirata
57cb9265bf
[Analysis] Drop const from a return type (NFC) (#147098)
We don't need const on a return type.
2025-07-04 18:38:28 -07:00
Nikita Popov
1d5d125648
[ConstantFolding] Consolidate poison propagation for intrinsics (#146878)
This consolidates the "fold poison arg to poison result" constant
folding logic for intrinsics, based on a common
intrinsicPropagatesPoison() helper, which is also used for poison
propagation reasoning in ValueTracking. This ensures that the set of
supported intrinsics is consistent.

This add ucmp, scmp, smul.fix, smul.fix.sat, canonicalize and sqrt to
the intrinsicPropagatesPoison list, as these were handled by
ConstantFolding but not ValueTracking. The ctpop test is an example of
the converse, where it was handled by ValueTracking but not
ConstantFolding.
2025-07-04 09:16:28 +02:00
Lei Huang
4a31f7f8ea
[ConstantFold] Special case atan +/-0.0 (#143962)
C's Annex F specifies that atan +/-0.0 returns the input value;
however, this behavior is optional and host C libraries may behave
differently. This change applies the Annex F behavior to constant
folding by LLVM.

Ref:
https://pubs.opengroup.org/onlinepubs/9799919799/functions/atan.html
2025-06-25 16:03:18 -04:00
Nikita Popov
80b79ce432
[ConstantFolding] Handle reading from type padding (#144330)
ReadDataFromGlobal() did not handle reads from the padding of types (in
the sense of type store size != type alloc size, rather than struct
padding).

Return zero in that case.

Fixes https://github.com/llvm/llvm-project/issues/144279.
2025-06-17 09:30:28 +02:00
Craig Topper
417ab37d85
[ConstantFolding] Fold deinterleave2 of any splat vector not just zeroinitializer (#144144)
While there remove an unnecessary dyn_cast from Constant to Constant.
Reverse a branch condition into an early out to reduce nesting.
2025-06-13 17:11:52 -07:00
Kazu Hirata
bcfbba12e6
[llvm] Compare std::optional<T> to values directly (NFC) (#143913)
This patch transforms:

  X && *X == Y

to:

  X == Y

where X is of std::optional<T>, and Y is of T or similar.
2025-06-13 08:11:20 -07:00
Nikolay Panchenko
ee35e34294
[ConstantFolding] Add folding for [de]interleave2, insert and extract (#141301)
The change adds folding for 4 vector intrinsics: `interleave2`,
`deinterleave2`, `vector_extract` and `vector_insert`. For the last 2
intrinsics the change does not use `ShuffleVector` fold mechanism as
it's much simpler to construct result vector explicitly.
2025-06-11 19:00:29 -04:00
Luke Lau
19b0e1227c
[ConstantFolding] Fold sqrt poison -> poison (#141821)
I noticed this when a sqrt produced by VectorCombine with a poison
operand wasn't getting folded away to poison.

Most intrinsics in general could probably be folded to poison if one of
their arguments are poison too. Are there any exceptions to this we need
to be aware of?
2025-06-11 13:27:14 +02:00
Craig Topper
112490f06a
[ConstantFolding] Add support for llvm.atan in constant folding. (#143416)
Fixes #143360
2025-06-09 12:38:08 -07:00
Lewis Crawford
1f7885cf9c
[ConstantFolding] Add flag to disable call folding (#140270)
Add an optional flag to disable constant-folding for function calls.
This applies to both intrinsics and libcalls.

This is not necessary in most cases, so is disabled by default, but in
cases that require bit-exact precision between the result from
constant-folding and run-time execution, having this flag can be useful,
and may help with debugging. Cases where mismatches can occur include
GPU execution vs host-side folding, cross-compilation scenarios, or
compilation vs execution environments with different math library
versions.

This applies only to calls, rather than all FP arithmetic. Methods such
as fast-math-flags can be used to limit reassociation, fma-fusion etc,
and basic arithmetic operations are precisely defined in IEEE 754.
However, other math operations such as sqrt, sin, pow etc. represented
by either libcalls or intrinsics are less well defined, and may vary
more between different architectures/library implementations.

As this option is not intended for most common use-cases, this patch
takes the more conservative approach of disabling constant-folding even
for operations like fmax, copysign, fabs etc. in order to keep the
implementation simple, rather than sprinkling checks for this flag
throughout.

The use-cases for this option are similar to StrictFP, but it is only
limited to FP call folding, rather than all FP operations, as it is
about precise arithmetic results, rather than FP environment behaviours.
It also can be used to when linking .bc files compiled with different
StrictFP settings with llvm-link.
2025-05-30 11:27:18 +01:00
Luke Lau
64106581b9
[Constant] Make Constant::getSplatValue return poison on poison (#141870)
This is a follow up from #141845. 

TargetTransformInfo::getOperandInfo needs to be updated to check for
undef values as otherwise a splat is considered a constant, and some
RISC-V cost model tests will start adding a cost to materialize the
constant.
2025-05-29 15:01:28 +01:00
Luke Lau
79ae407c95
[ConstantFolding] Fold intrinsics of scalable vectors with splatted operands (#141845)
As noted in
https://github.com/llvm/llvm-project/pull/141821#issuecomment-2917328924,
whilst we currently constant fold intrinsics of fixed-length vectors via
their scalar counterpart, we don't do the same for scalable vectors.

This handles the scalable vector case when the operands are splats.

One weird snag in ConstantVector::getSplat was that it produced a undef
if passed in poison, so this also contains a fix by checking for
PoisonValue before UndefValue.
2025-05-28 23:29:41 +01:00
Lewis Crawford
9c88b6d689
[ConstantFolding] Fold maximumnum and minimumnum (#138700)
Add constant-folding support for the maximumnum and minimumnum
intrinsics, and extend the tests to show the qnan vs snan behavior
differences between maxnum/maximum/maximumnum.
2025-05-08 18:00:49 +02:00
Luke Lau
d33c676468
[ConstantFolding] Constify ConstantFoldInstOperands and ConstantFoldInstruction argument. NFC (#138108)
I tried to use these with a const reference in a separate patch, but the
pointers weren't marked as const. It turns out that these don't mutate
the instruction.
2025-05-01 22:39:37 +08:00