1142 Commits

Author SHA1 Message Date
Noah Goldstein
46864f3b68 [InstSimplify] Simplify (shl nsw nuw X, BitWidth - 1) -> 0
https://alive2.llvm.org/ce/z/uFy5zT

Reviewed By: nikic, spatel

Differential Revision: https://reviews.llvm.org/D145327
2023-03-06 20:29:53 -06:00
Zhongyunde
15d5c59280 [InstCombine] Improvement the analytics through the dominating condition
Address the dominating condition, the urem fold is benefit from the analytics improvements.
Fix https://github.com/llvm/llvm-project/issues/60546

NOTE: delete the calls in simplifyBinaryIntrinsic and foldICmpWithDominatingICmp
is used to reduce compile time.

Reviewed By: nikic, arsenm, erikdesjardins
Differential Revision: https://reviews.llvm.org/D144248
2023-03-01 17:03:34 +08:00
Sanjay Patel
ae2322a0dc [InstSimplify] enhance simplifyWithOpReplaced() to allow more 'select' removal
This is a generalization of a suggestion from issue #60799
that allows removing a redundant guard of an input value
via icmp+select. It should also solve issue #60801.

This only comes into play for a select with an equality
condition where we are trying to substitute a constant into
the false arm of a select. (A 'true' select arm substitution
allows "refinement", so it is not on this code path.)

The constant must be the same in the compare and the select,
and it must be a "binop absorber" (X op C = C). That query
currently includes 'or', 'and', and 'mul', so there are tests
for all of those opcodes.

We then use "impliesPoison" on the false arm binop and the
original "Op" to be replaced to ensure that the select is not
actually blocking poison from leaking. That could be
potentially expensive as we recursively test each operand, but
it is currently limited to a depth of 2. That's enough to catch
our motivating cases, but probably nothing more complicated
(although that seems unlikely).

I don't know how to generalize a proof for Alive2 for this, but
here's a positive and negative test example to help illustrate
the subtle logic differences of poison/undef propagation:
https://alive2.llvm.org/ce/z/Sz5K-c

Differential Revision: https://reviews.llvm.org/D144493
2023-02-21 17:03:40 -05:00
Nikita Popov
4d192f2d2a [InstSimplify][CaptureTracking] Reduce scope of special case
As described in PR54002, the "icmp of load from global" special
case in CaptureTracking is incorrect, as is the InstSimplify code
that makes use of it.

This moves the special case from CaptureTracking into InstSimplify
to limit its scope to the buggy transform only, and not affect
other code using CaptureTracking as well.
2023-02-21 09:01:55 +01:00
Nikita Popov
be88b5814d [InstCombine] Call simplifyLoadInst()
InstCombine is supposed to be a superset of InstSimplify, but
failed to invoke load simplification.

Unfortunately, this causes a minor compile-time regression, which
will be mitigated in a future commit.
2023-02-20 10:49:44 +01:00
Matt Devereau
8299c764bd [InstSimplify] Simplify icmp between Shl instructions of the same value
define i1 @compare_vscales() {
  %vscale = call i64 @llvm.vscale.i64()
  %vscalex2 = shl nuw nsw i64 %vscale, 1
  %vscalex4 = shl nuw nsw i64 %vscale, 2
  %cmp = icmp ult i64 %vscalex2, %vscalex4
  ret i1 %cmp
}

This IR is currently emitted by LLVM. This icmp is redundant as this snippet
can be simplified to true or false as both operands originate from the same
@llvm.vscale.i64() call.

Differential Revision: https://reviews.llvm.org/D142542
2023-02-20 09:25:34 +00:00
Kohei Asano
a4d6c7dd99 [InstSimplify] Fold LoadInst for uniform constant global variables
Fold LoadInst for uniformly initialized constants, even if there
are non-constant GEP indices.

Goal proof: https://alive2.llvm.org/ce/z/oZtVby

Motivated by https://github.com/rust-lang/rust/issues/107208

Differential Revision: https://reviews.llvm.org/D144184
2023-02-20 09:43:52 +01:00
Kazu Hirata
f8f3db2756 Use APInt::count{l,r}_{zero,one} (NFC) 2023-02-19 22:04:47 -08:00
Nikita Popov
eeb125659c [InstSimplify] Slightly optimize simplifyLoad() (NFC)
Check upfront whether the load is based on a constant global
with definitive initializer. Don't bother computing offsets
otherwise.
2023-02-16 10:41:23 +01:00
Nikita Popov
9ca2c309ab [InstSimplify] Fix poison safety in insertvalue fold
We can only fold insertvalue undef, (extractvalue x, n) to x
if x is not poison, otherwise we might be replacing undef with
poison (https://alive2.llvm.org/ce/z/fnw3c8). The insertvalue
poison case is always fine.

I didn't go to particularly large effort to preserve cases where
folding with undef is still legal (mainly when there is a chain of
multiple inserts that end up covering the whole aggregate),
because this shouldn't really occur in practice: We should always
be generating the insertvalue poison form when constructing
aggregates nowadays.

Differential Revision: https://reviews.llvm.org/D144106
2023-02-16 09:39:44 +01:00
Sanjay Patel
74a2dd1356 [InstSimplify] fix/improve folding with an SNaN vector element operand
Follow-up to the equivalent change for scalars:
D143505 / 83ba349ae0a8
2023-02-14 19:10:56 -05:00
Sanjay Patel
83ba349ae0 [InstSimplify] fix/improve folding with an SNaN operand
There are 2 issues here:

1. In the default LLVM FP environment (regular FP math instructions),
   SNaN is some flavor of "don't care" which we will nail down in
   D143074, so this is just a quality-of-implementation improvement
   for default FP.
2. In the constrained FP environment (constrained intrinsics), SNaN
   must not propagate through a math operation; it has to be quieted
   according to IEEE-754 spec. That is independent of exception
   handling mode, so the current behavior is a miscompile.

Differential Revision: https://reviews.llvm.org/D143505
2023-02-14 17:51:06 -05:00
Sanjay Patel
20167e8483 [InstSimplify] !(X && Y) || X --> true (for poison-safe logical ops)
https://alive2.llvm.org/ce/z/xuvL46

This is the similar to the existing folds added with:
D138853 / f2973327496fc966c4e89597
7dbeb127eaf6
...but with the and/or swapped.
2023-01-29 10:24:52 -05:00
Sanjay Patel
7dbeb127ea [InstSimplify] X && !(X || Y) --> false
https://alive2.llvm.org/ce/z/7J8Exr

This is a commuted variant that was not included in:
D138853 / f2973327496fc966c4e89597
2023-01-26 13:38:43 -05:00
Sanjay Patel
d178c15cac [InstSimplify] (X || Y) && Y --> Y (for poison-safe logical ops)
https://alive2.llvm.org/ce/z/oT_tEh

This is the conjugate/sibling pattern suggested in post-commit
feedback for:
9444252a674df5952bb5af2b76348ae4b45

issue #60167
2023-01-22 10:44:45 -05:00
Sanjay Patel
9444252a67 [InstSimplify] with poison-safe logical ops: (X && Y) || X --> X
https://alive2.llvm.org/ce/z/ptZcJH

issue #60167
2023-01-20 17:35:24 -05:00
Noah Goldstein
78f29acae6 Add transform ctpop(X) -> 1 iff X is non-zero power of 2
Definitionally a non-zero power of 2 will only have 1 bit set so this
is a freebee.

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D141990
2023-01-19 11:26:24 -08:00
Sanjay Patel
1ce06176ec [InstSimplify] reduce "mul nsw i1" to "false"
https://alive2.llvm.org/ce/z/XYGvYg

Follow-up for:
68c197f07eeae71
2023-01-18 13:51:40 -05: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
serge-sans-paille
38818b60c5
Move from llvm::makeArrayRef to ArrayRef deduction guides - llvm/ part
Use deduction guides instead of helper functions.

The only non-automatic changes have been:

1. ArrayRef(some_uint8_pointer, 0) needs to be changed into ArrayRef(some_uint8_pointer, (size_t)0) to avoid an ambiguous call with ArrayRef((uint8_t*), (uint8_t*))
2. CVSymbol sym(makeArrayRef(symStorage)); needed to be rewritten as CVSymbol sym{ArrayRef(symStorage)}; otherwise the compiler is confused and thinks we have a (bad) function prototype. There was a few similar situation across the codebase.
3. ADL doesn't seem to work the same for deduction-guides and functions, so at some point the llvm namespace must be explicitly stated.
4. The "reference mode" of makeArrayRef(ArrayRef<T> &) that acts as no-op is not supported (a constructor cannot achieve that).

Per reviewers' comment, some useless makeArrayRef have been removed in the process.

This is a follow-up to https://reviews.llvm.org/D140896 that introduced
the deduction guides.

Differential Revision: https://reviews.llvm.org/D140955
2023-01-05 14:11:08 +01:00
Sanjay Patel
6c232db2ae [InstSimplify] fold selects where true/false arm is the same as condition
We managed to fold related patterns in issue #59704,
but we were missing these more basic folds:
https://alive2.llvm.org/ce/z/y6d7SN
2022-12-30 08:54:09 -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
Sanjay Patel
b16d04d2b9 [InstSimplify] fix formatting and add bool function argument comments; NFC
Make existing code conform with proposed additions in D140733.
2022-12-29 09:20:41 -05:00
Fangrui Song
2fa744e631 std::optional::value => operator*/operator->
value() has undesired exception checking semantics and calls
__throw_bad_optional_access in libc++. Moreover, the API is unavailable without
_LIBCPP_NO_EXCEPTIONS on older Mach-O platforms (see
_LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS).

This commit fixes LLVMAnalysis and its dependencies.
2022-12-16 22:44:08 +00:00
Fangrui Song
d4b6fcb32e [Analysis] llvm::Optional => std::optional 2022-12-14 07:32:24 +00:00
Matt Arsenault
d647e252b8 InstSimplify: Add basic folding of llvm.is.fpclass intrinsic
Copied from the existing llvm.amdgcn.class handling; eventually I will
fold that to the generic intrinsic when legal. The tests should
probably move into an instsimplify only test.
2022-12-12 21:54:04 -05:00
Sanjay Patel
9055661b95 [InstSimplify] try harder to propagate existing NaN values through FP folds
Any undef element in a vector would trigger the whole constant
to be replaced with a canonical NaN. This propagates each
element when possible.

issue #59122
2022-12-12 17:52:14 -05:00
Nikita Popov
8a09875dd1 [InstSimplify] Do not remove insertvalue of undef into poison
We cannot remove an insertvalue of undef if it inserts into a
potentially poison value. The new implementation matches that of
insertelement.

See https://alive2.llvm.org/ce/z/pCcFsW for the previously
incorrect transform.
2022-12-08 11:35:59 +01:00
Paul Walker
6e26ddbc7e [NFC][PatternMatch] Add helper for m_Intrinsic<Intrinsic::experimental_vector_reverse>. 2022-12-05 16:36:08 +00:00
Krzysztof Parzyszek
26424c96c0 Attributes: convert Optional to std::optional 2022-12-02 08:15:45 -06:00
Sanjay Patel
47f5da47f5 [InstSimplify] (X && Y) ? X : Y --> Y
Similar to the recent fold that was added for 'or' in D138815:
https://alive2.llvm.org/ce/z/PBapTJ
2022-11-30 15:44:48 -05:00
chenglin.bi
f297332749 [InstSimplify] Fold (X || Y) ? X : Y --> X
(X || Y) ? X : Y --> X
https://alive2.llvm.org/ce/z/oRQJee

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D138815
2022-11-30 10:14:17 +08:00
chenglin.bi
1fd4d91fa6 [InstSimplify] Fold !(X || Y) && X --> false
!(X || Y) && X --> false
https://alive2.llvm.org/ce/z/693Jgv

Fix: [56654](https://github.com/llvm/llvm-project/issues/56654)
Fix: [56780](https://github.com/llvm/llvm-project/issues/56780)

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D138853
2022-11-29 22:45:24 +08:00
chenglin.bi
0752fb57e4 [InstSimplify] Fold (X || Y) ? false : X --> false
(X || Y) ? false : X --> false
https://alive2.llvm.org/ce/z/y93yUm

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D138700
2022-11-29 22:08:50 +08:00
chenglin.bi
b400dde473 [InstSimplify] Use dominate condtion to simplify instructions
Fix #56795

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D138542
2022-11-26 21:41:41 +08:00
Matt Arsenault
fde4ef1973 InstSimplify: Fold arithmetic_fence as idempotent 2022-11-15 22:29:34 -08:00
Sanjay Patel
0a37290dc8 [InstSimplify] restrict logic fold with partial undef vector
https://alive2.llvm.org/ce/z/4ncsnX

Fixes #58977
2022-11-14 12:09:23 -05:00
Sanjay Patel
21f1b2da95 [InstSimplify] fold fsub nnan with Inf operand
Similar to fbc2c8f2fbbb, but if we have a non-canonical
fsub with constant operand 1, then flip the sign of the
Infinity:
https://alive2.llvm.org/ce/z/vKWfhW

If Infinity is operand 0, then the sign remains:
https://alive2.llvm.org/ce/z/73d97C
2022-11-11 08:42:44 -05:00
Sanjay Patel
fbc2c8f2fb [InstSimplify] fold X +nnan Inf
If we exclude NaN (and therefore the opposite Inf),
anything plus Inf is Inf:
https://alive2.llvm.org/ce/z/og3dj9
2022-11-10 17:13:26 -05:00
Matt Arsenault
7dd27a75a2 InstSimplify: Fold fdiv nnan ninf x, 0 -> poison
https://alive2.llvm.org/ce/z/JxX5in
2022-11-07 08:43:22 -08:00
David Green
b46427b9a2 [InstSimplify] (~A & B) | ~(A | B) --> ~A with logical and
According to https://alive2.llvm.org/ce/z/opsdrb, it is valid to convert
(~A & B) | ~(A | B) --> ~A even if the And is a Logical And. This came
up from the vector masking of predicated blocks.

Differential Revision: https://reviews.llvm.org/D137435
2022-11-07 10:03:18 +00:00
Daniel Sanders
021e6e05d3 [instsimplify] Move (extelt (inselt Vec, Value, Index), Index) -> Value from InstCombine
As requested in https://reviews.llvm.org/D135625#3858141

Differential Revision: https://reviews.llvm.org/D136099
2022-10-17 15:22:06 -07:00
Nikita Popov
ac74e7a780 [InstSimplify] Only check self-simplify in simplifyInstruction()
InstSimplify currently checks whether the instruction simplifies
back to itself, and returns undef in that case. Generally, this
should only occur in unreachable code.

However, this was also done for the simplifyInstructionWithOperands()
API. In that case, the instruction only serves as a template that
provides the opcode and other non-operand data. In this case,
simplifying back to the same "instruction" may be expected. This
caused PR58401 in conjunction with D134954.

As such, move this check into simplifyInstruction() only. The only
other caller of simplifyInstructionWithOperands() also handles the
self-simplification case explicitly.
2022-10-17 15:52:38 +02:00
Sanjay Patel
0a1210e482 [InstSimplify] try harder to fold fmul with 0.0 operand
https://alive2.llvm.org/ce/z/oShzr3

This was noted as a missing fold in D134876 (with additional
examples based on issue #58046).

I'm assuming that fmul with a zero operand is rare enough
that the use of ValueTracking will not noticeably increase
compile-time.

This adjusts a PowerPC codegen test that was added with D88388
because it would get folded away and no longer provide coverage
for the bug fix.
2022-10-04 11:20:01 -04:00
Sanjay Patel
7f7a0f2f83 [InstSimplify] reduce code duplication for fmul folds; NFC
This is a modification of the earlier attempt from:
7b7940f9da80

For fma callers, we only want to swap a 0.0 or 1.0 constant.
2022-10-04 10:29:53 -04:00
Sanjay Patel
ba7da14d83 Revert "[InstSimplify] reduce code duplication for fmul folds; NFC"
This reverts commit 7b7940f9da80de6aa0b8f28a0ef809dafe4cdffc.
This missed a test update.
2022-10-03 11:21:23 -04:00
Sanjay Patel
7b7940f9da [InstSimplify] reduce code duplication for fmul folds; NFC
The constant is already commuted for an fmul opcode,
but this code can be called more directly for fma,
so we have to swap for that caller. There are tests
in InstSimplify and InstCombine to verify that this
works as expected.
2022-10-03 10:36:02 -04:00
Sanjay Patel
3f906f057c [InstSimplify] look through vector select (shuffle) in min/max fold
This is an extension of the existing min/max+select fold (which already
has a very large number of variations) to allow a vector shuffle because
that's what we have in the motivating example from issue #42100.

A couple of Alive2 checks of variants (I don't know how to generalize
these in Alive):
https://alive2.llvm.org/ce/z/jUFAqT

And verify the PR42100 test:
https://alive2.llvm.org/ce/z/3EcASf

It's possible there is some generalization of the fold or a
VectorCombine/SLP answer for the motivating test, but I haven't found a
better/smaller solution yet.

We can also add even more variants here as follow-up patches. For example,
we can have shuffle followed by min/max; we also don't have this
canonicalization or the reverse:
https://alive2.llvm.org/ce/z/StHD9f

Differential Revision: https://reviews.llvm.org/D134879
2022-09-30 08:27:00 -04:00
Sanjay Patel
222e1c73f3 [InstSimplify] don't commute constant expression operand in min/max calls
The test shows that we would fail to consistently fold the
instruction based on the max value operand. This is also
the root cause for issue #57986, but I'll add an instcombine
test + assert for that exact problem in another commit.
2022-09-26 16:01:09 -04:00
Sanjay Patel
e9e994838a [InstSimplify] rearrange matching for select-of-min/max folds; NFC
This makes the code a little shorter and should be easier to extend
for a pattern like in issue #42100.
2022-09-26 15:02:40 -04:00