645 Commits

Author SHA1 Message Date
Gauravsingh Sisodia
114f780855
[InstCombine] Fold select of intrinsic into intrinsic of select (#178002)
Fix https://github.com/llvm/llvm-project/issues/140917

Transform:
`select cond, intrinsic(x, ...), intrinsic(y, ...)`
into:
`intrinsic(select cond, x, y, ...)`
for `ctpop/ctlz/cttz/abs`.

alive2 proof: https://alive2.llvm.org/ce/z/Zp55Dy
2026-02-03 17:44:34 +01:00
SiliconA-Z
00fb7f86f8
[InstCombine] Extend canonicalization of addition to positive numbers (#179343)
https://alive2.llvm.org/ce/z/6PQdaP

Extend https://github.com/llvm/llvm-project/pull/153053 to positive numbers too.
2026-02-04 00:38:43 +08:00
Aiden Grossman
16c8a02f2d
[InstCombine] Propagate profile metadata when combining selects (#177883)
When we simplify a pair of selects, we want to propagate profile
information when the condition remains the same and drop it when it does
not. Before this patch, we were keeping incorrect profile data in
addition to not annotating any new select instructions that had the same
value as a previous one.

Noticed by looking at 80d9df6b054cebfbe97d709195be4e61a7acc694.
2026-01-26 11:25:06 -10:00
valadaptive
9b3b643106
[InstCombine] Don't convert a compare+select into a minnum/maxnum intrinsic that can't be lowered back to a compare+select (#177821)
This is a step on the yak-shaving expedition to properly implement the
new `minnum`/`maxnum` signed-zero semantics.

`InstCombineSelect` will convert a `fcmp`+`select` sequence to a
`minnum`/`maxnum` intrinsic. It doesn't require the `fcmp` to have any
particular fast-math flags, just that the `select` has `nnan` and `nsz`
(or is being used in a context where the result doesn't care about
signed zero).

It's not correct to propagate the `nnan` flag from the `fcmp`
instruction for poison-propagation reasons. Patches like
https://github.com/llvm/llvm-project/pull/117977 and
https://github.com/llvm/llvm-project/pull/141010 have *generously* made
it so that if `fcmp` doesn't have fast-math flags, we can still perform
the transformation by simply dropping the flags on the generated
intrinsic.

Unfortunately, converting an `fcmp`+`select` with fast-math flags, to a
`minnum`/`maxnum` without fast-math flags, is actually a
*pessimization*. Common ISAs like x86 and WebAssembly do not provide
single floating-point minimum/maximum instructions that handle NaN in
the same way as `minnum`/`maxnum`. They have to fall back to a routine
or a libcall, which causes its own problems
(https://github.com/llvm/llvm-project/issues/54554).

[Here's an example](https://llvm.godbolt.org/z/avYxa7ccK). Using just
`llc`, the function compiles to a single `maxss`. But with `clang -O3`,
which enables InstCombine optimizations, we end up with a much larger
(and completely unnecessary) routine for handling NaNs.

We should only perform this transformation if it's safe to add `nnan`
and `nsz` to the `minnum`/`maxnum` call, since those are the flags
necessary for lowering it *back* into an `fcmp`+`select` (or equivalent
code).

There's currently one case where we might end up without `nsz` on the
intrinsic call: if the output has one use, and that use doesn't care
about signed zero. To account for that, we should also unconditionally
set `nsz` on the generated intrinsic call.

With this in place, it should be safe to eventually revert
https://reviews.llvm.org/D122610 and further consolidate
`minnum`/`maxnum` handling.
2026-01-25 18:06:36 -05:00
Gábor Spaits
80d9df6b05
[InstCombine] Combine select(C0, select(C1, b, a), b) -> select(C0&&!C1, a, b) (#177410)
Fixes #82350

Address cases like:
```
select(C0, select(C1, b, a), b) -> select(C0&!C1, a, b)
select(C0, a, select(C1, b, a)) -> select(C0|!C1, a, b)
```
    
It seem that it generates better code for the real world examples for
the few targets I have checked: https://godbolt.org/z/KeEMd9b8E .
On the most generic case it generates the same assembly code for the
sources and targets for all targets, expect RISC-V, where the targets
seem shoretr and better (less branching):
https://godbolt.org/z/3has1Td5G So I did not experience any regression
on any target in no scenario.

Proofs: https://alive2.llvm.org/ce/z/DoL3zQ
2026-01-24 08:40:46 +01:00
Nathan Corbyn
a8098629bc
[IR] Teach drop/hasPoisonGeneratingAnnotations() about abs, ctlz and cttz (#175941) 2026-01-15 00:01:58 +00:00
Justin Lebar
c39f8b4730
[Instcombine] Fix infinite loop in visitSelectInst (#173704)
Doing a nop replaceOperand leads us into an infinite loop here.

This was found by a fuzzer I'm working on.  The high-level design is to
randomly generate LLVM IR, run a pass on it, and then run the original
and new IR through the interpreter.  They should produce the same
results.  Right now I'm only fuzzing instcombine.
2026-01-09 10:31:11 +01:00
Yunbo Ni
57927e9ffc
[InstCombine] Restrict foldBitCeil to power-of-two integer widths (#173849)
The masking rewrite in `foldBitCeil` assumes a power-of-two bitwidth.

For non-power-of-two integer types, `(-ctlz) & (BitWidth - 1)` is not
equivalent to `BitWidth - ctlz` and can miscompile.

This patch restricts the transform to power-of-two bitwidths. 

Alive2 proof: https://alive2.llvm.org/ce/z/i2E6zT

Fixes #173787
2025-12-29 12:17:36 +00:00
Yunbo Ni
a7d8b88d18
[InstCombine] Add check for flag propagation in foldSelectIntoOp (#173735)
Fixes
https://github.com/llvm/llvm-project/pull/162003#issuecomment-3693943568.

The current flag propagation assumes that if a select has both `ninf`
and `nnan`, then the operands of the folded operation must be finite.
While this assumption holds for `fadd`, `fsub`, and `fmul`, it does not
hold for `fdiv`.

For example, assume we have: 

```
A = 1.0, B = +Inf
A / B = 0.0  (finite, non-NaN)
```

The current transform would turn `fdiv A, B; select ninf nnan cond, A/B,
A;` into `A / (select ninf nnan cond, B, 1.0)`. If `cond` is true, the
inner select returns `B = +Inf`, and due to the propagated `ninf`, this
becomes poison.

This patch add check for operators before flag propagation to avoid
`fdiv` cases.

Alive2: https://alive2.llvm.org/ce/z/o0MJmS
2025-12-28 18:33:23 +08: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
Matt Arsenault
463c9f08be
InstCombine: Stop using m_c_BinOp for non-commutative ops (#172327)
The previous flow tried both m_BinOp and m_c_BinOp for noncommutative
ops. Seems to have worked out OK though, since there are no test
changes.
2025-12-15 17:57:53 +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
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
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
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
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
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
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
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
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
Alan Zhao
fea9ef325b
[InstCombine] Preserve profile branch weights when folding logical booleans (#161293)
Logical booleans in LLVM are represented by select statements - e.g. the
statement

```
A && B
```

is represented as

```
select i1 %A, i1 %B, i1 false
```

When LLVM folds two of the same logical booleans into a logical boolean
and a bitwise boolean (e.g. `A && B && C` -> `A && (B & C)`), the first
logical boolean is a select statement that retains the original
condition from the first logical boolean of the original statement. This
means that the new select statement has the branch weights as the
original select statement.

Tracking issue: #147390
2025-10-06 18:58:35 +00:00
Yingwei Zheng
c41611bacb
[InstCombine] Fix pointer replacement in foldSelectValueEquivalence (#161701)
Closes https://github.com/llvm/llvm-project/issues/161636.

Compile-time impact (+0.06%):
https://llvm-compile-time-tracker.com/compare.php?from=c2ef022aa7413ddc9aba48fa6fbe6fbd0cb14e19&to=9a0f0302efc30580136d191e66bac929f08ee25f&stat=instructions%3Au
I used to disable this fold for pointers, because I cannot construct a
positive test that is covered by `foldSelectValueEquivalence ` but not
covered by `simplifySelectWithICmpCond`. But the IR diff shows we still
benefit from the fold in InstCombine:
+ Bail out on pointers:
https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2880
+ This patch: https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2882
2025-10-05 14:02:00 +08:00
Alan Zhao
3b38314a2b
Reapply "[InstCombine] Preserve profile after folding select instructions with conditionals" (#161885) (#161890)
This reverts commit 572b579632fb79ea6eb562a537c9ff1280b3d4f5.

This is a reland of #159666 but with a fix moving the `extern`
declaration of the flag under the LLVM namespace, which is needed to fix
a linker error caused by #161240.
2025-10-03 12:26:09 -07:00
Mehdi Amini
572b579632
Revert "[InstCombine] Preserve profile after folding select instructions with conditionals" (#161885)
Reverts llvm/llvm-project#159666

Many bots are broken right now.
2025-10-03 19:37:23 +02:00
Alan Zhao
c54d0d7a96
[InstCombine] Preserve profile after folding select instructions with conditionals (#159666)
If `select` simplification produces the transform:

```
(select A && B, T, F) -> (select A, T, F)
```

or

```
(select A || B, T, F) -> (select A, T, F)
```

it stands to reason that if the branches are the same, then the branch
weights remain the same since the net effect is a simplification of the
conditional.

There are also cases where InstCombine negates the conditional (and
therefore reverses the branches); this PR asserts that the branch
weights are reversed in this case.

Tracking issue: #147390
2025-10-03 10:19:08 -07:00
Nikita Popov
e48fe76277
[InstCombine] Remove foldSelectWithFrozenICmp() fold (#161659)
After https://github.com/llvm/llvm-project/pull/154336 this fold no
longer triggers, as the freeze will be pushed through to the icmp
operands, and generic handling will take care of it.
2025-10-02 13:18:24 +00:00
Matthew Devereau
eb85899872
[InstCombine] Fold selects into masked loads (#160522)
Selects can be folded into masked loads if the masks are identical.
2025-09-24 18:30:33 +01:00
Ramkumar Ramachandra
7fb3a91418
[PatternMatch] Introduce match functor (NFC) (#159386)
A common idiom is the usage of the PatternMatch match function within a
functional algorithm like all_of. Introduce a match functor to shorten
this idiom.

Co-authored-by: Luke Lau <luke@igalia.com>
2025-09-17 21:04:33 +01:00
AZero13
e07b5968d4
[InstCombine] Fold select pattern with sub and negation to abs intrinsic (#156246)
```llvm
%sub = sub nsw T %x, %y
%cmp = icmp sgt T %x, %y  ; or sge
%neg = sub T 0, %sub
%abs = select i1 %cmp, T %sub, T %neg
```
becomes:

```llvm
%sub = sub nsw T %x, %y
%abs = call T @llvm.abs.T(T %sub, i1 false)
```
Alive2: https://alive2.llvm.org/ce/z/ApdJX8

https://alive2.llvm.org/ce/z/gRTmZk
2025-09-14 20:29:37 +08: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
Nimit Sachdeva
62fd332085
[InstCombine] Optimize usub.sat pattern (#151044)
Fixes #79690

Generalized proof: https://alive2.llvm.org/ce/z/22ybrr

---------

Co-authored-by: Nimit Sachdeva <nimsach@amazon.com>
2025-09-02 16:47:03 +00:00
Ryan Buchner
1f1fd07c32
[InstCombine] Optimize (select %x, op(%x), 0) to op(%x) for operations where op(0) == 0 (#147605)
Currently this optimization only occurs for `mul`, but this generalizes
that for any operation that has a fixed point of `0`.

There is similar logic within `EarlyCSE` pass, but that is stricter in
terms of `poison` propagation so will not optimize for many operations.

Alive2 Proofs:
`and`:
https://alive2.llvm.org/ce/z/RraasX ; base-case
https://alive2.llvm.org/ce/z/gzfFTX ; commuted-case
https://alive2.llvm.org/ce/z/63XaoX ; compare against undef
https://alive2.llvm.org/ce/z/MVRVNd ; select undef
https://alive2.llvm.org/ce/z/2bsoYG ; vector
https://alive2.llvm.org/ce/z/xByeX- ; vector compare against undef
https://alive2.llvm.org/ce/z/zNdzmZ ; vector select undef

`fshl`:
https://alive2.llvm.org/ce/z/U3_PG3 ; base-case
https://alive2.llvm.org/ce/z/BWCnxT ; compare against undef
https://alive2.llvm.org/ce/z/8HGAE_ ; select undef
; vector times out

`fshr`:
https://alive2.llvm.org/ce/z/o6F47G ; base-case
https://alive2.llvm.org/ce/z/fVnBXy ; compare against undef
https://alive2.llvm.org/ce/z/suymYJ ; select undef
; vector times out

`umin`:
https://alive2.llvm.org/ce/z/GGMqf6 ; base-case
https://alive2.llvm.org/ce/z/6cx5-k ; commuted-case
https://alive2.llvm.org/ce/z/W5d9tz ; compare against undef
https://alive2.llvm.org/ce/z/nKbaUn ; select undef
https://alive2.llvm.org/ce/z/gxEGqc ; vector
https://alive2.llvm.org/ce/z/_SDpi_ ; vector compare against undef

`sdiv`:
https://alive2.llvm.org/ce/z/5XGs3q

`srem`:
https://alive2.llvm.org/ce/z/vXAnQM

`udiv`:
https://alive2.llvm.org/ce/z/e6_8Ug

`urem`:
https://alive2.llvm.org/ce/z/VmM2SL

`shl`:
https://alive2.llvm.org/ce/z/aCZr3u ; Argument with range
https://alive2.llvm.org/ce/z/YgDy8C ; Instruction with known bits
https://alive2.llvm.org/ce/z/6pIxR6 ; Constant

`lshr`:
https://alive2.llvm.org/ce/z/WCCBej

`ashr:
https://alive2.llvm.org/ce/z/egV4TR

---------

Co-authored-by: Ryan Buchner <rbuchner@ventanamicro.com>
Co-authored-by: Yingwei Zheng <dtcxzyw@qq.com>
2025-07-16 19:42:41 -07:00
Alex MacLean
59388fb0b9
[InstCombine] Preserve NSW/NUW flags when folding const BOp with min/max (#143471)
When folding `X Pred C2 ? X BOp C1 : C2 BOp C1` to `min/max(X, C2) BOp
C1`, if NUW/NSW flags are present on `X BOp C1` and could be safely
applied to `C2 BOp C1`, then they may be added on the BOp after the fold
is complete. https://alive2.llvm.org/ce/z/n_3aNJ

Preserving these flags can allow subsequent transforms to re-order the
min/max and BOp, which in the case of NVPTX would allow for some
potential future transformations which would improve
instruction-selection.
2025-06-13 11:16:44 -07:00
Yash Solanki
a361a3dc7a
[llvm][InstCombine] Fold select to cmp for weak and inverted inequalities (#143445) 2025-06-13 21:53:34 +08:00
Alex MacLean
09029045a8
[InstCombine] Fold max/min when incrementing/decrementing by 1 (#142466)
Add the following folds for integer min max folding in InstCombine:
 -  (X > Y) ? X : (Y - 1) ==> MIN(X, Y - 1)
 -  (X < Y) ? X : (Y + 1) ==> MAX(X, Y + 1)

These are safe when overflow corresponding to the sign of the comparison
is poison. (proof https://alive2.llvm.org/ce/z/oj5iiI).

The most common of these patterns is likely the minimum case which
occurs in some internal library code when clamping an integer index to a
range (The maximum cases are included for completeness). Here is a
simplified example:

int clampToWidth(int idx, int width) {
  if (idx >= width)
    return width - 1;
  return idx;
}

https://cuda.godbolt.org/z/nhPzWrc3W
2025-06-10 07:55:56 -07:00
Alex MacLean
107601ed06
[InstCombine] Allow min/max in constant BOp min/max folding (#142878)
Extend folding for `X Pred C2 ? X BOp C1 : C2 BOp C1` to `min/max(X, C2)
BOp C1` to allow min and max as `BOp`. This ensures a constant clamping
pattern is folded into a pair of min/max instructions. Here is a
simplified example of a case where this folding is not occurring
currently.

int clampToU8(int v) {
    if (v < 0) return 0;
    if (v > 255) return 255;
    return v;
}

https://godbolt.org/z/78jhKPWbv

Generic proof: https://alive2.llvm.org/ce/z/cdpLYy
2025-06-06 12:44:04 -07:00
Yingwei Zheng
5e2dcfe42c
[InstCombine] Avoid infinite loop in foldSelectValueEquivalence (#142754)
Before this patch, InstCombine hung because it replaced a value with a
more complex one:
```
%sel = select i1 %cmp, i32 %smax, i32 0 ->
%sel = select i1 %cmp, i32 %masked, i32 0 ->
%sel = select i1 %cmp, i32 %smax, i32 0 ->
...
```
This patch makes this replacement more conservative. It only performs
the replacement iff the new value is one of the operands of the original
value.

Closes https://github.com/llvm/llvm-project/issues/142405.
2025-06-04 19:42:56 +08:00
Ramkumar Ramachandra
b40e4ceaa6
[ValueTracking] Make Depth last default arg (NFC) (#142384)
Having a finite Depth (or recursion limit) for computeKnownBits is very
limiting, but is currently a load-bearing necessity, as all KnownBits
are recomputed on each call and there is no caching. As a prerequisite
for an effort to remove the recursion limit altogether, either using a
clever caching technique, or writing a easily-invalidable KnownBits
analysis, make the Depth argument in APIs in ValueTracking uniformly the
last argument with a default value. This would aid in removing the
argument when the time comes, as many callers that currently pass 0
explicitly are now updated to omit the argument altogether.
2025-06-03 17:12:24 +01:00
Yingwei Zheng
3ec0c5c7fe
[InstCombine] Propagate FMF from select instead of fcmp (#141010)
Previously,
3d6b53980c
propagates FMF from fcmp to avoid performance regressions. With the help
of https://github.com/llvm/llvm-project/pull/139861,
https://github.com/llvm/llvm-project/pull/141015, and
https://github.com/llvm/llvm-project/pull/141914, we can still convert
SPF into fabs/minnum/maxnum intrinsics even if some flags are missing.
This patch propagates FMF from select to address the long-standing
issue.

Closes https://github.com/llvm/llvm-project/issues/140994.
2025-05-31 16:25:10 +08:00
Yingwei Zheng
87fd352d91
[InstCombine] Use canIgnoreSignBitOfZero in spf->minmax fold (#141914)
Alive2: https://alive2.llvm.org/ce/z/dCZBB_
Fix remaining regressions caused by https://github.com/llvm/llvm-project/pull/141010.
2025-05-30 14:18:05 +08:00
Yingwei Zheng
6c86b7d7d8
[ValueTracking][InstCombine] Generalize ignoreSignBitOfZero/NaN to handle more cases (#141015)
This patch was originally part of
https://github.com/llvm/llvm-project/pull/139861. It generalizes
`ignoreSignBitOfZero/NaN` to handle more instructions/intrinsics.

BTW, I find it mitigates performance regressions caused by
https://github.com/llvm/llvm-project/pull/141010 (IR diff
https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2365/files). We don't
need to propagate FMF from fcmp into select, since we can infer demanded
properties from the user of select.
2025-05-28 19:17:51 +08:00
Yingwei Zheng
d13947bd6c
[InstCombine] Enable more fabs fold when the user ignores sign bit of zero/NaN (#139861)
When the only user of select is a fcmp or a fp operation with nnan/nsz,
the sign bit of zero/NaN can be ignored.
Alive2: https://alive2.llvm.org/ce/z/ZcxeIv

Compile-time impact:
https://llvm-compile-time-tracker.com/compare.php?from=7add1bcd02b1f72d580bb2e64a1fe4a8bdc085d9&to=cb419c7cbddce778673f3d4b414ed9b8064b8d6e&stat=instructions:u

Closes https://github.com/llvm/llvm-project/issues/133367.
2025-05-21 23:50:00 +08:00
Yingwei Zheng
a0c4876eed
[InstCombine] Fix ninf propagation for fcmp+sel -> minmax (#136433)
Proof: https://alive2.llvm.org/ce/z/nCrvfr
Closes https://github.com/llvm/llvm-project/issues/136430
2025-04-28 17:24:46 +08:00
Yingwei Zheng
3e1e4062e1
[InstCombine] Preserve signbit semantics of NaN with fold to fabs (#136648)
As per the LangRef and IEEE 754-2008 standard, the sign bit of NaN is
preserved if there is no floating-point operation being performed.
See also
862e35e25a
for reference.

Alive2: https://alive2.llvm.org/ce/z/QYtEGj
Closes https://github.com/llvm/llvm-project/issues/136646
2025-04-26 14:03:12 +08:00
Andreas Jonson
2d1e64669e
[InstCombine] Reuse common code between foldSelectICmpAndBinOp and foldSelectICmpAnd. (#131902)
The commit that was removed from
https://github.com/llvm/llvm-project/pull/127905 due to the conflict
with https://github.com/llvm/llvm-project/pull/128741.

The use of common code results in that the foldSelectICmpAndBinOp also
use knownbits in the same way as was added for foldSelectICmpAnd in
https://github.com/llvm/llvm-project/pull/128741.

proof for the use of knowbits in foldSelectICmpAndBinOp:
https://alive2.llvm.org/ce/z/RYXr_k
2025-03-19 19:57:48 +01:00
Andreas Jonson
b326cb6792
[InstCombine] Support trunc to i1 in foldSelectICmpAnd (#127905)
proof: https://alive2.llvm.org/ce/z/Ey6BoT
2025-03-18 18:41:34 +01:00
Julian Nagele
beb4a48297
[InstCombine] Use known bits to simplify mask in foldSelectICmpAnd (#128741)
Make use of known bits when trying to decompose a select/icmp bittest and folding it into an and. This means we can fold when additional information, for instance via a range attribute or metadata, allows us to conclude that the resulting mask is in fact a power of two.
2025-03-14 16:34:04 +00:00
Yingwei Zheng
c5f40bf024
[InstCombine] Fold X!=Y ? ctz(X^Y, true) : BW -> ctz(X^Y, false) (#128483)
Proof: https://alive2.llvm.org/ce/z/mzL6W2
Closes https://github.com/llvm/llvm-project/issues/128441.
2025-02-24 17:35:46 +08:00
Andreas Jonson
aa847ced07
[InstCombine] handle trunc to i1 in foldSelectICmpAndBinOp (#127390)
for `trunc nuw` saves a instruction and otherwise only other
instructions without the select, same behavior as for bit test before.

proof: https://alive2.llvm.org/ce/z/a6QmyV
2025-02-19 18:29:47 +01:00