Commit Graph

25 Commits

Author SHA1 Message Date
Nikita Popov 68e1ba8188 [SCEV] Fold umin_seq using known predicate
Fold %x umin_seq %y to %x if %x ule %y. This also subsumes the
special handling for constant operands, as if %y is constant this
folds to umin via implied poison reasoning, and if %x is constant
then either %x is not zero and it folds to umin, or it is known
zero, in which case it is ule anything.
2022-05-09 16:35:08 +02:00
Nikita Popov 7dddf12f44 [SCEV] Add more tests for umin_seq with known predicate (NFC) 2022-05-09 16:18:09 +02:00
Nikita Popov 18eaff1510 [ScalarEvolution] Fold %x umin_seq %y if %x cannot be zero
Fold %x umin_seq %y to %x umin %y if %x cannot be zero. They only
differ in semantics for %x==0.

More generally %x *_seq %y folds to %x * %y if %x cannot be the
saturation fold (though currently we only have umin_seq).
2022-05-09 15:11:05 +02:00
Nikita Popov 33f02de5df [ScalarEvolution] Add tests for umin_seq with non-zero operand (NFC) 2022-05-09 15:03:12 +02:00
Nikita Popov 47c559d6c1 [SCEV] Fold umin_seq to umin using implied poison reasoning
Similar to how we convert logical and/or to bitwise and/or, we should
also convert umin_seq to umin based on implied poison reasoning. In
%x umin_seq %y, if %y being poison implies %x being poison, then we
don't need the sequential evaluation: Having %y contribute towards
the result will never make the result more poisonous. An important
corollary of this is that if %y is never poison, we also don't need
the sequential evaluation.

This avoids some of the regressions in D124910.

Differential Revision: https://reviews.llvm.org/D124921
2022-05-05 09:43:49 +02:00
Nikita Popov 2f64a6cf9c [SCEV] Add additional poison implication tests (NFC) 2022-05-04 15:23:39 +02:00
Nikita Popov b62e9f63bb [SCEV] Add poison implication tests for umin_seq (NFC) 2022-05-04 14:47:46 +02:00
Roman Lebedev 49d9acc242
[SCEV] Recognize logical `or` as `not umin_seq (not, not)`
By definition, `umin_seq` has the exact same
poison stopping properties the original `select` had:
https://alive2.llvm.org/ce/z/MUfbTL
2022-02-10 17:42:55 +03:00
Roman Lebedev 16bc24e7be
[SCEV] Recognize logical `and` as `umin_seq`
By definition, `umin_seq` has the exact same
poison stopping properties the original `select` had:
https://alive2.llvm.org/ce/z/59KuZZ
2022-02-10 17:42:55 +03:00
Roman Lebedev 8dcba20674
[SCEV] `getSequentialMinMaxExpr()`: relax 2-op umin_seq w/ constant to umin
Currently, `computeExitLimitFromCondFromBinOp()` does that directly.
2022-01-14 17:07:48 +03:00
Roman Lebedev f34742d7c1
[NFC][SCEV] Add test with umin_seq w/ 1op and constant 2022-01-14 17:07:48 +03:00
Roman Lebedev c86a982d7d
[SCEV] `getSequentialMinMaxExpr()`: rewrite deduplication to be fully recursive
Since we don't merge/expand non-sequential umin exprs into umin_seq exprs,
we may have umin_seq(umin(umin_seq())) chain, and the innermost umin_seq
can have duplicate operands still.
2022-01-14 15:42:26 +03:00
Roman Lebedev 2c0c619541
[NFC][SCEV] Add test where it's the innermost umin_seq that has a duplicate operand 2022-01-14 01:15:45 +03:00
Roman Lebedev 993792bd1a
[SCEV] Don't consider umin_seq scev expr to be more complex that ptrtoint scev expr
Let's consider sequential min/max expression family
to be more complex than their non-sequential counterparts,
preserving internal ordering within them.
2022-01-13 23:59:47 +03:00
Roman Lebedev f14b575194
[NFC][SCEV] Add test for umin_seq complexity ordering 2022-01-13 23:59:47 +03:00
Roman Lebedev 5ceb070bbb
[SCEV] `getSequentialMinMaxExpr()`: look into `umin` when deduplicating operands
We could just merge all umin into umin_seq, but that is likely
a pessimization, so don't do that, but pretend that we did
for the purpose of deduplication.
2022-01-11 18:51:57 +03:00
Roman Lebedev b2be7dcf5b
[NFC][SCEV] More tests with operand-wise redundant operands of umin of umin_seq 2022-01-11 18:51:56 +03:00
Roman Lebedev 138d5c750b
[NFC][SCEV] Add more tests for umin_seq with redundant operands 2022-01-11 17:51:51 +03:00
Roman Lebedev 5e16650792
[SCEV] `getSequentialMinMaxExpr()`: keep only the first instance of an operand
Having the same operand more than once doesn't change the outcome here,
neither reduction-wise nor poison-wise.
We must keep the first instance specifically though.
2022-01-11 16:51:53 +03:00
Roman Lebedev 36075942f9
[SCEV] Add test for umin_seq with duplicate operands 2022-01-11 16:51:52 +03:00
Roman Lebedev 76a0abbc13
[SCEV] Reenable umin_seq support and fix the `computeSCEVAtScope()`
This reverts commit f62f47f5e1.
2022-01-11 16:03:35 +03:00
Roman Lebedev e0772cf00f
[NFC][SCEV] Add reproducers for umin_seq crashes
As reported in https://reviews.llvm.org/D116766#3233042
2022-01-11 16:03:35 +03:00
Philip Reames f62f47f5e1 Partial revert of 82fb4f4
Two crashes have been reported.  This change disables the new logic while leaving the new node in tree.  Hopefully, that's enough to allow investigation without breakage while avoiding massive churn.
2022-01-10 18:18:34 -08:00
Roman Lebedev 82fb4f4b22
[SCEV] Sequential/in-order `UMin` expression
As discussed in https://github.com/llvm/llvm-project/issues/53020 / https://reviews.llvm.org/D116692,
SCEV is forbidden from reasoning about 'backedge taken count'
if the branch condition is a poison-safe logical operation,
which is conservatively correct, but is severely limiting.

Instead, we should have a way to express those
poison blocking properties in SCEV expressions.

The proposed semantics is:
```
Sequential/in-order min/max SCEV expressions are non-commutative variants
of commutative min/max SCEV expressions. If none of their operands
are poison, then they are functionally equivalent, otherwise,
if the operand that represents the saturation point* of given expression,
comes before the first poison operand, then the whole expression is not poison,
but is said saturation point.
```
* saturation point - the maximal/minimal possible integer value for the given type

The lowering is straight-forward:
```
compare each operand to the saturation point,
perform sequential in-order logical-or (poison-safe!) ordered reduction
over those checks, and if reduction returned true then return
saturation point else return the naive min/max reduction over the operands
```
https://alive2.llvm.org/ce/z/Q7jxvH (2 ops)
https://alive2.llvm.org/ce/z/QCRrhk (3 ops)
Note that we don't need to check the last operand: https://alive2.llvm.org/ce/z/abvHQS
Note that this is not commutative: https://alive2.llvm.org/ce/z/FK9e97

That allows us to handle the patterns in question.

Reviewed By: nikic, reames

Differential Revision: https://reviews.llvm.org/D116766
2022-01-10 20:51:26 +03:00
Roman Lebedev 6a563e2570
[NFC][SCEV][IndVars] Add more tests for exit count w/ `select`
See https://github.com/llvm/llvm-project/issues/53020
2022-01-07 01:30:21 +03:00