summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2022-01-11 15:51:43 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2022-01-11 16:03:35 +0300
commit76a0abbc13cdfd3ae71f8db8a9376f65a9f6f725 (patch)
treeda663a084bb656ca67c8ca2d6968fb5e881fed19
parente0772cf00f572e73b8508e719402ee2449f99bd1 (diff)
downloadllvm-76a0abbc13cdfd3ae71f8db8a9376f65a9f6f725.tar.gz
[SCEV] Reenable umin_seq support and fix the `computeSCEVAtScope()`
This reverts commit f62f47f5e1f641b41d3b7d593c058ebec2883534.
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp9
-rw-r--r--llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll56
-rw-r--r--llvm/test/Transforms/IndVarSimplify/exit-count-select.ll32
3 files changed, 56 insertions, 41 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 2589b3c4013d..160012b3d79a 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -8254,7 +8254,7 @@ ScalarEvolution::computeExitLimitFromCondFromBinOp(
if (EL0.ExactNotTaken != getCouldNotCompute() &&
EL1.ExactNotTaken != getCouldNotCompute()) {
BECount = getUMinFromMismatchedTypes(EL0.ExactNotTaken, EL1.ExactNotTaken,
- /*Sequential=*/false);
+ /*Sequential=*/!PoisonSafe);
// If EL0.ExactNotTaken was zero and ExitCond was a short-circuit form,
// it should have been simplified to zero (see the condition (3) above)
@@ -9185,7 +9185,8 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
return V;
}
- if (const SCEVCommutativeExpr *Comm = dyn_cast<SCEVCommutativeExpr>(V)) {
+ if (isa<SCEVCommutativeExpr>(V) || isa<SCEVSequentialMinMaxExpr>(V)) {
+ const auto *Comm = cast<SCEVNAryExpr>(V);
// Avoid performing the look-up in the common case where the specified
// expression has no loop-variant portions.
for (unsigned i = 0, e = Comm->getNumOperands(); i != e; ++i) {
@@ -9207,7 +9208,9 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
return getMulExpr(NewOps, Comm->getNoWrapFlags());
if (isa<SCEVMinMaxExpr>(Comm))
return getMinMaxExpr(Comm->getSCEVType(), NewOps);
- llvm_unreachable("Unknown commutative SCEV type!");
+ if (isa<SCEVSequentialMinMaxExpr>(Comm))
+ return getSequentialMinMaxExpr(Comm->getSCEVType(), NewOps);
+ llvm_unreachable("Unknown commutative / sequential min/max SCEV type!");
}
}
// If we got here, all operands are loop invariant.
diff --git a/llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll b/llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll
index 02b607a305d0..5bcfaf952ed0 100644
--- a/llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll
+++ b/llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll
@@ -5,15 +5,15 @@ define i32 @logical_and_2ops(i32 %n, i32 %m) {
; CHECK-LABEL: 'logical_and_2ops'
; CHECK-NEXT: Classifying expressions for: @logical_and_2ops
; CHECK-NEXT: %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
-; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin %m) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin_seq %m) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %i.next = add i32 %i, 1
-; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin %m)) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin_seq %m)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_2ops
-; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin %m)
+; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin_seq %m)
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
-; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin %m)
+; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin_seq %m)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
@@ -34,15 +34,15 @@ define i32 @logical_or_2ops(i32 %n, i32 %m) {
; CHECK-LABEL: 'logical_or_2ops'
; CHECK-NEXT: Classifying expressions for: @logical_or_2ops
; CHECK-NEXT: %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
-; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin %m) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin_seq %m) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %i.next = add i32 %i, 1
-; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin %m)) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin_seq %m)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 true, i1 %cond_p1
; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_or_2ops
-; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin %m)
+; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin_seq %m)
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
-; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin %m)
+; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin_seq %m)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
@@ -63,17 +63,17 @@ define i32 @logical_and_3ops(i32 %n, i32 %m, i32 %k) {
; CHECK-LABEL: 'logical_and_3ops'
; CHECK-NEXT: Classifying expressions for: @logical_and_3ops
; CHECK-NEXT: %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
-; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin %m umin %k) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin_seq %m umin_seq %k) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %i.next = add i32 %i, 1
-; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin %m umin %k)) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin_seq %m umin_seq %k)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond_p3 = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> %cond_p3 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %cond = select i1 %cond_p3, i1 %cond_p2, i1 false
; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_3ops
-; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin %m umin %k)
+; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin_seq %m umin_seq %k)
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
-; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin %m umin %k)
+; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin_seq %m umin_seq %k)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
@@ -96,17 +96,17 @@ define i32 @logical_or_3ops(i32 %n, i32 %m, i32 %k) {
; CHECK-LABEL: 'logical_or_3ops'
; CHECK-NEXT: Classifying expressions for: @logical_or_3ops
; CHECK-NEXT: %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
-; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin %m umin %k) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin_seq %m umin_seq %k) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %i.next = add i32 %i, 1
-; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin %m umin %k)) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin_seq %m umin_seq %k)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond_p3 = select i1 %cond_p0, i1 true, i1 %cond_p1
; CHECK-NEXT: --> %cond_p3 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %cond = select i1 %cond_p3, i1 true, i1 %cond_p2
; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_or_3ops
-; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin %m umin %k)
+; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin_seq %m umin_seq %k)
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
-; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin %m umin %k)
+; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin_seq %m umin_seq %k)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
@@ -129,28 +129,28 @@ define i32 @computeSCEVAtScope(i32 %d.0) {
; CHECK-LABEL: 'computeSCEVAtScope'
; CHECK-NEXT: Classifying expressions for: @computeSCEVAtScope
; CHECK-NEXT: %d.1 = phi i32 [ %inc, %for.body ], [ %d.0, %for.cond.preheader ]
-; CHECK-NEXT: --> {%d.0,+,1}<nsw><%for.cond> U: full-set S: full-set Exits: 0 LoopDispositions: { %for.cond: Computable, %while.cond: Variant }
+; CHECK-NEXT: --> {%d.0,+,1}<nsw><%for.cond> U: full-set S: full-set Exits: (((-1 * %d.0) umin_seq (-1 * %d.0)) + %d.0) LoopDispositions: { %for.cond: Computable, %while.cond: Variant }
; CHECK-NEXT: %e.1 = phi i32 [ %inc3, %for.body ], [ %d.0, %for.cond.preheader ]
-; CHECK-NEXT: --> {%d.0,+,1}<nsw><%for.cond> U: full-set S: full-set Exits: 0 LoopDispositions: { %for.cond: Computable, %while.cond: Variant }
+; CHECK-NEXT: --> {%d.0,+,1}<nsw><%for.cond> U: full-set S: full-set Exits: (((-1 * %d.0) umin_seq (-1 * %d.0)) + %d.0) LoopDispositions: { %for.cond: Computable, %while.cond: Variant }
; CHECK-NEXT: %0 = select i1 %tobool1, i1 %tobool2, i1 false
-; CHECK-NEXT: --> %0 U: full-set S: full-set Exits: false LoopDispositions: { %for.cond: Variant, %while.cond: Variant }
+; CHECK-NEXT: --> %0 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant, %while.cond: Variant }
; CHECK-NEXT: %inc = add nsw i32 %d.1, 1
-; CHECK-NEXT: --> {(1 + %d.0),+,1}<nw><%for.cond> U: full-set S: full-set Exits: 1 LoopDispositions: { %for.cond: Computable, %while.cond: Variant }
+; CHECK-NEXT: --> {(1 + %d.0),+,1}<nw><%for.cond> U: full-set S: full-set Exits: (1 + ((-1 * %d.0) umin_seq (-1 * %d.0)) + %d.0) LoopDispositions: { %for.cond: Computable, %while.cond: Variant }
; CHECK-NEXT: %inc3 = add nsw i32 %e.1, 1
-; CHECK-NEXT: --> {(1 + %d.0),+,1}<nw><%for.cond> U: full-set S: full-set Exits: 1 LoopDispositions: { %for.cond: Computable, %while.cond: Variant }
+; CHECK-NEXT: --> {(1 + %d.0),+,1}<nw><%for.cond> U: full-set S: full-set Exits: (1 + ((-1 * %d.0) umin_seq (-1 * %d.0)) + %d.0) LoopDispositions: { %for.cond: Computable, %while.cond: Variant }
; CHECK-NEXT: %f.1 = phi i32 [ %inc8, %for.body5 ], [ 0, %for.cond4.preheader ]
-; CHECK-NEXT: --> {0,+,1}<%for.cond4> U: [0,1) S: [0,1) Exits: 0 LoopDispositions: { %for.cond4: Computable, %while.cond: Variant }
+; CHECK-NEXT: --> {0,+,1}<%for.cond4> U: full-set S: full-set Exits: (((-1 * %d.0) umin_seq (-1 * %d.0)) + %d.0) LoopDispositions: { %for.cond4: Computable, %while.cond: Variant }
; CHECK-NEXT: %inc8 = add i32 %f.1, 1
-; CHECK-NEXT: --> {1,+,1}<%for.cond4> U: [1,2) S: [1,2) Exits: 1 LoopDispositions: { %for.cond4: Computable, %while.cond: Variant }
+; CHECK-NEXT: --> {1,+,1}<%for.cond4> U: full-set S: full-set Exits: (1 + ((-1 * %d.0) umin_seq (-1 * %d.0)) + %d.0) LoopDispositions: { %for.cond4: Computable, %while.cond: Variant }
; CHECK-NEXT: Determining loop execution counts for: @computeSCEVAtScope
-; CHECK-NEXT: Loop %for.cond: backedge-taken count is (-1 * %d.0)
+; CHECK-NEXT: Loop %for.cond: backedge-taken count is ((-1 * %d.0) umin_seq (-1 * %d.0))
; CHECK-NEXT: Loop %for.cond: max backedge-taken count is -1
-; CHECK-NEXT: Loop %for.cond: Predicated backedge-taken count is (-1 * %d.0)
+; CHECK-NEXT: Loop %for.cond: Predicated backedge-taken count is ((-1 * %d.0) umin_seq (-1 * %d.0))
; CHECK-NEXT: Predicates:
; CHECK: Loop %for.cond: Trip multiple is 1
-; CHECK-NEXT: Loop %for.cond4: backedge-taken count is 0
-; CHECK-NEXT: Loop %for.cond4: max backedge-taken count is 0
-; CHECK-NEXT: Loop %for.cond4: Predicated backedge-taken count is 0
+; CHECK-NEXT: Loop %for.cond4: backedge-taken count is (((-1 * %d.0) umin_seq (-1 * %d.0)) + %d.0)
+; CHECK-NEXT: Loop %for.cond4: max backedge-taken count is -1
+; CHECK-NEXT: Loop %for.cond4: Predicated backedge-taken count is (((-1 * %d.0) umin_seq (-1 * %d.0)) + %d.0)
; CHECK-NEXT: Predicates:
; CHECK: Loop %for.cond4: Trip multiple is 1
; CHECK-NEXT: Loop %while.cond: <multiple exits> Unpredictable backedge-taken count.
diff --git a/llvm/test/Transforms/IndVarSimplify/exit-count-select.ll b/llvm/test/Transforms/IndVarSimplify/exit-count-select.ll
index 8e6eaceaade4..3ebafd1ef8b1 100644
--- a/llvm/test/Transforms/IndVarSimplify/exit-count-select.ll
+++ b/llvm/test/Transforms/IndVarSimplify/exit-count-select.ll
@@ -4,12 +4,14 @@
define i32 @logical_and_2ops(i32 %n, i32 %m) {
; CHECK-LABEL: @logical_and_2ops(
; CHECK-NEXT: entry:
+; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[M:%.*]], i32 [[N:%.*]])
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
-; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[M:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT: ret i32 [[UMIN]]
+; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[N]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i32 0, i32 [[UMIN]]
+; CHECK-NEXT: ret i32 [[TMP1]]
;
entry:
br label %loop
@@ -27,12 +29,14 @@ exit:
define i32 @logical_or_2ops(i32 %n, i32 %m) {
; CHECK-LABEL: @logical_or_2ops(
; CHECK-NEXT: entry:
+; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[M:%.*]], i32 [[N:%.*]])
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
-; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[M:%.*]], i32 [[N:%.*]])
-; CHECK-NEXT: ret i32 [[UMIN]]
+; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[N]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i32 0, i32 [[UMIN]]
+; CHECK-NEXT: ret i32 [[TMP1]]
;
entry:
br label %loop
@@ -50,13 +54,17 @@ exit:
define i32 @logical_and_3ops(i32 %n, i32 %m, i32 %k) {
; CHECK-LABEL: @logical_and_3ops(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[K:%.*]], i32 [[M:%.*]])
+; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[M:%.*]], 0
+; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[K:%.*]], i32 [[M]])
+; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[N:%.*]])
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
-; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[N:%.*]])
-; CHECK-NEXT: ret i32 [[UMIN1]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[N]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[TMP0]]
+; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 0, i32 [[UMIN1]]
+; CHECK-NEXT: ret i32 [[TMP3]]
;
entry:
br label %loop
@@ -76,13 +84,17 @@ exit:
define i32 @logical_or_3ops(i32 %n, i32 %m, i32 %k) {
; CHECK-LABEL: @logical_or_3ops(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[K:%.*]], i32 [[M:%.*]])
+; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[M:%.*]], 0
+; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[K:%.*]], i32 [[M]])
+; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[N:%.*]])
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
-; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[N:%.*]])
-; CHECK-NEXT: ret i32 [[UMIN1]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[N]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[TMP0]]
+; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 0, i32 [[UMIN1]]
+; CHECK-NEXT: ret i32 [[TMP3]]
;
entry:
br label %loop