492 Commits

Author SHA1 Message Date
Noah Goldstein
54ec8bcaf8 Recommit "[InstCombine] Expand foldSelectICmpAndOr -> foldSelectICmpAndBinOp to work for more binops" (3rd Try)
Fixed bug that assumed binop was commutative.
Was re-reviewed by nikic and chapuni

Differential Revision: https://reviews.llvm.org/D148414
2023-09-01 17:15:51 -05:00
Matt Arsenault
5ae881ff0a InstCombine: Fold out scale-if-denormal pattern
Fold select (fcmp oeq x, 0), (fmul x, y), x => x

This cleans up a pattern left behind by denormal range checks under
denormals are zero.

The pattern starts out as something like:
  x = x < smallest_normal ? x * K : x;

The comparison folds to an == 0 when the denormal mode treats input
denormals as zero. This makes library denormal checks free after
linked into DAZ enabled code.

alive2 is mostly happy with this, but there are some issues. First,
there are many reported failures in some of the negative tests that
happen to trigger some preexisting canonicalize introducing
combine. Second, alive2 is incorrectly asserting that denormals must
be flushed with the DAZ modes. It's allowed to drop a canonicalize.

https://reviews.llvm.org/D157030
2023-09-01 07:47:12 -04:00
Yingwei Zheng
074f23e3e1
[InstCombine] Fold two select patterns into or-and
This patch is the follow-up improvement of D122152.
Fixes https://github.com/llvm/llvm-project/issues/64558.

`select (a | c), a, b -> select a, true, (select ~c, b, false)` where `c` is free to invert
`select (c & ~b), a, b -> select b, true, (select c, a, false)`
Alive2: https://alive2.llvm.org/ce/z/KwxtMA

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D158983
2023-08-30 00:57:08 +08:00
Noah Goldstein
2acf00bd0a Revert "Recommit "[InstCombine] Expand foldSelectICmpAndOr -> foldSelectICmpAndBinOp to work for more binops" (2nd Try)"
Still appears to be buggy:
https://lab.llvm.org/buildbot/#/builders/124/builds/8260

This reverts commit 397a9cc4d875712a648271ecbac05ac6382c5708.
2023-08-25 02:22:23 -05:00
Noah Goldstein
397a9cc4d8 Recommit "[InstCombine] Expand foldSelectICmpAndOr -> foldSelectICmpAndBinOp to work for more binops" (2nd Try)
Was missing a nullptr check before derefencing. Fixed + test case
included in the patch.

Re-Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D148414
2023-08-24 19:43:10 -05:00
David Spickett
2121e35ac2 Revert "[InstCombine] Expand foldSelectICmpAndOr -> foldSelectICmpAndBinOp to work for more binops"
This reverts commit d3402bc4460acefbc3d5278743601fa090784614.

This has caused a second stage build failure on one of our Armv7 32 bit builders:
https://lab.llvm.org/buildbot/#/builders/182/builds/7193
2023-08-17 10:13:47 +00:00
Noah Goldstein
d3402bc446 [InstCombine] Expand foldSelectICmpAndOr -> foldSelectICmpAndBinOp to work for more binops
This just expands on the existing logic that worked for `Or` and
applies it to any binop where `0` is the identity value on the RHS
i.e: `add`, `or`, `xor`, `shl`, etc...

Proofs For Some: https://alive2.llvm.org/ce/z/XZo6JD

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D148414
2023-08-16 22:43:05 -05:00
Noah Goldstein
00f0381461 [InstCombine] Refactor foldSelectICmpAndOr to use decomposeBitTestICmp instead of bespoke logic
This is essentially NFC as the cases `decomposeBitTestICmp` covers
that weren't already covered explicitly, will be canonicalized into
the cases explicitly covered. As well the unsigned cases don't apply
as the `Mask` is not a power of 2.

That being said, using a well established helper is less bug prone and
if some canonicalization changes, will prevent regressions here.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D148744
2023-08-16 22:43:05 -05:00
Noah Goldstein
82292d1ae5 [InstCombine] Remove requirement on trunc in slt/sgt case in foldSelectICmpAndOr
AFAICT, the trunc is not needed for correctness/performance and just
blocks what should be handlable cases.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D148413
2023-08-16 22:43:05 -05:00
Noah Goldstein
2c606dc16f [InstCombine] Cleanup code in foldSelectICmpAndOr; NFC
There was just alot of boolean logic to propegate conditions that seem
clearer in conditions.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D148412
2023-08-16 22:43:05 -05:00
Antonio Frighetto
211692137a [InstCombine] Fold select of srem and conditional add
Simplify a pattern that may show up when computing
the remainder of euclidean division. Particularly,
when the divisor is a power of two and never negative,
the signed remainder can be folded with a bitwise and.

Fixes 64305.

Proofs: https://alive2.llvm.org/ce/z/9_KG6c

Differential Revision: https://reviews.llvm.org/D156811
2023-08-08 00:02:16 +00:00
Paweł Bylica
966318005a
[InstCombine] Preserve metadata when combining select+binop
Fixes https://github.com/llvm/llvm-project/issues/63910

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D155461
2023-07-19 15:20:49 +02:00
Nikita Popov
cd1dcd2c95 [InstCombine] Handle const select arm in foldSelectCtlzToCttz()
The select arm that takes the ctlz result can also instead be a
constant with the bit width (as this is what the ctlz evaluates to
for a==0).

This avoids a regression when strengthening the
simplifyWithOpReplaced() fold.

Proof: https://alive2.llvm.org/ce/z/DMRL5A
2023-07-14 12:00:39 +02:00
Matt Arsenault
0f4eb557e8 ValueTracking: Replace CannotBeNegativeZero
This is now just a wrapper around computeKnownFPClass.
2023-07-12 13:14:05 -04:00
Peixin Qiao
ab73bd3897 [InstCombine] Enhance select icmp and folding
This folds (a << k) ? 2^k * a : 0 to 2^k * a.

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

Fix #62155.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D148420
2023-07-12 22:39:45 +08:00
Nikita Popov
336d7281ad [InstCombine] Preserve inbounds when folding select of GEP
The select base, (gep base, offset) to gep base, select (0, offset)
fold used to drop inbounds, because the gep base, 0 this introduces
might not be inbounds. After the semantics change in D154051, such
a GEP is always considered inbounds, in which allows us to preserve
the flag here.

As the PhaseOrdering test demonstrates, this can result in major
optimization improvements in some cases.

Differential Revision: https://reviews.llvm.org/D154055
2023-07-07 09:56:33 +02:00
Matt Arsenault
17eaa55e9f InstCombine: Fold select of ldexp to ldexp of select
The select-of-different-exp pattern appears in the device
libraries. I haven't seen the select-of-values case.
2023-06-22 14:22:01 -04:00
Nikita Popov
8378f1f4cd [InstCombine] Remove adjustMinMax() fold (PR62088)
This fold is buggy if the constant adjustment overflows.
Additionally, since we now canonicalize to min/max intrinsics,
the constants picked here don't actually matter, as long as SPF
still recognizes the pattern.

Fixes https://github.com/llvm/llvm-project/issues/62088.
2023-05-30 16:06:38 +02:00
Florian Hahn
cd2fc73b49
Revert "[ValueTracking][InstCombine] Add a new API to allow to ignore poison generating flags or metadatas when implying poison"
This reverts commit 754f3ae65518331b7175d7a9b4a124523ebe6eac.

Unfortunately the change can cause regressions due to dropping flags
from instructions (like nuw,nsw,inbounds), prevent further optimizations
depending on those flags.

A simple example is the IR below, where `inbounds` is dropped with the
patch and the phase-ordering test added in 7c91d82ab912fae8b.

    define i1 @test(ptr %base, i64 noundef %len, ptr %p2) {
    bb:
      %gep = getelementptr inbounds i32, ptr %base, i64 %len
      %c.1 = icmp uge ptr %p2, %base
      %c.2 = icmp ult ptr %p2, %gep
      %select = select i1 %c.1, i1 %c.2, i1 false
      ret i1 %select
    }

For more discussion, see D149404.
2023-05-29 15:44:37 +01:00
Nikita Popov
2938f9b46f [InstCombine] Fix worklist management in select value equiv fold (NFCI)
Requeue the modified instruction.

This should be NFC apart from worklist order effects.
2023-05-23 16:37:56 +02:00
luxufan
754f3ae655 [ValueTracking][InstCombine] Add a new API to allow to ignore poison generating flags or metadatas when implying poison
This patch add a new API `impliesPoisonIgnoreFlagsOrMetadatas` which is
the same as `impliesPoison` but ignoring poison generating flags or
metadatas in the process of implying poison and recording these ignored
instructions.

In InstCombineSelect, replacing `impliesPoison` with
`impliesPoisonIgnoreFlagsOrMetadatas` to allow more patterns like
`select i1 %a, i1 %b, i1 false` to be optimized to and/or instructions
by droping the poison generating flags or metadatas.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149404
2023-05-19 14:50:32 +08:00
Nuno Lopes
8a1373d308 Revert "[InstCombine] Generate better code for std::bit_floor from libstdc++"
This reverts commit d775fc390d3c78cc81872e276c4b1314f19af577.

The patch is wrong wrt undef and the author didn't fix it after 2 weeks.
2023-04-30 09:56:34 +01:00
ManuelJBrito
d22edb9794 [IR][NFC] Change UndefMaskElem to PoisonMaskElem
Following the change in shufflevector semantics,
poison will be used to represent undefined elements in shufflevector masks.

Differential Revision: https://reviews.llvm.org/D149256
2023-04-27 18:01:54 +01:00
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