469 Commits

Author SHA1 Message Date
Kazu Hirata
d775fc390d [InstCombine] Generate better code for std::bit_floor from libstdc++
Without this patch, std::bit_floor<uint32_t> in libstdc++ is compiled
as:

  %eq0 = icmp eq i32 %x, 0
  %lshr = lshr i32 %x, 1
  %ctlz = tail call i32 @llvm.ctlz.i32(i32 %lshr, i1 false)
  %sub = sub i32 32, %ctlz
  %shl = shl i32 1, %sub
  %sel = select i1 %eq0, i32 0, i32 %shl

With this patch:

  %eq0 = icmp eq i32 %x, 0
  %ctlz = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
  %lshr = lshr i32 -2147483648, %1
  %sel = select i1 %eq0, i32 0, i32 %lshr

This patch recognizes the specific pattern emitted for std::bit_floor
in libstdc++.

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

This patch fixes:

https://github.com/llvm/llvm-project/issues/61183

Differential Revision: https://reviews.llvm.org/D145890
2023-04-15 11:32:33 -07:00
Kazu Hirata
231fa27435 [InstCombine] Generate better code for std::bit_ceil
Without this patch, std::bit_ceil<uint32_t> is compiled as:

  %dec = add i32 %x, -1
  %lz = tail call i32 @llvm.ctlz.i32(i32 %dec, i1 false)
  %sub = sub i32 32, %lz
  %res = shl i32 1, %sub
  %ugt = icmp ugt i32 %x, 1
  %sel = select i1 %ugt, i32 %res, i32 1

With this patch, we generate:

  %dec = add i32 %x, -1
  %ctlz = tail call i32 @llvm.ctlz.i32(i32 %dec, i1 false)
  %sub = sub nsw i32 0, %ctlz
  %and = and i32 %1, 31
  %sel = shl nuw i32 1, %and
  ret i32 %sel

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

This patch recognizes the specific pattern from std::bit_ceil in
libc++ and libstdc++ and drops the conditional move.  In addition to
the LLVM IR generated for std::bit_ceil(X), this patch recognizes
variants like:

  std::bit_ceil(X - 1)
  std::bit_ceil(X + 1)
  std::bit_ceil(X + 2)
  std::bit_ceil(-X)
  std::bit_ceil(~X)

This patch fixes:

https://github.com/llvm/llvm-project/issues/60802

Differential Revision: https://reviews.llvm.org/D145299
2023-03-23 19:26:43 -07:00
Nikita Popov
fdda602c04 Revert "[InstCombine] Return instruction from replaceUse()"
This reverts commit 27c4e233104ba765cd986b3f8b0dcd3a6c3a9f89.

I think I made a mistake with the use in RemoveConditionFromAssume(),
because the instruction being changed is not the current one, but
the next assume. Revert the change for now.
2023-03-14 17:46:33 +01:00
Nikita Popov
27c4e23310 [InstCombine] Return instruction from replaceUse()
Same as with other replacement methods, it's generally necessary
to report a change on the instruction itself, e.g. by returning
it from the visit method (or possibly explicitly adding it to the
worklist).

Return Instruction * from replaceUse() to encourage the usual
"return replaceXYZ" pattern.
2023-03-14 16:53:03 +01:00
Nikita Popov
271b5cf562 [InstCombine] Fix infinite combine loop (PR61361)
In the degenerate case where the select is fed by an unsimplified
icmp with two constant operands, don't try to replace one constant
with another. Wait for the icmp to be simplified first instead.

Fixes https://github.com/llvm/llvm-project/issues/61361.
2023-03-14 16:43:00 +01:00
Sanjay Patel
74a58499b7 [InstCombine] fold signed absolute diff patterns
This overlaps partially with the codegen patch D144789. This needs no-wrap
for correctness, and I'm not sure if there's an unsigned equivalent:
https://alive2.llvm.org/ce/z/ErmQ-9
https://alive2.llvm.org/ce/z/mr-c_A

This is obviously an improvement in IR, and it looks like a codegen win
for all targets and data types that I sampled.

The 'nabs' case is left as a potential follow-up (and seems less likely
to occur in real code).

Differential Revision: https://reviews.llvm.org/D145073
2023-03-06 13:49:48 -05:00
Paul Walker
15915fa10a [InstCombine] Implement "A & (~A | B) --> A & B" like transforms for boolean based selects.
Alive2 links for "A & (~A | B) --> A & B":
https://alive2.llvm.org/ce/z/oKiodu (scalar)
https://alive2.llvm.org/ce/z/8yn8GL (vector)

Alive2 links for "A | (~A & B) --> A | B"
https://alive2.llvm.org/ce/z/v5GEKu (scalar)
https://alive2.llvm.org/ce/z/wvtJsj (vector)

NOTE: The commutative variants of these transforms, for example:
  "(~A | B) & A --> A & B"
are already handled by simplifying the underlying selects to
normal logical operations due to that combination having simpler
poison semantics.

Differential Revision: https://reviews.llvm.org/D145157
2023-03-06 13:53:41 +00:00
Sanjay Patel
452279efe2 [InstCombine] prevent miscompiles from select-of-div/rem transform
This avoids the danger shown in issue #60906.
There were no regression tests for these patterns, so these potential
failures have been around for a long time.

We freeze the condition and preserve the optimization because
getting rid of a div/rem is always a win.

Here are a couple of examples that can be corrected by freezing the
condition:
https://alive2.llvm.org/ce/z/sXHTTC

Differential Revision: https://reviews.llvm.org/D144671
2023-03-01 08:54:23 -05:00
Sanjay Patel
2ea0e530d3 [InstCombine] simplify test for div/rem; NFC
This is too conservative as noted in the TODO comment.
2023-02-28 14:21:13 -05:00
Sander de Smalen
68b56e3a74 [InstCombine] NFC: Add implied condition to block in foldSelectInstWithICmp
Added the condition 'TrueVal->getType()->isIntOrIntVectorTy' to a block of code
in foldSelectInstWithICmp which is only valid if the TrueVal is integer type.

This change was split off from D136861.
2023-02-23 16:11:00 +00:00
Sanjay Patel
f48f178717 [InstCombine] canonicalize cmp+select as smin/smax
(V == SMIN) ? SMIN+1 : V --> smax(V, SMIN+1)
(V == SMAX) ? SMAX-1 : V --> smin(V, SMAX-1)

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

Follow-up for the unsigned variants added with:
86b4d8645fc1b866

issue #60374
2023-02-12 07:54:43 -05:00
Sanjay Patel
86b4d8645f [InstCombine] canonicalize cmp+select as umin/umax
(V == 0) ? 1 : V --> umax(V, 1)
(V == UMAX) ? UMAX-1 : V --> umin(V, UMAX-1)

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

This is one pair of the variants discussed in issue #60374.

Enhancements for the other end of the constant range and
signed variants are potential follow-ups, but that may
require more work because we canonicalize at least one
min/max like that to icmp+zext.
2023-02-08 17:25:58 -05:00
Roman Lebedev
c02e4a40c4
Reland "[InstCombine] Fold nested selects"
The change was reverted because one of the changes were suspected of
causing a miscompile, but said miscompile was (confirmed to be) fixed
before the revert happened, by 07ecdd9b1a8af51f07d5f4dfe46845c801482a39.

https://alive2.llvm.org/ce/z/GjCXkB
https://alive2.llvm.org/ce/z/Guz2tt

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

This reverts commit d73383c145ea83d25063246e0c34f5a41fd35293,
and relands commmit 9ddff66d0c9c3e18d56e6b20aa26a2a8cdfb6d2b.
2023-01-12 18:02:43 +03:00
Jamie Hill-Daniel
6b9317f52a [InstCombine] Fold zero check followed by decrement to usub.sat
Fold (a == 0) : 0 ? a - 1 into usub.sat(a, 1).

Differential Revision: https://reviews.llvm.org/D140798
2023-01-09 14:22:25 +01:00
chenglin.bi
33794cffcf [InstCombine] Fold logic-and/logic-or by distributive laws part2
Follow up https://reviews.llvm.org/D139408, support `and/or+select` patterns
X && Z || Y && Z --> (X || Y) && Z
https://alive2.llvm.org/ce/z/EMCkBG
https://alive2.llvm.org/ce/z/Q-YRvr
https://alive2.llvm.org/ce/z/SFkVQc
https://alive2.llvm.org/ce/z/S9MCuJ
https://alive2.llvm.org/ce/z/KZ7zzz

(X || Z) && (Y || Z) --> (X && Y) || Z
https://alive2.llvm.org/ce/z/Ggpa8-
https://alive2.llvm.org/ce/z/nhQRLY
https://alive2.llvm.org/ce/z/zpmEnq
https://alive2.llvm.org/ce/z/7omsrf
https://alive2.llvm.org/ce/z/CWBzBp

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D139630
2023-01-09 10:21:17 +08:00
Sanjay Patel
953cdcb989 [InstCombine] early exit to reduce indents in foldSelectIntoOp(); NFC 2023-01-02 13:33:27 -05:00
Sanjay Patel
862e35e25a [InstCombine] preserve signbit semantics of NAN with fold to fabs
As discussed in issue #59279, we want fneg/fabs to conform to the
IEEE-754 spec for signbit operations - quoting from section 5.5.1
of IEEE-754-2008:
"negate(x) copies a floating-point operand x to a destination in
the same format, reversing the sign bit"
"abs(x) copies a floating-point operand x to a destination in the
same format, setting the sign bit to 0 (positive)"
"The operations treat floating-point numbers and NaNs alike."

So we gate this transform with "nnan" in addition to "nsz":
(X > 0.0) ? X : -X --> fabs(X)

Without that restriction, we could have for example:
(+NaN > 0.0) ? +NaN : -NaN --> -NaN
(because an ordered compare with NaN is always false)
That would be different than fabs(+NaN) --> +NaN.

More fabs/fneg patterns demonstrated here:
https://godbolt.org/z/h8ecc659d
(without any FMF, these are correct independently of this patch -
no fabs should be created)

The code change is a one-liner, but we have lots of tests diffs
because there are many variations of the basic pattern.

Differential Revision: https://reviews.llvm.org/D139785
2022-12-28 10:28:23 -05:00
Paul Walker
87c494b897 [InstCombine] Bubble vector.reverse of select operands to their result.
This mirrors a similar shufflevector transformation so the same
effect is obtained for scalable vectors. The transformation is
only performed when it can be proven the number of resulting
reversals is not increased. By bubbling the reversals from operand
to result this should typically be the case and ideally leads to
back-back shuffles that can be elimitated entirely.

Differential Revision: https://reviews.llvm.org/D139339
2022-12-21 15:53:14 +00:00
Nikita Popov
79068275e7 [InstCombine] Recursively replace select value equivalence
In the X == C ? f(X) : Y -> X == C ? f(C) : Y fold, perform the
replacement in f(X) recursively. For now, this just goes two
instructions up rather than one instruction up.
2022-12-21 15:55:44 +01:00
Roman Lebedev
d73383c145
Revert "[InstCombine] Fold nested selects"
One of these two changes is exposing (or causing) some more miscompiles.
A reproducer is in progress, so reverting until resolved.

This reverts commit 9ddff66d0c9c3e18d56e6b20aa26a2a8cdfb6d2b.
2022-12-20 18:36:42 +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
f61de3c1aa
[NFC][PatternMatching] Promote m_LogicalOp matchers into PatternMatch.h 2022-12-19 00:24:28 +03:00
Roman Lebedev
dfacb8d211
[NFC][InstCombine] Add some readability by using DecomposedSelect struct 2022-12-17 05:18:54 +03:00
Kazu Hirata
6eb0b0a045 Don't include Optional.h
These files no longer use llvm::Optional.
2022-12-14 21:16:22 -08:00
Fangrui Song
d4b6fcb32e [Analysis] llvm::Optional => std::optional 2022-12-14 07:32:24 +00:00
chenglin.bi
c8647738cd [InstCombine] Fold logic-and/logic-or by distributive laws
X && Z || Y && Z --> (X || Y) && Z
https://alive2.llvm.org/ce/z/nM6kZb

(X || Z) && (Y || Z) --> (X && Y) || Z
https://alive2.llvm.org/ce/z/_EWLRR

Fix: https://github.com/llvm/llvm-project/issues/53861

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D139408
2022-12-14 04:43:06 +08:00
Roman Lebedev
79909c031d
[NFC][InstCombine] fold-nested-selects: fix profitability check
We'd check the cost of the wrong 'cond', after potentially skipping `not`.
2022-12-13 01:03:38 +03:00
Sanjay Patel
0ee6bad6a6 [InstCombine] try to forward-propagate some FMF to select
This is intended to mitigate potential regressions that
would result from restricting this fold for NANs as
discussed in issue #59279.

Ideally, we could do this more generally because we have
known problems seeing/generating FMF on a select, but there
are likely many corner cases that need to verified.

For example, I thought this propagation would be valid
without looking at the condition value and for 'nsz' too,
but according to Alive2, it is not:
https://alive2.llvm.org/ce/z/AnG6As
2022-12-11 08:58:42 -05:00
Roman Lebedev
9ddff66d0c
[InstCombine] Fold nested selects
https://alive2.llvm.org/ce/z/GjCXkB
https://alive2.llvm.org/ce/z/Guz2tt

Fixes https://github.com/llvm/llvm-project/issues/59393
2022-12-11 01:00:31 +03:00
Sanjay Patel
eec18b521a [InstCombine] reorder FP select folds
There was a code comment about detecting min/max, and we were already
doing that later.

The real motivation is hinted at by the new TODO comment. I'm hoping
to untangle some FMF ambiguity in follow-on patches. See discussion
in issue #59279.

There are enough unknowns in FMF handling that I can't say with
certainty that this change is NFC, but it doesn't cause any existing
regression tests to change.
2022-12-10 10:07:42 -05:00
chenglin.bi
b4c8cfc7c2 [InstCombine] fold more icmp + select patterns by distributive laws
follow up D139076, add icmp with not only eq/ne, but also gt/lt/ge/le.

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D139253
2022-12-07 23:55:49 +08:00
chenglin.bi
e719550e6f [InstCombine] fold icmp + select pattern by distributive laws
`C ? (Y != X) : (Z != X) --> (C ? Y : Z) != X`
`C ? (Y == X) : (Z == X) --> (C ? Y : Z) == X`

https://alive2.llvm.org/ce/z/-frXfs

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D139076
2022-12-03 07:56:19 +08:00
chenglin.bi
683b9fc7bd [Instcombine] Code refactors for foldSelectOpOp; NFC
Reuse the code about find common operator.

Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D139075
2022-12-02 22:27:10 +08:00
Sanjay Patel
b24e2f6ef6 [InstCombine] use logical-and matcher to avoid crash
Follow-on to:
ec0b406e16c44f1554

This should prevent crashing for example like issue #58552
by not matching a select-of-vectors-with-scalar-condition.

The test that shows a regression seems unlikely to occur
in real code.

This also picks up an optimization in the case where a real
(bitwise) logic op is used. We could already convert some
similar select ops to real logic via impliesPoison(), so
we don't see more diffs on commuted tests. Using commutative
matchers (when safe) might also handle one of the TODO tests.
2022-11-02 08:23:52 -04:00
Sanjay Patel
ec0b406e16 [InstCombine] use logical-or matcher to avoid crash
This should prevent crashing for the example in issue #58552
by not matching a select-of-vectors-with-scalar-condition.

A similar change is likely needed for the related fold to
properly fix that kind of bug.

The test that shows a regression seems unlikely to occur
in real code.

This also picks up an optimization in the case where a real
(bitwise) logic op is used. We could already convert some
similar select ops to real logic via impliesPoison(), so
we don't see more diffs on commuted tests. Using commutative
matchers (when safe) might also handle one of the TODO tests.
2022-11-01 16:47:41 -04:00
Sanjay Patel
4299b28a9b [InstCombine] add helper function for select-of-bools folds; NFC
This set of folds keeps growing, and it contains
bugs like issue #58552, so make it easier to
spot those via backtrace.
2022-11-01 11:06:18 -04:00
Sanjay Patel
5dcfc32822 [InstCombine] allow more commutative matches for logical-and to select fold
This is a sibling transform to the fold just above it. That was changed
to allow the corresponding commuted patterns with:
307307456277
e1bd759ea567
8628e6df7000
2022-10-24 16:40:43 -04:00
Sanjay Patel
8628e6df70 [InstCombine] use freeze to enable poison-safe logic->select fold
Without a freeze, this transform can leak poison to the output:
https://alive2.llvm.org/ce/z/GJuF9i

This makes the transform as uniform as possible, and it can help
reduce patterns like issue #58313 (although that particular
example probably still needs another transform).

Differential Revision: https://reviews.llvm.org/D136527
2022-10-22 10:42:14 -04:00
Sanjay Patel
e1bd759ea5 [InstCombine] allow more matches for logical-ands --> select
This allows patterns with real 'and' instructions because
those are safe to transform:
https://alive2.llvm.org/ce/z/7-U_Ak
2022-10-22 08:15:50 -04:00
Sanjay Patel
3073074562 [InstCombine] allow more commutative matches for logical-and to select fold
When the common value is part of either select condition,
this is safe to reduce. Otherwise, it is not poison-safe
(with the select form of the pattern):
https://alive2.llvm.org/ce/z/FxQTzB

This is another patch motivated by issue #58313.
2022-10-21 13:29:13 -04:00
Sanjay Patel
d7fecf26f4 [InstCombine] allow some commutative matches for logical-and to select fold
This is obviously correct for real logic instructions,
and it also works for the poison-safe variants that use
selects:
https://alive2.llvm.org/ce/z/wyHiwX

This is motivated by the lack of 'xor' folding seen in issue #58313.
This more general fold should help reduce some of those patterns,
but I'm not sure if this specific case does anything for that
particular example.
2022-10-21 11:28:38 -04:00
Sanjay Patel
f6fc3e23b9 [InstCombine] refactor matching code for logical ands; NFCI
Separating the matches makes it easier
to enhance for commutative patterns.
2022-10-21 11:28:38 -04:00
Sanjay Patel
bf75e937bb [InstCombine] match logical and/or more generally in fold to select
This allows the regular bitwise logic opcodes in addition to the
poison-safe select variants:
https://alive2.llvm.org/ce/z/8xB9gy

Handling commuted variants safely is likely trickier, so that's
left to another patch.
2022-10-21 09:03:36 -04:00
Sanjay Patel
d85505a932 [InstCombine] fold logical and/or to xor
(A | B) & ~(A & B) --> A ^ B

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

We already have the equivalent fold for real
logic instructions, but this pattern may occur
with selects too.

This is part of solving issue #58313.
2022-10-13 16:12:20 -04:00
Nikita Popov
c2e76f914c [InstCombine] Use simplifyWithOpReplaced() for non-bool selects
Perform the simplifyWithOpReplaced() fold even for non-bool
selects. This subsumes a number of recently added folds for
zext/sext of the condition.

We still need to manually handle variations with both sext/zext
and not, because simplifyWithOpReplaced() only performs one
level of replacements.
2022-09-22 15:46:00 +02:00
Nikita Popov
41dde5d858 [InstSimplify] Support vectors in simplifyWithOpReplaced()
We can handle vectors inside simplifyWithOpReplaced(), as long as
cross-lane operations are excluded. The equality can hold (or not
hold) for each vector lane independently, so we shouldn't use the
replacement value from other lanes.

I believe the only operations relevant here are shufflevector (where
all previous bugs were seen) and calls (which might use shuffle-like
intrinsics and would require more careful classification).

Differential Revision: https://reviews.llvm.org/D134348
2022-09-22 10:45:42 +02:00
Markus Böck
b751da43b2 [InstCombine] Handle integer extension in select patterns using the condition as value
These patterns were previously only implemented for i1 type but can be extended for any integer type by also handling zext and sext operands.

Differential Revision: https://reviews.llvm.org/D134142
2022-09-20 22:25:13 +02:00
Sanjay Patel
53eede597e [InstCombine] look through 'not' of ctlz/cttz op with 0-is-undef
https://alive2.llvm.org/ce/z/MNsC1S

This pattern was flagged at:
https://discourse.llvm.org/t/instcombines-select-optimizations-dont-trigger-reliably/64927
2022-09-12 15:06:21 -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
Fangrui Song
de9d80c1c5 [llvm] LLVM_FALLTHROUGH => [[fallthrough]]. NFC
With C++17 there is no Clang pedantic warning or MSVC C5051.
2022-08-08 11:24:15 -07:00