667 Commits

Author SHA1 Message Date
Eric Gullufsen
b9bbe2f603 [InstCombine] Preserve nsw/nuw flags in canonicalization
canonicalizeLogicFirst reorders logic op / math op for suitable
constants, and this commit makes this function pass through
nsw/nuw flags on the Add.

Differential Revision: https://reviews.llvm.org/D147568
2023-04-05 10:12:54 -04:00
Matt Arsenault
3b44109b71 InstCombine: Introduce new is.fpclass from logic of fcmp
Fixes regressions from patch to turn more classes into fcmp.
2023-03-26 09:34:29 -04:00
Matt Arsenault
8a37512924 ValueTracking: Extract fcmpToClassTest out of InstCombine
Also update unsigned to FPClassTest
2023-03-16 23:14:40 -04:00
Matt Arsenault
0d18f315d8 InstCombine: Handle folding fcmp of 0 into llvm.is.fpclass
This needs to consider the denormal mode.
2023-03-15 07:07:55 -04:00
Matt Arsenault
08f0388711 InstCombine: Fold and/or of fcmp into class
This is motivated by patterns like !isfinite || zero. The AMDGPU math
libraries have a lot of patterns like this, and I'm trying to fix the
code to be more portable and less dependent on directly calling class
intrinsics.

I believe this is the first place where new is.fpclass calls are
introduced. There are more class-like compares that could be
recognized; this is a set I currently care about plus a few extras.

Keep the == 0 cases disabled for now. It depends on the denormal
mode. If we just check IEEE mode now, it will break my use case
without another patch I'm working on.
2023-02-23 06:19:40 -04:00
Kazu Hirata
f8f3db2756 Use APInt::count{l,r}_{zero,one} (NFC) 2023-02-19 22:04:47 -08:00
Yingchi Long
f9e2fb9d8e [InstCombine] combine intersection for inequality icmps
```
define i1 @src(i32 %A) {
  %mask1 = and i32 %A, 15 ; 0x0f
  %tst1 = icmp eq i32 %mask1, 3 ; 0x03
  %mask2 = and i32 %A, 255 ; 0xff
  %tst2 = icmp eq i32 %mask2, 243; 0xf3
  %res = or i1 %tst1, %tst2
  ret i1 %res
}
```

->

```
define i1 @tgt(i32 %A) {
  %1 = and i32 %A, 15
  %res = icmp eq i32 %1, 3
  ret i1 %res
}
```

Proof: https://alive2.llvm.org/ce/z/4AyvcE

Assume that `(B & D) & (C ^ E) == 0`, and `(B & D) == D || (B & D) == B`,
transforms:

```
(icmp ne (A & B), C) & (icmp ne (A & D), E)
-> (icmp ne (A & (B&D)), (C&E))
```

Fixes: https://github.com/llvm/llvm-project/issues/59680

Reviewed By: spatel, bcl5980

Differential Revision: https://reviews.llvm.org/D140666
2023-02-10 12:50:39 +08:00
Matt Arsenault
9ad6bdd747 InstCombine: Fold and (fcmp), (is.fpclass) into is.fpclass
Fold class test performed by an fcmp into another class. For now this
avoids introducing new class calls then there isn't one that already
exists.
2023-02-08 21:40:20 -04:00
chenglin.bi
4a66b3b20e [InstCombine] Fold pattern xor(and, or) to select
(A & B) ^ (A | C) --> A ? ~B : C

https://alive2.llvm.org/ce/z/KCBfXr
https://alive2.llvm.org/ce/z/Pm-zJN
https://alive2.llvm.org/ce/z/VT8uC2

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D141660
2023-02-03 17:12:16 +08:00
Sanjay Patel
2d7bb60667 [InstCombine] improve description of not+shift transform; NFC
This was added recently with:
e44a305690add9f75
2023-01-26 08:58:45 -05:00
Sanjay Patel
e44a305690 [InstCombine] invert canonicalization of sext (x > -1) --> not (ashr x)
https://alive2.llvm.org/ce/z/2iC4oB

This is similar to changes made for zext + lshr:
21d3871b7c90
6c39a3aae1dc

The existing fold did not account for extra uses, so we
see some instruction count reductions in the test diffs.

This is intended to improve analysis (icmp likely has more
transforms than any other opcode), make other transforms
more symmetric with zext/lshr, and it can be inverted
in codegen if profitable.

As with the earlier changes, there is potential to uncover
infinite combine loops, but I have not found any yet.
2023-01-24 16:44:15 -05:00
Sanjay Patel
0bb7be5ff6 [InstCombine] canonicalize 'not' ahead of bitcast+sext
not (bitcast (sext i1 X)) --> bitcast (sext (not i1 X))

https://alive2.llvm.org/ce/z/-6Ygkd

This shows up as a potential regression if we change
canonicalization of ashr+not to icmp+sext.
2023-01-24 15:46:46 -05:00
Guillaume Chatelet
48f5d77eee [NFC] Use TypeSize::getKnownMinValue() instead of TypeSize::getKnownMinSize()
This change is one of a series to implement the discussion from
https://reviews.llvm.org/D141134.
2023-01-11 16:36:39 +00:00
chenglin.bi
87b2c760d0 [Instcombine] fold logic ops to select
(C & X) | ~(C | Y) -> C ? X : ~Y

https://alive2.llvm.org/ce/z/4yLh_i

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D139080
2023-01-05 12:04:35 +08:00
Sanjay Patel
cb9569049c [InstCombine] fold mask with not-of-sext-bool to select
~sext(A) & Op1 --> A ? 0 : Op1

With no extra uses, this pattern is already reduced,
but we would miss it in examples such as issue #59773.

https://alive2.llvm.org/ce/z/WGLcSR
2023-01-02 13:33:28 -05:00
Roman Lebedev
cf58063a40
[InstCombine] Canonicalize math-y conditional negation into a select
https://alive2.llvm.org/ce/z/vPs-gZ

This is a larger pattern than would seem necessary, with minimal being:
* `and` https://alive2.llvm.org/ce/z/q9-MqK
* `or`  https://alive2.llvm.org/ce/z/AUUEMZ
* `xor` https://alive2.llvm.org/ce/z/dm3Ume
.. so for all others, we canonicalize away from math to `select`,
but there we canonicalize in the opposite direction.

Fixes https://github.com/llvm/llvm-project/issues/59791
2023-01-02 21:26:37 +03:00
Sanjay Patel
30af2e3191 [InstCombine] avoid miscompile in sinkNotIntoLogicalOp()
Fixes #59704
2022-12-29 14:33:41 -05:00
Roman Lebedev
a7b898b49a
[InstCombine] Disallow constant expressions in not canonicalization
As per post-commit feedback - we generally do not like Constant Expressions,
and trying to deal with them leads to inconsistent results
that may very well be non-optimal. So just don't.
2022-12-20 19:56:37 +03:00
Roman Lebedev
e51b7bff19
[InstCombine] Fix inversion of constants
`canFreelyInvertAllUsersOf()`, in general, does not make sense
for constants, and constant expressions are likely even more problematic.
For those, we just want to create a simple constant expression and be done.

Fixes https://github.com/llvm/llvm-project/issues/59613
2022-12-20 18:20:32 +03:00
Matt Arsenault
effde7f43e InstCombine: Match pattern that appears in clang's __builtin_isnormal
and (fcmp ord x, 0), (fcmp u* x, inf) -> fcmp o* x, inf
and (fcmp ord x, 0), (fcmp u* fabs(x), inf) -> fcmp o* x, inf

Clang emits this peculiar pattern as an isfinite check in
__builtin_isnormal which can be simplified. We should fix clang to
emit this in the first place, but should also fold it here.
2022-12-19 08:09:22 -05:00
Roman Lebedev
3ae00753c1
[InstCombine] sinkNotIntoOtherHandOfLogicalOp(): don't forget to re-set insert position
Several bots are unhappy, and this appears to be the reason:
we might be inserting into wrong basic block,
one that does not dominate the I.
2022-12-19 05:17:03 +03:00
Roman Lebedev
6adeec881a
[InstCombine] sinkNotIntoOtherHandOfLogicalOp(): allow extra invertible uses of hand-to-invert 2022-12-19 05:00:58 +03:00
Roman Lebedev
b20ccccda2
[InstCombine] Support sinking not into logical operand with invertible hands
The important bit here is that we gracefully handle other uses,
iff they can be adapted to inversion.

I'll note, the previous logic was actively bad,
it increased instruction count since it didn't actually ensure
that the inversions happened.
2022-12-19 04:11:16 +03:00
Roman Lebedev
9f0c9e4725
[InstCombine] Try to sink not of one operand of logical operation into another hand
Matches what we do for binary operations, but a special care needs
is needed to preserve operand order, as the logical operations
are not strictly commutative!
2022-12-19 01:10:16 +03:00
Roman Lebedev
4def99e642
[InstCombine] Try to fold not into cmp iff other users of cmp are freely invertible
There is still some such patterns that require collaboration
of folds to handle,that we don't currently do.
2022-12-19 00:24:28 +03:00
Nikita Popov
43b5fbae3b Revert "[InstCombine] Handle logical op in simplifyRangeCheck() (PR59484)"
This reverts commit 492c471839a66e354ebe696bd3e15f7477c63613.

As pointed out by nloped, the transform in f2 is not correct: If
%shr is poison, then freeze may result in a negative value. The
transform is correct in the case where the freeze is pushed through
the operation in a way that guarantees the result is non-negative,
which is the case I had tested.
2022-12-14 12:04:21 +01:00
Matt Arsenault
8fc25caae5 InstCombine: Fold logic of fp_classes together
Move logical operators on pairs of llvm.is.fpclass on the same value
into the test mask of a single is_fpclass.

or (class x, mask0), (class x, mask1) -> class x, (mask0 | mask1)
and (class x, mask0), (class x, mask1) -> class x, (mask0 & mask1)
xor (class x, mask0), (class x, mask1) -> class x, (mask0 ^ mask1)

The and/or cases should appear frequently in the builtin math
libraries; haven't seen the xor case but handle it for completeness.
2022-12-13 10:51:41 -05:00
Matt Arsenault
19d428f717 InstCombine: Fold negations of is_fpclass intrinsics
Can invert the result by inverting the test mask.
2022-12-13 08:06:19 -05:00
Nikita Popov
5dbfca30c1 [InstCombine] Support logical ops in foldAndOrOfICmpsWithConstEq() (NFC)
This is largely just for the sake of completeness. For logical ops,
this is mostly subsumed by foldSelectValueEquivalence() in a more
generic way. The only exception is vector support, as select
value equivalence folding currently doesn't support this for the
case where the replacement does not simplify.
2022-12-13 11:34:01 +01:00
Nikita Popov
de59d222ab [InstCombine] Support logical ops in foldAndOrOfICmpEqZeroAndICmp()
If the and/or is logical and one of the operands only occurs on the
RHS, we need to freeze it: https://alive2.llvm.org/ce/z/vuMuE_
2022-12-13 10:36:55 +01:00
Nikita Popov
492c471839 [InstCombine] Handle logical op in simplifyRangeCheck() (PR59484)
We need to freeze to avoid propagating a potentially poison
upper bound (https://alive2.llvm.org/ce/z/MsD38k).

This resolves the existing TODO in the code.

Fixes https://github.com/llvm/llvm-project/issues/59484.
2022-12-13 09:51:18 +01:00
Fangrui Song
21cd58baa1 [Transforms/InstCombine] llvm::Optional => std::optional 2022-12-13 08:26:08 +00:00
chenglin.bi
10c3df728c [Instcombine] Canonicalize ~((A & B) ^ (A | ?)) -> (A & B) | ~(A | ?)
~((A & B) ^ (A | ?)) -> (A & B) | ~(A | ?)
https://alive2.llvm.org/ce/z/JHN2p4

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D139299
2022-12-07 23:52:07 +08:00
Fangrui Song
89fae41ef1 [IR] llvm::Optional => std::optional
Many llvm/IR/* files have been migrated by other contributors.
This migrates most remaining files.
2022-12-05 04:13:11 +00:00
Kazu Hirata
343de6856e [Transforms] Use std::nullopt instead of None (NFC)
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated.  The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-02 21:11:37 -08: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
5c759edc57 [InstCombine] reduce another or-xor bitwise logic pattern
~(A & ?) | (A ^ B) --> ~((A & ?) & B)
https://alive2.llvm.org/ce/z/mxex6V

This is similar to 9d218b61cc50 where we peeked through
another logic op to find a common operand.
2022-09-03 09:32:08 -04:00
Sanjay Patel
addbdac5d5 [InstCombine] fold power-of-2 ctlz/cttz with inverted result
When X is a power-of-two or zero and zero input is poison:
ctlz(i32 X) ^ 31 --> cttz(X)
cttz(i32 X) ^ 31 --> ctlz(X)

https://alive2.llvm.org/ce/z/Cs7sFE
2022-09-01 08:57:55 -04:00
Chenbing Zheng
35a3048c25 [InstCombine] add support for multi-use Y of (X op Y) op Z --> (Y op Z) op X
For (X op Y) op Z --> (Y op Z) op X
we can still do transform when Y is multi-use. In D131356 limit it to one-use,
this patch remove this limit.

This is still not a complete solution, I add a todo test to show it.
In this case, X and Y are both multi use, we can't differentiate how to convert based on this.
But at least we don't make the code worse,and it can solve half the scenarios.
2022-08-31 10:55:05 +08:00
Sanjay Patel
ab6892967c [InstCombine] allow sext in fold of mask using signbit, part 2
https://alive2.llvm.org/ce/z/rcbZmx

Sibling tranform to 275aa24c0a51

This pattern is seen in the examples in issue #57381.
2022-08-28 11:50:52 -04:00
Sanjay Patel
275aa24c0a [InstCombine] allow sext in fold of mask using signbit
~(iN X s>> (N-1)) & Y --> (X s< 0) ? 0 : Y -- with optional sext

https://alive2.llvm.org/ce/z/wFFnZT
2022-08-28 09:01:30 -04:00
Sanjay Patel
7abf233f44 [InstCombine] allow poison (undef) element in vector signbit transforms
If the shift constant has undefined lanes, we can assume those
are the same as the defined lanes in these transforms:
https://alive2.llvm.org/ce/z/t6TTJ2

Replace undef with poison in the test while here to support
the transition away from undef.
2022-08-27 11:57:05 -04:00
Eric Gullufsen
eb1e2b3997 [InstCombine] Canonicalize "and, add", "or, add", "xor, add"
Canonicalize
```
((x + C1) & C2) --> ((x & C2) + C1)
((x + C1) ^ C2) --> ((x ^ C2) + C1)
((x + C1) | C2) --> ((x | C2) + C1)
```
for suitable constants `C1` and `C2`.

Alive2 proofs: [[ https://alive2.llvm.org/ce/z/BqMDVZ | add, or --> or, add ]]
[[ https://alive2.llvm.org/ce/z/BhAeCl | add, xor --> xor, add ]]
[[ https://alive2.llvm.org/ce/z/jYRHEt | add, and --> and, add ]]

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D131142
2022-08-26 17:23:29 -04:00
Philip Reames
c58791c286 Revert "[InstCombine] Canonicalize "and, add", "or, add", "xor, add""
This reverts commit d2f110c693c88d1bb7caee4f72ebb14766f85239.  test/Transforms/InstCombine/freeze.ll fails on ninja check-llvm on x86_64.
2022-08-26 11:18:31 -07:00
Eric Gullufsen
d2f110c693 [InstCombine] Canonicalize "and, add", "or, add", "xor, add"
Canonicalize
```
((x + C1) & C2) --> ((x & C2) + C1)
((x + C1) ^ C2) --> ((x ^ C2) + C1)
((x + C1) | C2) --> ((x | C2) + C1)
```
for suitable constants `C1` and `C2`.

Alive2 proofs: [[ https://alive2.llvm.org/ce/z/BqMDVZ | add, or --> or, add ]]
[[ https://alive2.llvm.org/ce/z/BhAeCl | add, xor --> xor, add ]]
[[ https://alive2.llvm.org/ce/z/jYRHEt | add, and --> and, add ]]

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D131142
2022-08-26 14:07:43 -04:00
Jay Foad
f82c55fa08 [InstCombine] Change order of canonicalization of ADD and AND
Canonicalize ((x + C1) & C2) --> ((x & C2) + C1) for suitable constants
C1 and C2, instead of the other way round. This should allow more
constant ADDs to be matched as part of addressing modes for loads and
stores.

Differential Revision: https://reviews.llvm.org/D130080
2022-08-22 20:03:53 +01:00
Sanjay Patel
15e3d86911 [InstCombine] reassociate bitwise logic chains based on uses
(X op Y) op Z --> (Y op Z) op X

This isn't a complete solution (see TODO tests for possible refinements),
but it shows some nice wins and doesn't seem to cause any harm. I think
the most potential danger is from conflicting with other folds and causing
an infinite loop - that's the reason for avoiding patterns with constant
operands.

Alternatively, we could try this in the reassociate pass, but we would not
immediately see all of the logic folds that instcombine provides. I also
looked at improving ValueTracking's isImpliedCondition() (and we should
still add some enhancements there), but that would not work in general for
bitwise logic reduction.

The tests that reduce completely to 0/-1 are motivated by issue #56653.

Differential Revision: https://reviews.llvm.org/D131356
2022-08-21 09:42:14 -04:00
Sanjay Patel
b066195b3f [InstCombine] fold bitwise logic or+or+xor+not
(~A | C) | (A ^ B) --> ~(A & B) | C
https://alive2.llvm.org/ce/z/Qw3aiJ

This extends the existing fold (just above the new match)
to peek through another 'or' instruction.

This should let the motivating case from issue #57174
simplify completely.
2022-08-18 17:14:41 -04:00
Sanjay Patel
8b56fa92de [InstCombine] fix "X|(X^Y)" pattern-matching for commuted variants 2022-08-13 11:02:28 -04:00
Sanjay Patel
9d218b61cc [InstCombine] reduce or-xor-or patterns
(A | ?) | (A ^ B) --> (A | ?) | B
https://alive2.llvm.org/ce/z/dbNQw4

This extends the existing transform to peek through
another 'or' instruction for the common operand.

This is the underlying missing fold that should allow
issue #56711 and issue #57120 to reduce even more.
2022-08-13 09:52:01 -04:00