llvm.org GIT mirror llvm / 597dad3
Propagate non-local comparisons. Fixes PR1757. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@113025 91177308-0d34-0410-b5e6-96231b3b80d8 Owen Anderson 9 years ago
2 changed file(s) with 72 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
1616 #include "llvm/Instructions.h"
1717 #include "llvm/Pass.h"
1818 #include "llvm/Analysis/LazyValueInfo.h"
19 #include "llvm/Support/CFG.h"
1920 #include "llvm/Transforms/Utils/Local.h"
2021 #include "llvm/ADT/Statistic.h"
2122 using namespace llvm;
2324 STATISTIC(NumPhis, "Number of phis propagated");
2425 STATISTIC(NumSelects, "Number of selects propagated");
2526 STATISTIC(NumMemAccess, "Number of memory access targets propagated");
27 STATISTIC(NumCmps, "Number of comparisons propagated");
2628
2729 namespace {
2830 class CorrelatedValuePropagation : public FunctionPass {
3133 bool processSelect(SelectInst *SI);
3234 bool processPHI(PHINode *P);
3335 bool processMemAccess(Instruction *I);
36 bool processCmp(CmpInst *C);
3437
3538 public:
3639 static char ID;
113116
114117 ++NumMemAccess;
115118 I->replaceUsesOfWith(Pointer, C);
119 return true;
120 }
121
122 /// processCmp - If the value of this comparison could be determined locally,
123 /// constant propagation would already have figured it out. Instead, walk
124 /// the predecessors and statically evaluate the comparison based on information
125 /// available on that edge. If a given static evaluation is true on ALL
126 /// incoming edges, then it's true universally and we can simplify the compare.
127 bool CorrelatedValuePropagation::processCmp(CmpInst *C) {
128 Value *Op0 = C->getOperand(0);
129 if (isa(Op0) &&
130 cast(Op0)->getParent() == C->getParent())
131 return false;
132
133 Constant *Op1 = dyn_cast(C->getOperand(1));
134 if (!Op1) return false;
135
136 pred_iterator PI = pred_begin(C->getParent()), PE = pred_end(C->getParent());
137 if (PI == PE) return false;
138
139 LazyValueInfo::Tristate Result = LVI->getPredicateOnEdge(C->getPredicate(),
140 C->getOperand(0), Op1, *PI, C->getParent());
141 if (Result == LazyValueInfo::Unknown) return false;
142
143 ++PI;
144 while (PI != PE) {
145 LazyValueInfo::Tristate Res = LVI->getPredicateOnEdge(C->getPredicate(),
146 C->getOperand(0), Op1, *PI, C->getParent());
147 if (Res != Result) return false;
148 ++PI;
149 }
150
151 ++NumCmps;
152
153 if (Result == LazyValueInfo::True)
154 C->replaceAllUsesWith(ConstantInt::getTrue(C->getContext()));
155 else
156 C->replaceAllUsesWith(ConstantInt::getFalse(C->getContext()));
157
158 C->eraseFromParent();
159
116160 return true;
117161 }
118162
132176 case Instruction::PHI:
133177 BBChanged |= processPHI(cast(II));
134178 break;
179 case Instruction::ICmp:
180 case Instruction::FCmp:
181 BBChanged |= processCmp(cast(II));
182 break;
135183 case Instruction::Load:
136184 case Instruction::Store:
137185 BBChanged |= processMemAccess(II);
5555 %should_be_const = load i8* %a
5656 ; CHECK: ret i8 7
5757 ret i8 %should_be_const
58 }
59
60 ; PR1757
61 ; CHECK: @test4
62 define i32 @test4(i32) {
63 EntryBlock:
64 ; CHECK: icmp sgt i32 %0, 2
65 %.demorgan = icmp sgt i32 %0, 2
66 br i1 %.demorgan, label %GreaterThanTwo, label %LessThanOrEqualToTwo
67
68 GreaterThanTwo:
69 ; CHECK-NOT: icmp eq i32 %0, 2
70 icmp eq i32 %0, 2
71 ; CHECK: br i1 false
72 br i1 %1, label %Impossible, label %NotTwoAndGreaterThanTwo
73
74 NotTwoAndGreaterThanTwo:
75 ret i32 2
76
77 Impossible:
78 ret i32 1
79
80 LessThanOrEqualToTwo:
81 ret i32 0
5882 }