llvm.org GIT mirror llvm / 1593dd6
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 Owen Anderson 9 years ago
3 changed file(s) with 63 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
451451
452452 // If this is a pointer, and there's a load from that pointer in this BB,
453453 // then we know that the pointer can't be NULL.
454 bool NotNull = false;
454455 if (Val->getType()->isPointerTy()) {
455 const PointerType *PTy = cast(Val->getType());
456456 for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();BI != BE;++BI){
457457 LoadInst *L = dyn_cast(BI);
458458 if (L && L->getPointerAddressSpace() == 0 &&
459459 L->getPointerOperand()->getUnderlyingObject() ==
460460 Val->getUnderlyingObject()) {
461 return LVILatticeVal::getNot(ConstantPointerNull::get(PTy));
461 NotNull = true;
462 break;
462463 }
463464 }
464465 }
474475 if (Result.isOverdefined()) {
475476 DEBUG(dbgs() << " compute BB '" << BB->getName()
476477 << "' - overdefined because of pred.\n");
478 // If we previously determined that this is a pointer that can't be null
479 // then return that rather than giving up entirely.
480 if (NotNull) {
481 const PointerType *PTy = cast(Val->getType());
482 Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy));
483 }
484
477485 return Result;
478486 }
479487 ++NumPreds;
480488 }
489
481490
482491 // If this is the entry block, we must be asking about an argument. The
483492 // value is overdefined.
2020 #include "llvm/ADT/Statistic.h"
2121 using namespace llvm;
2222
23 STATISTIC(NumPhis, "Number of phis propagated");
24 STATISTIC(NumSelects, "Number of selects propagated");
23 STATISTIC(NumPhis, "Number of phis propagated");
24 STATISTIC(NumSelects, "Number of selects propagated");
25 STATISTIC(NumMemAccess, "Number of memory access targets propagated");
2526
2627 namespace {
2728 class CorrelatedValuePropagation : public FunctionPass {
2930
3031 bool processSelect(SelectInst *SI);
3132 bool processPHI(PHINode *P);
33 bool processMemAccess(Instruction *I);
3234
3335 public:
3436 static char ID;
5355
5456 bool CorrelatedValuePropagation::processSelect(SelectInst *S) {
5557 if (S->getType()->isVectorTy()) return false;
58 if (isa(S->getOperand(0))) return false;
5659
5760 Constant *C = LVI->getConstant(S->getOperand(0), S->getParent());
5861 if (!C) return false;
9699 return Changed;
97100 }
98101
102 bool CorrelatedValuePropagation::processMemAccess(Instruction *I) {
103 Value *Pointer = 0;
104 if (LoadInst *L = dyn_cast(I))
105 Pointer = L->getPointerOperand();
106 else
107 Pointer = cast(I)->getPointerOperand();
108
109 if (isa(Pointer)) return false;
110
111 Constant *C = LVI->getConstant(Pointer, I->getParent());
112 if (!C) return false;
113
114 ++NumMemAccess;
115 I->replaceUsesOfWith(Pointer, C);
116 return true;
117 }
118
99119 bool CorrelatedValuePropagation::runOnFunction(Function &F) {
100120 LVI = &getAnalysis();
101121
105125 bool BBChanged = false;
106126 for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) {
107127 Instruction *II = BI++;
108 if (SelectInst *SI = dyn_cast(II))
109 BBChanged |= processSelect(SI);
110 else if (PHINode *P = dyn_cast(II))
111 BBChanged |= processPHI(P);
128 switch (II->getOpcode()) {
129 case Instruction::Select:
130 BBChanged |= processSelect(cast(II));
131 break;
132 case Instruction::PHI:
133 BBChanged |= processPHI(cast(II));
134 break;
135 case Instruction::Load:
136 case Instruction::Store:
137 BBChanged |= processMemAccess(II);
138 break;
139 }
112140 }
113141
114142 // Propagating correlated values might leave cruft around.
3838 ; CHECK: ret i1 %res
3939 ret i1 %res
4040 }
41
42 ; PR4855
43 @gv = internal constant i8 7
44 ; CHECK: @test3
45 define i8 @test3(i8* %a) nounwind {
46 entry:
47 %cond = icmp eq i8* %a, @gv
48 br i1 %cond, label %bb2, label %bb
49
50 bb: ; preds = %entry
51 ret i8 0
52
53 bb2: ; preds = %entry
54 ; CHECK-NOT: load i8* %a
55 %should_be_const = load i8* %a
56 ; CHECK: ret i8 7
57 ret i8 %should_be_const
58 }