diff options
-rw-r--r-- | lib/Transforms/Scalar/CorrelatedValuePropagation.cpp | 48 | ||||
-rw-r--r-- | test/Transforms/CorrelatedValuePropagation/basic.ll | 24 |
2 files changed, 72 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index 2fd3c8dcb9..0d4e45de34 100644 --- a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -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); diff --git a/test/Transforms/CorrelatedValuePropagation/basic.ll b/test/Transforms/CorrelatedValuePropagation/basic.ll index 7752ebd7ee..24666e901e 100644 --- a/test/Transforms/CorrelatedValuePropagation/basic.ll +++ b/test/Transforms/CorrelatedValuePropagation/basic.ll @@ -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 |