427 Commits

Author SHA1 Message Date
Z572
e6d2bb0ed8
[InstCombine] Simplifiy (-x * y * -x) into (x * y * x) (#72953)
fix https://github.com/llvm/llvm-project/issues/72259
proof: https://alive2.llvm.org/ce/z/HsrmTC
2023-12-21 19:13:09 +08:00
Z572
1c494198c3
[InstCombine] simplify (X * C0) / (X * C1) into C0 / C1. (#73204)
fix #72114
proof: https://alive2.llvm.org/ce/z/xqprFm
2023-12-13 17:17:06 +08:00
Nikita Popov
5295b12cd0 [PatternMatch] Add m_AddLike matcher (NFC)
This matches either a plain "add" or an "or disjoint" that can
be converted into an add. The AddLike terminology is adopted from
the SDAG layer.
2023-12-07 14:45:12 +01:00
Nikita Popov
410bf5e142 [InstCombine] Use disjoint flag in mul of or fold
Slightly more powerful if the information used to infer disjoint
was lost.
2023-12-05 15:24:50 +01:00
Nikita Popov
4b3ea337ad [ValueTracking] Convert isKnownNonNegative() to use SimplifyQuery (NFC) 2023-11-29 10:52:52 +01:00
Yingwei Zheng
865c1fda6f
[InstCombine] Preserve NSW flags for neg instructions (#72548)
Alive2: https://alive2.llvm.org/ce/z/F9HG3M

This missed optimization is discovered with the help of
https://github.com/AliveToolkit/alive2/pull/962.
2023-11-17 14:02:47 +08:00
Z572
c350a1eaae
[InstCombine] Simplifiy sdiv -X, X into X == INT_MIN ? 1 : -1 (#71768)
Alive2: https://alive2.llvm.org/ce/z/dHddwH
Fixes #69574
2023-11-15 23:30:08 +08:00
Allen
a0cd6265bc
[InstCombine] Split the FMul with reassoc into a helper function, NFC (#71493)
The reassoc check is really hard to find because the handle branch it
too large, so spilt it into a helper function.
2023-11-07 15:30:56 +08:00
zhongyunde 00443407
7e3d1103e6 [InstCombine] optimize powi(X,Y)/X with Ofast (#67236)
Try to transform the powi(X, Y) / X into powi(X, Y-1) with Ofast.
For this case, when the Y is 3, then powi(X, 2) is replaced by X * X in
the further step.

Fixes https://github.com/llvm/llvm-project/pull/67216
Reviewed By: dtcxzyw, nikic, jcranmer-intel
2023-10-21 08:56:14 +08:00
XChy
f2898def69
[InstCombine] Don't mix X << Y / Z << Y with X << Y / X << Z (#69302)
Fixes #69291.
This patch improve the logic handling different patterns to avoid mixing these
pattern.
2023-10-17 18:47:49 +08:00
XChy
0823cb7911
[InstCombine] Fold (X << Y) / (X << Z) -> 1 << Y >> Z (#68863)
Resolve #68857.
Alive2 proofs:
[Whole proofs](https://alive2.llvm.org/ce/z/A5b85F)
2023-10-15 22:51:45 +08:00
Nikita Popov
80fa5a6377 [ValueTracking] Use SimplifyQuery in haveNoCommonBitsSet() (NFC)
Pass SimplifyQuery instead of unpacked list of arguments.
2023-10-10 11:39:59 +02:00
Nikita Popov
6cd5eb1f54 [InstCombine] Avoid some uses of ConstantExpr::getZExt() (NFC)
Add helpers getLosslessUnsignedTrunc/getLosslessSignedTrunc for
this common pattern.
2023-09-28 17:02:33 +02:00
Nikita Popov
1fc73cacb2 [InstCombine] Propagate nsw flag when negating
When pushing a sub nsw 0, %x negation into an expression, try to
preserve the nsw flag for the cases where this is possible. Do this
by passing the flag through recursive Negator::negate() calls.

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

Differential Revision: https://reviews.llvm.org/D158510
2023-09-14 09:09:45 +02:00
Matt Arsenault
0ec9ccb39e InstCombine: Fix typo in comment 2023-08-24 07:42:37 -04:00
Antonio Frighetto
f12a5561b2 [InstCombine] Fold binop of select and cast of select condition
Simplify binary operations, whose operands involve a `select`
instruction and a cast of the `select` condition. Specifically,
the binop is canonicalized into a `select` with folded arguments
as follows:

(Binop (zext C), (select C, T, F))
  -> (select C, (binop 1, T), (binop 0, F))

(Binop (sext C), (select C, T, F))
  -> (select C, (binop -1, T), (binop 0, F))

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

Differential Revision: https://reviews.llvm.org/D153963
2023-07-20 19:42:58 +00:00
Noah Goldstein
453d983d56 [InstCombine] Add transforms for (rem (shl Y, X), (shl Z, X))
This is just filling in a missing case from D144225.

We treat `(shl Y, X)` and `(shl Z, X)` as `(mul Z, 1 << X)` and `(mul
Y, 1 << X)` then reuse the same transformations that already exist.

Reviewed By: sdesmalen

Differential Revision: https://reviews.llvm.org/D147108
2023-07-06 14:46:34 -05:00
Noah Goldstein
2cb6b06c89 [InstCombine] Add constant combines for (urem/srem (shl X, Y), (shl X, Z))
Forked from D142901 to deduce more `nsw`/`nuw` flag for the output
`shl`.

We can handle the following cases + some `nsw`/`nuw` flags:

The rationale for doing this all in `InstCombine` rather than handling
the constant `shl` cases in `InstSimplify` is we often create a new
instruction because we are able to deduce more `nsw`/`nuw` flags than
the original instruction had.

Differential Revision: https://reviews.llvm.org/D144225
2023-07-06 14:46:34 -05:00
Zhongyunde
90d30fde12 [InstCombine] Add frozen for the condition value of SelectInst
If the condition value of SelectInst may be a poison or undef value,
infer constant range at SelectInst use is incorrect, similar to D143883.
Fixes https://github.com/llvm/llvm-project/issues/62401

Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D149339
2023-04-27 21:35:54 +08:00
Noah Goldstein
bfe2f5d38b [InstCombine] Fix buggy (mul X, Y) -> (shl X, Log2(Y)) transform PR62175
Bug was because we recognized patterns like `(shl 4, Z)` as a power of
2 we could take Log2 of (`2 + Z`), but doing `(shl X, (2 + Z))` can
cause a poison shift.
    https://alive2.llvm.org/ce/z/yuJm_k

The fix is to verify that `Log2(Y)` will be a non-poisonous shift
amount. We can do this with:
    `nsw` flag:
        - https://alive2.llvm.org/ce/z/yyyJBr
        - https://alive2.llvm.org/ce/z/YgubD_
    `nuw` flag:
        - https://alive2.llvm.org/ce/z/-4mpyV
        - https://alive2.llvm.org/ce/z/a6ik6r
    Prove `Y != 0`:
        - https://alive2.llvm.org/ce/z/ced4su
        - https://alive2.llvm.org/ce/z/X-JJHb

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D148609
2023-04-18 17:17:48 -05:00
Noah Goldstein
513251b765 [InstCombine] Improve transforms for (mul X, Y) -> (shl X, log2(Y)
Using the more robust log2 search allows us to fold more cases (same
logic as exists for idiv/irem).

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D146347
2023-04-07 14:58:20 -05:00
Serguei Katkov
f38365aef4 [InstCombine] Add support for maximum(a,b) + minimum(a,b) => a + b
Unfortunately alive2 cannot prove the correctness due to fails by timeout even for
float type half.

However it should be correct. If a and b are not NaN, maximum and minimum will just
return different values (a and b) and take into account a + b == b + a this is the same.
If a or b is NaN, than maximum and minimum are equal to NaN and NaN + NaN is NaN.
a + b is also a NaN.

In terms of preserving fast flags, we cannot preserve ninf due to
minimum(NaN, Infinity) == maximum(NaN, Infinity) == NaN,
minimum(NaN, Infinity) +ninf maximum(NaN, Infinity) == NaN +ninf NaN = NaN
However transformation will change
minimum(NaN, Infinity) + maximum(NaN, Infinity) to NaN +ninf Infinity == poison.

But if fadd is marked as nnan, we can preserve because NaN +ninf/nnan NaN = poison as well.

The same optimization for
  maximum(a,b) * minimum(a,b) => a * b
is added.
All said above for fadd is correct for fmul.

Reviewed By: mkazantsev
Differential Revision: https://reviews.llvm.org/D147299
2023-04-07 12:38:04 +07:00
Serguei Katkov
624973806c [InstCombine] Add support for max(a,b) + min(a,b) => a + b. Re-land.
The same optimization for
  max(a,b) * min(a,b) => a * b
is added.

Correctness check:
uadd: https://alive2.llvm.org/ce/z/2rXDek
sadd: https://alive2.llvm.org/ce/z/zNu_er
uadd + nuw/nsw: https://alive2.llvm.org/ce/z/EaiNjB
sadd + nuw/nsw: https://alive2.llvm.org/ce/z/w_2Nrs

umul: https://alive2.llvm.org/ce/z/dgXRLr
smul: https://alive2.llvm.org/ce/z/hBjGzz
umul + nuw/nsw: https://alive2.llvm.org/ce/z/EaiNjB
smul + nuw/nsw: https://alive2.llvm.org/ce/z/87MNeS

Reviewed By: goldstein.w.n
Differential Revision: https://reviews.llvm.org/D147296
2023-04-07 11:56:05 +07:00
Serguei Katkov
4665f3c838 Revert "[InstCombine] Add support for max(a,b) + min(a,b) => a + b."
Revert commit due to failure on buildbot:
error: 'match_combine_or' may not intend to support class template argument deduction

This reverts commit b86a06ef284f2637bef89bf5bb20157a8b195568.
2023-04-07 11:14:28 +07:00
Serguei Katkov
b86a06ef28 [InstCombine] Add support for max(a,b) + min(a,b) => a + b.
The same optimization for
  max(a,b) * min(a,b) => a * b
is added.

Correctness check:
uadd: https://alive2.llvm.org/ce/z/2rXDek
sadd: https://alive2.llvm.org/ce/z/zNu_er
uadd + nuw/nsw: https://alive2.llvm.org/ce/z/EaiNjB
sadd + nuw/nsw: https://alive2.llvm.org/ce/z/w_2Nrs

umul: https://alive2.llvm.org/ce/z/dgXRLr
smul: https://alive2.llvm.org/ce/z/hBjGzz
umul + nuw/nsw: https://alive2.llvm.org/ce/z/EaiNjB
smul + nuw/nsw: https://alive2.llvm.org/ce/z/87MNeS

Reviewed By: goldstein.w.n
Differential Revision: https://reviews.llvm.org/D147296
2023-04-07 10:24:07 +07:00
Noah Goldstein
aba71f37d0 [InstCombine] Add constant combines for (urem/srem (mul X, Y), (mul X, Z))
We can handle the following cases + some `nsw`/`nuw` flags:

`(srem (mul X, Y), (mul X, Z))`
    [If `srem(Y, Z) == 0`]
        -> 0
            - https://alive2.llvm.org/ce/z/PW4XZ-
    [If `srem(Y, Z) == Y`]
        -> `(mul nuw nsw X, Y)`
            - https://alive2.llvm.org/ce/z/DQe9Ek
        -> `(mul nsw X, Y)`
            - https://alive2.llvm.org/ce/z/Nr_MdH

    [If `Y`/`Z` are constant]
        -> `(mul/shl nuw nsw X, (srem Y, Z))`
            - https://alive2.llvm.org/ce/z/ccTFj2
            - https://alive2.llvm.org/ce/z/i_UQ5A
        -> `(mul/shl nsw X, (srem Y, Z))`
            - https://alive2.llvm.org/ce/z/mQKc63
            - https://alive2.llvm.org/ce/z/uERkKH

`(urem (mul X, Y), (mul X, Z))`
    [If `urem(Y, Z) == 0`]
        -> 0
            - https://alive2.llvm.org/ce/z/LL7UVR
    [If `srem(Y, Z) == Y`]
        -> `(mul nuw nsw X, Y)`
            - https://alive2.llvm.org/ce/z/9Kgs_i
        -> `(mul nuw X, Y)`
            - https://alive2.llvm.org/ce/z/ow9i8u

    [If `Y`/`Z` are constant]
        -> `(mul nuw nsw X, (srem Y, Z))`
            - https://alive2.llvm.org/ce/z/mNnQqJ
            - https://alive2.llvm.org/ce/z/Bj_DR-
            - https://alive2.llvm.org/ce/z/X6ZEtQ
        -> `(mul nuw X, (srem Y, Z))`
            - https://alive2.llvm.org/ce/z/SJYtUV

The rationale for doing this all in `InstCombine` rather than handling
the constant `mul` cases in `InstSimplify` is we often create a new
instruction because we are able to deduce more `nsw`/`nuw` flags than
the original instruction had.

Reviewed By: MattDevereau, sdesmalen

Differential Revision: https://reviews.llvm.org/D143014
2023-03-16 13:01:46 -05:00
Sanjay Patel
703423c269 [InstCombine] relax constraint on udiv fold
The pair of div folds was just added with:
4966d8ebe1bbe5bd6a4d28

But as noted in the post-commit review, we don't actually need
the no-remainder requirement for an unsigned division (still
need the no-unsigned-wrap though):
https://alive2.llvm.org/ce/z/qHjK3Q
2023-02-20 15:08:32 -05:00
Sanjay Patel
4966d8ebe1 [InstCombine] distribute div over add with matching mul-by-constant
((X * C2) + C1) / C2 --> X + C1/C2
https://alive2.llvm.org/ce/z/P66io8
https://alive2.llvm.org/ce/z/vghegw

This could be made more general -- the multiplier could be a
multiple of the divisor -- but this is the pattern from
issue #60754.
2023-02-20 13:45:06 -05:00
zhongyunde
ee9a0f30ca [InstCombine] canonicalize urem as cmp+select
Fix https://github.com/llvm/llvm-project/issues/60546

Reviewed By: nikic, efriedma, RKSimon, spatel

Differential Revision: https://reviews.llvm.org/D143883
2023-02-20 23:52:10 +08:00
Kazu Hirata
a28b252d85 Use APInt::getSignificantBits instead of APInt::getMinSignedBits (NFC)
Note that getMinSignedBits has been soft-deprecated in favor of
getSignificantBits.
2023-02-19 23:56:52 -08:00
Kazu Hirata
f8f3db2756 Use APInt::count{l,r}_{zero,one} (NFC) 2023-02-19 22:04:47 -08:00
Sanjay Patel
1378e7d8b8 [InstSimplify] add no-wrap parameters to simplifyMul and add more tests; NFC
This gives mul the same capabilities as add/sub.
A potential improvement with nsw was noted in:
1720ec6da040729f17
2023-01-18 13:29:30 -05:00
Sanjay Patel
072b03c471 [InstCombine] fold pow(X,Y) / X -> pow(X, Y-1)
This is one of the patterns suggested in issue #34943.
2023-01-13 17:13:46 -05:00
Sanjay Patel
61af2ab681 [InstCombine] fold pow(X,Y) * X -> pow(X, Y+1) (with fast-math)
This is one of the patterns suggested in issue #34943.
2023-01-13 17:13:46 -05:00
Sanjay Patel
914576c1f0 [InstCombine] fold pow(X,Y) * pow(Z,Y) -> pow(X*Z, Y) (with fast-math)
This is one of the patterns suggested in issue #34943.
2023-01-13 13:26:10 -05:00
Sanjay Patel
f0faea5714 [InstSimplify] fold exact divide to poison if it is known to not divide evenly
This is related to the discussion in D140665. I was looking over the demanded
bits implementation in IR and noticed that we just bail out of a potential
fold if a udiv is exact:
82be8a1d2b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp (L799)

Also, see tests added with 7f0c11509e8f.

Then, I saw that we could lose a fold to poison if we zap the exact with that
transform, so this patch tries to catch that as a preliminary step.

Alive2 proofs:
https://alive2.llvm.org/ce/z/zCjKM7
https://alive2.llvm.org/ce/z/-tz_RK (trailing zeros must be "less-than")
https://alive2.llvm.org/ce/z/c9CMsJ (general proof and specific example)

Differential Revision: https://reviews.llvm.org/D140733
2022-12-29 10:26:50 -05:00
Chenbing Zheng
1f84e72b7b [InstCombine] Fold (X << Z) / (X * Y) -> (1 << Z) / Y
Alive2: https://alive2.llvm.org/ce/z/CBJLeP
2022-12-29 17:30:49 +08:00
Chenbing Zheng
bff1f8c79b [InstCombine] complete (X << Z) / (Y << Z) --> X / Y
Add one more situations for this fold.
For unsigned div, 'nsw' on both shifts + 'nuw' on the dividend.

Alive2: https://alive2.llvm.org/ce/z/sELF76

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D139997
2022-12-23 11:56:52 +08:00
Matt Arsenault
e661185fb3 InstCombine: Fold fdiv nnan x, 0 -> copysign(inf, x)
https://alive2.llvm.org/ce/z/gLBFKB
2022-11-07 22:00:15 -08:00
Sanjay Patel
f03b069c5b [InstCombine] fold mul with decremented "shl -1" factor (2nd try)
This is a corrected version of:
bc886e9b587b

I made a copy-paste error that created an "add" instead of the
intended "sub" on that attempt. The regression tests showed the
bug, but I overlooked that.

As I said in a comment on issue #58717, the bug reports resulting
from the botched patch confirm that the pattern does occur in
many real-world applications, so hopefully eliminating the multiply
results in better code.

I added one more regression test in this version of the patch,
and here's an Alive2 proof to show that exact example:
https://alive2.llvm.org/ce/z/dge7VC

Original commit message:

This is a sibling to:
6064e92b0a84
...but we canonicalize the shl+add to shl+xor,
so the pattern is different than I expected:
https://alive2.llvm.org/ce/z/8CX16e

I have not found any patterns that are safe
to propagate no-wrap, so that is not included
here.

Differential Revision: https://reviews.llvm.org/D137157
2022-11-02 09:30:01 -04:00
Florian Mayer
e1de7ac20f Revert "[InstCombine] fold mul with decremented "shl -1" factor"
This reverts commit bc886e9b587b9d009f49b12eaaa9ebc1c71905a1.

Broke MSAN bootstrap buildbots with Assertion `RangeAfterCopy % ExtraScale == 0 && "Extra instruction requires immediate to be aligned"' failed.
2022-10-31 17:39:05 -07:00
Sanjay Patel
bc886e9b58 [InstCombine] fold mul with decremented "shl -1" factor
This is a sibling to:
6064e92b0a84
...but we canonicalize the shl+add to shl+xor,
so the pattern is different than I expected:
https://alive2.llvm.org/ce/z/8CX16e

I have not found any patterns that are safe
to propagate no-wrap, so that is not included
here.
2022-10-31 09:06:55 -04:00
zhongyunde
f58311796c [InstCombine] refactor the SimplifyUsingDistributiveLaws NFC
Precommit for D136015
Reviewed By: spatel
Differential Revision: https://reviews.llvm.org/D137019
2022-10-30 21:04:06 +08:00
Sanjay Patel
6064e92b0a [InstCombine] fold mul with incremented "shl 1" factor
X * ((1 << Z) + 1) --> (X << Z) + X

https://alive2.llvm.org/ce/z/P-7WK9

It's possible that we could do better with propagating
no-wrap, but this carries over the existing logic and
appears to be correct.

The naming differences on the existing folds are a result
of using getName() to set the final value via Builder.
That makes it easier to transfer no-wrap rather than the
gymnastics required from the raw create instruction APIs.
2022-10-29 12:50:19 -04:00
Sanjay Patel
50000ec2cb [InstCombine] create helper function for mul patterns with 1<<X; NFC
There are at least 2 other potential patterns that could go here.
2022-10-29 12:50:19 -04:00
Sanjay Patel
d344146857 [InstCombine] reduce code duplication in visitMul(); NFC 2022-10-29 09:26:02 -04:00
Sanjay Patel
44b7da89d7 [InstCombine] fmul nnan X, 0.0 --> copysign(0.0, X)
https://alive2.llvm.org/ce/z/ybgM5F

Differential Revision: https://reviews.llvm.org/D136166
2022-10-18 11:34:02 -04:00
Sanjay Patel
e5ee0b06d6 [InstCombine] try to determine "exact" for sdiv
If the divisor is a power-of-2 or negative-power-of-2 and the dividend
is known to have >= trailing zeros than the divisor, the division is exact:
https://alive2.llvm.org/ce/z/UGBksM (general proof)
https://alive2.llvm.org/ce/z/D4yPS- (examples based on regression tests)

This isn't the most direct optimization (we could create ashr in these
examples instead of relying on existing folds for exact divides), but
it's possible that there's a more general constraint than just a pow2
divisor, so this might be extended in the future.

This should solve issue #58348.

Differential Revision: https://reviews.llvm.org/D135970
2022-10-16 10:59:56 -04:00
Sanjay Patel
340ae45be0 [InstCombine] use isKnownNonNegative() for readability; NFCI
This should be functionally equivalent - both calls are thin
wrappers around computeKnownBits(). We'll probably want to use
known-bits directly in follow-up patches because that could
determine "exact" for example (see issue #58348).
2022-10-16 10:59:56 -04:00
Sanjay Patel
7b9482df3d [InstCombine] fold sdiv with common shl amount in operands
(X << Z) / (Y << Z) --> X / Y

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

This requires a surprising "nuw" constraint because we have
to guard against immediate UB via signed-div overflow with
-1 divisor.

This extends 008a89037a49ca0d9 and is another transform
derived from issue #58137.
2022-10-12 11:32:15 -04:00