9560 Commits

Author SHA1 Message Date
AZero13
58cffea94a
[InstCombine] Canonicalize signed saturated additions (#153053)
https://alive2.llvm.org/ce/z/YGT5SN
https://alive2.llvm.org/ce/z/PVDxCw
https://alive2.llvm.org/ce/z/8buR2N

This is tricky because with positive numbers, we only go up, so we can
in fact always hit the signed_max boundary. This is important because
the intrinsic we use has the behavior of going the OTHER way, aka clamp
to INT_MIN if it goes in that direction.

And the range checking we do only works for positive numbers.

Because of this issue, we can only do this for constants as well.
2025-11-19 01:15:26 +08:00
Peter Collingbourne
b3c54914ef
InstCombine: Stop transforming EQ/NE of SHR to 0 to ULT/UGT if >1 use
This is a small code size optimization that lets us avoid both shifting
and comparing to a constant if we need the shifted value anyway. On most
architectures the zero comparison is cheaper than a constant comparison
(or free if the shift sets flags).

Although this change appears to remove the optimization entirely, we
continue to do this transform if there is one use because of the code
below the removed code that transforms the shift into an and, followed
by the PR10267 case in InstCombinerImpl::foldICmpAndConstConst that
transforms the and into a ult/ugt. Added a test case to verify this
explicitly.

Per [1] reduces clang .text size by 0.09% and dynamic instruction count
by 0.01%.

[1] https://llvm-compile-time-tracker.com/compare.php?from=1f38d49ebe96417e368a567efa4d650b8a9ac30f&to=0873787a12b8f2eab019d8211ace4bccc1807343&stat=size-text

Reviewers: nikic, dtcxzyw

Reviewed By: dtcxzyw

Pull Request: https://github.com/llvm/llvm-project/pull/168007
2025-11-17 19:39:20 -08:00
Paul Walker
f84ad4504d
[LLVM][InstCombine] not (bitcast (cmp A, B) --> bitcast (!cmp A, B) (#167693) 2025-11-13 11:47:12 +00:00
Daniel Thornburgh
c9ff2df8c3
[IR] "modular-format" attribute for functions using format strings (#147429)
A new InstCombine transform uses this attribute to rewrite calls to a
modular version of the implementation along with llvm.reloc.none
relocations against aspects of the implementation needed by the call.

This change only adds support for the 'float' aspect, but it also builds
the structure needed for others.

See issue #146159
2025-11-11 11:52:56 -08:00
Vladislav Dzhidzhoev
e2a2c03eef
[DebugInfo] Add Verifier check for incorrectly-scoped retainedNodes (#166855)
These checks ensure that retained nodes of a DISubprogram belong to the
subprogram.

Tests with incorrect IR are fixed. We should not have variables of one subprogram present in retained nodes of other subprograms.

Also, interface for accessing DISubprogram's retained nodes is slightly
refactored. `DISubprogram::visitRetainedNodes` and
`DISubprogram::forEachRetainedNode` are added to avoid repeating checks
like
```
if (const auto *LV = dyn_cast<DILocalVariable>(N))
  ...
else if (const auto *L = dyn_cast<DILabel>(N))
  ...
else if (const auto *IE = dyn_cast<DIImportedEntity>(N))
  ...
```
2025-11-10 13:13:49 +01:00
Florian Hahn
700b77b5e5
[InstCombine] Don't sink if it would require dropping deref assumptions. (#166945)
Currently sinking assumes in instcombine drops assumes if they would
prevent sinking. Removing dereferenceable assumptions earlier on can
inhibit vectorization of early-exit loops in practice.

Special-case deferenceable assumptions so that they block sinking. This
can be combined with a separate change to drop dereferencebale
assumptions after vectorization: https://clang.godbolt.org/z/jGqcx3sbs

PR: https://github.com/llvm/llvm-project/pull/166945
2025-11-09 21:08:46 +00:00
Andreas Jonson
b9ea93cd5c
[InstCombine] Fold operation into select, when one operand is zext of select's condition (#166816)
Proof https://alive2.llvm.org/ce/z/oCQyTG
2025-11-08 15:22:32 +01:00
Florian Hahn
ac047f2bd2
[InstCombnine] Add test for sinking with dereferneceable assumes.
Add tests showing sinking and dropping dereferenceable assumes prevents
vectorization.
2025-11-07 14:41:17 +00:00
Valeriy Savchenko
3e90ecaa2f
[ValueTracking] Refine known bits for linear interpolation patterns (#166378)
In this patch, we try to detect the lerp pattern: a * (b - c) + c * d
where a >= 0, b >= 0, c >= 0, d >= 0, and b >= c.

In that particular case, we can use the following chain of reasoning:

a * (b - c) + c * d <= a' * (b - c) + a' * c = a' * b where a' = max(a,
d)

Since that is true for arbitrary a, b, c and d within our constraints,
we can
conclude that:

  max(a * (b - c) + c * d) <= max(max(a), max(d)) * max(b) = U

Considering that any result of the lerp would be less or equal to U, it
would
have at least the number of leading 0s as in U.

While being quite a specific situation, it is fairly common in computer
graphics in the shape of alpha blending.

In conjunction with #165877, increases vectorization factor for lerp
loops.
2025-11-07 09:03:55 +00:00
Gábor Spaits
628d53aba5
[InstCombine] Enable FoldOpIntoSelect and foldOpIntoPhi when the Op's other parameter is non-const (#166102)
This patch enables `FoldOpIntoSelect` and `foldOpIntoPhi` for the cases
when Op's second parameter is a non-constant.
It doesn't seem to bring significant improvements, but the compile
time impact is neglegable.
2025-11-05 10:04:32 +01:00
Alan Zhao
c4763e2b90
[profcheck][InstCombine] Preserve branch weights in logical identities (#165810)
For the simplification
```
(C && A) || (!C && B) --> sel C, A, B
```
(and related), if `C` (or (`!C`)) is the condition in the select
instruction representing the logical and, we can preserve that logical
and's branch weights when emitting the new instruction. Otherwise, the
profile data is unknown.

If `C` is the condition of both logical ands, then we just take the
branch weights of the first logical and (though in practice they should
be equal.)

Furthermore, `select-safe-transforms.ii` now passes under the profcheck
configuration, so we remove it from the failing tests.

Tracking issue: #147390
2025-11-03 09:32:42 -08:00
Wenju He
79bf8c0331
[InstCombine] Fold select(X >s 0, 0, -X) | smax(X, 0) to abs(X) (#165200)
The IR pattern is compiled from OpenCL code:
  __builtin_astype(x > (uchar2)(0) ? x : -x, uchar2);
where smax is created by foldSelectInstWithICmp + canonicalizeSPF.

smax could also come from direct elementwise max call:
  int c = b > (int)(0) ? (int)(0) : -b;
  int d = __builtin_elementwise_max(b, (int)(0));
  *a = c | d;

https://alive2.llvm.org/ce/z/2-brvr
https://alive2.llvm.org/ce/z/Dowjzk
https://alive2.llvm.org/ce/z/kathwZ

---------

Co-authored-by: Yingwei Zheng <dtcxzyw@qq.com>
Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
2025-11-03 07:38:21 +08:00
azwolski
7631c73850
[InstCombine] Baseline test exposing vector fp-to-int conversion becoming scalar (#165800)
Baseline test for https://github.com/llvm/llvm-project/issues/165793
exposing the change from a vector fp-to-int conversion into a scalar one
inside the loop.

Additionally, removed
`llvm/test/Transforms/InstCombine/vec_extract_var_elt-inseltpoison.ll`,
which was a duplicate of
`llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll` differing only
by the use of poison in the insert element.
The poison variant has been merged into
`llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll`.

Also improved test naming and updated test checks.
2025-11-01 15:25:50 +08:00
Nikita Popov
1d7d26cf71 [InstCombine] Support ptrtoaddr of gep fold
This fold can be directly reused for ptrtoaddr. One caveat is
that for an inttoptr base, it currently won't work for pointers
with non-address bits. It's possible to support this case.
2025-10-28 12:55:54 +01:00
Nikita Popov
b6bbc4b194 [InstCombine] Support ptrtoaddr of ptrmask fold
For now not trying to share the code with ptrtoint, as there's very
little code.

Also fix IRBuilder::CreatePtrToAddr to actually create a PtrToAddr
instruction...
2025-10-28 12:22:19 +01:00
Nikita Popov
7900e63fbb [InstCombine] Support ptrtoaddr when converting to align assume bundle
ptrtoaddr can be treated the same way as ptrtoint here.
2025-10-28 12:02:47 +01:00
Wenju He
45b1bcfa26
[Instcombine] Avoid widening trunc+sext to trunc+shl+ashr when not profitable (#160483)
Skip the transform that replaces:
  %a = trunc i64 %x to i16
  %b = sext i16 %a to i32
with
  %a = trunc i64 %x to i32
  %b = shl i32 %a, 16
  %c = ashr exact i32 %b, 16
when (pre-trunc) source type is wider than the final destination type.
Modern architectures typically have efficient sign-extend instruction.
It is preferable to preserve the sext for this case.

Resolves #116019

Also fold sext(trunc nsw) to trunc nsw when narrowing source.
2025-10-28 09:01:50 +08:00
Changpeng Fang
1fb2ab37af
[InstCombine] Add the missing insertion point before IRBuilder instruction creation (#165315)
Should set the insertion point appropriately before we create an
instruction with IRBuilder.

Fixes: SWDEV-562571
2025-10-27 17:00:42 -07:00
Nikita Popov
de9e18dc75
[InstCombine] Handle ptrtoaddr in gep of pointer sub fold (#164818)
This extends the `ptradd x, ptrtoint(y) - ptrtoint(x)` to `y`
InstCombine fold to support ptrtoaddr. In the case where x and y have
the same underlying object, this is handled by InstSimplify already. If
the underlying object may differ, the replacement can only be performed
if provenance does not matter.

For pointers with non-address bits we need to be careful here, because
the pattern will return a pointer with the non-address bits of x and the
address bits of y. As such, uses in ptrtoaddr are safe to replace, but
uses in ptrtoint are not. Whether uses in icmp are safe to replace
depends on the outcome of the pending discussion on icmp semantics (I'll
adjust this in https://github.com/llvm/llvm-project/pull/163936 if/when
that lands).
2025-10-27 09:16:48 +01:00
Congzhe
e246fffb25
Reland "[InstructionSimplify] Enhance simplifySelectInst() (#163453)" (#164694)
This reverts commit f1c1063.

PR #163453 was merged and reverted since it exposed a crash. 
After investigation the crash was unrelated and is then fixed in #164628.

This is an attempt to reland #163453.
2025-10-26 00:39:49 -04:00
AZero13
4a6c5c6ea8
[InstCombine] Fold shifts + selects with -1 to scmp(X, 0) (#164129)
This is because the sign function with 0 tends to be folded to ashr and
other things.

Alive2: https://alive2.llvm.org/ce/z/Q59KvH
2025-10-25 00:46:41 +08:00
Mihail Mihov
6034ab3d98
[InstCombine] Add CTLZ -> CTTZ simplification (#164733)
This PR adds the simplification `ctlz(~x & (x - 1)) -> bitwidth -
cttz(x, false)` ([Alive2](https://alive2.llvm.org/ce/z/vVDRCu)).

Closes issue #164436
2025-10-25 00:40:11 +08:00
Benjamin Maxwell
8ebec3d551
[InstCombine] Constant fold binops through vector.insert (#164624)
This patch improves constant folding through `llvm.vector.insert`. It
does not change anything for fixed-length vectors (which can already be
folded to ConstantVectors for these cases), but folds scalable vectors
that otherwise would not be folded.

These folds preserve the destination vector (which could be undef or
poison), giving targets more freedom in lowering the operations.
2025-10-24 09:03:40 +01:00
paperchalice
249883d0c5
[test][Transforms] Remove unsafe-fp-math uses part 2 (NFC) (#164786)
Post cleanup for #164534.
2025-10-23 20:31:31 +08:00
Paul Walker
902b07f711
[LLVM][InstCombine][SVE] Improve isAllActivePredicate by looking through from.svbool. (#164446)
When a predicate is of the form "%a = sve.from.vsbool(%b)" we know all
bits in %a come from %b and thus if %b is all true then %a must also be
all true.
2025-10-23 12:17:19 +01:00
Nikita Popov
f801b6f67e
[InstCombine] Add support for ptrtoaddr in pointer difference folds (#164428)
This adds support for folding `ptrtoaddr(p2) - ptrtoaddr(p)` pointer
subtractions. We can treat ptrtoaddr the same as ptrtoint as the
transform is truncation safe anyway (and in fact supports explicit
truncation as well).

The only interesting case is the subtraction of zext of ptrtoaddr. For
this transform it's important that the address bits are not truncated --
and if any pointer bits are truncated, that the truncation is consistent
for both operands. I've explicitly spelled out the three different cases
for this, which also fixes a miscompile in the existing ptrtoint fold.
2025-10-23 11:57:24 +02:00
Benjamin Maxwell
c80495c1b0
[InstCombine] Allow folding cross-lane operations into PHIs/selects (#164388)
Previously, cross-lane operations were disallowed here, but they are
only problematic if the `select` condition is a vector, as the input of
the operation is not simply one of the arms of the phi/select.
2025-10-23 09:27:57 +01:00
Arthur Eubanks
f1c1063acb
Revert "[InstCombinePHI] Enhance PHI CSE to remove redundant phis" (#164520)
Reverts llvm/llvm-project#163453

Causes crashes, see
https://github.com/llvm/llvm-project/pull/163453#issuecomment-3429922732
2025-10-22 08:51:10 +00:00
Congzhe
9a9fbbba5c
[InstructionSimplify] Enhance simplifySelectInst() (#163453)
Fold select instructions with true and false values that act as the same 
phi, which cleans up the IR and open up opportunities for other passes 
such as loop vectorization.
2025-10-21 16:12:26 -04:00
Alan Zhao
9c42b3efc3
[InstCombine][profcheck] Preserve profile with negated select conditionals (#164342)
If a select instruction is replaced with one whose conditional is the
negation of the original, then the replacement's branch weights are the
reverse of the original's.

Tracking issue: #147390
2025-10-21 10:03:30 -07:00
Nikita Popov
6c4d121e7f [IR] Do not combine ptrtoaddr and trunc
The ptrtoaddr result type is required to match the pointer address
width. This means that, unlikely with ptrtoint, it's not legal to
merge a ptrtoint and trunc. This previously resulted in an IR
verifier failure.
2025-10-21 15:12:36 +02:00
Paul Walker
bdcbc1e5e7
[LLVM][InstCombine] Preserve vector types when shrinking FP constants. (#163598)
While my objective is to make the shrinkfp path safe for ConstantFP
based splats I discovered the following issues also affect
ConstantVector based splats:

1. PreferBFloat is not set for bfloat vectors.
2. getMinimumFPType() returns a scalar type for vector constants where
getSplatValue() is successful.
2025-10-21 11:55:21 +01:00
Nikita Popov
2e7afb1170 [InstCombine] Move ptrtoaddr tests to InstSimplify (NFC)
All the existing tests test code either in ConstantFolding or
InstSimplify, so move them to use -passes=instsimplify instead of
-passes=instcombine. This makes sure we keep InstSimplify coverage
even if there are subsuming InstCombine folds.

This requires writing some of the constant folding tests in a
different way, as InstSimplify does not try to re-fold already
existing constant expressions.
2025-10-20 14:39:40 +02:00
Nikita Popov
ee50839700 [InstSimplify] Support ptrtoaddr in simplifyCastInst()
Handle ptrtoaddr the same way as ptrtoint. The fold already only
operates on the index/address bits.
2025-10-20 14:18:34 +02: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
AZero13
49180d8329
[InstCombine] Add missing patterns for scmp and ucmp (#149225)
Fixes: [#146178](https://github.com/llvm/llvm-project/issues/146178)

https://alive2.llvm.org/ce/z/ZitMnX
https://alive2.llvm.org/ce/z/aJZ2BQ
2025-10-18 18:33:13 +00:00
kper
fcb5293ad0
[InstCombine]: Canonicalize to a mask when trunc nuw (#163628)
The canonicalize is also triggered when the `trunc` is `nuw`.

Proof: https://alive2.llvm.org/ce/z/eWvWe3
Fixes: https://github.com/llvm/llvm-project/issues/162451
2025-10-18 00:13:29 +08:00
Nikita Popov
c3366256fa
[InstCombine] Call InstSimplify for cast instructions (#162849)
InstCombine currently fails to call into InstSimplify for cast
instructions. I noticed this because the transform from
https://github.com/llvm/llvm-project/pull/98649 can be triggered via
`-passes=instsimplify` but not `-passes=instcombine`, which is not
supposed to happen.
2025-10-16 11:27:47 +02:00
Aiden Grossman
6dcdf27056
[InstCombine] Propagate Profile when Folding Implied Conditionals (#163412)
In the case where we have a conditional that is implied by a previous
conditional (like x < 10 => x < 20 in a select), we can simply propagate
the profile information along the select.
2025-10-14 09:24:29 -07:00
Nikita Popov
4a3e0001e3
[IR] Handle trunc for ptrtoaddr(inttoptr) cast pair (#162842)
For ptrtoint(inttoptr) and ptrtoaddr(inttoptr), handle the case where
the source and destination size do not match and convert to either zext
or trunc. We can't do this if the middle size is smaller than both
src/dest, because we'd have to perform an additional masking operation
in that case.

Most of these cases are handled by dint of ptrtoint/inttoptr size
canonicalization (so I added some unit tests instead). However, the
ptrtoaddr(inttoptr) case where the pointer size and address size differ
is relevant, as in that case the mismatch in integer sizes is canonical.
2025-10-13 09:10:41 +00:00
Nikita Popov
af4367a6db
[InstCombine] Skip foldFBinOpOfIntCastsFromSign for vector ops (#162804)
Converting a vector float op into a vector int op may be non-profitable,
especially for targets where the float op for a given type is legal, but
the integer op is not.

We could of course also try to address this via a reverse transform in
the backend, but I don't think it's worth the bother, given that vectors
were never the intended use case for this transform in the first place.

Fixes https://github.com/llvm/llvm-project/issues/162749.
2025-10-13 10:13:34 +02:00
Yingwei Zheng
9e63b7ae4c
[InstCombine] Fix flag propagation in foldSelectIntoOp (#162003)
Consider the following transform:
```
C = binop float A, nnan OOp
D = select ninf, i1 cond, float C, float A
->
E = select ninf, i1 cond, float OOp, float Identity
F = binop float A, E
```
We cannot propagate ninf from the original select, because OOp may be
inf, and the flag only guarantees that FalseVal (op OOp) is never
infinity.
Examples: -inf + +inf = NaN, -inf - -inf = NaN, 0 * inf = NaN
Specifically, if the original select has both ninf and nnan, we can
safely propagate the flag.

Alive2: 
+ fadd: https://alive2.llvm.org/ce/z/TWfktv
+ fsub: https://alive2.llvm.org/ce/z/RAsjJb
+ fmul: https://alive2.llvm.org/ce/z/8eg4ND

Closes https://github.com/llvm/llvm-project/issues/161634.
2025-10-11 10:04:55 +08:00
Nikita Popov
f04ae1f4b1 [InstCombine] Perform common cast transforms for ptrtoaddr 2025-10-10 15:08:21 +02:00
Brad Smith
31e85cc572
[Android] Drop workarounds for older Android API levels pre 9, 17 and 21 (#161911)
Drop workarounds for Android API levels pre 9, 17, 21.

The minimum Android API currently supported by the LTS NDK is 21.
2025-10-10 03:59:44 -04:00
Nikita Popov
187a8e3e08
[InstSimplify] Support ptrtoaddr in pointer subtraction fold (#162672)
Add a new m_PtrToIntOrAddr() matcher which matches both ptrtoint and
ptrtoaddr. Pointer arithmetic only works on the address bits, so
supporting ptrtoaddr is always fine here.
2025-10-10 09:30:30 +02:00
Alan Zhao
a1b5e975c9
[InstCombine][profcheck] Preserve profile when folding constant value equivalences (#162736) 2025-10-09 21:43:02 -07: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
69f2de1996 [InstCombine] Add test for inttoptr of ptrtoaddr (NFC)
And document that we're intentionally not folding this case.
For inttoptr of ptrtoint this is controlled by the
-disable-i2p-p2i-opt flag, but I don't think there is a need to
replicate this known unsound fold for ptrtoaddr, given their
different usage characteristics.
2025-10-09 10:39:25 +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
zGoldthorpe
7910ed2232
[InstCombine] Canonicalise packed-integer-selecting shifts (#162147)
This patch resolves recent regressions related to [issue
#92891](https://github.com/llvm/llvm-project/issues/92891).
It specifically enables the following types of reductions.

```llvm
define i16 @src(i32 %mask, i32 %upper, i32 range(i32 0, 65536) %lower) {
  %upper.shl = shl nuw i32 %upper, 16
  %pack = or disjoint i32 %upper.shl, %lower
  %mask.bit = and i32 %mask, 16
  %sel = lshr i32 %pack, %mask.bit
  %trunc = trunc i32 %sel to i16
  ret i16 %trunc
}
; =>
define i16 @tgt(i32 %mask, i32 %upper, i32 range(i32 0, 65536) %lower) {
  %mask.bit = and i32 %mask, 16
  %mask.bit.z = icmp eq i32 %mask.bit, 0
  %sel = select i1 %mask.bit.z, i32 %lower, i32 %upper
  %trunc = trunc i32 %sel to i16
  ret i16 %trunc
}
```

Alive2 proofs: [gJ9MpP](https://alive2.llvm.org/ce/z/gJ9MpP)
2025-10-08 06:58:11 -06:00