972 Commits

Author SHA1 Message Date
Léonard Oest O'Leary
ff36411b23
[InstCombine] Use zext's nneg flag for icmp folding (#70845)
This PR fixes https://github.com/llvm/llvm-project/issues/55013 : the
max intrinsics is not generated for this simple loop case :
https://godbolt.org/z/hxz1xhMPh. This is caused by a ICMP not being
folded into a select, thus not generating the max intrinsics.

For the story :

Since LLVM 14, SCCP pass got smarter by folding sext into zext for
positive ranges : https://reviews.llvm.org/D81756. After this change,
InstCombine was sometimes unable to fold ICMP correctly as both of the
arguments pointed to mismatched zext/sext. To fix this, @rotateright
implemented this fix : https://reviews.llvm.org/D124419 that tries to
resolve the mismatch by knowing if the argument of a zext is positive
(in which case, it is like a sext) by using ValueTracking, however
ValueTracking is not smart enough to infer that the value is positive in
some cases. Recently, @nikic implemented #67982 which keeps the
information that a zext is non-negative. This PR simply uses this
information to do the folding accordingly.

TLDR : This PR uses the recent nneg tag on zext to fold the icmp
accordingly in instcombine.

This PR also contains test cases for sext/zext folding with InstCombine
as well as a x86 regression tests for the max/min case.
2023-11-13 00:53:53 +08:00
Nikita Popov
567c02a80e [InstCombine] Remove inttoptr/ptrtoint handling from indexed compare fold
Looking through inttoptr / ptrtoint intermixed with GEPs is very
questionable from a provenance perspective. We also don't seem to
have any test coverage that shows this is useful (apart from one
test I added to guard against a crash).
2023-11-08 11:13:57 +01:00
Nikita Popov
abc27bd31f [InstCombine] Avoid some FP cast constant expressions (NFCI)
Instead of doing fptoxi and xitofp casts to check for round-trip,
directly check the IsExact flag on the convertToInteger() API.
2023-11-06 14:42:42 +01:00
Nikita Popov
03110ddeb2 [IR] Remove ZExtOperator (NFC)
Now that zext constant expressions are no longer supported,
ZExtInst should be used instead.
2023-11-03 14:52:59 +01:00
Nikita Popov
930bc6c7b5 [InstCombine] Avoid use of ConstantExpr::getSExtOrTrunc()
InstCombine will canonicalize the index type, no need to handle
the non-canonical case.
2023-11-01 16:10:57 +01:00
Nikita Popov
5c8a71d82b [InstCombine] Remove unnecessary icmp of all-zero gep folds (NFC)
All-zero GEPs will be removed anyway, no need to special-case them
here.
2023-10-30 10:01:21 +01:00
Amara Emerson
2228b35f93 Revert "Revert "[InstCombine] Add oneuse checks to shr + cmp constant folds.""
This reverts commit d37b283cdd37feca5ea71456cf350005add268e7.

There was a simple logic bug in the else path. Tests codegen is different with
the fix.
2023-10-28 03:12:15 -07:00
Noah Goldstein
0289dad538 [InstCombine] Add folds for (icmp eq/ne (and (add/sub/xor A, P2), P2), 0/P2)
- `(icmp eq/ne (and (add/sub/xor X, P2), P2), P2)`
    -> `(icmp eq/ne (and X, P2), 0)`
- `(icmp eq/ne (and (add/sub/xor X, P2), P2), 0)`
    -> `(icmp eq/ne (and X, P2), P2)`

Folds like this come up with reasonable regularity in odd/even loops.

Proofs: https://alive2.llvm.org/ce/z/45pq2x

Closes #67836
2023-10-27 17:36:30 -05:00
Amara Emerson
d37b283cdd Revert "[InstCombine] Add oneuse checks to shr + cmp constant folds."
This reverts commit a66051c68a43af39f9fd962f71d58ae0efcf860d.

This seems to have caused issue #70509 so reverting until I have time
to investigate.
2023-10-27 14:27:58 -07:00
Amara Emerson
a66051c68a [InstCombine] Add oneuse checks to shr + cmp constant folds.
This change has virtually no code size regressions on the llvm test suite (+ SPECs)
while having these improvements (measured with -Os on Darwin arm64):

External/S.../CFP2006/450.soplex/450.soplex    214024.00      213920.00     -0.0%
External/S...7speed/641.leela_s/641.leela_s     93412.00       93348.00     -0.1%
External/S...17rate/541.leela_r/541.leela_r     93412.00       93348.00     -0.1%
MultiSourc.../Applications/JM/lencod/lencod    426044.00      425748.00     -0.1%
MultiSourc...rks/mediabench/gsm/toast/toast     20436.00       20416.00     -0.1%
MultiSourc...ench/telecomm-gsm/telecomm-gsm     20436.00       20416.00     -0.1%
MultiSourc...Prolangs-C/assembler/assembler     16172.00       16156.00     -0.1%
MultiSourc...nch/mpeg2/mpeg2dec/mpeg2decode     35332.00       35256.00     -0.2%
SingleSour...Adobe-C++/stepanov_abstraction      6904.00        6888.00     -0.2%
External/SPEC/CINT2000/254.gap/254.gap         366060.00      365132.00     -0.3%
MultiSourc...-ProxyApps-C++/PENNANT/PENNANT     79688.00       79484.00     -0.3%
External/S...NT2006/464.h264ref/464.h264ref    352044.00      351132.00     -0.3%
SingleSour...arks/Adobe-C++/functionobjects     15524.00       15480.00     -0.3%
SingleSour...arks/Adobe-C++/stepanov_vector     10728.00       10696.00     -0.3%
SingleSour...ks/Misc-C++/stepanov_container     16900.00       16848.00     -0.3%
MultiSource/Applications/oggenc/oggenc         124184.00      123780.00     -0.3%
SingleSour...tout-C++/Shootout-C++-wordfreq      7060.00        7036.00     -0.3%
MultiSourc...ity-rijndael/security-rijndael      8976.00        8936.00     -0.4%
MultiSource/Benchmarks/McCat/18-imp/imp          9816.00        9772.00     -0.4%
SingleSour...chmarks/Misc-C++/stepanov_v1p2      1772.00        1764.00     -0.5%
MultiSourc...iabench/g721/g721encode/encode      5492.00        5464.00     -0.5%
MultiSourc...rks/McCat/03-testtrie/testtrie      1364.00        1344.00     -1.5%
SingleSour.../execute/GCC-C-execute-pr42833       400.00         364.00     -9.0%

Doing so also prevents a regression described in https://reviews.llvm.org/D143624

Differential Revision: https://reviews.llvm.org/D149918
2023-10-26 11:36:10 -07:00
Nikita Popov
ea99df2e84 [InstCombine] Rename some variables (NFC)
Split NFC rename out from #69882.
2023-10-25 17:08:40 +02:00
Nikita Popov
c912f88c21 [InstCombine] Remove false commutativity from processUMulZExtIdiom() (NFCI)
This fold requires a fold against a constant, which will always be
on the RHS. If the swapped fold actually did trigger, it would
result in a miscompile, because it did not work with the swapped
predicate when swapping operands.
2023-10-25 11:31:31 +02:00
Nikita Popov
82aeedc852 [InstCombine] Remove unnecessary eq/ne handling from processUMulZExtIdiom() (NFCI)
The eq/ne pattern being matched will get canonicalized to the
ugt/ult form.
2023-10-25 11:18:44 +02:00
Nikita Popov
4baeed803f [InstCombine] Remove unnecessary handling of non-canonical predicates (NFCI)
ule/uge with a constant will be converted to ult/ugt, so there is
no need to handle these variants.
2023-10-25 10:42:25 +02:00
Nikita Popov
3a39346a06 [InstCombine] Remove unnecessary typed pointer handling (NFC) 2023-10-25 10:34:39 +02:00
Nikita Popov
7df92fbe74 [InstCombine] Remove redundant icmp gep fold (NFCI)
Gep with zero indices will be folded away independently. It will
only be retained for splat geps, for which the transform is not
applicable anyway.
2023-10-25 10:31:02 +02:00
Nikita Popov
b901acad54 [InstCombine] Remove unnecessary typed pointer fold (NFCI)
Pointer bitcasts will be optimized away, no need to fold them for
icmps in particular.
2023-10-24 16:43:22 +02:00
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