[llvm] 16bc24e - [SCEV] Recognize logical `and` as `umin_seq`
Roman Lebedev via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 10 06:47:08 PST 2022
Author: Roman Lebedev
Date: 2022-02-10T17:42:55+03:00
New Revision: 16bc24e7be90f32056a1915d8c57adf1478384e0
URL: https://github.com/llvm/llvm-project/commit/16bc24e7be90f32056a1915d8c57adf1478384e0
DIFF: https://github.com/llvm/llvm-project/commit/16bc24e7be90f32056a1915d8c57adf1478384e0.diff
LOG: [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
Added:
Modified:
llvm/include/llvm/Analysis/ScalarEvolution.h
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll
llvm/test/Analysis/ScalarEvolution/exit-count-select.ll
llvm/test/Analysis/ScalarEvolution/logical-operations.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 6ff1a5081761..f27019bcbf20 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -1627,6 +1627,11 @@ class ScalarEvolution {
Value *TrueVal,
Value *FalseVal);
+ /// See if we can model this select-like instruction via umin_seq expression.
+ const SCEV *createNodeForSelectOrPHIViaUMinSeq(Value *I, Value *Cond,
+ Value *TrueVal,
+ Value *FalseVal);
+
/// Given a value \p V, which is a select-like instruction (currently this is
/// either a select instruction or a phi node), which is assumed equivalent to
/// Cond ? TrueVal : FalseVal
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 358ec952ab24..54d9f2520024 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -5986,6 +5986,23 @@ const SCEV *ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(
return getUnknown(I);
}
+const SCEV *ScalarEvolution::createNodeForSelectOrPHIViaUMinSeq(
+ Value *V, Value *Cond, Value *TrueVal, Value *FalseVal) {
+ // For now, only deal with i1-typed `select`s.
+ if (!V->getType()->isIntegerTy(1) || !Cond->getType()->isIntegerTy(1) ||
+ !TrueVal->getType()->isIntegerTy(1) ||
+ !FalseVal->getType()->isIntegerTy(1))
+ return getUnknown(V);
+
+ // i1 cond ? i1 x : i1 0 --> umin_seq cond, x
+ if (auto *FalseConst = dyn_cast<ConstantInt>(FalseVal)) {
+ if (FalseConst->isZero())
+ return getUMinExpr(getSCEV(Cond), getSCEV(TrueVal), /*Sequential=*/true);
+ }
+
+ return getUnknown(V);
+}
+
const SCEV *ScalarEvolution::createNodeForSelectOrPHI(Value *V, Value *Cond,
Value *TrueVal,
Value *FalseVal) {
@@ -6003,7 +6020,7 @@ const SCEV *ScalarEvolution::createNodeForSelectOrPHI(Value *V, Value *Cond,
}
}
- return getUnknown(V);
+ return createNodeForSelectOrPHIViaUMinSeq(V, Cond, TrueVal, FalseVal);
}
/// Expand GEP instructions into add and multiply operations. This allows them
diff --git a/llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll b/llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll
index 3b25bb94b712..0962fb53d424 100644
--- a/llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll
+++ b/llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll
@@ -9,7 +9,7 @@ define i32 @logical_and_2ops(i32 %n, i32 %m) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; 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: --> (%cond_p0 umin_seq %cond_p1) 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_seq %m)
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
@@ -67,9 +67,9 @@ define i32 @logical_and_3ops(i32 %n, i32 %m, i32 %k) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; 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_p0 umin_seq %cond_p1) 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: --> (%cond_p0 umin_seq %cond_p1 umin_seq %cond_p2) 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_seq %m umin_seq %k)
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
@@ -450,7 +450,7 @@ define i32 @computeSCEVAtScope(i32 %d.0) {
; 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: %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: --> (%tobool1 umin_seq %tobool2) U: full-set S: full-set Exits: false 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: %inc3 = add nsw i32 %e.1, 1
@@ -520,7 +520,7 @@ define i64 @uminseq_vs_ptrtoint_complexity(i64 %n, i64 %m, i64* %ptr) {
; CHECK-NEXT: %i.next = add i64 %i, 1
; 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: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %ptr.int = ptrtoint i64* %ptr to i64
; CHECK-NEXT: --> (ptrtoint i64* %ptr to i64) U: full-set S: full-set
; CHECK-NEXT: %r = add i64 %i, %ptr.int
diff --git a/llvm/test/Analysis/ScalarEvolution/exit-count-select.ll b/llvm/test/Analysis/ScalarEvolution/exit-count-select.ll
index e20bc21d7f67..ba8a75ac4750 100644
--- a/llvm/test/Analysis/ScalarEvolution/exit-count-select.ll
+++ b/llvm/test/Analysis/ScalarEvolution/exit-count-select.ll
@@ -11,7 +11,7 @@ define void @logical_and_m_const(i32 %n) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,4) S: [1,4) Exits: (1 + (2 umin %n))<nuw><nsw> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_i, i1 %cond_i2, i1 false
-; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT: --> (%cond_i umin_seq %cond_i2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_m_const
; CHECK-NEXT: Loop %loop: backedge-taken count is (2 umin %n)
; CHECK-NEXT: Loop %loop: max backedge-taken count is 2
@@ -42,7 +42,7 @@ define void @logical_and_nonzero(i32 %m) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,4) S: [1,4) Exits: (1 + (2 umin %m))<nuw><nsw> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_i, i1 %cond_i2, i1 false
-; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT: --> (%cond_i umin_seq %cond_i2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_nonzero
; CHECK-NEXT: Loop %loop: backedge-taken count is (2 umin %m)
; CHECK-NEXT: Loop %loop: max backedge-taken count is 2
@@ -74,7 +74,7 @@ define void @logical_and_zero(i32 %m) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,2) S: [1,2) Exits: 1 LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_i, i1 %cond_i2, i1 false
-; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT: --> (%cond_i umin_seq %cond_i2) U: full-set S: full-set Exits: false LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_zero
; CHECK-NEXT: Loop %loop: backedge-taken count is 0
; CHECK-NEXT: Loop %loop: max backedge-taken count is 0
@@ -107,7 +107,7 @@ define void @logical_and_inversed(i32 %n, i32 %m) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_i, i1 %cond_i2, i1 false
-; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT: --> (%cond_i umin_seq %cond_i2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_inversed
; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count.
; CHECK-NEXT: Loop %loop: Unpredictable max backedge-taken count.
diff --git a/llvm/test/Analysis/ScalarEvolution/logical-operations.ll b/llvm/test/Analysis/ScalarEvolution/logical-operations.ll
index cdca89d0e038..e0bcba78b086 100644
--- a/llvm/test/Analysis/ScalarEvolution/logical-operations.ll
+++ b/llvm/test/Analysis/ScalarEvolution/logical-operations.ll
@@ -136,7 +136,7 @@ define i1 @logical_and(i1 %x, i1 %y) {
; CHECK-LABEL: 'logical_and'
; CHECK-NEXT: Classifying expressions for: @logical_and
; CHECK-NEXT: %r = select i1 %x, i1 %y, i1 false
-; CHECK-NEXT: --> %r U: full-set S: full-set
+; CHECK-NEXT: --> (%x umin_seq %y) U: full-set S: full-set
; CHECK-NEXT: Determining loop execution counts for: @logical_and
;
%r = select i1 %x, i1 %y, i1 false
@@ -147,7 +147,7 @@ define i1 @select_x_or_false(i1 %c, i1 %x) {
; CHECK-LABEL: 'select_x_or_false'
; CHECK-NEXT: Classifying expressions for: @select_x_or_false
; CHECK-NEXT: %r = select i1 %c, i1 %x, i1 false
-; CHECK-NEXT: --> %r U: full-set S: full-set
+; CHECK-NEXT: --> (%c umin_seq %x) U: full-set S: full-set
; CHECK-NEXT: Determining loop execution counts for: @select_x_or_false
;
%r = select i1 %c, i1 %x, i1 false
More information about the llvm-commits
mailing list