1131 Commits

Author SHA1 Message Date
Chang Lin
0ae9aaf539
[InstCombine] When rewriting GEPs, check that the types match. (#186886) 2026-03-20 17:37:00 -07:00
Alexis Engelke
080bc25728
[IR][NFCI] Remove *WithoutDebug (#187240)
The function instructionsWithoutDebug serves two uses: skipping debug
intrinsics and skipping pseudo instructions. Nonetheless, these
functions are expensive due to out-of-line filtering using
std::function. Ideally, the filter should be inlined, but that would
require including IntrinsicInst.h in BasicBlock.h.

We no longer use debug intrinsics, so the first use (parameter false) is
no longer needed. The second use is sometimes needed, but the
distinction between PseudoProbe instructions can be made at the call
sites more easily in many cases.

Therefore, remove instructionsWithoutDebug/sizeWithoutDebug.

c-t-t stage2-O3 -0.21%.
2026-03-18 15:08:41 +00:00
Alexis Engelke
d2ffc11f6b
[CFG][InstCombine][NFC] Use block numbers when finding backedges (#186668)
The functions traverse all basic blocks, so SmallPtrSets use a single
vector indexed by block number.
2026-03-15 16:45:25 +01:00
Alexis Engelke
efcd3b6108
[IPO][InstCombine][Vectorize][NFCI] Drop uses of BranchInst (#186596)
Refactor remaining parts of Transforms apart from Scalar and Utils.
2026-03-14 17:49:00 +00:00
Alexis Engelke
94da4039cb
[Analysis][NFC] Drop use of BranchInst (#186374)
Largely straight-forward replacement.
2026-03-13 13:42:19 +00:00
Matt Arsenault
2f5d9b6d96
InstCombine: Support basic phis in SimplifyDemandedFPClass (#184124)
Some complex function edge case epilogs are only handled under
some control flow paths (e.g. lgamma and erfcinv).
2026-03-11 16:03:28 +00:00
Alexis Engelke
4fd826d1f9
[IR] Split Br into UncondBr and CondBr (#184027)
BranchInst currently represents both unconditional and conditional
branches. However, these are quite different operations that are often
handled separately. Therefore, split them into separate opcodes and
classes to allow distinguishing these operations in the type system.
Additionally, this also slightly improves compile-time performance.
2026-03-11 12:31:10 +00:00
Gergo Stomfai
1043228613
[IR] Add BooleanMap matcher (#184463)
Add matcher when the output value is logically controlled by an input
value.

See
https://github.com/llvm/llvm-project/pull/180596#discussion_r2804366023
2026-03-10 10:45:16 +01:00
Nikita Popov
6ecbc0c96e
[InstCombine] Canonicalize GEP source element types (#180745)
Canonicalize GEP source element types from `%T` to `[sizeof(%T) x i8]`.

This is intended to flush out any remaining places that rely on GEP
element types, as part of the `ptradd` migration. The impact of this
change is expected to be fairly minimal (we might enable a few more
hoist/sink style folds that depend on equal GEP types).
2026-03-06 14:48:01 +00:00
Kiva
b86f24fd0e
[InstCombine] make foldBinOpIntoSelectOrPhi fold on all operands (#183692)
This PR makes `foldBinOpIntoSelectOrPhi` fold to select/phi both for
operands 0 and 1.

Alive2: https://alive2.llvm.org/ce/z/T56TMM
Also fixes #183498
2026-03-04 10:23:57 +01:00
Nikita Popov
deb70a6d64
[InstCombine] Don't strip leading zero index for overaligned vector GEP (#184364)
In this case the stride is not equal to the type alloc size.

Fixes issue reported in:
https://github.com/llvm/llvm-project/pull/180745#discussion_r2860093376
2026-03-04 08:57:27 +01:00
Nikita Popov
9d5ca5282d
[IR] Return bool from replaceUsesWithIf() (#184107)
We regularly want to know whether replaceUsesWithIf() actually replaced
any uses for the purpose of change tracking. It's possible to do this by
maintaining a Changed flag inside the callback, but it's cleaner if the
method directly returns whether it modified anything.
2026-03-02 14:50:55 +01:00
Nikita Popov
63e3e89b85
[InstCombine] Only ignore first zero index during GEP canonicalization (#180764)
When canonicalizing GEPs to have a single index, only ignore the first
leading zero index. This fixes a hole in the canonicalization in case
there was a struct zero offset, which can't be removed by the the
leading zero stripping.
2026-02-23 08:55:00 +00:00
Eli Friedman
bd3b163dce
Revert "[InstCombine] Allow freezing multiple operands (#154336)" (#182769)
This reverts commit f8f6965ceece9e330ddb66db5f402ecfb5e3ad34.

This is causing infinte loops interacting with other transforms. See
discussion on #182647 .
2026-02-22 14:22:56 -08:00
Shilei Tian
70905e0afa
[RFC][IR] Remove Constant::isZeroValue (#181521)
`Constant::isZeroValue` currently behaves same as
`Constant::isNullValue` for all types except floating-point, where it
additionally returns true for negative zero (`-0.0`). However, in
practice, almost all callers operate on integer/pointer types where the
two are equivalent, and the few FP-relevant callers have no meaningful
dependence on the `-0.0` behavior.

This PR removes `isZeroValue` to eliminate the confusing API. All
callers are changed to `isNullValue` with no test failures.

`isZeroValue` will be reintroduced in a future change with clearer
semantics: when null pointers may have non-zero bit patterns,
`isZeroValue` will check for bitwise-all-zeros, while `isNullValue` will
check for the semantic null (which
may be non-zero).
2026-02-15 12:06:42 -05:00
Kiva
03ab85cb87
[InstCombine] fold gepi _, (srem x, y) to gepi _, (urem x, y) if y is power-of-2 (#180148)
This PR adds a small, targeted InstCombine fold for the pattern:
```
%idx = srem i64 %x, 2^k
%p   = getelementptr inbounds nuw i8, ptr %base, i64 %idx
```

When the GEP is inbounds + nuw, and the divisor is a non-zero
power-of-two constant, the signed remainder cannot produce a negative
offset without violating the inbounds/nuw constraints. In that case we
can canonicalize the index to a non-negative form and expose the common
power-of-two rewrite:

- Rewrite the GEP index from `srem %x, 2^k` to `urem %x, 2^k`
- Create a new GEP with the new index and replace the original GEP
- the `urem %x, 2^k` will further folds to `and %x (2^k-1)`

resulting the following pattern

```
%idx = and i64 %x, (2^k-1)
%p   = getelementptr inbounds nuw i8, ptr %base, i64 %idx
```

Fixes #180097.
generalized alive2 proof: https://alive2.llvm.org/ce/z/8EBxug
2026-02-09 22:26:07 +08:00
Rahul Joshi
017ca73917
[NFC][LLVM] Remove pass initialization from pass constructors (#180158) 2026-02-06 09:06:32 -08:00
Luke Lau
d8073d9b4b
[InstCombine] Bubble splices of binop operands to their result (#179432)
In #172961 we are trying to remove llvm.experimental.vp.reverse now that
llvm.vector.splice.right supports variable offsets.

A VP reverse reverses the first EVL elements of the vector, e.g.
01234567 -> 210xxxxx when EVL=3, where x=poison.

This can now be represented by splice.right(reverse(V), poison, EVL):

       01234567
    -> 76543210 (reverse)
    -> 210xxxxx (splice.right)

This PR implements the vp.reverse combines that pull through binops, but
generalized to vector.splice. Specifically, this implements the
following combines:

    Op(splice(V1, poison, offset), splice(V2, poison, offset)) -> splice(Op(V1, V2), poison, offset)
    Op(splice(V1, poison, offset), RHSSplat) -> splice(Op(V1, RHSSplat), poison, offset)
    Op(LHSSplat, splice(V2, poison, offset)) -> splice(Op(LHSSplat, V2), poison, offset)

We can then remove the vp.reverse intrinsic and its related combines
soon after, once we migrate the loop vectorizer over.
2026-02-04 06:09:49 +00:00
Snehasish Kumar
fc7ad8127a
[InstCombine][profcheck] Preserve !prof metadata when folding select. (#177707)
The new select `InstCombinerImpl::foldBinOpSelectBinOp` reuses the same
condition in the same BB as the original so the profile info can be
trivially copied over.
2026-01-27 23:21:00 -08:00
Snehasish Kumar
da3f2934c3
[InstCombine][profcheck] Propogate profile metadata when transforming br (X && !Y) to br (!X || Y) (#175939)
Updated visitBranchInst to propagate and swap !prof metadata when transforming br (X && !Y) to br (!X || Y).
2026-01-27 23:18:53 -08:00
Alan Zhao
e47e51a30a
[profcheck][InstCombine] Fix missing profile data identified by not.ll test (#176497)
Tracking issue: #147390
2026-01-21 10:06:29 -08:00
Mircea Trofin
071bd59bd4
[profcheck][instcombine] Propagate branch weigths in folded GEP (#176247)
Patch following #170439. The branch weigths of the new select are the same as of the original's.

Issue #147390
2026-01-15 22:08:31 +00:00
Jianjian Guan
b153f17b8a
[InstCombine] Fold chained GEP with constant base into single GEP (#170439)
Fixes https://github.com/llvm/llvm-project/issues/167014.
2026-01-15 17:25:05 +08:00
Antonio Frighetto
bf5975e2ba
[InstCombine] Restrain folding switch condition operation into case to one-use
It may be profitable to simplify the switch condition operation into
their cases if such a condition is used only by the switch.
2026-01-13 14:41:37 +01:00
Sayan Sivakumaran
9e1a185be4
[InstCombine] Fold intrinsics over multi-use selects when the intrinsic is the only user (#172723)
Closes #172176.

Previously, `FoldOpIntoSelect` wouldn't fold multi-use selects if
`MultiUse` wasn't explicitly true. This prevents useful folding when the
select is used multiple times in the same intrinsic call. Similar to
what is done in `foldOpIntoPhi`, we'll now check that all of the uses
come from a single user, rather than checking that there is only one
use.
2026-01-09 17:25:43 +01:00
Matt Arsenault
1f2663e1f2
InstCombine: Prepare to handle multiple uses in SimplifyDemandedFPClass (#174863)
Follow the structure of SimplifyDemandedBits. Doesn't handle anything
in the multiple use case for now, and continues just calling
computeKnownFPClass.
2026-01-08 17:35:23 +01:00
Antonio Frighetto
2d050f0143
[InstCombine] Canonicalize switch(X^C) expressions to switch(X)
`switch(X^C)` expressions can be folded to `switch(X)`. Minor
opportunity to generalize simplifications in `visitSwitchInst`
via an inverse function helper as well.

Proof: https://alive2.llvm.org/ce/z/TMRy_3.

Fixes: https://github.com/llvm/llvm-project/issues/174255.
Fixes: https://github.com/llvm/llvm-project/issues/143368.
2026-01-05 21:23:14 +01:00
Gábor Spaits
58822a6933
[InstCombine] Fold (select C, (x bin_op a), x) bin_op b into x bin_op select C, (a bin_op b), b (#173511)
Fixes #154246.

The original pattern in the issue was the following:
```llvm
define i8 @src(i8 %arg0, i8 %arg1) {
  %v0 = icmp eq i8 %arg1, -1
  %v1 = or i8 %arg0, 4
  %v2 = select i1 %v0, i8 %v1, i8 %arg0
  %v3 = or i8 %v2, 1
  ret i8 %v3
}
```
to
```llvm
define i8 @tgt(i8 %arg0, i8 %arg1) {
  %v0 = icmp eq i8 %arg1, -1
  %v3.v = select i1 %v0, i8 5, i8 1
  %v3 = or i8 %arg0, %v3.v
  ret i8 %v3
}
```
(Alive2: https://alive2.llvm.org/ce/z/Nq6b4)

This PR works with other binary operators too like `add` and `mul`.
2026-01-04 20:45:25 +01:00
Matt Arsenault
cbb2aa9b2d
InstCombine: Replace some isa<FPMathOperator> with dyn_cast (#172356)
This isa and get flag pattern is essentially an abstracted
isa and dyn_cast, so make this more direct.
2025-12-15 20:10:29 +00:00
Nikita Popov
09b0885569
[LangRef] Specify icmp on pointers to only compare address (#163936)
This changes LangRef to specify that pointer icmp only compares the
address bits of the pointers. That is, `icmp pred %a, %b` is equivalent
to `icmp pred ptrtoaddr(%a), ptrtoaddr(%b)`.

Similarly, it specifies that the `nonnull` attribute requires that the
address bits are non-zero.

There are a couple of motivations for this:

* For inequality comparisons, this is really the only sensible
semantics. Relational comparison of address and metadata bits as a
single integer is generally meaningless (unless the metadata bits are
equal).
* This matches (as far as I understand) the behavior of existing CHERI
implementations.
* LLVM can only reason about the address bits. These semantics allow
pointers with non-address bits to receive essentially the same
comparison optimization support as ordinary pointers.

In terms of implementation, this PR adjusts:
 * The AMDGPULowerBufferFatPointers pass.
* An InstCombine fold that may replace pointers with different
non-address bits.
 * The fold that replaces pointers based on dominating pointer equality.

It does not adjust:
* ISel, because we don't have in-tree targets where we can show a
difference.
* Various icmp+ptrtoint transforms, because we'll have to change this
code for ptrtoaddr optimization support anyway, and these changes are
tightly related.

Related discussion starting from:
https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/60?u=nikic
2025-12-04 15:24:23 +00: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
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
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
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
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
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
Mircea Trofin
8aa49974df
[NFC][InstCombine] Make use of unknown profile info clear in the API name (#162766)
Making the choice more clear from the API name, otherwise it'd be very easy for one to just "not bother" with the `MDFrom`​, especially since it is optional and follows the optional `Name`​ - but this time we'd have a harder time detecting it's effectivelly dropped metadata.
2025-10-10 09:33:45 -07:00
Cullen Rhodes
100db53856
[InstCombine][nfc] Remove dead invoke inst check in foldOpIntoPhi (#161871)
There's a check above the pred block is terminated with an unconditional
branch, so this code is unreachable.
2025-10-08 09:44:57 +01:00
Rahul Joshi
9ebf1e9175
[NFC][InstCombine] Fix namespace usage in InstCombine (#161902) 2025-10-04 05:28:24 -07:00
Nicolai Hähnle
11a4b2d950
Cleanup the LLVM exported symbols namespace (#161240)
There's a pattern throughout LLVM of cl::opts being exported. That in
itself is probably a bit unfortunate, but what's especially bad about it
is that a lot of those symbols are in the global namespace. Move them
into the llvm namespace.

While doing this, I noticed some other variables in the global namespace
and moved them as well.
2025-10-01 15:32:07 -07:00
Yingwei Zheng
73d9974c91
[InstCombine] Avoid self-replacing in getUndefReplacement (#161500)
Self-replacing has a different meaning in InstCombine. It will replace
all uses with poison.
Closes https://github.com/llvm/llvm-project/issues/161492.
2025-10-01 22:02:30 +08:00
mikael-nilsson-arm
69586331e8
[InstCombine] Opt phi(freeze(undef), C) -> phi(C, C) (#161181)
Try to choose a value for freeze that enables the PHI to be replaced
with its input constants if they are equal.
2025-10-01 10:13:42 +02:00
Alan Zhao
045e09f22b
[InstCombine] Set !prof metadata on Selects identified by add.ll test (#158743)
These select instructions are created from non-branching instructions,
so their branch weights are unknown.

Tracking issue: #147390
2025-09-29 20:37:06 +00:00
Alan Zhao
b5afe416c7
[InstCombine] Preserve profile data with select instructions and binary operators (#158375)
Tracking issue: #147390
2025-09-15 20:12:08 +00:00
Nikita Popov
a301e1a895
[InstCombine] Split GEPs with multiple non-zero offsets (#151333)
Split GEPs that have more than one non-zero offset into two GEPs. This
is in preparation for the ptradd migration, which can only represent
such GEPs.

This also enables CSE and LICM of the common base.
2025-09-10 16:51:58 +02:00
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
Nikita Popov
349523e26b
[InstCombine] Merge constant offset geps across variable geps (#156326)
Fold:

    %gep1 = ptradd %p, C1
    %gep2 = ptradd %gep1, %x
    %res = ptradd %gep2, C2

To:

    %gep = ptradd %gep, %x
    %res = ptradd %gep, C1+C2

An alternative to this would be to generally canonicalize constant
offset GEPs to the right. I found the results of doing that somewhat
mixed, so I'm going for this more obviously beneficial change for now.

Proof for flag preservation on reassociation:
https://alive2.llvm.org/ce/z/gmpAMg
2025-09-03 10:47:32 +02:00
Kazu Hirata
a36a4019d3
[InstCombine] Remove unnecessary casts (NFC) (#156394)
These variables are already non const.
2025-09-01 23:12:07 -07:00
Nikita Popov
055bfc0271
[InstCombine] Strip leading zero indices from GEP (#155415)
GEPs are often in the form `gep [N x %T], ptr %p, i64 0, i64 %idx`.
Canonicalize these to `gep %T, ptr %p, i64 %idx`.

This enables transforms that only support one GEP index to work and
improves CSE.

Various transforms were recently hardened to make sure they still work
without the leading index.
2025-09-01 09:58:11 +02:00