951 Commits

Author SHA1 Message Date
Matt Arsenault
a517b4ad2d InstSimplify: Perform cheaper check first 2023-04-14 14:36:56 -04:00
Nikita Popov
0b88adacd6 [InstSimplify] Add MaxRecurse argument to simplifyInstructionWithOperands (NFC) 2023-04-14 11:19:19 +02:00
Nikita Popov
c508e93327 [InstSimplify] Remove unused ORE argument (NFC) 2023-04-14 10:38:32 +02:00
Craig Topper
1f60c8d025 [IR] Replace calls to ConstantFP::getNullValue with ConstantFP::getZero. NFC
There is no getNullValue in ConstantFP. Due to inheritance, we're calling
Constant::getNullValue which handles any type including FP.
Since we already know we want an FP constant we can use ConstantFP::getZero
which might be faster and is a more readable name for an FP zero.
2023-04-03 23:14:02 -07:00
Noah Goldstein
87c97d052c [InstSimplify] Extend simplifications for (icmp ({z|s}ext X), C) where C is vector
Previous logic only applied for `ConstantInt` which misses all vector
cases. New code works for splat/non-splat vectors as well. No change
to the underlying simplifications.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D147275
2023-04-03 11:04:57 -05:00
Arthur Eubanks
3f23c7f5be [InstSimplify] Actually use NewOps for calls in simplifyInstructionWithOperands
Resolves a TODO.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D146599
2023-03-22 09:22:00 -07:00
Arthur Eubanks
852cfc2ed3 [NFC] Fix incorrect comment for simplifyRightShift 2023-03-21 12:05:37 -07:00
Paul Walker
62e46f2621 [LLVM] Remove support for constant scalable vector GEPs.
This work has fallen out from D134648 as a requirement to loosen
the "constness" of vscale.

Differential Revision: https://reviews.llvm.org/D145404
2023-03-14 16:48:33 +00:00
Nikita Popov
be687aff05 [InstSimplify] Adjust context instruction when threading phi (PR61312)
When threading operations over phis, we need to adjust the context
instruction to the terminator of the incoming block. This was
handled when threading icmps, but not when threading binops.

Fixes https://github.com/llvm/llvm-project/issues/61312.
2023-03-10 10:34:27 +01:00
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