567 Commits

Author SHA1 Message Date
Nikita Popov
0f7d148db4 [InstCombine] Add shared helper for logical and bitwise and/or (NFC)
Add a helper for shared folds between logical and bitwise and/or
and move the and/or of icmp and fcmp folds in there. This makes
it easier to extend to more folds.

A possible extension would be to base the current and/or of icmp
reassociation logic on this helper, so that it for example also
applies to fcmp.
2024-10-17 14:25:44 +02:00
Ramkumar Ramachandra
682fa797b7
InstCombine/Select: remove redundant code (NFC) (#112388)
InstCombinerImpl::foldSelectInstWithICmp has some inlined code for
select-icmp-xor simplification, but this simplification is already done
by other code, via another path:

  (X & Y) == 0 ? X : X ^ Y ->
  ((X & Y) == 0 ? 0 : Y) ^ X ->
  (X & Y) ^ X ->
  X & ~Y

Cover the cases that it claims to simplify, and demonstrate that
stripping it doesn't cause test changes.
2024-10-16 12:44:09 +01:00
Yingwei Zheng
0936195311
[InstCombine] Drop samesign in InstCombine (#112480)
Closes https://github.com/llvm/llvm-project/issues/112476.
2024-10-16 19:13:52 +08:00
Alexey Bader
583fa4f5b7
[InstCombine] Extend fcmp+select folding to minnum/maxnum intrinsics (#112088)
Today, InstCombine can fold fcmp+select patterns to minnum/maxnum
intrinsics when the nnan and nsz flags are set. The ordering of the
operands in both the fcmp and select instructions is important for the
folding to occur.

maxnum patterns:
1. (a op b) ? a : b -> maxnum(a, b), where op is one of {ogt, oge}
2. (a op b) ? b : a -> maxnum(a, b), where op is one of {ule, ult}

The second pattern is supposed to make the order of the operands in the
select instruction irrelevant. However, the pattern matching code uses
the CmpInst::getInversePredicate method to invert the comparison
predicate. This method doesn't take into account the fast-math flags,
which can lead missing the folding opportunity.

The patch extends the pattern matching code to handle unordered fcmp
instructions. This allows the folding to occur even when the select
instruction has the operands in the inverse order.

New maxnum patterns:
1. (a op b) ? a : b -> maxnum(a, b), where op is one of {ugt, uge}
2. (a op b) ? b : a -> maxnum(a, b), where op is one of {ole, olt}

The same changes are applied to the minnum intrinsic.
2024-10-15 22:05:16 +04:00
Ramkumar Ramachandra
1c6c850937
InstCombine: extend select-equiv to support vectors (#111966)
foldSelectEquivalence currently doesn't support GVN-like replacements on
vector types. Put in the checks for potentially lane-crossing
operations, and lift the limitation.
2024-10-15 11:10:45 +01:00
Rahul Joshi
fa789dffb1
[NFC] Rename Intrinsic::getDeclaration to getOrInsertDeclaration (#111752)
Rename the function to reflect its correct behavior and to be consistent
with `Module::getOrInsertFunction`. This is also in preparation of
adding a new `Intrinsic::getDeclaration` that will have behavior similar
to `Module::getFunction` (i.e, just lookup, no creation).
2024-10-11 05:26:03 -07:00
Marina Taylor
d0d12fc78a
[InstCombine] Fold (X==Z) ? (Y==Z) : (!(Y==Z) && X==Y) --> X==Y (#108619)
This corresponds to the canonicalized form of some logic that was
seen in Swift-generated code for comparing optional pointers:
`(X==Z || Y==Z) ? (X==Z && Y==Z) : X==Y --> X==Y`
where `Z` was the constant `0`.

https://alive2.llvm.org/ce/z/J_3aa9
2024-10-03 15:33:30 +01:00
Nikita Popov
b8d1bae648
[CmpInstAnalysis] Return decomposed bit test as struct (NFC) (#109819)
decomposeBitTestICmp() currently returns the result via two out
parameters plus an in-place modification of Pred. This changes it to
return an optional struct instead.

The motivation here is twofold. First, I'd like to extend this code to
handle cases where the comparison is against a value other than zero,
which would mean yet another out parameter. Second, while doing that I
was badly bitten by the in-place modification, so I'd like to get rid of
it.
2024-09-25 10:14:15 +02:00
Volodymyr Vasylkun
d4798498c4
[InstCombine] Fold (x == y) ? 0 : (x > y ? 1 : -1) into ucmp/scmp(x,y) (#107314)
This also handles commuted cases of the same fold, with either the
condition or the true/false values of the inner select being swapped.
2024-09-23 15:41:22 +01:00
Nikita Popov
3bc38fb27a
[InstCombine] Generalize and consolidate phi translation check (#106051)
The foldOpIntoPhi() transforms requires all operands to be
phi-translatable. This can be the case either because they are phi nodes
in the same block, or because the operand dominates the block.

Currently, most callers of foldOpIntoPhi() satisfy this pre-condition by
requiring a constant operand, which trivially dominates everything. Only
selects had handling for variable operands.

Move this logic into foldOpIntoPhi(), so things are handled correctly if
other callers are generalized. Also make the implementation a bit more
general by querying the dominator tree.
2024-09-04 16:22:43 +02:00
c8ef
43c6fb29a6
[InstCombine] Update the select operand when the cond is trunc and has the nuw or nsw property. (#105914)
This patch updates the select operand when the cond has the nuw or nsw
property. Considering the semantics of the nuw and nsw flag, if there is
no poison value in this expression, this code assumes that X can only be
0, 1 or -1.

close: #96765
alive2: https://alive2.llvm.org/ce/z/3n3n2Q
2024-08-24 19:56:59 +08:00
Volodymyr Vasylkun
da6f423251
[InstCombine] Fold (x < y) ? -1 : zext(x > y) and (x > y) ? 1 : sext(x < y) to ucmp/scmp(x, y) (#105272)
This patch expands already existing funcionality to include these two
additional folds, which are nearly identical to the ones already
implemented.

Proofs: https://alive2.llvm.org/ce/z/Xy7s4j
2024-08-23 22:31:03 +01:00
Volodymyr Vasylkun
abf69a167b
[InstCombine] Fold (x < y) ? -1 : zext(x != y) into u/scmp(x,y) (#101049)
This patch adds the aforementioned fold to InstCombine. This pattern is
produced after naive implementations of 3-way comparison in high-level
languages are transformed into LLVM IR and then optimized.

Proofs: https://alive2.llvm.org/ce/z/w4QLq_
2024-08-19 13:02:29 +01:00
Nikita Popov
5d28678277 [InstCombine] Fix incorrect zero ext in select of lshr/ashr fold
The -1 constant should be sign extended, not zero extended.

Split out from https://github.com/llvm/llvm-project/pull/80309.
2024-08-16 15:02:16 +02:00
Bjorn Pettersson
145aff6d92 Clean up pointer casts etc after opaque pointers transition. NFC (#102631) 2024-08-12 13:28:53 +02:00
Rose
ede49fa5f3 [InstCombine] Canonicalize more saturated-add variants (#100008)
LLVM is not evaluating X u > C, a, b the same way it evaluates X <= C, b, a.

To fix this, let's move the folds to after the canonicalization of -1 to TrueVal.

Let's allow splat vectors with poison elements to be recognized too!

Finally, for completion, handle the one case that isn't caught by the above checks because it is canonicalized to eq:
X == -1 ? -1 : X + 1 -> uadd.sat(X, 1)

Alive2 Proof:
https://alive2.llvm.org/ce/z/WEcgYH
2024-08-07 14:16:50 -07:00
Rose Silicon
278c0ad99e
[InstCombine] (NFC) Remove improper TODO for a - UMIN (#101076)
It is already handled in a different method, especially as a - UMIN(a,
b) cannot be handled by a select statement, unless it means something
like: "(c < b) ? b - ((b > c) ? c : b) : 0;" but LLVM handles that case
as well.
2024-08-06 13:39:03 -07:00
Yingwei Zheng
6def5170e8
[InstCombine] Fold (X & Mask) == 0 ? TC : FC -> TC binop (X & Mask) (#100437)
Alive2: https://alive2.llvm.org/ce/z/d9wV7N
2024-08-06 22:04:24 +08:00
Yingwei Zheng
62e9f40949
[PatternMatch] Use m_SpecificCmp matchers. NFC. (#100878)
Compile-time improvement:
http://llvm-compile-time-tracker.com/compare.php?from=13996378d81c8fa9a364aeaafd7382abbc1db83a&to=861ffa4ec5f7bde5a194a7715593a1b5359eb581&stat=instructions:u
baseline: 803eaf29267c6aae9162d1a83a4a2ae508b440d3
```
Top 5 improvements:
  stockfish/movegen.ll 2541620819 2538599412 -0.12%
  minetest/profiler.cpp.ll 431724935 431246500 -0.11%
  abc/luckySwap.c.ll 581173720 580581935 -0.10%
  abc/kitTruth.c.ll 2521936288 2519445570 -0.10%
  abc/extraUtilTruth.c.ll 1216674614 1215495502 -0.10%
Top 5 regressions:
  openssl/libcrypto-shlib-sm4.ll 1155054721 1155943201 +0.08%
  openssl/libcrypto-lib-sm4.ll 1155054838 1155943063 +0.08%
  spike/vsm4r_vv.ll 1296430080 1297039258 +0.05%
  spike/vsm4r_vs.ll 1312496906 1313093460 +0.05%
  nuttx/lib_rand48.c.ll 126201233 126246692 +0.04%
Overall: -0.02112308%
```
2024-07-29 10:04:06 +08:00
Yingwei Zheng
248fcab2fc
[InstCombine] Do not use operand info in replaceInInstruction (#99492)
Consider the following case:
```
%cmp = icmp eq ptr %p, null
%load = load i32, ptr %p, align 4
%sel = select i1 %cmp, i32 %load, i32 0
```
`foldSelectValueEquivalence` converts `load i32, ptr %p, align 4` into
`load i32, ptr null, align 4`, which causes immediate UB. `%load` is
speculatable, but it doesn't hold after operand substitution.

This patch introduces a new helper
`isSafeToSpeculativelyExecuteWithVariableReplaced`. It ignores operand
info in these instructions since their operands will be replaced later.

Fixes #99436.

---------

Co-authored-by: Nikita Popov <github@npopov.com>
2024-07-22 11:59:54 +08:00
Tim Gymnich
c034c44362
[InstCombine] Fold select of symmetric selects (#99245)
fixes #98800

Fold patterns like:
   select c2 (select c1 a b) (select c1 b a)
into:
   select (xor c1 c2) b a

Alive2 proofs:
https://alive2.llvm.org/ce/z/4QAm4K
https://alive2.llvm.org/ce/z/vTVRnC
2024-07-17 22:57:42 +08:00
Nikita Popov
3969d2c3b5 [InstCombine] Disable select known bits fold for vectors
This is not safe if the simplification ends up looking through
lane-crossing operations. For now, we don't have a good way to
limit this in computeKnownBits(), so just disable vector handling
entirely.

Fixes https://github.com/llvm/llvm-project/issues/97475.
2024-07-03 09:56:48 +02:00
Alex MacLean
8361d9065e
[InstCombine] disable select folding resulting in extra instructions (#97184)
Disable conversion of a `(select (icmp))` when it would result in more
instructions `(xor (lshr (and)))`. This transformation produces more
instructions and can interfere with other more profitable folds for
`select`. For example before this change the following folding would
occur:
```llvm
  %1 = icmp slt i32 %X, 0
  %2 = select i1 %1, i64 0, i64 8
```
to 
```llvm
  %1 = lshr i32 %X, 28
  %2 = and i32 %1, 8
  %3 = xor i32 %2, 8
  %4 = zext nneg i32 %3 to i64
```
2024-07-01 08:10:56 -07:00
Nikita Popov
77eb056830
[InstCombine] Simplify select using KnownBits of condition (#95923)
Simplify the arms of a select based on the KnownBits implied by its condition.
For now this only handles the case where the select arm folds to a constant,
but this can be generalized to handle other patterns by using
SimplifyDemandedBits instead (in that case we would also have to limit to
non-undef conditions).

This is implemented by adding a new member to SimplifyQuery that can be used
to inject an additional condition. The affected values are pre-computed and
we don't call computeKnownBits() if the select arms don't contain affected
values. This reduces the cost in some pathological cases.
2024-07-01 09:26:01 +02:00
Nikita Popov
2d209d964a
[IR] Add getDataLayout() helpers to BasicBlock and Instruction (#96902)
This is a helper to avoid writing `getModule()->getDataLayout()`. I
regularly try to use this method only to remember it doesn't exist...

`getModule()->getDataLayout()` is also a common (the most common?)
reason why code has to include the Module.h header.
2024-06-27 16:38:15 +02:00
Stephen Tozer
d75f9dd1d2 Revert "[IR][NFC] Update IRBuilder to use InsertPosition (#96497)"
Reverts the above commit, as it updates a common header function and
did not update all callsites:

  https://lab.llvm.org/buildbot/#/builders/29/builds/382

This reverts commit 6481dc57612671ebe77fe9c34214fba94e1b3b27.
2024-06-24 18:00:22 +01:00
Stephen Tozer
6481dc5761
[IR][NFC] Update IRBuilder to use InsertPosition (#96497)
Uses the new InsertPosition class (added in #94226) to simplify some of
the IRBuilder interface, and removes the need to pass a BasicBlock
alongside a BasicBlock::iterator, using the fact that we can now get the
parent basic block from the iterator even if it points to the sentinel.
This patch removes the BasicBlock argument from each constructor or call
to setInsertPoint.

This has no functional effect, but later on as we look to remove the
`Instruction *InsertBefore` argument from instruction-creation
(discussed
[here](https://discourse.llvm.org/t/psa-instruction-constructors-changing-to-iterator-only-insertion/77845)),
this will simplify the process by allowing us to deprecate the
InsertPosition constructor directly and catch all the cases where we use
instructions rather than iterators.
2024-06-24 17:27:43 +01:00
Noah Goldstein
b37a4b9991 [InstCombine] Improve coverage of foldSelectValueEquivalence for non-constants
If f(Y) simplifies to Y, replace with Y. This requires Y to be
non-undef.

Closes #94719
2024-06-23 11:15:47 +08:00
Nikita Popov
9e6625d6a2 [InstCombine] Preserve all gep flags in another select of gep fold 2024-06-19 12:18:01 +02:00
Nikita Popov
4c8ce5d301 [InstCombine] Preserve all flags in select of gep fold
Preserve the flag intersection.
2024-06-19 12:01:48 +02:00
Nikita Popov
9a86d0a6b5 [InstCombine] Prefer source over result element type (NFC)
For single-index GEPs the source and result element types are the
same, but using the source type is semantically more correct.
2024-06-17 11:03:00 +02:00
Zain Jaffal
22ff7c5dc9
[ValueTracking][NFC] move isKnownInversion to ValueTracking (#95321)
I am using `isKnownInversion` in the following pr 
https://github.com/llvm/llvm-project/pull/94915

it is useful to have the method in a shared class so I can reuse it. I am not sure if `ValueTracking` is the correct place but it looks like most of the methods with the pattern `isKnownX` belong there.
2024-06-13 07:14:08 +01:00
Nikita Popov
ec16f44d08 [InstCombine] Use named values in comment (NFC)
Also use opaque pointers.
2024-06-12 15:08:48 +02:00
Noah Goldstein
7e7c29ba08 [InstCombine] Improve coverage of foldSelectValueEquivalence for constants
We don't need the `noundef` check if the new simplification is a
constant.

This cleans up regressions from folding multiuse:
    `(icmp eq/ne (sub/xor x, y), 0)` -> `(icmp eq/ne x, y)`.

Closes #88298
2024-06-06 20:02:57 -05:00
Nikita Popov
9bea770b63 [InstCombine] Only requite not-undef in select equiv fold
As the comment already indicates, only replacement with undef
is problematic, as it introduces an additional use of undef.
Use the correct ValueTracking helper.
2024-06-06 09:38:08 +02:00
Yingwei Zheng
0a39c88e81
[InstCombine] Fold select Cond, not X, X into Cond ^ X (#93591)
See the following example:
```
define i1 @src(i64 %x, i1 %y) {
  %1526 = icmp ne i64 %x, 0
  %1527 = icmp eq i64 %x, 0
  %sel = select i1 %y, i1 %1526, i1 %1527
  ret i1 %sel
}

define i1 @tgt(i64 %x, i1 %y) {
  %1527 = icmp eq i64 %x, 0
  %sel = xor i1 %y, %1527
  ret i1 %sel
}
```
I find that this pattern is common in C/C++/Rust code base.
This patch folds `select Cond, Y, X` into `Cond ^ X` iff:
1. X has the same type as Cond
2. X is poison -> Y is poison
3. X == !Y

Alive2: https://alive2.llvm.org/ce/z/hSmkHS
2024-06-04 23:50:17 +08:00
Nikita Popov
3cd67eeca2 [InstCombine] Drop range attr in select of ctz fold
The range may no longer be valid after the select has been
optimized away.

This fixes the kernel miscompiles reported at
https://github.com/ClangBuiltLinux/linux/issues/2031.
2024-06-04 15:48:08 +02:00
Yingwei Zheng
b5f4210e9f
[InstCombine] Drop nuw flag when CtlzOp is a sub nuw (#91776)
See the following case:
```
define i32 @src1(i32 %x) {
  %dec = sub nuw i32 -2, %x
  %ctlz = tail call i32 @llvm.ctlz.i32(i32 %dec, i1 false)
  %sub = sub nsw i32 32, %ctlz
  %shl = shl i32 1, %sub
  %ugt = icmp ult i32 %x, -2
  %sel = select i1 %ugt, i32 %shl, i32 1
  ret i32 %sel
}

define i32 @tgt1(i32 %x) {
  %dec = sub nuw i32 -2, %x
  %ctlz = tail call i32 @llvm.ctlz.i32(i32 %dec, i1 false)
  %sub = sub nsw i32 32, %ctlz
  %and = and i32 %sub, 31
  %shl = shl nuw i32 1, %and
  ret i32 %shl
}
```
`nuw` in `%dec` should be dropped after the select instruction is
eliminated.

Alive2: https://alive2.llvm.org/ce/z/7S9529

Fixes https://github.com/llvm/llvm-project/issues/91691.
2024-05-13 14:27:59 +08:00
Eli Friedman
f893dccbba
Replace uses of ConstantExpr::getCompare. (#91558)
Use ICmpInst::compare() where possible, ConstantFoldCompareInstOperands
in other places. This only changes places where the either the fold is
guaranteed to succeed, or the code doesn't use the resulting compare if
we fail to fold.
2024-05-09 16:50:01 -07:00
Maciej Gabka
bfc0317153
Move several vector intrinsics out of experimental namespace (#88748)
This patch is moving out following intrinsics:
* vector.interleave2/deinterleave2
* vector.reverse
* vector.splice

from the experimental namespace.

All these intrinsics exist in LLVM for more than a year now, and are
widely used, so should not be considered as experimental.
2024-04-29 10:16:45 +01:00
Nikita Popov
7339f7ba30
[InstCombine] Fix poison propagation in select of bitwise fold (#89701)
We're replacing the select with the false value here, but it may be more
poisonous if m_Not contains poison elements. Fix this by introducing a
m_NotForbidPoison matcher and using it here.

Fixes https://github.com/llvm/llvm-project/issues/89500.
2024-04-24 10:57:17 +09:00
Yingwei Zheng
6309440c21
[InstCombine] Fix unexpected overwriting in foldSelectWithSRem (#89539)
Fixes #89516
2024-04-21 22:41:32 +08:00
Nikita Popov
1baa385065
[IR][PatternMatch] Only accept poison in getSplatValue() (#89159)
In #88217 a large set of matchers was changed to only accept poison
values in splats, but not undef values. This is because we now use
poison for non-demanded vector elements, and allowing undef can cause
correctness issues.

This patch covers the remaining matchers by changing the AllowUndef
parameter of getSplatValue() to AllowPoison instead. We also carry out
corresponding renames in matchers.

As a followup, we may want to change the default for things like m_APInt
to m_APIntAllowPoison (as this is much less risky when only allowing
poison), but this change doesn't do that.

There is one caveat here: We have a single place
(X86FixupVectorConstants) which does require handling of vector splats
with undefs. This is because this works on backend constant pool
entries, which currently still use undef instead of poison for
non-demanded elements (because SDAG as a whole does not have an explicit
poison representation). As it's just the single use, I've open-coded a
getSplatValueAllowUndef() helper there, to discourage use in any other
places.
2024-04-18 15:44:12 +09:00
Andreas Jonson
ff3523f67b
[IR] Drop poison-generating return attributes when necessary (#89138)
Rename has/dropPoisonGeneratingFlagsOrMetadata to
has/dropPoisonGeneratingAnnotations and make it also handle
nonnull, align and range return attributes on calls, similar
to the existing handling for !nonnull, !align and !range metadata.
2024-04-18 15:27:36 +09:00
Nikita Popov
525d00e5ed [InstCombine] Fix poison propagation in round up alignment fold
We can't directly use the high bits value if it is more poisonous
due to poison elements in the masks.

This fixes the issue reported in
https://github.com/llvm/llvm-project/pull/88217#issuecomment-2061034941.
2024-04-18 10:58:15 +09:00
XChy
313a33b9df
[InstCombine] Reduce nested logical operator if poison is implied (#86823)
Fixes #76623
Alive2 proof: https://alive2.llvm.org/ce/z/gX6znJ (I'm not sure how to
write a proof for such transform, maybe there are mistakes)

In most cases, `icmp(a, C1) && (other_cond && icmp(a, C2))` will be
reduced to `icmp(a, C1) & (other_cond && icmp(a, C2))`, since latter
icmp always implies the poison of the former. After reduction, it's
easier to simplify the icmp chain.
Similarly, this patch does the same thing for `(A && B) && C --> A && (B
& C)`. Maybe we could constraint such reduction only on icmps if there
is regression in benchmarks.
2024-04-10 14:19:44 +08:00
hanbeom
4ef22fce82
[InstCombine] Simplify select if it combinated and/or/xor (#73362)
`and/or/xor` operations can each be changed to sum of logical
operations including operators other than themselves.

 `x&y -> (x|y) ^ (x^y)`
 `x|y -> (x&y) | (x^y)`
 `x^y -> (x|y) ^ (x&y)`

if left of condition of `SelectInst` is `and/or/xor` logical
operation and right is equal to `0, -1`, or a `constant`, and
if `TrueVal` consist of `and/or/xor` logical operation then we
can optimize this case.

This patch implements this combination.

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

Fixes https://github.com/llvm/llvm-project/issues/71792.
2024-04-03 14:29:10 +08:00
Michele Scandale
09eb9f1136
[InstCombine] Fix for folding select into floating point binary operators. (#83200)
Folding a `select` into a floating point binary operators can only be
done if the result is preserved for both case. In particular, if the
other operand of the `select` can be a NaN, then the transformation
won't preserve the result value.
2024-03-19 09:47:07 -07:00
Artem Tyurin
141145232f
[IRBuilder] Fold binary intrinsics (#80743)
Fixes https://github.com/llvm/llvm-project/issues/61240.
2024-03-15 09:58:25 +01:00
Nikita Popov
9f45c5e1a6
[InstCombine] Fix infinite loop in select equivalence fold (#84036)
When replacing with a non-constant, it's possible that the result of the
simplification is actually more complicated than the original, and may
result in an infinite combine loop.

Mitigate the issue by requiring that either the replacement or
simplification result is constant, which should ensure that it's
simpler. While this check is crude, it does not appear to cause
optimization regressions in real-world code in practice.

Fixes https://github.com/llvm/llvm-project/issues/83127.
2024-03-06 09:33:51 +01:00