[llvm-branch-commits] [llvm] afbb6d9 - [CVP] Simplify and generalize switch handling

Nikita Popov via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Dec 12 12:16:51 PST 2020


Author: Nikita Popov
Date: 2020-12-12T21:12:27+01:00
New Revision: afbb6d97b501502b89bedc3da2a5d7ec00f56dba

URL: https://github.com/llvm/llvm-project/commit/afbb6d97b501502b89bedc3da2a5d7ec00f56dba
DIFF: https://github.com/llvm/llvm-project/commit/afbb6d97b501502b89bedc3da2a5d7ec00f56dba.diff

LOG: [CVP] Simplify and generalize switch handling

CVP currently handles switches by checking an equality predicate
on all edges from predecessor blocks. Of course, this can only
work if the value being switched over is defined in a different block.

Replace this implementation with a call to getPredicateAt(), which
also does the predecessor edge predicate check (if not defined in
the same block), but can also do quite a bit more: It can reason
about phi-nodes by checking edge predicates for incoming values,
it can reason about assumes, and it can reason about block values.

As such, this makes the implementation both simpler and more
powerful. The compile-time impact on CTMark is in the noise.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
    llvm/test/Transforms/CorrelatedValuePropagation/basic.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index b7b1b9c6aa58..b671d68031a8 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -330,15 +330,6 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,
   Value *Cond = I->getCondition();
   BasicBlock *BB = I->getParent();
 
-  // If the condition was defined in same block as the switch then LazyValueInfo
-  // currently won't say anything useful about it, though in theory it could.
-  if (isa<Instruction>(Cond) && cast<Instruction>(Cond)->getParent() == BB)
-    return false;
-
-  // If the switch is unreachable then trying to improve it is a waste of time.
-  pred_iterator PB = pred_begin(BB), PE = pred_end(BB);
-  if (PB == PE) return false;
-
   // Analyse each switch case in turn.
   bool Changed = false;
   DenseMap<BasicBlock*, int> SuccessorsCount;
@@ -351,35 +342,9 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,
 
     for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) {
       ConstantInt *Case = CI->getCaseValue();
-
-      // Check to see if the switch condition is equal to/not equal to the case
-      // value on every incoming edge, equal/not equal being the same each time.
-      LazyValueInfo::Tristate State = LazyValueInfo::Unknown;
-      for (pred_iterator PI = PB; PI != PE; ++PI) {
-        // Is the switch condition equal to the case value?
-        LazyValueInfo::Tristate Value = LVI->getPredicateOnEdge(CmpInst::ICMP_EQ,
-                                                                Cond, Case, *PI,
-                                                                BB, SI);
-        // Give up on this case if nothing is known.
-        if (Value == LazyValueInfo::Unknown) {
-          State = LazyValueInfo::Unknown;
-          break;
-        }
-
-        // If this was the first edge to be visited, record that all other edges
-        // need to give the same result.
-        if (PI == PB) {
-          State = Value;
-          continue;
-        }
-
-        // If this case is known to fire for some edges and known not to fire for
-        // others then there is nothing we can do - give up.
-        if (Value != State) {
-          State = LazyValueInfo::Unknown;
-          break;
-        }
-      }
+      LazyValueInfo::Tristate State =
+          LVI->getPredicateAt(CmpInst::ICMP_EQ, Cond, Case, I,
+                              /* UseBlockValue */ true);
 
       if (State == LazyValueInfo::False) {
         // This case never fires - remove it.

diff  --git a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll
index 20d285641da1..0c41bb6270f9 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll
@@ -285,11 +285,7 @@ define void @switch_nonzero_zext(i8 %s) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[SWITCH:%.*]], label [[EXIT:%.*]]
 ; CHECK:       switch:
 ; CHECK-NEXT:    [[S_EXT:%.*]] = zext i8 [[S]] to i32
-; CHECK-NEXT:    switch i32 [[S_EXT]], label [[EXIT]] [
-; CHECK-NEXT:    i32 0, label [[UNREACHABLE:%.*]]
-; CHECK-NEXT:    i32 1, label [[EXIT]]
-; CHECK-NEXT:    i32 -1, label [[EXIT]]
-; CHECK-NEXT:    ]
+; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ; CHECK:       unreachable:
@@ -319,11 +315,7 @@ define void @switch_assume_nonzero(i32 %s) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[S:%.*]], 0
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
-; CHECK-NEXT:    switch i32 [[S]], label [[EXIT:%.*]] [
-; CHECK-NEXT:    i32 0, label [[UNREACHABLE:%.*]]
-; CHECK-NEXT:    i32 1, label [[EXIT]]
-; CHECK-NEXT:    i32 -1, label [[EXIT]]
-; CHECK-NEXT:    ]
+; CHECK-NEXT:    br label [[EXIT:%.*]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ; CHECK:       unreachable:
@@ -355,11 +347,7 @@ define void @switch_nonzero_phi(i1 %cond) {
 ; CHECK-NEXT:    br label [[SWITCH]]
 ; CHECK:       switch:
 ; CHECK-NEXT:    [[S:%.*]] = phi i32 [ 1, [[IF]] ], [ -1, [[ELSE]] ]
-; CHECK-NEXT:    switch i32 [[S]], label [[EXIT:%.*]] [
-; CHECK-NEXT:    i32 0, label [[UNREACHABLE:%.*]]
-; CHECK-NEXT:    i32 1, label [[EXIT]]
-; CHECK-NEXT:    i32 -1, label [[EXIT]]
-; CHECK-NEXT:    ]
+; CHECK-NEXT:    br label [[EXIT:%.*]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ; CHECK:       unreachable:


        


More information about the llvm-branch-commits mailing list