[llvm] c913dcc - [SCEV] Use lshr in implications
Max Kazantsev via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 24 22:25:38 PST 2022
Author: Max Kazantsev
Date: 2022-01-25T13:25:19+07:00
New Revision: c913dccfde69617e2357ac25532f25d2a81bca2c
URL: https://github.com/llvm/llvm-project/commit/c913dccfde69617e2357ac25532f25d2a81bca2c
DIFF: https://github.com/llvm/llvm-project/commit/c913dccfde69617e2357ac25532f25d2a81bca2c.diff
LOG: [SCEV] Use lshr in implications
This patch adds support for implication inference logic for the
following pattern:
```
lhs < (y >> z) <= y, y <= rhs --> lhs < rhs
```
We should be able to use the fact that value shifted to right is
not greater than the original value (provided it is non-negative).
Differential Revision: https://reviews.llvm.org/D116150
Reviewed-By: apilipenko
Added:
Modified:
llvm/include/llvm/Analysis/ScalarEvolution.h
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/test/Transforms/IndVarSimplify/shift-range-checks.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index fd23ba7ae3872..1e6dac44cf2b7 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -1898,6 +1898,15 @@ class ScalarEvolution {
const SCEV *FoundLHS, const SCEV *FoundRHS,
unsigned Depth);
+ /// Test whether the condition described by Pred, LHS, and RHS is true
+ /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
+ /// true.
+ ///
+ /// This routine tries to reason about shifts.
+ bool isImpliedCondOperandsViaShift(ICmpInst::Predicate Pred, const SCEV *LHS,
+ const SCEV *RHS, const SCEV *FoundLHS,
+ const SCEV *FoundRHS);
+
/// If we know that the specified Phi is in the header of its containing
/// loop, we know the loop executes a constant number of times, and the PHI
/// node is just a recurrence involving constants, fold it.
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 3019ff526b66d..fdfbd2c3ca77f 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -11468,6 +11468,48 @@ bool ScalarEvolution::isImpliedViaMerge(ICmpInst::Predicate Pred,
return true;
}
+bool ScalarEvolution::isImpliedCondOperandsViaShift(ICmpInst::Predicate Pred,
+ const SCEV *LHS,
+ const SCEV *RHS,
+ const SCEV *FoundLHS,
+ const SCEV *FoundRHS) {
+ // We want to imply LHS < RHS from LHS < (RHS >> shiftvalue). First, make
+ // sure that we are dealing with same LHS.
+ if (RHS == FoundRHS) {
+ std::swap(LHS, RHS);
+ std::swap(FoundLHS, FoundRHS);
+ Pred = ICmpInst::getSwappedPredicate(Pred);
+ }
+ if (LHS != FoundLHS)
+ return false;
+
+ auto *SUFoundRHS = dyn_cast<SCEVUnknown>(FoundRHS);
+ if (!SUFoundRHS)
+ return false;
+
+ Value *Shiftee, *ShiftValue;
+
+ using namespace PatternMatch;
+ if (match(SUFoundRHS->getValue(),
+ m_LShr(m_Value(Shiftee), m_Value(ShiftValue)))) {
+ auto *ShifteeS = getSCEV(Shiftee);
+ // Prove one of the following:
+ // LHS <u (shiftee >> shiftvalue) && shiftee <=u RHS ---> LHS <u RHS
+ // LHS <=u (shiftee >> shiftvalue) && shiftee <=u RHS ---> LHS <=u RHS
+ // LHS <s (shiftee >> shiftvalue) && shiftee <=s RHS && shiftee >=s 0
+ // ---> LHS <s RHS
+ // LHS <=s (shiftee >> shiftvalue) && shiftee <=s RHS && shiftee >=s 0
+ // ---> LHS <=s RHS
+ if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE)
+ return isKnownPredicate(ICmpInst::ICMP_ULE, ShifteeS, RHS);
+ if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE)
+ if (isKnownNonNegative(ShifteeS))
+ return isKnownPredicate(ICmpInst::ICMP_SLE, ShifteeS, RHS);
+ }
+
+ return false;
+}
+
bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS,
const SCEV *FoundLHS,
@@ -11479,6 +11521,9 @@ bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred,
if (isImpliedCondOperandsViaNoOverflow(Pred, LHS, RHS, FoundLHS, FoundRHS))
return true;
+ if (isImpliedCondOperandsViaShift(Pred, LHS, RHS, FoundLHS, FoundRHS))
+ return true;
+
if (isImpliedCondOperandsViaAddRecStart(Pred, LHS, RHS, FoundLHS, FoundRHS,
CtxI))
return true;
diff --git a/llvm/test/Transforms/IndVarSimplify/shift-range-checks.ll b/llvm/test/Transforms/IndVarSimplify/shift-range-checks.ll
index 1dc91d105ab3c..ab4cea2d879f5 100644
--- a/llvm/test/Transforms/IndVarSimplify/shift-range-checks.ll
+++ b/llvm/test/Transforms/IndVarSimplify/shift-range-checks.ll
@@ -5,8 +5,6 @@
declare i1 @cond()
declare void @exit(i32 %code)
-; FIXME: We can remove 2nd check here because it is implied by check
-; against the shifted value.
define void @test_01(i32* %p, i32 %shift) {
; CHECK-LABEL: @test_01(
; CHECK-NEXT: entry:
@@ -18,8 +16,7 @@ define void @test_01(i32* %p, i32 %shift) {
; CHECK-NEXT: [[LESS_THAN_SHIFTED:%.*]] = icmp slt i32 [[IV]], [[X_SHIFTED]]
; CHECK-NEXT: br i1 [[LESS_THAN_SHIFTED]], label [[GUARDED:%.*]], label [[FAILURE:%.*]]
; CHECK: guarded:
-; CHECK-NEXT: [[LESS_THAN_X:%.*]] = icmp ult i32 [[IV]], [[X]]
-; CHECK-NEXT: br i1 [[LESS_THAN_X]], label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]]
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]]
; CHECK: backedge:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
@@ -64,8 +61,6 @@ never_happens:
unreachable
}
-; FIXME: We can remove 2nd check here because it is implied by check
-; against the shifted value.
define void @test_02(i32* %p, i32 %shift) {
; CHECK-LABEL: @test_02(
; CHECK-NEXT: entry:
@@ -77,8 +72,7 @@ define void @test_02(i32* %p, i32 %shift) {
; CHECK-NEXT: [[LESS_THAN_SHIFTED:%.*]] = icmp sgt i32 [[X_SHIFTED]], [[IV]]
; CHECK-NEXT: br i1 [[LESS_THAN_SHIFTED]], label [[GUARDED:%.*]], label [[FAILURE:%.*]]
; CHECK: guarded:
-; CHECK-NEXT: [[LESS_THAN_X:%.*]] = icmp ugt i32 [[X]], [[IV]]
-; CHECK-NEXT: br i1 [[LESS_THAN_X]], label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]]
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]]
; CHECK: backedge:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
@@ -123,8 +117,6 @@ never_happens:
unreachable
}
-; FIXME: We can remove 2nd check here because it is implied by check
-; against the shifted value.
define void @test_03(i32* %p, i32 %shift) {
; CHECK-LABEL: @test_03(
; CHECK-NEXT: entry:
@@ -136,8 +128,7 @@ define void @test_03(i32* %p, i32 %shift) {
; CHECK-NEXT: [[LESS_THAN_SHIFTED:%.*]] = icmp ult i32 [[IV]], [[X_SHIFTED]]
; CHECK-NEXT: br i1 [[LESS_THAN_SHIFTED]], label [[GUARDED:%.*]], label [[FAILURE:%.*]]
; CHECK: guarded:
-; CHECK-NEXT: [[LESS_THAN_X:%.*]] = icmp ult i32 [[IV]], [[X]]
-; CHECK-NEXT: br i1 [[LESS_THAN_X]], label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]]
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]]
; CHECK: backedge:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
@@ -182,8 +173,6 @@ never_happens:
unreachable
}
-; FIXME: We can remove 2nd check here because it is implied by check
-; against the shifted value.
define void @test_04(i32* %p, i32 %shift) {
; CHECK-LABEL: @test_04(
; CHECK-NEXT: entry:
@@ -195,8 +184,7 @@ define void @test_04(i32* %p, i32 %shift) {
; CHECK-NEXT: [[LESS_THAN_SHIFTED:%.*]] = icmp ugt i32 [[X_SHIFTED]], [[IV]]
; CHECK-NEXT: br i1 [[LESS_THAN_SHIFTED]], label [[GUARDED:%.*]], label [[FAILURE:%.*]]
; CHECK: guarded:
-; CHECK-NEXT: [[LESS_THAN_X:%.*]] = icmp ugt i32 [[X]], [[IV]]
-; CHECK-NEXT: br i1 [[LESS_THAN_X]], label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]]
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]]
; CHECK: backedge:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
More information about the llvm-commits
mailing list