From 76a0abbc13cdfd3ae71f8db8a9376f65a9f6f725 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Tue, 11 Jan 2022 15:51:43 +0300 Subject: [SCEV] Reenable umin_seq support and fix the `computeSCEVAtScope()` This reverts commit f62f47f5e1f641b41d3b7d593c058ebec2883534. --- llvm/lib/Analysis/ScalarEvolution.cpp | 9 ++-- .../ScalarEvolution/exit-count-select-safe.ll | 56 +++++++++++----------- .../Transforms/IndVarSimplify/exit-count-select.ll | 32 +++++++++---- 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(V)) { + if (isa(V) || isa(V)) { + const auto *Comm = cast(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(Comm)) return getMinMaxExpr(Comm->getSCEVType(), NewOps); - llvm_unreachable("Unknown commutative SCEV type!"); + if (isa(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: <> 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: <> 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: <> 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: <> 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: <> 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: <> 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}<%for.cond> U: full-set S: full-set Exits: 0 LoopDispositions: { %for.cond: Computable, %while.cond: Variant } +; CHECK-NEXT: --> {%d.0,+,1}<%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}<%for.cond> U: full-set S: full-set Exits: 0 LoopDispositions: { %for.cond: Computable, %while.cond: Variant } +; CHECK-NEXT: --> {%d.0,+,1}<%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: <> LoopDispositions: { %for.cond: Variant, %while.cond: Variant } ; CHECK-NEXT: %inc = add nsw i32 %d.1, 1 -; CHECK-NEXT: --> {(1 + %d.0),+,1}<%for.cond> U: full-set S: full-set Exits: 1 LoopDispositions: { %for.cond: Computable, %while.cond: Variant } +; CHECK-NEXT: --> {(1 + %d.0),+,1}<%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}<%for.cond> U: full-set S: full-set Exits: 1 LoopDispositions: { %for.cond: Computable, %while.cond: Variant } +; CHECK-NEXT: --> {(1 + %d.0),+,1}<%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: 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 -- cgit v1.2.1