228 Commits

Author SHA1 Message Date
Noah Goldstein
dd48a9b056 [ValueTracking] Handle conflicts when computing knownbits of PHI nodes in deadcode; PR65022
Bug was introduced in: https://reviews.llvm.org/D157807

The prior logic assumed that the information from the knownbits
returned from analyzing the `icmp` and its operands in the context
basicblock would be consistent.

This is not necessarily the case if we are analyzing deadcode.

For example with `(icmp sgt (select cond, 0, 1), -1)`. If we take
knownbits for the `select` using knownbits from the operator, we will
know the signbit is zero. If we are analyzing a not-taken from based
on the `icmp` (deadcode), we will also "know" that the `select` must
be negative (signbit is one). This will result in a conflict in
knownbits.

The fix is to just give up on analying the phi-node if its deadcode. We 1) don't want to waste time continuing to analyze it and 2) will be removing it (and its dependencies) later.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D158960
2023-09-01 02:11:50 -05:00
Noah Goldstein
846ff921ff [ValueTracking] Compute sdiv as non-zero if abs(num) u>= abs(denum)
Just covering an additional case.

Proof: https://alive2.llvm.org/ce/z/MJz9fT

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D157302
2023-08-24 19:43:10 -05:00
Noah Goldstein
d0b4ed9a2c [ValueTracking] Add tests for knowing sdiv is non-zero; NFC
Differential Revision: https://reviews.llvm.org/D157301
2023-08-24 19:43:10 -05:00
Noah Goldstein
7c9fe735d4 [ValueTracking] Strengthen analysis in computeKnownBits of phi
Use the comparison based analysis to strengthen the standard
knownbits analysis rather than choosing either/or.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D157807
2023-08-22 10:59:03 -05:00
Noah Goldstein
39e9862e6b [ValueTracking] Use predicates for incoming phi-edges to deduce non-zero
This is basically a copy and paste of the same logic we do in
`computeKnownBits` but adapts it for just `isKnownNonZero`.

Differential Revision: https://reviews.llvm.org/D157801
2023-08-22 10:59:02 -05:00
Noah Goldstein
61df774ab7 [ValueTracking] Improve analysis of knownbits from incoming phi edges.
Just fill in missing cases (TODO) for `ugt`, `uge`, `sgt`, `sge`,
`slt`, and `sle`. These are all in the same spirit as `ult`/`uge`, but
each of the other conditions have different constraints.

Proofs: https://alive2.llvm.org/ce/z/gnj4o-

Differential Revision: https://reviews.llvm.org/D157800
2023-08-22 10:59:02 -05:00
Noah Goldstein
fb92c0700b [ValueTracking] Add tests for deducing non-zero based for incoming phi-edges; NFC
Differential Revision: https://reviews.llvm.org/D157798
2023-08-22 10:59:02 -05:00
Noah Goldstein
35d916e11b [ValueTracking] Add tests for getting knownbits from phi-edges; NFC
Differential Revision: https://reviews.llvm.org/D157797
2023-08-22 10:59:02 -05:00
Nikita Popov
69bd66b3ce [Tests] Remove some and/or constant expressions in tests (NFC)
In preparation for their removal in D158081.
2023-08-21 12:05:32 +02:00
Dhruv Chawla
d53b3df570
[InstCombine] Remove unneeded isa<PHINode> check in foldOpIntoPhi
This check is redundant as it is covered by the call to
isPotentiallyReachable.

Depends on D155726.

Differential Revision: https://reviews.llvm.org/D155718
2023-08-16 21:09:08 +05:30
Noah Goldstein
fbb40df2bf [ValueTracking] In isKnownToBeAPowerOfTwo an i1 value is always true if OrZero is set
This is trivially true.

Differential Revision: https://reviews.llvm.org/D157310
2023-08-09 14:42:55 -05:00
Noah Goldstein
dff3d8a279 [ValueTracking] Add support for mul in isKnownToBeAPowerOfTwo
pow2 * pow2 is a power of 2 or zero.

Proof: https://alive2.llvm.org/ce/z/FNiiXd

Differential Revision: https://reviews.llvm.org/D157308
2023-08-09 14:42:55 -05:00
Noah Goldstein
4f818daca6 [ValueTracking] Add support for fshl/fshr in isKnownToBeAPowerOfTwo
If the funnel shifts are rotates (op0 == op1) then the number of 1s/0s
don't change so we can just look through op0/op1.

Proofs: https://alive2.llvm.org/ce/z/Pja5yu

Differential Revision: https://reviews.llvm.org/D157307
2023-08-09 14:42:55 -05:00
Noah Goldstein
6f4d660d7f [ValueTracking] Add support for bswap and bitreverse in isKnownToBeAPowerOfTwo
Both of these intrinsics don't change the number of 1s/0s so we can
look directly through them.

Proofs: https://alive2.llvm.org/ce/z/gnZuwC

Differential Revision: https://reviews.llvm.org/D157306
2023-08-09 14:42:55 -05:00
Noah Goldstein
bab8058d3b [ValueTracking] If OrZero is set, look through trunc in isKnownToBePowerOfTwo
Just move coverage.

Proof: https://alive2.llvm.org/ce/z/H37tVX

Differential Revision: https://reviews.llvm.org/D157304
2023-08-09 14:42:54 -05:00
Noah Goldstein
0690817bcc [ValueTracking] Add tests for more isKnownToBeAPowerOfTwo cases; NFC
Differential Revision: https://reviews.llvm.org/D157303
2023-08-09 14:42:54 -05:00
Nikita Popov
d01aec4c76 [InstCombine] Set dead phi inputs to poison in more cases
Set phi inputs to poison whenever we find a dead edge (either
during initial worklist population or the main InstCombine run),
instead of only doing this for successors of dead blocks.

This means that the phi operand is set to poison even if for
critical edges without an intermediate block.

There are quite a few test changes, because the pattern is fairly
common in vectorizer output, for cases where we know the vectorized
loop will be entered.
2023-08-01 11:53:47 +02:00
Nikita Popov
41895843b5 [InstCombine] Only perform one iteration
InstCombine is a worklist-driven algorithm, which works roughly
as follows:

* All instructions are initially pushed to the worklist.
  The initial order is in RPO program order.
* All newly inserted instructions get added to the worklist.
* When an instruction is folded, its users get added back to the
  worklist.
* When the use-count of an instruction decreases, it gets added
  back to the worklist.
* And a few of other heuristics on when we should revisit
  instructions.

On top of the worklist algorithm, InstCombine layers an additional
fix-point iteration: If any fold was performed in the previous
iteration, then InstCombine will re-populate the worklist from
scratch and fold the entire function again. This continues until
a fix-point is reached.

In the vast majority of cases, InstCombine will reach a fix-point
within a single iteration: However, a second iteration is performed
to verify that this is indeed the fixpoint. We can see this in the
statistics for llvm-test-suite:

    "instcombine.NumOneIteration": 411380,
    "instcombine.NumTwoIterations": 117921,
    "instcombine.NumThreeIterations": 236,
    "instcombine.NumFourOrMoreIterations": 2,

The way to read these numbers is that in 411380 cases, InstCombine
performs no folds. In 117921 cases it performs a fold and reaches
the fix-point within one iteration (the second iteration verifies
the fixpoint). In the remaining 238 cases, more than one iteration
is needed to reach the fixpoint.

In other words, only in 0.04% of cases are additional iterations
needed to reach a fixpoint. Conversely, in 22.3% of cases InstCombine
performs a completely useless extra iteration to verify the fix point.

This patch removes the fixpoint iteration from InstCombine, and always
only perform a single iteration. This results in a major compile-time
improvement of around 4% at negligible codegen impact.

This explicitly does accept that we will not reach a fixpoint in all
cases. However, this is mitigated by two factors: First, the data
suggests that this happens very rarely in practice. Second,
InstCombine runs many times during the optimization pipeline
(8 times even without LTO), so there are many chances to recover
such cases.

In order to prevent accidental optimization regressions in the
future, this implements a verify-fixpoint option, which is enabled
by default when instcombine is specified in -passes and disabled
when InstCombinePass() is constructed from C++. This means that
test cases need to explicitly use the no-verify-fixpoint option
if they fail to reach a fixed point (for a well understand reason
we cannot / do not want to avoid).

Differential Revision: https://reviews.llvm.org/D154579
2023-07-31 10:56:49 +02:00
Nikita Popov
2e0af16c93 [ValueTracking] Support add+icmp assumes for KnownBits
Support the canonical range check pattern for KnownBits assumptions.
This is the same as the generic ConstantRange handling, just shifted
by an offset.
2023-07-05 16:15:47 +02:00
Nikita Popov
dfb369399d [ValueTracking] Directly use KnownBits shift functions
Make ValueTracking directly call the KnownBits shift helpers, which
provides more precise results.

Unfortunately, ValueTracking has a special case where sometimes we
determine non-zero shift amounts using isKnownNonZero(). I have my
doubts about the usefulness of that special-case (it is only tested
in a single unit test), but I've reproduced the special-case via an
extra parameter to the KnownBits methods.

Differential Revision: https://reviews.llvm.org/D151816
2023-06-01 09:46:16 +02:00
Nikita Popov
a1dec5dacb [ValueTracking] Avoid optimizing away condition in test (NFC)
This is not what we're interested in testing, and it allows to
essentially optimize away the entire function with more powerful
optimization.
2023-05-26 16:38:37 +02:00
Nikita Popov
8f12057e8e [ValueTracking] Avoid UB in test (NFC)
Don't use br undef, as it is UB.
2023-05-26 15:55:20 +02:00
Noah Goldstein
2622b2f409 [ValueTracking] Use select condition to help determine if select is non-zero
In `select c, x, y` the condition `c` dominates the resulting `x` or
`y` chosen by the `select`. This adds logic to `isKnownNonZero` to try
and use the `icmp` for the `c` condition to see if it implies the
select `x` or `y` are known non-zero.

For example in:
    ```
    %c = icmp ugt i8 %x, %C
    %r = select i1 %c, i8 %x, i8 %y
    ```
    The true arm of select `%x` is non-zero (when "returned" by the
    `select`) because `%c` being true implies `%x` is non-zero.

Alive2 Links (with `x {pred} C`):
    - EQ  iff `C != 0`:
        - https://alive2.llvm.org/ce/z/umLabn
    - NE  iff `C == 0`:
        - https://alive2.llvm.org/ce/z/DQvy8Y
    - UGT [always]:
        - https://alive2.llvm.org/ce/z/HBkjgQ
    - UGE iff `C != 0`:
        - https://alive2.llvm.org/ce/z/LDNifB
    - SGT iff `C s>= 0`:
        - https://alive2.llvm.org/ce/z/QzWDj3
    - SGE iff `C s> 0`:
        - https://alive2.llvm.org/ce/z/rR4g3D
    - SLT iff `C s<= 0`:
        - https://alive2.llvm.org/ce/z/uysayx
    - SLE iff `C s< 0`:
        - https://alive2.llvm.org/ce/z/2jYc7e

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D147900
2023-05-23 13:52:40 -05:00
Noah Goldstein
530bbc8f69 [ValueTracking] Add tests for using condition in select for non-zero analysis; NFC
Differential Revision: https://reviews.llvm.org/D147899
2023-05-23 13:52:40 -05:00
Noah Goldstein
8a60814ed5 [ValueTracking] Use KnownBits functions for computeKnownBits of saturating add/sub functions
The knownbits implementation covers all the cases previously handled
by `uadd.sat`/`usub.sat` as well some additional ones. We previously
were not handling the `ssub.sat`/`sadd.sat` cases at all.

Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D150103
2023-05-23 13:52:40 -05:00
Noah Goldstein
1e963b4081 [ValueTracking] Add tests for knownbits of saturating add/sub functions; NFC
Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D150101
2023-05-23 13:52:39 -05:00
Noah Goldstein
4fd3401e76 [KnownBits] Improve implementation of KnownBits::abs
`abs` preserves the lowest set bit, so if we know the lowest set bit,
set it in the output.

As well, implement the case where the operand is known negative.

Reviewed By: foad, RKSimon

Differential Revision: https://reviews.llvm.org/D150100
2023-05-23 13:52:39 -05:00
Noah Goldstein
261e5d0951 [ValueTracking] Add tests for knownbits of abs; NFC
Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D150099
2023-05-16 18:58:13 -05:00
Noah Goldstein
124547eae8 [ValueTracking] Use KnownBits::sdiv for sdiv opcode in computeKnownBits
We now of an implementation of `KnownBits::sdiv` so we can implement
this case.

Differential Revision: https://reviews.llvm.org/D150096
2023-05-16 18:58:12 -05:00
Noah Goldstein
99795afb28 [ValueTracking] Pass exact flag to KnownBits::udiv in computeKnownBits
This information was previously missing but we can use it for
determining the low-bits.

Differential Revision: https://reviews.llvm.org/D150095
2023-05-16 18:58:12 -05:00
Noah Goldstein
7d05ab99ed [KnownBits] Improve KnownBits::udiv
We can more precisely determine the upper bits doing `MaxNum /
MinDenum` as opposed to only using the MSB.

As well, if the `exact` flag is set, we can sometimes determine some
of the low-bits.

Differential Revision: https://reviews.llvm.org/D150094
2023-05-16 18:58:12 -05:00
Noah Goldstein
53a079c8f7 [ValueTracking] Add tests for knownbits of sdiv and udiv; NFC
Differential Revision: https://reviews.llvm.org/D150092
2023-05-16 18:58:12 -05:00
Noah Goldstein
774ecc20e1 [ValueTracking] deduce X * Y != 0 if LowestKnownBit(X) * LowestKnownBit(Y) != 0
For `X * Y`, if there exists a subset of `X` and subset of `Y` s.t `sX * sY != 0`,
then `X * Y != 0`.
    - See first proof: https://alive2.llvm.org/ce/z/28C9CG
    - NB: This is why the previous Odd case works.

In knownbits we could exhaustively hunt for such a subset, but
`LSB(X)` and `LSB(Y)` actually works. If `LSB(X) * LSB(Y) != 0`, then
`X * Y != 0`
    - See proof: https://alive2.llvm.org/ce/z/p5wWid

In `isKnownNonZero` we can use this as if the `LowestKnownOne(X) *
LowestKnownOne(Y) != 0`, then `X * Y != 0`, and we don't need to try
and other subsets.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D150425
2023-05-16 18:58:12 -05:00
Noah Goldstein
7f82f108c2 [ValueTracking] Add tests for deducing X * Y != 0 if LSB(X) * LSB(Y) != 0; NFC
Differential Revision: https://reviews.llvm.org/D150424
2023-05-16 18:58:12 -05:00
Noah Goldstein
7770b0abfd [KnownBits] Improve KnownBits::rem(X, Y) in cases where we can deduce low-bits of output
The first `cttz(Y)` bits in `X` are translated 1-1 in the output.

Alive2 Links:
    https://alive2.llvm.org/ce/z/Qc47p7
    https://alive2.llvm.org/ce/z/19ut5H

Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D149421
2023-05-07 19:11:53 -05:00
Noah Goldstein
7b1f123b15 [KnownBits] Add tests for getting lowbits of rem X, Y; NFC
Reviewed By: foad

Differential Revision: https://reviews.llvm.org/D149420
2023-05-07 19:11:53 -05:00
Noah Goldstein
5eedfff695 [ValueTracking] Add additional cases for isKnownNonZero(mul X, Y)
If either `X` or `Y` is odd and the other is non-zero, the result is
non-zero.

Alive2 Link:
    https://alive2.llvm.org/ce/z/9V7-es

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149418
2023-04-30 10:06:46 -05:00
Noah Goldstein
d840391401 [ValueTracking] Add logic for isKnownNonZero(smin/smax X, Y)
For `smin` if either `X` or `Y` is negative, the result is non-zero.
For `smax` if either `X` or `Y` is strictly positive, the result is
non-zero.

For both if `X != 0` and `Y != 0` the result is non-zero.

Alive2 Link:
    https://alive2.llvm.org/ce/z/7yvbgN
    https://alive2.llvm.org/ce/z/zizbvq

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149417
2023-04-30 10:06:46 -05:00
Noah Goldstein
e78c30a10f [ValueTracking] Add logic for isKnownNonZero(umin X, Y)
`(umin X, Y) != 0` -> `X != 0 && Y != 0`

Alive2 Link:
    https://alive2.llvm.org/ce/z/AQh67i

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149416
2023-04-30 10:06:46 -05:00
Noah Goldstein
883daa7ac4 [ValueTracking] Add logic for isKnownNonZero(umax X, Y)
`(umax X, Y) != 0` -> `X != 0 || Y != 0`

Alive2 Link:
    https://alive2.llvm.org/ce/z/_Z9AUT

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149415
2023-04-30 10:06:46 -05:00
Noah Goldstein
167ecdaa2c [ValueTracking] Add logic for isKnownNonZero(sadd.sat X, Y)
The logic here is the same for `add` so reuse the existing helper
`isNonZeroAdd`

Alive2 Link:
    https://alive2.llvm.org/ce/z/mhKvC5

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149414
2023-04-30 10:06:46 -05:00
Noah Goldstein
461ded4631 [ValueTracking] Add logic for isKnownNonZero(ssub.sat X, Y)
The logic here is the same for normal `(sub X, Y)`, so just reused
`isNonZeroSub`.

Alive2 Link:
    https://alive2.llvm.org/ce/z/9kSkMv

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149412
2023-04-30 10:06:45 -05:00
Noah Goldstein
f1dfa4938a [ValueTracking] Add logic for isKnownNonZero(sshl.sat/ushl.sat X, Y)
`(sshl/ushl X, Y) != 0` -> `X != 0`

Alive2 Links
    https://alive2.llvm.org/ce/z/4WLM2p
    https://alive2.llvm.org/ce/z/BHFng4

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149411
2023-04-30 10:06:45 -05:00
Noah Goldstein
ea5a0d4b90 [ValueTracking] Add logic for isKnownNonZero(ctlz/cttz X)
for `cttz` if `X[0]` is non-zero, then the expression is non-zero.
for `ctlz` if `X[SignBit]` is non-zero, then the expression in
non-zero.

Alive2 Links:
    cttz (false): https://alive2.llvm.org/ce/z/ySQzbg
    cttz (true): https://alive2.llvm.org/ce/z/auiTCJ
    ctlz (false): https://alive2.llvm.org/ce/z/yk3sTJ
    ctlz (true): https://alive2.llvm.org/ce/z/-JuDty

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149410
2023-04-30 10:06:45 -05:00
Noah Goldstein
c7f7f601f2 [ValueTracking] Handle bitcasts between vec-int-ptr in isKnownNonZero
We where missing these cases so something like:
`(bitcast to i32 (or v216 x, <2, 1>))`

would not be found to be non-zero.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149409
2023-04-30 10:06:45 -05:00
Noah Goldstein
f7bf984ed3 [ValueTracking] Add more tests for isKnownNonZero cases; NFC
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149408
2023-04-30 10:06:45 -05:00
Noah Goldstein
4cd1b67491 [ValueTracking] Add logic for fshl/fshr(A, B, C) != 0 if A == B && A ! = 0
Having `A == B` is quite common for rotate patterns.

Alive2 Links:
    - https://alive2.llvm.org/ce/z/mPXi9c
    - https://alive2.llvm.org/ce/z/UfDHoI

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149372
2023-04-28 01:57:37 -05:00
Noah Goldstein
74157bf6e2 [ValueTracking] Add tests for proving fshr/fshl is non-zero; NFC
Differential Revision: https://reviews.llvm.org/D149371
2023-04-28 01:57:31 -05:00
Noah Goldstein
d8e9dd33b2 [ValueTracking] Add logic for udiv x,y != 0 if y u<= x
Alive2 Link:
        https://alive2.llvm.org/ce/z/2DKh46

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149203
2023-04-27 13:48:41 -05:00
Noah Goldstein
75b48b4077 [ValueTracking] Add logic for add nuw x,y != 0 -> x != 0 || y != 0
Alive2 Link:
    https://alive2.llvm.org/ce/z/TKpqxc

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149204
2023-04-26 23:48:20 -05:00