From 1593dd6779d7ab1db13c44f32f987c32aff2b54b Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Fri, 3 Sep 2010 19:08:37 +0000 Subject: [PATCH] Add support for simplifying a load from a computed value to a load from a global when it is provable that they're equivalent. This fixes PR4855. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@112994 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/LazyValueInfo.cpp | 13 +++++- .../Scalar/CorrelatedValuePropagation.cpp | 40 ++++++++++++++++--- .../CorrelatedValuePropagation/basic.ll | 18 +++++++++ 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/lib/Analysis/LazyValueInfo.cpp b/lib/Analysis/LazyValueInfo.cpp index b4923f9a717..e32dbc44471 100644 --- a/lib/Analysis/LazyValueInfo.cpp +++ b/lib/Analysis/LazyValueInfo.cpp @@ -452,14 +452,15 @@ LVILatticeVal LVIQuery::getBlockValue(BasicBlock *BB) { // If this is a pointer, and there's a load from that pointer in this BB, // then we know that the pointer can't be NULL. + bool NotNull = false; if (Val->getType()->isPointerTy()) { - const PointerType *PTy = cast(Val->getType()); for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();BI != BE;++BI){ LoadInst *L = dyn_cast(BI); if (L && L->getPointerAddressSpace() == 0 && L->getPointerOperand()->getUnderlyingObject() == Val->getUnderlyingObject()) { - return LVILatticeVal::getNot(ConstantPointerNull::get(PTy)); + NotNull = true; + break; } } } @@ -475,11 +476,19 @@ LVILatticeVal LVIQuery::getBlockValue(BasicBlock *BB) { if (Result.isOverdefined()) { DEBUG(dbgs() << " compute BB '" << BB->getName() << "' - overdefined because of pred.\n"); + // If we previously determined that this is a pointer that can't be null + // then return that rather than giving up entirely. + if (NotNull) { + const PointerType *PTy = cast(Val->getType()); + Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy)); + } + return Result; } ++NumPreds; } + // If this is the entry block, we must be asking about an argument. The // value is overdefined. if (NumPreds == 0 && BB == &BB->getParent()->front()) { diff --git a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index c673b0b3326..2fd3c8dcb98 100644 --- a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -21,8 +21,9 @@ #include "llvm/ADT/Statistic.h" using namespace llvm; -STATISTIC(NumPhis, "Number of phis propagated"); -STATISTIC(NumSelects, "Number of selects propagated"); +STATISTIC(NumPhis, "Number of phis propagated"); +STATISTIC(NumSelects, "Number of selects propagated"); +STATISTIC(NumMemAccess, "Number of memory access targets propagated"); namespace { class CorrelatedValuePropagation : public FunctionPass { @@ -30,6 +31,7 @@ namespace { bool processSelect(SelectInst *SI); bool processPHI(PHINode *P); + bool processMemAccess(Instruction *I); public: static char ID; @@ -54,6 +56,7 @@ Pass *llvm::createCorrelatedValuePropagationPass() { bool CorrelatedValuePropagation::processSelect(SelectInst *S) { if (S->getType()->isVectorTy()) return false; + if (isa(S->getOperand(0))) return false; Constant *C = LVI->getConstant(S->getOperand(0), S->getParent()); if (!C) return false; @@ -97,6 +100,23 @@ bool CorrelatedValuePropagation::processPHI(PHINode *P) { return Changed; } +bool CorrelatedValuePropagation::processMemAccess(Instruction *I) { + Value *Pointer = 0; + if (LoadInst *L = dyn_cast(I)) + Pointer = L->getPointerOperand(); + else + Pointer = cast(I)->getPointerOperand(); + + if (isa(Pointer)) return false; + + Constant *C = LVI->getConstant(Pointer, I->getParent()); + if (!C) return false; + + ++NumMemAccess; + I->replaceUsesOfWith(Pointer, C); + return true; +} + bool CorrelatedValuePropagation::runOnFunction(Function &F) { LVI = &getAnalysis(); @@ -106,10 +126,18 @@ bool CorrelatedValuePropagation::runOnFunction(Function &F) { bool BBChanged = false; for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) { Instruction *II = BI++; - if (SelectInst *SI = dyn_cast(II)) - BBChanged |= processSelect(SI); - else if (PHINode *P = dyn_cast(II)) - BBChanged |= processPHI(P); + switch (II->getOpcode()) { + case Instruction::Select: + BBChanged |= processSelect(cast(II)); + break; + case Instruction::PHI: + BBChanged |= processPHI(cast(II)); + break; + case Instruction::Load: + case Instruction::Store: + BBChanged |= processMemAccess(II); + break; + } } // Propagating correlated values might leave cruft around. diff --git a/test/Transforms/CorrelatedValuePropagation/basic.ll b/test/Transforms/CorrelatedValuePropagation/basic.ll index 9a9fc0f639d..7752ebd7ee6 100644 --- a/test/Transforms/CorrelatedValuePropagation/basic.ll +++ b/test/Transforms/CorrelatedValuePropagation/basic.ll @@ -39,3 +39,21 @@ bb3: ; preds = %bb1 ; CHECK: ret i1 %res ret i1 %res } + +; PR4855 +@gv = internal constant i8 7 +; CHECK: @test3 +define i8 @test3(i8* %a) nounwind { +entry: + %cond = icmp eq i8* %a, @gv + br i1 %cond, label %bb2, label %bb + +bb: ; preds = %entry + ret i8 0 + +bb2: ; preds = %entry +; CHECK-NOT: load i8* %a + %should_be_const = load i8* %a +; CHECK: ret i8 7 + ret i8 %should_be_const +} \ No newline at end of file