9595 Commits

Author SHA1 Message Date
Cullen Rhodes
64d4d10875
[InstCombine] Add more freeze PHI tests (NFC) (#172842)
Adds a number of test cases where we have to be careful when pushing
freeze around. These first two tests are taken from #157678 which failed
to land to due compile-time issues. The last two tests were reduced from
llvm-opt-benchmark workloads on #171435 which was an attempt at
addressing underlying cause of the hangs.
2025-12-19 09:16:57 +00:00
Nikita Popov
e957c81750 [InstCombine] Use getSigned() for negative number in shift transform
Fixes the issue reported at:
https://github.com/llvm/llvm-project/pull/171456#issuecomment-3668263635
2025-12-18 11:00:39 +01:00
Miloš Poletanović
44a52ea8be
[InstCombine] Fix unsafe PHINode cast and simplify logic in PointerReplacer (#172332)
Fixes #171883.

Basically, if the operand of the phi is an Instruction but it's not
available, the [condition
](1847a4efae/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp (L300))would
just break, and when we reach the[ deferral
check](1847a4efae/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp (L313)),
execution would continue even though there is a non-Instruction operand,
leading to a crash in the [subsequent processing
loop](1847a4efae/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp (L320)).
2025-12-17 12:07:40 +00:00
Krzysztof Drewniak
e7dd7b81ac
[AMDGPU] tensor_{load_to/store_from}_lds => ..._d2 simplification (#171540)
This commit adds the rewrite

```
llvm.amdgcn.tensor.{load.to/store.from}.lds(
  <4 x i32> %d0, <8 x i32> %d1, <4 x i32> zeroinitializer,
  <4 x i32> zeroinitializer, i32 [cachepolicy])
=>
llvm.amdgcn.tensor.{load.to/store.from}.lds.d2(
  <4 x i32> %$d0, <8 x i32> %d1, i32 [cachepolicy])
```

This is justifed because, when the short encoding that uses the NULL
SGPR for registers 2 and 3 is used, the hardware acts as if those
registers were 0, including in the gather mode.

It is always safe not to run this transformation.

(Note: tests were LLM'd and then tweaked.)
2025-12-15 08:11:03 -08:00
Matt Arsenault
6e47d4ef45
Reapply "InstCombine: Fold ldexp with constant exponent to fmul" (#171895) (#171977) 2025-12-12 12:55:55 +01:00
Matt Arsenault
975bda005e
InstCombine: Add more ldexp by constant tests (#171976) 2025-12-12 12:55:26 +01:00
Paul Walker
54744bc0a6
[LLVM][AArch64] Add "u" variants of sve.[s,u]hsub intrinsics (#170894) 2025-12-12 11:22:34 +00:00
Matt Arsenault
757c5b3bc7
Revert "InstCombine: Fold ldexp with constant exponent to fmul" (#171895)
Reverts llvm/llvm-project#171731

Fails on a libc test
2025-12-11 21:12:59 +00:00
Matt Arsenault
5eb2ec2179
InstCombine: Fold ldexp with constant exponent to fmul (#171731)
If we can represent this with an fmul, prefer it as a canonical
form. More optimizations will understand fmul, and allows contract to
fma.
2025-12-11 19:20:45 +01:00
Matt Arsenault
481ce81695
IR: Stop requiring nsz to reassociate fmul (#171726)
nsz can only change the behavior of the sign bit.
The sign bit for fmul can be implemented as xor,
which is associative. DAGCombiner already reassociates
the multiply by 2 constants without nsz.

Fixes #64967
2025-12-11 11:11:00 +00:00
Matt Arsenault
4f5071ffe3
InstCombine: Add baseline test for #64697 fmul reassociation (#171725)
Currently fmul is not reassociated unless it has nsz, although
this should be unnecessary.
2025-12-11 11:37:22 +01:00
Adar Dagan
488202935e
[ValueTracking] Enhance overflow computation for unsigned mul (#171568)
Changed the range computation in computeOverflowForUnsignedMul to use
computeConstantRange as well.

This expands the patterns that InstCombine manages to narrow a mul that
has values that come from zext, for example if a value comes from a div
operation then the known bits doesn't give the narrowest possible range
for that value.

---------

Co-authored-by: Adar Dagan <adar.dagan@mobileye.com>
2025-12-11 08:13:23 +01:00
valadaptive
7f2bbba60d
[AArch64][ARM] Optimize more tbl/tbx calls into shufflevector (#169748)
Resolves #169701.

This PR extends the existing InstCombine operation which folds `tbl1`
intrinsics to `shufflevector` if the mask operand is constant. Before
this change, it only handled 64-bit `tbl1` intrinsics with no
out-of-bounds indices. I've extended it to support both 64-bit and
128-bit vectors, and it now handles the full range of `tbl1`-`tbl4` and
`tbx1`-`tbx4`, as long as at most two of the input operands are actually
indexed into.

For the purposes of `tbl`, we need a dummy vector of zeroes if there are
any out-of-bounds indices, and for the purposes of `tbx`, we use the
"fallback" operand. Both of those take up an operand for the purposes of
`shufflevector`.

This works a lot like https://github.com/llvm/llvm-project/pull/169110,
with some added complexity because we need to handle multiple operands.
I raised a couple questions in that PR that still need to be answered:
- Is it correct to check `IsA<UndefValue>` for each mask index, and set
the output mask index to -1 if so? This is later folded to a poison
value, and I'm not sure about the subtle differences between poison and
undef and when you can substitute one for the other. As I mentioned in
#169110, the existing x86 pass (`simplifyX86vpermilvar`) already behaves
this way when it comes to undef.
- How can I write an Alive2 proof for this? It's very hard to find good
documentation or tutorials about Alive2.

As with #169110, most of the regression test cases were generated using
Claude. Everything else was written by me.
2025-12-09 16:11:26 +00:00
Tirthankar Mazumder
d94958b2f2
[InstCombine] Fold icmp samesign u{gt/lt} (X +nsw C2), C -> icmp s{gt/lt} X, (C - C2) (#169960)
Fixes #166973

Partially addresses #134028

Alive2 proof: https://alive2.llvm.org/ce/z/BqHQNN
2025-12-08 13:05:37 +01:00
Aiden Grossman
a94ee7e608
[InstCombine] Fix profile metadata when folding implied conditionals (#170756)
\#163412 touched this last and directly propagated the profile
information. This was not correct for the motivating example:

  %a = icmp eq i32 %z, 0
  %b = icmp eq i32 %z, 1
  %v2 = select i1 %b, i1 true, i1 %pred, !prof !18
  %v3 = and i1 %a, %v2

to

  %a = icmp eq i32 %z, 0
  %v3 = select i1 %a, i1 %pred, i1 false

z == 1 does not imply that z == 0 for i8. In general for the and case,
we need a => b, which means that b must be equivalent or more
restrictive than a, which means we cannot propagate profile information
without additional information on the value distribution of z. For the
or case we need !a => b. We again cannot derive profile information for
a/!a without additional value distribution information.
2025-12-05 09:17:13 -08:00
valadaptive
80760b0b1d
[SimplifyLibCalls] Recognize and simplify f[min/max]imumnum (#170699)
Unlike fmin and fmax, these are deterministic with regards to signed
zero.
2025-12-05 16:23:41 +00:00
Paul Walker
f1998360c3
[LLVM][AArch64] Add "u" variants of SVE saturating/rounding shift left intrinsics. (#170503)
This follows the same path used for regular shift intrinsics whereby the
"don't care about the result of inactive lanes" property of the
associated _x builtins is preserved. In doing this we gain the ability
to switch between reversed and movprfx variants depending on what best
fits register allocation.
2025-12-05 11:34:42 +00:00
valadaptive
bae2401295
[InstCombine] Add regression tests for f[min][max]imum_num libcalls (#170695)
Add tests corresponding to the existing fmin/fmax tests, as we'll later
begin optimizing these into intrinsics.
2025-12-05 11:54:52 +01: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
Paul Walker
b4b369a6bf
[LLVM][InstCombine][AArch64] sve.dup(V, all_active, S) ==> splat(S) (#170292)
Also refactors the rest of instCombineSVEDup to simplify the code.
2025-12-04 10:58:26 +00:00
Yingwei Zheng
6af1c3f3a9
[ValueTracking] Support scalable vector splats in computeKnownBits (#170345)
Similar to https://github.com/llvm/llvm-project/pull/170325, this patch
adds support for scalable vector splats in computeKnownBits.
2025-12-03 20:37:30 +08:00
Drew Kersnar
9c78bc5de4
Revert "[LSV] Merge contiguous chains across scalar types" (#170381)
Reverts llvm/llvm-project#154069. I pointed out a number of issues
post-merge, most importantly examples of miscompiles:
https://github.com/llvm/llvm-project/pull/154069#issuecomment-3603854626.

While the motivation of the change is clear, I think the implementation
approach is flawed. It seems like the goal is to allow elements like
`load <2xi16>` and `load i32` to be vectorized together despite the
current algorithm not grouping them into the same equivalence classes. I
personally think that if we want to attempt this it should be a more
wholistic approach, maybe even redefining the concept of an equivalence
class. This current solution seems like it would be really hard to do
bug-free, and even if the bugs were not present, it is only able to
merge chains that happen to be adjacent to each other after
`splitChainByContiguity`, which seems like it is leaving things up to
chance whether this optimization kicks in. But we can discuss more in
the re-land. Maybe the broader approach I'm proposing is too difficult,
and a narrow optimization is worthwhile. Regardless, this should be
reverted, it needs more iteration before it is correct.
2025-12-02 18:27:58 -05: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
David Green
f741851731 Revert "[AArch64][ARM] Move ARM-specific InstCombine transforms into Transforms/Utils (#169589)"
This reverts commit 1c32b6f51ccaaf9c65be11d7dca9e5a476cddb5a due to failures on
BUILD_SHARED_LIBS builds.
2025-12-02 11:46:50 +00:00
valadaptive
1c32b6f51c
[AArch64][ARM] Move ARM-specific InstCombine transforms into Transforms/Utils (#169589)
Back when `TargetTransformInfo::instCombineIntrinsic` was added in
https://reviews.llvm.org/D81728, several transforms common to both ARM
and AArch64 were kept in the non-target-specific `InstCombineCalls.cpp`
so they could be shared between the two targets.

I want to extend the transform of the `tbl` intrinsics into static
`shufflevector`s in a similar manner to
https://github.com/llvm/llvm-project/pull/169110 (right now it only
works with a 64-bit `tbl1`, but `shufflevector` should allow it to work
with up to 2 operands, and it can definitely work with 128-bit vectors).
I think separating out the transform into a TTI hook is a prerequisite.

~~I'm not happy about creating an entirely new module for this and
having to wire it up through CMake and everything, but I'm not sure
about the alternatives. If any maintainers can think of a cleaner way of
doing this, I'm very open to it.~~

I've moved the transforms into
`Transforms/Utils/ARMCommonInstCombineIntrinsic.cpp`, which is a lot
simpler.
2025-12-02 11:17:12 +00:00
Anshil Gandhi
fbdf8ab590
[LSV] Merge contiguous chains across scalar types (#154069)
This change enables the LoadStoreVectorizer to merge and vectorize
contiguous chains even when their scalar element types differ, as long
as the total bitwidth matches. To do so, we rebase offsets between
chains, normalize value types to a common integer type, and insert the
necessary casts around loads and stores. This uncovers more
vectorization opportunities and explains the expected codegen updates
across AMDGPU tests.

Key changes:
- Chain merging
  - Build contiguous subchains and then merge adjacent ones when:
- They refer to the same underlying pointer object and address space.
    - They are either all loads or all stores.
    - A constant leader-to-leader delta exists.
- Rebasing one chain into the other's coordinate space does not overlap.
    - All elements have equal total bit width.
- Rebase the second chain by the computed delta and append it to the
first.

- Type normalization and casting
- Normalize merged chains to a common integer type sized to the total
bits.
- For loads: create a new load of the normalized type, copy metadata,
and cast back to the original type for uses if needed.
  - For stores: bitcast the value to the normalized type and store that.
- Insert zext/trunc for integer size changes; use bit-or-pointer casts
when sizes match.

- Cleanups
  - Erase replaced instructions and DCE pointer operands when safe.
- New helpers: computeLeaderDelta, chainsOverlapAfterRebase,
rebaseChain, normalizeChainToType, and allElemsMatchTotalBits.

Impact:
- Increases vectorization opportunities across mixed-typed but
size-compatible access chains.
- Large set of expected AMDGPU codegen diffs due to more/changed
vectorization.

This PR resolves #97715.
2025-12-01 23:05:17 -05:00
Yingwei Zheng
9416b19e4f
[InstCombine] Add missing constant check (#170068)
`cast<Constant>` is not guarded by a type check during canonicalization
of predicates. This patch adds a type check in the outer if to avoid the
crash. `dyn_cast` may introduce another nested if, so I just use
`isa<Constant>` instead.

Address the crash reported in
https://github.com/llvm/llvm-project/pull/153053#issuecomment-3593914124.
2025-12-01 15:20:45 +08:00
actink
583fba3524
[InstCombine] fold icmp of select with invertible shl (#147182)
Proof: https://alive2.llvm.org/ce/z/a5fzlJ
Closes https://github.com/llvm/llvm-project/issues/146642

---------

Co-authored-by: Yingwei Zheng <dtcxzyw@qq.com>
2025-11-28 08:54:47 +08:00
Luke Lau
bb9449d5bb
[InstCombine] Fold @llvm.experimental.get.vector.length when cnt <= max_lanes (#169293)
On RISC-V, some loops that the loop vectorizer vectorizes pre-LTO may
turn out to have the exact trip count exposed after LTO, see #164762.

If the trip count is small enough we can fold away the
@llvm.experimental.get.vector.length intrinsic based on this corollary
from the LangRef:

> If %cnt is less than or equal to %max_lanes, the return value is equal
to %cnt.

This on its own doesn't remove the @llvm.experimental.get.vector.length
in #164762 since we also need to teach computeKnownBits about
@llvm.experimental.get.vector.length and the sub recurrence, but this PR
is a starting point.

I've added this in InstCombine rather than InstSimplify since we may
need to insert a truncation (@llvm.experimental.get.vector.length can
take an i64 %cnt argument, the result is always i32).

Note that there was something similar done in VPlan in #167647 for when
the loop vectorizer knows the trip count.
2025-11-27 07:16:03 +00:00
Peter Collingbourne
d2379effe9
Add deactivation symbol operand to ConstantPtrAuth.
Deactivation symbol operands are supported in the code generator by
building on the previously added support for IRELATIVE relocations.

Reviewers: ojhunt, fmayer, ahmedbougacha, nikic, efriedma-quic

Reviewed By: fmayer

Pull Request: https://github.com/llvm/llvm-project/pull/133537
2025-11-26 12:39:40 -08:00
Peter Collingbourne
6227eb90da
Add IR and codegen support for deactivation symbols.
Deactivation symbols are a mechanism for allowing object files to disable
specific instructions in other object files at link time. The initial use
case is for pointer field protection.

For more information, see the RFC:
https://discourse.llvm.org/t/rfc-deactivation-symbols/85556

Reviewers: ojhunt, nikic, fmayer, arsenm, ahmedbougacha

Reviewed By: fmayer

Pull Request: https://github.com/llvm/llvm-project/pull/133536
2025-11-26 12:37:09 -08:00
Valeriy Savchenko
d125cab13f
[InstCombine] Support multi-use values in cast elimination transforms (#165877)
`canEvaluateTruncated` and `canEvaluateSExtd` previously rejected
multi-use values to avoid duplication. This was overly conservative, if
all users of a multi-use value are part of the transform, we can
evaluate it in a different type without duplication.

This change tracks visited values and defers decisions on multi-use
values until we verify all their users were visited.
`EvaluateInDifferentType` now memoizes multi-use values to avoid
creating duplicates.

Applied to truncation and sext. Zext unchanged due to its dual-return
nature.
2025-11-25 17:43:26 +00:00
Marco Elver
02c9e8987a
[InstCombine][MemProf] Preserve all metadata (#169242)
When rewriting operator new calls to their hot/cold variants for PGHO,
`!alloc_token` metadata was being dropped. This metadata is required by
the AllocToken pass to correctly instrument the optimized allocation.

Fix it by preserving all metadata.
2025-11-25 16:56:06 +01:00
Meredith Julian
5d2fc9408e
[InstCombine] Fix phi scalarization with binop (#169120)
InstCombine phi scalarization would always create a new binary op with
the phi as the first operand, which is not correct for non-commutable
binary ops such as sub. This fix preserves the original binary op
ordering in the new binary op and adds a test for this behavior.
Currently, this transformation can produce silently incorrect IR, and in
the case of the added test, would optimize it out entirely.
2025-11-24 12:48:32 +01:00
Pedro Lobo
e8af134bb7
[InstCombine] Generalize trunc-shift-icmp fold from (1 << Y) to (Pow2 << Y) (#169163)
Extends the `icmp(trunc(shl))` fold to handle any power of 2 constant as
the shift base, not just 1. This generalizes the following patterns by
adjusting the comparison offsets by `log2(Pow2)`.

```llvm
(trunc (1 << Y) to iN) == 0    --> Y u>= N
(trunc (1 << Y) to iN) != 0    --> Y u<  N
(trunc (1 << Y) to iN) == 2**C --> Y ==  C
(trunc (1 << Y) to iN) != 2**C --> Y !=  C

; to

(trunc (Pow2 << Y) to iN) == 0    --> Y u>= N - log2(Pow2)
(trunc (Pow2 << Y) to iN) != 0    --> Y u<  N - log2(Pow2)
(trunc (Pow2 << Y) to iN) == 2**C --> Y ==  C - log2(Pow2)
(trunc (Pow2 << Y) to iN) != 2**C --> Y !=  C - log2(Pow2)
```

Proof: https://alive2.llvm.org/ce/z/2zwTkp
2025-11-22 15:44:06 +00:00
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