Propagate non-local comparisons. Fixes PR1757.
authorOwen Anderson <resistor@mac.com>
Fri, 3 Sep 2010 22:47:08 +0000 (22:47 +0000)
committerOwen Anderson <resistor@mac.com>
Fri, 3 Sep 2010 22:47:08 +0000 (22:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@113025 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
test/Transforms/CorrelatedValuePropagation/basic.ll

index 2fd3c8dcb98a6545f5acf075ba34cb7401c7aba5..0d4e45de3466461932fc127d62a8b0429e5ea044 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/Instructions.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/LazyValueInfo.h"
+#include "llvm/Support/CFG.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/ADT/Statistic.h"
 using namespace llvm;
@@ -24,6 +25,7 @@ using namespace llvm;
 STATISTIC(NumPhis,      "Number of phis propagated");
 STATISTIC(NumSelects,   "Number of selects propagated");
 STATISTIC(NumMemAccess, "Number of memory access targets propagated");
+STATISTIC(NumCmps,      "Number of comparisons propagated");
 
 namespace {
   class CorrelatedValuePropagation : public FunctionPass {
@@ -32,6 +34,7 @@ namespace {
     bool processSelect(SelectInst *SI);
     bool processPHI(PHINode *P);
     bool processMemAccess(Instruction *I);
+    bool processCmp(CmpInst *C);
     
   public:
     static char ID;
@@ -117,6 +120,47 @@ bool CorrelatedValuePropagation::processMemAccess(Instruction *I) {
   return true;
 }
 
+/// processCmp - If the value of this comparison could be determined locally,
+/// constant propagation would already have figured it out.  Instead, walk
+/// the predecessors and statically evaluate the comparison based on information
+/// available on that edge.  If a given static evaluation is true on ALL
+/// incoming edges, then it's true universally and we can simplify the compare.
+bool CorrelatedValuePropagation::processCmp(CmpInst *C) {
+  Value *Op0 = C->getOperand(0);
+  if (isa<Instruction>(Op0) &&
+      cast<Instruction>(Op0)->getParent() == C->getParent())
+    return false;
+  
+  Constant *Op1 = dyn_cast<Constant>(C->getOperand(1));
+  if (!Op1) return false;
+  
+  pred_iterator PI = pred_begin(C->getParent()), PE = pred_end(C->getParent());
+  if (PI == PE) return false;
+  
+  LazyValueInfo::Tristate Result = LVI->getPredicateOnEdge(C->getPredicate(), 
+                                    C->getOperand(0), Op1, *PI, C->getParent());
+  if (Result == LazyValueInfo::Unknown) return false;
+
+  ++PI;
+  while (PI != PE) {
+    LazyValueInfo::Tristate Res = LVI->getPredicateOnEdge(C->getPredicate(), 
+                                    C->getOperand(0), Op1, *PI, C->getParent());
+    if (Res != Result) return false;
+    ++PI;
+  }
+  
+  ++NumCmps;
+  
+  if (Result == LazyValueInfo::True)
+    C->replaceAllUsesWith(ConstantInt::getTrue(C->getContext()));
+  else
+    C->replaceAllUsesWith(ConstantInt::getFalse(C->getContext()));
+  
+  C->eraseFromParent();
+
+  return true;
+}
+
 bool CorrelatedValuePropagation::runOnFunction(Function &F) {
   LVI = &getAnalysis<LazyValueInfo>();
   
@@ -133,6 +177,10 @@ bool CorrelatedValuePropagation::runOnFunction(Function &F) {
       case Instruction::PHI:
         BBChanged |= processPHI(cast<PHINode>(II));
         break;
+      case Instruction::ICmp:
+      case Instruction::FCmp:
+        BBChanged |= processCmp(cast<CmpInst>(II));
+        break;
       case Instruction::Load:
       case Instruction::Store:
         BBChanged |= processMemAccess(II);
index 7752ebd7ee6fccbb5b918412c115caa12bf3a42a..24666e901e9ebd83a16fc491c1973880a813bb34 100644 (file)
@@ -56,4 +56,28 @@ bb2:            ; preds = %entry
         %should_be_const = load i8* %a
 ; CHECK: ret i8 7
         ret i8 %should_be_const
+}
+
+; PR1757
+; CHECK: @test4
+define i32 @test4(i32) {
+EntryBlock:
+; CHECK: icmp sgt i32 %0, 2  
+  %.demorgan = icmp sgt i32 %0, 2    
+  br i1 %.demorgan, label %GreaterThanTwo, label %LessThanOrEqualToTwo
+
+GreaterThanTwo:
+; CHECK-NOT: icmp eq i32 %0, 2
+  icmp eq i32 %0, 2
+; CHECK: br i1 false
+  br i1 %1, label %Impossible, label %NotTwoAndGreaterThanTwo
+
+NotTwoAndGreaterThanTwo:
+  ret i32 2
+
+Impossible:
+  ret i32 1
+
+LessThanOrEqualToTwo:
+  ret i32 0
 }
\ No newline at end of file