Commit Graph

634 Commits

Author SHA1 Message Date
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 9d218b61cc 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 275aa24c0a

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 d2f110c693.  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
Sanjay Patel 763b31237f [InstCombine] move comments closer to relevant code; NFC 2022-08-13 09:16:33 -04:00
Sanjay Patel 28ad5dc3f7 [InstCombine] try harder to narrow bitwise logic with cast operands
This works with any logic + extend:
https://alive2.llvm.org/ce/z/vzsqQD

The motivating case is from issue #56294, but that's still not optimal
(it should simplify completely).
2022-07-28 07:23:22 -04:00
Chenbing Zheng 1a0187c9e7 [InstCombine] remove useless ‘InstCombiner::’. nfc
Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D130220
2022-07-22 09:24:24 +08:00
Chenbing Zheng 8075f680c8 [InstCombine] add fold (X > C - 1) ^ (X < C + 1) --> X != C
Considering the correctness of this pattern, we should avoid that C - 1
is non-negative and C + 1 is negative.

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

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D129622
2022-07-21 10:08:21 +08:00
Sanjay Patel 26fbb79c33 [InstCombine] reduce code for signbit folds; NFC 2022-07-18 11:04:58 -04:00
Daniel Bertalan ef7aed3e11 [InstCombine] Do not fold 'and (sext (ashr X, Shift)), C' if Shift < 0
The 'and (sext (ashr X, ShiftC)), C' --> 'lshr (sext X), ShiftC'
transformation would access out of bounds bits in APInt::getLowBitsSet
if the shift count was larger than X's bit width or if it was negative.

Fixes #56424
2022-07-07 19:13:55 +02:00
Sanjay Patel f9f40aa10d [InstCombine] fold negated low-bit-mask to cmp+select
(-(X & 1)) & Y --> (X & 1) == 0 ? 0 : Y
https://alive2.llvm.org/ce/z/rhpH3i

This is noted as a missing IR canonicalization in issue #55618.
We already managed to fix codegen to the expected form.
2022-07-03 12:25:26 -04:00
Eric Gullufsen 73202130e5 [InstCombine] Optimize test for same-sign of values
(icmp slt (X & Y), 0) | (icmp sgt (X | Y), -1) -> (icmp sgt (X ^ Y), -1)
(icmp slt (X | Y), 0) & (icmp sgt (X & Y), -1) -> (icmp slt (X ^ Y), 0)

[[ https://alive2.llvm.org/ce/z/qXxEFP | alive2 example ]]
[[ https://godbolt.org/z/aWf9c6j74 | godbolt  ]]

[[ https://godbolt.org/z/5Ydn5TehY | godbolt for inverted form ]]
[[ https://alive2.llvm.org/ce/z/93AODr | alive2 for inverted form ]]
[[ https://github.com/llvm/llvm-project/issues/55988 | issue #55988 ]]

Differential Revision: https://reviews.llvm.org/D127903
2022-06-19 16:18:19 -04:00
Sanjay Patel bfde861935 [InstCombine] convert mask and shift of power-of-2 to cmp+select
When the mask is a power-of-2 constant and op0 is a shifted-power-of-2
constant, test if the shift amount equals the offset bit index:

(ShiftC << X) & C --> X == (log2(C) - log2(ShiftC)) ? C : 0
(ShiftC >> X) & C --> X == (log2(ShiftC) - log2(C)) ? C : 0

This is an alternate to D127610 with a more general pattern.
We match only shift+and instead of the trailing xor, so we see a few
more tests diffs. I think we discussed this initially in D126617.

Here are proofs for shifts in both directions:
https://alive2.llvm.org/ce/z/CFrLs4

The test diffs look equal or better for IR, and this makes the
patterns more uniform in IR. The backend can partially invert this
in both cases if that is profitable. It is not trivially reversible,
however, so if we find perf regressions that are not easy to undo,
then we may want to revert this.

Differential Revision: https://reviews.llvm.org/D127801
2022-06-17 10:51:57 -04:00
chenglin.bi 286198ff04 [InstCombine] Optimize lshr+shl+and conversion pattern
if `C1` and `C3` are pow2 and `Log2(C3) >= C2`:
    ((C1 >> X) << C2) & C3 -> X == (Log2(C1)+C2-Log2(C3)) ? C3 : 0
https://alive2.llvm.org/ce/z/zvrkKF

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D127469
2022-06-14 11:06:10 +08:00
Sanjay Patel 310adb658c [InstCombine] reorder mask folds for efficiency
This shows narrowing improvements on the logic tests
(transforms recently added with e247b0e5c9).

This is not a complete fix. That would require adding
folds to visitOr/visitXor. But it enables the expected
transforms for the basic patterns in the affected tests.
2022-06-13 09:49:57 -04:00
Sanjay Patel e247b0e5c9 [InstCombine] add narrowing transform for low-masked binop with zext operand (2nd try)
The 1st try ( afa192cfb6 ) was reverted because it could
cause an infinite loop with constant expressions.

A test for that and an extra condition to enable the transform
are added now. I also added code comments to better describe
the transform and the existing, related transform.

Original commit message:
https://alive2.llvm.org/ce/z/hRy3rE

As shown in D123408, we can produce this pattern when moving
casts around, and we already have a related fold for a binop
with a constant operand.
2022-06-10 12:42:27 -04:00
Sanjay Patel 6fedc6a2b4 Revert "[InstCombine] add narrowing transform for low-masked binop with zext operand"
This reverts commit afa192cfb6.
This can cause an infinite loop as shown with an example in the
post-commit thread.
2022-06-10 08:25:10 -04:00
chenglin.bi de7a6ae1ff [InstCombine] Optimize shl+lshr+and conversion pattern
if `C1` and `C3` are pow2 and `Log2(C3)+C2 < BitWidth`:
    ((C1 << X) >> C2) & C3 -> X == (Log2(C3)+C2-Log2(C1)) ? C3 : 0;

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

Fix issue https://github.com/llvm/llvm-project/issues/55739

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D126617
2022-06-10 09:36:58 +08:00
Sanjay Patel afa192cfb6 [InstCombine] add narrowing transform for low-masked binop with zext operand
https://alive2.llvm.org/ce/z/hRy3rE

As shown in D123408, we can produce this pattern when moving
cast around, and we already have a related fold for a binop
with a constant operand.
2022-06-09 16:59:26 -04:00
Simon Moll b8c2781ff6 [NFC] format InstructionSimplify & lowerCaseFunctionNames
Clang-format InstructionSimplify and convert all "FunctionName"s to
"functionName".  This patch does touch a lot of files but gets done with
the cleanup of InstructionSimplify in one commit.

This is the alternative to the less invasive clang-format only patch: D126783

Reviewed By: spatel, rengolin

Differential Revision: https://reviews.llvm.org/D126889
2022-06-09 16:10:08 +02:00
Biplob Mishra d87bfa9ad0 [InstCombine] Combine instructions of type or/and where AND masks can be combined.
The patch simplifies some of the patterns as below

(A | (B & C0)) | (B & C1) -> A | (B & C0|C1)
((B & C0) | A) | (B & C1) -> (B & C0|C1) | A

In some scenarios like byte reverse on half word, we can see this pattern multiple times and this conversion can optimize these patterns.

Additionally this commit fixes the issue reported with the test case.
int f(int a, int b) {
  int c = ((unsigned char)(a >> 23) & 925);
  if (a)
    c = (a >> 23 & b) | ((unsigned char)(a >> 23) & 925) | (b >> 23 & 157);
  return c;
}

The previous revision/commit did not check one-use of an intermediate value that this transform re-uses.
When that value has another use, an existing transform will try to invert the transform here.
By adding one-use checks, we avoid the infinite loops seen with the earlier commit.

Differential Revision: https://reviews.llvm.org/D124119
2022-06-09 10:58:30 +01:00
Alexander Kornienko aa98e7e1eb Revert "[InstCombine] Combine instructions of type or/and where AND masks can be combined."
This reverts commit ec4adf1f6c. The commit causes
clang to hang on a certain input:
```
$ cat q.cc
int f(int a, int b) {
  int c = ((unsigned char)(a >> 23) & 925);
  if (a)
    c = (a >> 23 & b) | ((unsigned char)(a >> 23) & 925) | (b >> 23 & 157);
  return c;
}

$ time ./clang-15-10515 --target=x86_64--linux-gnu -O1  -c q.cc
^C

real    0m45.072s
user    0m0.025s
sys     0m0.099s
```
2022-06-01 14:20:00 +02:00
Chenbing Zheng 1486a9c9fe [InstCombine] [NFC] refector foldXorOfICmps
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D126268
2022-05-26 11:07:18 +08:00
Nikita Popov a7c079aaa2 [InstCombine] Support logical and in masked icmp fold
Most of the folds implemented in this function work fine with
logical operations. We only need to be careful for the cases that
work on non-constant masks, where the RHS operand shouldn't be
poison.

This is a conservative implementation that bails out of illegal
transforms, but we could also change these to insert freeze instead.
2022-05-24 11:16:33 +02:00
Nikita Popov 5abaabed22 [InstCombine] Use m_APInt() in asymmetric masked icmp fold
This is mostly intended as code cleanup, but it does also add
support for splat vectors to this fold.
2022-05-24 10:57:28 +02:00
Nikita Popov c0e06c7448 [InstCombine] Handle logical and/or in recursive and/or of icmps fold
The and/or of icmps fold is also applied in reassociated form.
However, this currently only happens for bitwise and of bitwise
and, but not for bitwise and of logical and (or other combinations,
but this is the one being addressed here).

We can do this for bitwise+logical combinations as well, but need
to be a bit careful about which of the resulting ands are logical:
https://alive2.llvm.org/ce/z/WYSjGh
https://alive2.llvm.org/ce/z/guxYnz
https://alive2.llvm.org/ce/z/S5SYxY
https://alive2.llvm.org/ce/z/2rAWeW
2022-05-24 10:13:10 +02:00
Nikita Popov f45c1e436e [InstCombine] Change operand order in recursive and/or of icmps fold
The order obviously doesn't matter for bitwise and/or, but would
matter for logical and/or, so change it to preserve the original
order.
2022-05-23 17:29:33 +02:00
Nikita Popov 45226d04f0 [InstCombine] Reuse icmp of and/or folds for logical and/or
Similarly to a change recently done for fcmps, add a flag that
indicates whether the and/or is logical to foldAndOrOfICmps, and
reuse the function when folding logical and/or.

We were already calling some parts of it, but this gives us a
clearer indication of which parts may need poison-safe variants,
and would also allow to fold combinations of bitwise and logical
and/or.

This change should be close to NFC, because all folds this enables
were either already called previously, or can make use of implied
poison reasoning.
2022-05-23 15:37:07 +02:00
Sanjay Patel f0071d43e4 [InstCombine] add use check to fold of bitwise logic with cast ops
This was shown as a potential regression in D126040.
2022-05-20 09:08:53 -04:00
Sanjay Patel be7f09f7b2 [IR] create and use helper functions that test the signbit; NFCI 2022-05-16 11:26:23 -04:00
Biplob Mishra ec4adf1f6c [InstCombine] Combine instructions of type or/and where AND masks can be combined.
The patch simplifies some of the patterns as below

(A | (B & C0)) | (B & C1) -> A | (B & C0|C1)
((B & C0) | A) | (B & C1) -> (B & C0|C1) | A

In some scenarios like byte reverse on half word, we can see this pattern multiple times and this conversion can optimize these patterns.

Differential Revision: https://reviews.llvm.org/D124119
2022-05-16 12:43:33 +01:00
Fraser Cormack bafab9c09f [InstCombine] Fix scalable-vector bitwise select matching
D113035 enhanced the matching of bitwise selects from vector types. This
change unfortunately introduced crashes as it tries to cast scalable
vector types to integers.

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D124997
2022-05-06 12:59:39 +01:00
Alexander Shaposhnikov ec7122f64b [InstCombine] Fold ((A&B)^C)|B
Fold ((A&B)^C)|B into C|B.

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

This addresses the issue https://github.com/llvm/llvm-project/issues/55169

Test plan: ninja check-all

Differential revision: https://reviews.llvm.org/D124710
2022-05-05 00:56:20 +00:00
Nikita Popov 982cbed819 [InstCombine] Fold logical and/or of range icmps with nowrap flags
This is an edge-case where we don't convert to bitwise and/or based
on implies poison reasoning, so explicitly try to perform the fold
in logical form. The transform itself is poison-safe, as both icmps
are based on the same value and any nowrap flags are discarded as
part of the fold (https://alive2.llvm.org/ce/z/aCwC8b for the used
example).
2022-04-29 14:42:42 +02:00
Nikita Popov 57aaeefc18 [InstCombine] Pass ICmpInsts to foldAndOrOfICmpsUsingRanges() (NFC)
Pass the whole instruction rather than unpacking it. This makes it
easier to reuse the function in another place, as the entire
logic is encapsulated.
2022-04-29 12:46:31 +02:00
Nikita Popov 1f53932a95 [InstCombine] Remove foldAndOrOfEqualityCmpsWithConstants() fold
This fold handles a special subset of foldAndOrOfICmpsUsingRanges(),
use the more generic implementation instead.

The result can differ if a representation using a range comparison
is possible, in which case that is preferred over masking. There is
a canonicalization opportunity here.
2022-04-29 12:23:00 +02:00
Nikita Popov 5515263e44 [InstCombine] Fold and of two ranges differing by mask
This is the de Morgan conjugated variant of the existing fold for
ors. Implement this by switching the range code to always work
on ors and perform invert operands at the start and end. This makes
reasoning easier and makes the extension more obviosuly correct.
2022-04-29 12:01:38 +02:00