[SCEV] Reenable umin_seq support and fix the `computeSCEVAtScope()`

This reverts commit f62f47f5e1.
This commit is contained in:
Roman Lebedev 2022-01-11 15:51:43 +03:00
parent e0772cf00f
commit 76a0abbc13
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
3 changed files with 56 additions and 41 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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