955 Commits

Author SHA1 Message Date
XChy
b22917e6e2
[InstCombine] Fold Ext(i1) Pred shr(A, BW - 1) => i1 Pred A s< 0 (#68244)
Resolves #67916 .
This patch folds `Ext(icmp (A, xxx)) Pred shr(A, BW - 1)` into `i1 Pred
A s< 0`.
[Alive2](https://alive2.llvm.org/ce/z/k53Xwa).
2023-10-13 22:02:57 +08:00
Antonio Frighetto
1c12dcc910 [InstCombine] Extend sext/zext boolean additions to vectors
Reported-by: shao-hua-li

Fixes: https://github.com/llvm/llvm-project/issues/68745.
2023-10-12 14:38:54 +00:00
Yingwei Zheng
b3b3336e82
[InstCombine] Simplify the pattern a ne/eq (zext/sext (a ne/eq c)) (#65852)
This patch folds the pattern `a ne/eq (zext/sext (a ne/eq c))` into a boolean constant or a compare.
Clang vs GCC: https://godbolt.org/z/4ro817WE8
Proof for `zext`: https://alive2.llvm.org/ce/z/6z9NRF
Proof for `sext`: https://alive2.llvm.org/ce/z/tv5wuE
Fixes #65073.
2023-10-06 20:57:58 +08:00
elhewaty
5d8fb473d3
[InstCombine] Fold comparison of adding two z/sext booleans (#67895)
- Add test coverage for sext/zext boolean additions
- [InstCombine] Fold comparison of adding two z/sext booleans

Fixes https://github.com/llvm/llvm-project/issues/64859.
2023-10-06 17:29:13 +08:00
Yingwei Zheng
c4e2fcff78
[InstCombine] Don't simplify icmp eq/ne OneUse(A ^ Cst1), Cst2 in foldICmpEquality
This special case will be handled in foldICmpXorConstant later.
See also commit e9cb50a1e351e90be1a8e4ac1a4564cfc44a984b.
2023-09-29 21:21:00 +08:00
Yingwei Zheng
e9cb50a1e3
[InstCombine] Fix infinite loop in #67273
Closes #67783.
2023-09-29 20:26:39 +08:00
Nikita Popov
6ce7461eea [InstCombine] Avoid uses of ConstantExpr::getCast()
Add a generalized getLosslessTrunc() helper to simplify this.
2023-09-29 11:32:41 +02:00
Nikita Popov
b4afade175 [InstCombine] Avoid use of ConstantExpr::getZExtOrBitcast() (NFC)
Use the constant folding API instead. In the second case using
IR builder should also work, but the way the instructions are
created an inserted there is very unusual, so I've left it alone.
2023-09-29 09:44:43 +02:00
Yingwei Zheng
e158add121
[InstCombine] Canonicalize icmp eq/ne (A ^ C), B to icmp eq/ne (A ^ B), C (#67273)
This patch canonicalizes `icmp eq/ne (A ^ Cst), B` to `icmp eq/ne (A ^ B), Cst` since the latter form exposes more optimizations.
Proof: https://alive2.llvm.org/ce/z/9DbhGc
Fixes #65968.
2023-09-26 19:33:31 +08:00
Yingwei Zheng
416e891d66
[Reland][InstCombine] Fold icmp eq/ne min|max(X, Y), Z (#67087)
This patch further improves the simplification of pattern `icmp eq/ne
min|max(X, Y), Z` as discussed in
[D156238](https://reviews.llvm.org/D156238).
When `X < Z`:
`min(X, Y) == Z -> false`
`min(X, Y) != Z -> true`
`max(X, Y) == Z -> Y == Z`
`max(Y, Z) != Z -> Y != Z`
When `X > Z`:
`max(X, Y) == Z -> false`
`max(X, Y) != Z -> true`
`min(X, Y) == Z -> Y == Z`
`min(Y, Z) != Z -> Y != Z`

Alive2:  https://alive2.llvm.org/ce/z/evkmaq
2023-09-25 15:46:39 +08:00
Vitaly Buka
4c1c96e6fc Revert "[InstCombine] Fold icmp eq/ne min|max(X, Y), Z (#67087)"
Details in https://reviews.llvm.org/D156238

This reverts commit d2abe8dc662a94e6c9aca5b64af53c7f815b5701.
2023-09-24 18:48:02 -07:00
Yingwei Zheng
d2abe8dc66
[InstCombine] Fold icmp eq/ne min|max(X, Y), Z (#67087)
This patch further improves the simplification of pattern `icmp eq/ne
min|max(X, Y), Z` as discussed in
[D156238](https://reviews.llvm.org/D156238).
When `X < Z`:
`min(X, Y) == Z -> false`
`min(X, Y) != Z -> true`
`max(X, Y) == Z -> Y == Z`
`max(Y, Z) != Z -> Y != Z`
When `X > Z`:
`max(X, Y) == Z -> false`
`max(X, Y) != Z -> true`
`min(X, Y) == Z -> Y == Z`
`min(Y, Z) != Z -> Y != Z`

Alive2:  https://alive2.llvm.org/ce/z/evkmaq
2023-09-25 03:59:49 +08:00
Yingwei Zheng
5163319ee2
[InstCombine] Use ConstantInt::getBool instead of Constant::getIntegerValue. NFC.
See also https://reviews.llvm.org/D156238#inline-1546774
2023-09-16 17:41:10 +08:00
Noah Goldstein
119194ada6 [InstCombine] Transform (icmp ult/uge (and X, Y), X) -> (icmp ne/eq (and X, Y), X)
eq/ne are generally easier to reason about elsewhere.

ult -> ne: https://alive2.llvm.org/ce/z/5wxXGt
uge -> eq: https://alive2.llvm.org/ce/z/Dw6kqG

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D145425
2023-09-13 15:50:17 -05:00
Jeremy Morse
e54277fa10 [NFC][RemoveDIs] Use iterators over inst-pointers when using IRBuilder
This patch adds a two-argument SetInsertPoint method to IRBuilder that
takes a block/iterator instead of an instruction, and updates many call
sites to use it. The motivating reason for doing this is given here [0],
we'd like to pass around more information about the position of debug-info
in the iterator object. That necessitates passing iterators around most of
the time.

[0] https://discourse.llvm.org/t/rfc-instruction-api-changes-needed-to-eliminate-debug-intrinsics-from-ir/68939

Differential Revision: https://reviews.llvm.org/D152468
2023-09-11 20:01:19 +01:00
Yingwei Zheng
44e5afdb91
[InstCombine] Generalize foldICmpWithMinMax
This patch generalizes the fold of `icmp pred min/max(X, Y), Z` to address the issue https://github.com/llvm/llvm-project/issues/62898.

For example, we can fold `smin(X, Y) < Z` into `X < Z` when `Y > Z` is implied by constant folds/invariants/dom conditions.

Alive2 (with `--disable-undef-input` due to the limitation of --smt-to=10000): https://alive2.llvm.org/ce/z/rB7qLc
You can run the standalone translation validation tool `alive-tv` locally to verify these transformations.
```
alive-tv transforms.ll --smt-to=600000 --exit-on-error
```

Reviewed By: goldstein.w.n

Differential Revision: https://reviews.llvm.org/D156238
2023-09-11 02:26:48 +08:00
bipmis
370880cdcc [InstCombine] Fold icmp into phi beyond the same BB.
The icmp is being folded in phi only if they belong in the same BB.
This patch extends the same beyond the BB.
Have seen scenarios where this seems to be beneficial.

Differential Revision: https://reviews.llvm.org/D157740
2023-09-07 16:53:29 +01:00
Noah Goldstein
3cf54c533d [InstCombine] Add transforms for (icmp upred (or X, Y), X)
We can simplify ule/ugt -> eq/ne and we can remove the `Or` in some
cases of eq/ne.

`icmp (X | Y) u<= X` --> `(X | Y) == X`
    - https://alive2.llvm.org/ce/z/qnbbPv
`icmp (X | Y) u> X` --> `(X | Y) != X`
    - https://alive2.llvm.org/ce/z/fvLqg3
`icmp (X | Y) eq/ne X`
     - --> `(~X & Y) eq/ne 0` iff X is freely invertible
     - --> `(X & ~Y) eq/ne -1` iff Y is freely invertible
          - https://alive2.llvm.org/ce/z/cpPV_W

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D144610
2023-08-16 02:00:15 -05:00
Bjorn Pettersson
fd05c34b18 Stop using legacy helpers indicating typed pointer types. NFC
Since we no longer support typed LLVM IR pointer types, the code can
be simplified into for example using PointerType::get directly instead
of using Type::getInt8PtrTy and Type::getInt32PtrTy etc.

Differential Revision: https://reviews.llvm.org/D156733
2023-08-02 12:08:37 +02:00
Maksim Kita
ac357a4773 [InstCombine] Fold icmp or sub chain ((x1 - y1) | (x2 - y2)) == 0
Improve ((x1 ^ y1) | (x2 ^ y2)) == 0 transform to also support sub ((x1 - y1) | (x2 - y2)) == 0.
Depends D155703.

Differential Revision: https://reviews.llvm.org/D155704
2023-07-26 19:16:41 +03:00
Nikita Popov
8249d6724c [InstCombine] Avoid uses of ConstantExpr::getOr()
Replace these with IRBuilder uses, as we don't (from a type
perspective) care about Constant results.

Switch the predicate to m_ImmConstant() instead of isa<Constant>
to guarantee that these do get folded away and our assumptions
about simplifications hold true.
2023-07-24 16:50:45 +02:00
Noah Goldstein
ee50c09117 [InstCombine] Fix bug in canonicalization of Pow2 Tests (From: D152673)
D152673 Incorrectly didn't account for operand position in the `icmp`,
i.e it treated `icmp uge x, y` the same as `icmp uge y, x` which is
incorrect:
https://reviews.llvm.org/rG142f7448e770f25b774b058a7eab1f107c4daad9

The fix takes operand position into account. The new tests
exhaustively cover all operand positions for `ule`, `uge`, `ult`,
`ugt` (the set of predicates) and all transform verify with the new
commit.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D156058
2023-07-23 11:57:30 -05:00
Noah Goldstein
413c119c6a [InstCombine] If there is a known-bit transform is_pow2 check to just check for any other bits
in `ctpop(X) eq/ne 1` or `ctpop(X) ugt/ule 1`, if there is any
known-bit in `X`, instead of going through `ctpop`, we can just test
if there are any other known bits in `X`. If there are, `X` is not a
power of 2. If there aren't, `X` is a power of 2.

https://alive2.llvm.org/ce/z/eLMJgU

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D152677
2023-07-21 14:15:06 -05:00
Noah Goldstein
142f7448e7 [InstCombine] Canonicalize (X^(X-1)) u{ge,lt} X as pow2 test
https://alive2.llvm.org/ce/z/T8osF6

Differential Revision: https://reviews.llvm.org/D152673
2023-07-21 14:15:06 -05:00
Nikita Popov
cdab6116eb [InstCombine] Avoid ConstantExpr::getAnd() (NFCI)
In preparation for removing and constant expressions.
2023-07-20 14:20:49 +02:00
Maksim Kita
da822ce90e [InstCombine] Generalise ((x1 ^ y1) | (x2 ^ y2)) == 0 transform
Generalise ((x1 ^ y1) | (x2 ^ y2)) == 0 transform to more than two pairs of variables https://github.com/llvm/llvm-project/issues/57831.
Depends D154384.

Reviewed By: goldstein.w.n, nikic

Differential Revision: https://reviews.llvm.org/D154306
2023-07-15 16:57:16 -05:00
Noah Goldstein
ddd18d02c7 [InstCombine] Transform icmp eq/ne ({su}div exact X,Y),C -> icmp eq/ne X, Y*C
We can do this if `Y*C` doesn't overflow. This is trivial if `C` is
0/1. Otherwise we actually generate a `mul` instruction iff the `div`
has one use.

Alive2 Links:
    udiv: https://alive2.llvm.org/ce/z/GWPW67
    sdiv: https://alive2.llvm.org/ce/z/bUoX9h

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D150091
2023-07-13 19:36:59 -05:00
Noah Goldstein
d50c1fcb5d [InstCombine] Fold (icmp eq/ne (zext i1 X) (sext i1 Y))-> (icmp eq/ne (or X, Y), 0)
This comes up when adding two `bool` types in C/C++
```
    bool foo(bool a, bool b) {
        return a + b;
    }
    ...
    ->
    define i1 @foo(i1 %a, i1 %b) {
        %conv = zext i1 %a to i32
        %conv3.neg = sext i1 %b to i32
        %tobool4 = icmp ne i32 %conv, %conv3.neg
        ret i1 %tobool4
}
```

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

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D154574
2023-07-12 17:17:52 -05:00
Dhruv Chawla
23f0f061c3
[InstCombine] Fold icmps comparing uadd_sat with a constant
This patch is a continuation of D154206. It introduces a fold for the
operation "uadd_sat(X, C) pred C2" where "C" and "C2" are constants. The
fold is:

uadd_sat(X, C) pred C2
=> (X >= ~C) || ((X + C) pred C2) -> when (UINT_MAX pred C2) is true
=> (X < ~C)  && ((X + C) pred C2) -> when (UINT_MAX pred C2) is false

This patch also generalizes the fold to work with any saturating
intrinsic as long as the saturating value is known.

Proofs: https://alive2.llvm.org/ce/z/wWeirP

Differential Revision: https://reviews.llvm.org/D154565
2023-07-08 12:50:39 +05:30
Dhruv Chawla
b66006fbf7
[InstCombine] Fold icmps comparing usub_sat with a constant
This patch introduces a fold for the operation "usub_sat(X, C) pred C2"
where "C" and "C2" are constants. The fold is:

usub_sat(X, C) pred C2
=> (X < C)  || ((X - C) pred C2) -> when (0 pred C2) is true
=> (X >= C) && ((X - C) pred C2) -> when (0 pred C2) is false

These expressions can generally be folded into a simpler expression. As
they can sometimes emit more than one instruction, they are limited to
cases where the "usub_sat" has only one user.

Fixes #58342.

Proofs: https://alive2.llvm.org/ce/z/ws_N2J

Differential Revision: https://reviews.llvm.org/D154206
2023-07-05 18:55:52 +05:30
Noah Goldstein
13f16f4dea [InstCombine] Canonicalize (icmp eq/ne (and x, C), x) -> (icmp eq/ne (and x, ~C), 0)
This increases the likelyhood `x` is single-use and is typically
easier to analyze.

Proofs: https://alive2.llvm.org/ce/z/8ZpS2W

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D154004
2023-06-29 13:14:37 -05:00
Noah Goldstein
e92a27bcb7 [InstCombine] Verify CmpInst is equality in foldICmpPow2Test; PR63327
When D152728 hoisted the code to a helper function, it moved the call
to the helper outside of `foldICmpEquality`, so an equality check is
needed in the helper.

Reviewed By: nikic, fhahn

Differential Revision: https://reviews.llvm.org/D153041
2023-06-15 12:21:24 -05:00
Nikita Popov
03de1cb715 [InstCombine][CGP] Move swapMayExposeCSEOpportunities() fold
InstCombine tries to swap compare operands to match sub instructions
in order to expose "CSE opportunities". However, it doesn't really
make sense to perform this transform in the middle-end, as we cannot
actually CSE the instructions there.

The backend already performs this fold in
18f5446a45/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (L4236)
on the SDAG level, however this only works within a single basic block.

To handle cross-BB cases, we do need to handle this in the IR layer.
This patch moves the fold from InstCombine to CGP in the backend,
while keeping the same (somewhat dubious) heuristic.

Differential Revision: https://reviews.llvm.org/D152541
2023-06-15 14:17:58 +02:00
Noah Goldstein
758ffdbfcc [InstCombine] Factor out power of 2 comparison patterns to helper; NFC
Differential Revision: https://reviews.llvm.org/D152728
2023-06-12 13:52:43 -05:00
Noah Goldstein
5189eff345 [InstCombine] Canonicalize (icmp eq/ne X, rotate(X)) to always use rotate-left
We canonicalize rotate-right -> rotate-left in other places. Makes
sense to do so here as well.
Proof: https://alive2.llvm.org/ce/z/HL3TpK

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D152349
2023-06-10 14:38:46 -05:00
Noah Goldstein
2df6309555 [InstCombine] Transform (icmp eq/ne rotate(X,AX),rotate(Y,AY)) -> (icmp eq/ne rotate(Y,AX-AY))
Only do so if we don't create more instructions, so either both
rotates have one use or one of the rotates has one use and both `AX`
and `AY` are constant.
Proof: https://alive2.llvm.org/ce/z/rVmJgz

Differential Revision: https://reviews.llvm.org/D152348
2023-06-10 14:38:46 -05:00
Noah Goldstein
e387f49d13 [InstCombine] Remove deadcode in (icmp SignTest(shl/shr X)); NFC
This is dead as of: D145341

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D152181
2023-06-06 15:14:10 -05:00
Noah Goldstein
73ce343125 [InstCombine] Add transform (icmp pred (shl {nsw and/or nuw} X, Y), C) -> (icmp pred X, C)
Three new transforms:
    1) `(icmp pred (shl nsw nuw X, Y), C)` [if `C <= 0`] -> `(icmp pred X, C)`
        - ugt: https://alive2.llvm.org/ce/z/K_57J_
        - sgt: https://alive2.llvm.org/ce/z/BL8u_a
        - sge: https://alive2.llvm.org/ce/z/yZZVYz
        - uge: https://alive2.llvm.org/ce/z/R4jwwJ
        - ule: https://alive2.llvm.org/ce/z/-gbmth
        - sle: https://alive2.llvm.org/ce/z/ycZVsh
        - slt: https://alive2.llvm.org/ce/z/4MzHYm
        - sle: https://alive2.llvm.org/ce/z/fgNfex
        - ult: https://alive2.llvm.org/ce/z/cXfvH5
        - eq : https://alive2.llvm.org/ce/z/sZh_Ti
        - ne : https://alive2.llvm.org/ce/z/UrqSWA

    2) `(icmp eq/ne (shl {nsw|nuw} X, Y), 0)` -> `(icmp eq/ne X, 0)`
        - eq+nsw: https://alive2.llvm.org/ce/z/aSJN6D
        - eq+nuw: https://alive2.llvm.org/ce/z/r2_-br
        - ne+nuw: https://alive2.llvm.org/ce/z/RkETtu
        - ne+nsw: https://alive2.llvm.org/ce/z/8iSfW3

    3) `(icmp slt (shl nsw X, Y), 0/1)` -> `(icmp pred X, 0/1)`
       `(icmp sgt (shl nsw X, Y), 0/-1)` -> `(icmp pred X, 0/-1)`
        - slt: https://alive2.llvm.org/ce/z/eZYRan
        - sgt: https://alive2.llvm.org/ce/z/QQeP26

    Transform 3) is really sle/slt/sge/sgt with 0, but sle/sge
    canonicalize to slt/sgt respectively so its implemented as such.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D145341
2023-06-05 13:01:03 -05:00
Nikita Popov
97b5cc214a [ValueTracking] Remove ORE argument (NFC-ish)
The ORE argument threaded through ValueTracking is used only in a
single, untested place. It is also essentially never passed: The
only places that do so have been added very recently as part of the
KnownFPClass migration, which is vanishingly unlikely to hit this
code path. Remove this effectively dead argument.

Differential Revision: https://reviews.llvm.org/D151562
2023-06-02 09:11:53 +02:00
Nikita Popov
0213c6d0df [InstCombine] Use DL-aware constant folding for phi compare
Serves the dual purpose of avoiding an extra InstCombine iteration
for the DL-aware folding and removing one icmp constexpr use.
2023-06-01 16:02:36 +02:00
Nikita Popov
b9e328fd91 [InstCombine] Fix worklist management in rewriteGEPAsOffset() more thoroughly
We need to add the replaced instruction itself to the worklist as
well. We want to remove the old instructions, but can't easily do
so directly, as the icmp is also one of the users and we need to
retain it until the fold has finished.
2023-06-01 11:00:49 +02:00
Nikita Popov
63babf54c2 [InstCombine] Fix worklist management in transformToIndexedCompare()
Use replaceInstUsesWith() rather than plain RAUW to make sure the
old instructions are added back to the worklist for DCE.
2023-06-01 10:35:13 +02:00
Tejas Joshi
c75a0f5a9a [InstCombine] Optimize compares with multiple selects as operands
In case of a comparison with two select instructions having the same
condition, check whether one of the resulting branches can be simplified.
If so, just compare the other branch and select the appropriate result.
For example:

    %tmp1 = select i1 %cmp, i32 %y, i32 %x
    %tmp2 = select i1 %cmp, i32 %z, i32 %x
    %cmp2 = icmp slt i32 %tmp2, %tmp1

The icmp will result false for the false value of selects and the result
will depend upon the comparison of true values of selects if %cmp is
true. Thus, transform this into:

    %cmp = icmp slt i32 %y, %z
    %sel = select i1 %cond, i1 %cmp, i1 false

Differential Revision: https://reviews.llvm.org/D150360
2023-05-26 16:05:32 +02:00
Matt Arsenault
60b8e3a66b InstCombine: Pass all parameters to isKnownNeverNaN
Allows assume handling to work.
2023-05-18 08:04:37 +01:00
Matt Arsenault
86d0b524f3 ValueTracking: Expand signature of isKnownNeverInfinity/NaN
This is in preparation for replacing the implementation
with a wrapper around computeKnownFPClass.
2023-05-16 20:42:58 +01:00
Noah Goldstein
13441eb0f8 [InstCombine] Add folds for (icmp spred (ssub.sat X, Y), 0) -> X spred Y
Alive2 links:
    eq: https://alive2.llvm.org/ce/z/Fv3mvc
    ne: https://alive2.llvm.org/ce/z/AEuEXU
    sle: https://alive2.llvm.org/ce/z/mfKGUS
    sge: https://alive2.llvm.org/ce/z/tX3_M4
    sgt: https://alive2.llvm.org/ce/z/x7VgnZ
    slt: https://alive2.llvm.org/ce/z/rQN4TM

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149521
2023-05-03 11:11:49 -05:00
Noah Goldstein
dc13624e88 [InstCombine] Fold (cmp eq/ne (umax X, Y),0) -> (cmp eq/ne (or X, Y),0)
`or` is almost always preferable.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149426
2023-04-29 12:38:43 -05:00
Noah Goldstein
ecad53c3f4 [InstCombine] Don't fold uadd.sat to or if it increase instruction count
In the `(cmp eq/ne (uadd.sat X, Y),0)` case, we where missing a
`hasOneUse` check.

Differential Revision: https://reviews.llvm.org/D149425
2023-04-29 12:38:41 -05:00
Noah Goldstein
726f8ecac2 Recommit "[InstCombine] Add transforms for (icmp {u|s}ge/le (xor X, Y), X)" (2nd Try)
Wasn't related to the bug it was original thought to be causing.
2023-04-18 17:17:54 -05:00
Noah Goldstein
9d8a984160 Revert "[InstCombine] Add transforms for (icmp {u|s}ge/le (xor X, Y), X)"
May be related to PR62175

This reverts commit a3fd060d4223c6a7470554561bc479d4b8e423f4.
2023-04-18 01:23:40 -05:00