1 //===- CorrelatedValuePropagation.cpp - Propagate CFG-derived info --------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the Correlated Value Propagation pass.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "correlated-value-propagation"
15 #include "llvm/Transforms/Scalar.h"
16 #include "llvm/Function.h"
17 #include "llvm/Instructions.h"
18 #include "llvm/Pass.h"
19 #include "llvm/Analysis/LazyValueInfo.h"
20 #include "llvm/Support/CFG.h"
21 #include "llvm/Transforms/Utils/Local.h"
22 #include "llvm/ADT/Statistic.h"
25 STATISTIC(NumPhis
, "Number of phis propagated");
26 STATISTIC(NumSelects
, "Number of selects propagated");
27 STATISTIC(NumMemAccess
, "Number of memory access targets propagated");
28 STATISTIC(NumCmps
, "Number of comparisons propagated");
31 class CorrelatedValuePropagation
: public FunctionPass
{
34 bool processSelect(SelectInst
*SI
);
35 bool processPHI(PHINode
*P
);
36 bool processMemAccess(Instruction
*I
);
37 bool processCmp(CmpInst
*C
);
41 CorrelatedValuePropagation(): FunctionPass(ID
) {
42 initializeCorrelatedValuePropagationPass(*PassRegistry::getPassRegistry());
45 bool runOnFunction(Function
&F
);
47 virtual void getAnalysisUsage(AnalysisUsage
&AU
) const {
48 AU
.addRequired
<LazyValueInfo
>();
53 char CorrelatedValuePropagation::ID
= 0;
54 INITIALIZE_PASS_BEGIN(CorrelatedValuePropagation
, "correlated-propagation",
55 "Value Propagation", false, false)
56 INITIALIZE_PASS_DEPENDENCY(LazyValueInfo
)
57 INITIALIZE_PASS_END(CorrelatedValuePropagation
, "correlated-propagation",
58 "Value Propagation", false, false)
60 // Public interface to the Value Propagation pass
61 Pass
*llvm::createCorrelatedValuePropagationPass() {
62 return new CorrelatedValuePropagation();
65 bool CorrelatedValuePropagation::processSelect(SelectInst
*S
) {
66 if (S
->getType()->isVectorTy()) return false;
67 if (isa
<Constant
>(S
->getOperand(0))) return false;
69 Constant
*C
= LVI
->getConstant(S
->getOperand(0), S
->getParent());
72 ConstantInt
*CI
= dyn_cast
<ConstantInt
>(C
);
73 if (!CI
) return false;
75 S
->replaceAllUsesWith(S
->getOperand(CI
->isOne() ? 1 : 2));
83 bool CorrelatedValuePropagation::processPHI(PHINode
*P
) {
86 BasicBlock
*BB
= P
->getParent();
87 for (unsigned i
= 0, e
= P
->getNumIncomingValues(); i
< e
; ++i
) {
88 Value
*Incoming
= P
->getIncomingValue(i
);
89 if (isa
<Constant
>(Incoming
)) continue;
91 Constant
*C
= LVI
->getConstantOnEdge(P
->getIncomingValue(i
),
92 P
->getIncomingBlock(i
),
96 P
->setIncomingValue(i
, C
);
100 if (Value
*ConstVal
= P
->hasConstantValue()) {
101 P
->replaceAllUsesWith(ConstVal
);
102 P
->eraseFromParent();
111 bool CorrelatedValuePropagation::processMemAccess(Instruction
*I
) {
113 if (LoadInst
*L
= dyn_cast
<LoadInst
>(I
))
114 Pointer
= L
->getPointerOperand();
116 Pointer
= cast
<StoreInst
>(I
)->getPointerOperand();
118 if (isa
<Constant
>(Pointer
)) return false;
120 Constant
*C
= LVI
->getConstant(Pointer
, I
->getParent());
121 if (!C
) return false;
124 I
->replaceUsesOfWith(Pointer
, C
);
128 /// processCmp - If the value of this comparison could be determined locally,
129 /// constant propagation would already have figured it out. Instead, walk
130 /// the predecessors and statically evaluate the comparison based on information
131 /// available on that edge. If a given static evaluation is true on ALL
132 /// incoming edges, then it's true universally and we can simplify the compare.
133 bool CorrelatedValuePropagation::processCmp(CmpInst
*C
) {
134 Value
*Op0
= C
->getOperand(0);
135 if (isa
<Instruction
>(Op0
) &&
136 cast
<Instruction
>(Op0
)->getParent() == C
->getParent())
139 Constant
*Op1
= dyn_cast
<Constant
>(C
->getOperand(1));
140 if (!Op1
) return false;
142 pred_iterator PI
= pred_begin(C
->getParent()), PE
= pred_end(C
->getParent());
143 if (PI
== PE
) return false;
145 LazyValueInfo::Tristate Result
= LVI
->getPredicateOnEdge(C
->getPredicate(),
146 C
->getOperand(0), Op1
, *PI
, C
->getParent());
147 if (Result
== LazyValueInfo::Unknown
) return false;
151 LazyValueInfo::Tristate Res
= LVI
->getPredicateOnEdge(C
->getPredicate(),
152 C
->getOperand(0), Op1
, *PI
, C
->getParent());
153 if (Res
!= Result
) return false;
159 if (Result
== LazyValueInfo::True
)
160 C
->replaceAllUsesWith(ConstantInt::getTrue(C
->getContext()));
162 C
->replaceAllUsesWith(ConstantInt::getFalse(C
->getContext()));
164 C
->eraseFromParent();
169 bool CorrelatedValuePropagation::runOnFunction(Function
&F
) {
170 LVI
= &getAnalysis
<LazyValueInfo
>();
172 bool FnChanged
= false;
174 for (Function::iterator FI
= F
.begin(), FE
= F
.end(); FI
!= FE
; ++FI
) {
175 bool BBChanged
= false;
176 for (BasicBlock::iterator BI
= FI
->begin(), BE
= FI
->end(); BI
!= BE
; ) {
177 Instruction
*II
= BI
++;
178 switch (II
->getOpcode()) {
179 case Instruction::Select
:
180 BBChanged
|= processSelect(cast
<SelectInst
>(II
));
182 case Instruction::PHI
:
183 BBChanged
|= processPHI(cast
<PHINode
>(II
));
185 case Instruction::ICmp
:
186 case Instruction::FCmp
:
187 BBChanged
|= processCmp(cast
<CmpInst
>(II
));
189 case Instruction::Load
:
190 case Instruction::Store
:
191 BBChanged
|= processMemAccess(II
);
196 FnChanged
|= BBChanged
;