1*9880d681SAndroid Build Coastguard Worker //===-- IPConstantPropagation.cpp - Propagate constants through calls -----===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This pass implements an _extremely_ simple interprocedural constant
11*9880d681SAndroid Build Coastguard Worker // propagation pass. It could certainly be improved in many different ways,
12*9880d681SAndroid Build Coastguard Worker // like using a worklist. This pass makes arguments dead, but does not remove
13*9880d681SAndroid Build Coastguard Worker // them. The existing dead argument elimination pass should be run after this
14*9880d681SAndroid Build Coastguard Worker // to clean up the mess.
15*9880d681SAndroid Build Coastguard Worker //
16*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
17*9880d681SAndroid Build Coastguard Worker
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/IPO.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CallSite.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "ipconstprop"
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker STATISTIC(NumArgumentsProped, "Number of args turned into constants");
32*9880d681SAndroid Build Coastguard Worker STATISTIC(NumReturnValProped, "Number of return values turned into constants");
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker namespace {
35*9880d681SAndroid Build Coastguard Worker /// IPCP - The interprocedural constant propagation pass
36*9880d681SAndroid Build Coastguard Worker ///
37*9880d681SAndroid Build Coastguard Worker struct IPCP : public ModulePass {
38*9880d681SAndroid Build Coastguard Worker static char ID; // Pass identification, replacement for typeid
IPCP__anon2b7dec040111::IPCP39*9880d681SAndroid Build Coastguard Worker IPCP() : ModulePass(ID) {
40*9880d681SAndroid Build Coastguard Worker initializeIPCPPass(*PassRegistry::getPassRegistry());
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker bool runOnModule(Module &M) override;
44*9880d681SAndroid Build Coastguard Worker };
45*9880d681SAndroid Build Coastguard Worker }
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker /// PropagateConstantsIntoArguments - Look at all uses of the specified
48*9880d681SAndroid Build Coastguard Worker /// function. If all uses are direct call sites, and all pass a particular
49*9880d681SAndroid Build Coastguard Worker /// constant in for an argument, propagate that constant in as the argument.
50*9880d681SAndroid Build Coastguard Worker ///
PropagateConstantsIntoArguments(Function & F)51*9880d681SAndroid Build Coastguard Worker static bool PropagateConstantsIntoArguments(Function &F) {
52*9880d681SAndroid Build Coastguard Worker if (F.arg_empty() || F.use_empty()) return false; // No arguments? Early exit.
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker // For each argument, keep track of its constant value and whether it is a
55*9880d681SAndroid Build Coastguard Worker // constant or not. The bool is driven to true when found to be non-constant.
56*9880d681SAndroid Build Coastguard Worker SmallVector<std::pair<Constant*, bool>, 16> ArgumentConstants;
57*9880d681SAndroid Build Coastguard Worker ArgumentConstants.resize(F.arg_size());
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker unsigned NumNonconstant = 0;
60*9880d681SAndroid Build Coastguard Worker for (Use &U : F.uses()) {
61*9880d681SAndroid Build Coastguard Worker User *UR = U.getUser();
62*9880d681SAndroid Build Coastguard Worker // Ignore blockaddress uses.
63*9880d681SAndroid Build Coastguard Worker if (isa<BlockAddress>(UR)) continue;
64*9880d681SAndroid Build Coastguard Worker
65*9880d681SAndroid Build Coastguard Worker // Used by a non-instruction, or not the callee of a function, do not
66*9880d681SAndroid Build Coastguard Worker // transform.
67*9880d681SAndroid Build Coastguard Worker if (!isa<CallInst>(UR) && !isa<InvokeInst>(UR))
68*9880d681SAndroid Build Coastguard Worker return false;
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker CallSite CS(cast<Instruction>(UR));
71*9880d681SAndroid Build Coastguard Worker if (!CS.isCallee(&U))
72*9880d681SAndroid Build Coastguard Worker return false;
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker // Check out all of the potentially constant arguments. Note that we don't
75*9880d681SAndroid Build Coastguard Worker // inspect varargs here.
76*9880d681SAndroid Build Coastguard Worker CallSite::arg_iterator AI = CS.arg_begin();
77*9880d681SAndroid Build Coastguard Worker Function::arg_iterator Arg = F.arg_begin();
78*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = ArgumentConstants.size(); i != e;
79*9880d681SAndroid Build Coastguard Worker ++i, ++AI, ++Arg) {
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker // If this argument is known non-constant, ignore it.
82*9880d681SAndroid Build Coastguard Worker if (ArgumentConstants[i].second)
83*9880d681SAndroid Build Coastguard Worker continue;
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker Constant *C = dyn_cast<Constant>(*AI);
86*9880d681SAndroid Build Coastguard Worker if (C && ArgumentConstants[i].first == nullptr) {
87*9880d681SAndroid Build Coastguard Worker ArgumentConstants[i].first = C; // First constant seen.
88*9880d681SAndroid Build Coastguard Worker } else if (C && ArgumentConstants[i].first == C) {
89*9880d681SAndroid Build Coastguard Worker // Still the constant value we think it is.
90*9880d681SAndroid Build Coastguard Worker } else if (*AI == &*Arg) {
91*9880d681SAndroid Build Coastguard Worker // Ignore recursive calls passing argument down.
92*9880d681SAndroid Build Coastguard Worker } else {
93*9880d681SAndroid Build Coastguard Worker // Argument became non-constant. If all arguments are non-constant now,
94*9880d681SAndroid Build Coastguard Worker // give up on this function.
95*9880d681SAndroid Build Coastguard Worker if (++NumNonconstant == ArgumentConstants.size())
96*9880d681SAndroid Build Coastguard Worker return false;
97*9880d681SAndroid Build Coastguard Worker ArgumentConstants[i].second = true;
98*9880d681SAndroid Build Coastguard Worker }
99*9880d681SAndroid Build Coastguard Worker }
100*9880d681SAndroid Build Coastguard Worker }
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker // If we got to this point, there is a constant argument!
103*9880d681SAndroid Build Coastguard Worker assert(NumNonconstant != ArgumentConstants.size());
104*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
105*9880d681SAndroid Build Coastguard Worker Function::arg_iterator AI = F.arg_begin();
106*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++AI) {
107*9880d681SAndroid Build Coastguard Worker // Do we have a constant argument?
108*9880d681SAndroid Build Coastguard Worker if (ArgumentConstants[i].second || AI->use_empty() ||
109*9880d681SAndroid Build Coastguard Worker AI->hasInAllocaAttr() || (AI->hasByValAttr() && !F.onlyReadsMemory()))
110*9880d681SAndroid Build Coastguard Worker continue;
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker Value *V = ArgumentConstants[i].first;
113*9880d681SAndroid Build Coastguard Worker if (!V) V = UndefValue::get(AI->getType());
114*9880d681SAndroid Build Coastguard Worker AI->replaceAllUsesWith(V);
115*9880d681SAndroid Build Coastguard Worker ++NumArgumentsProped;
116*9880d681SAndroid Build Coastguard Worker MadeChange = true;
117*9880d681SAndroid Build Coastguard Worker }
118*9880d681SAndroid Build Coastguard Worker return MadeChange;
119*9880d681SAndroid Build Coastguard Worker }
120*9880d681SAndroid Build Coastguard Worker
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker // Check to see if this function returns one or more constants. If so, replace
123*9880d681SAndroid Build Coastguard Worker // all callers that use those return values with the constant value. This will
124*9880d681SAndroid Build Coastguard Worker // leave in the actual return values and instructions, but deadargelim will
125*9880d681SAndroid Build Coastguard Worker // clean that up.
126*9880d681SAndroid Build Coastguard Worker //
127*9880d681SAndroid Build Coastguard Worker // Additionally if a function always returns one of its arguments directly,
128*9880d681SAndroid Build Coastguard Worker // callers will be updated to use the value they pass in directly instead of
129*9880d681SAndroid Build Coastguard Worker // using the return value.
PropagateConstantReturn(Function & F)130*9880d681SAndroid Build Coastguard Worker static bool PropagateConstantReturn(Function &F) {
131*9880d681SAndroid Build Coastguard Worker if (F.getReturnType()->isVoidTy())
132*9880d681SAndroid Build Coastguard Worker return false; // No return value.
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker // We can infer and propagate the return value only when we know that the
135*9880d681SAndroid Build Coastguard Worker // definition we'll get at link time is *exactly* the definition we see now.
136*9880d681SAndroid Build Coastguard Worker // For more details, see GlobalValue::mayBeDerefined.
137*9880d681SAndroid Build Coastguard Worker if (!F.isDefinitionExact())
138*9880d681SAndroid Build Coastguard Worker return false;
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker // Check to see if this function returns a constant.
141*9880d681SAndroid Build Coastguard Worker SmallVector<Value *,4> RetVals;
142*9880d681SAndroid Build Coastguard Worker StructType *STy = dyn_cast<StructType>(F.getReturnType());
143*9880d681SAndroid Build Coastguard Worker if (STy)
144*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i)
145*9880d681SAndroid Build Coastguard Worker RetVals.push_back(UndefValue::get(STy->getElementType(i)));
146*9880d681SAndroid Build Coastguard Worker else
147*9880d681SAndroid Build Coastguard Worker RetVals.push_back(UndefValue::get(F.getReturnType()));
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker unsigned NumNonConstant = 0;
150*9880d681SAndroid Build Coastguard Worker for (BasicBlock &BB : F)
151*9880d681SAndroid Build Coastguard Worker if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
152*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = RetVals.size(); i != e; ++i) {
153*9880d681SAndroid Build Coastguard Worker // Already found conflicting return values?
154*9880d681SAndroid Build Coastguard Worker Value *RV = RetVals[i];
155*9880d681SAndroid Build Coastguard Worker if (!RV)
156*9880d681SAndroid Build Coastguard Worker continue;
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker // Find the returned value
159*9880d681SAndroid Build Coastguard Worker Value *V;
160*9880d681SAndroid Build Coastguard Worker if (!STy)
161*9880d681SAndroid Build Coastguard Worker V = RI->getOperand(0);
162*9880d681SAndroid Build Coastguard Worker else
163*9880d681SAndroid Build Coastguard Worker V = FindInsertedValue(RI->getOperand(0), i);
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker if (V) {
166*9880d681SAndroid Build Coastguard Worker // Ignore undefs, we can change them into anything
167*9880d681SAndroid Build Coastguard Worker if (isa<UndefValue>(V))
168*9880d681SAndroid Build Coastguard Worker continue;
169*9880d681SAndroid Build Coastguard Worker
170*9880d681SAndroid Build Coastguard Worker // Try to see if all the rets return the same constant or argument.
171*9880d681SAndroid Build Coastguard Worker if (isa<Constant>(V) || isa<Argument>(V)) {
172*9880d681SAndroid Build Coastguard Worker if (isa<UndefValue>(RV)) {
173*9880d681SAndroid Build Coastguard Worker // No value found yet? Try the current one.
174*9880d681SAndroid Build Coastguard Worker RetVals[i] = V;
175*9880d681SAndroid Build Coastguard Worker continue;
176*9880d681SAndroid Build Coastguard Worker }
177*9880d681SAndroid Build Coastguard Worker // Returning the same value? Good.
178*9880d681SAndroid Build Coastguard Worker if (RV == V)
179*9880d681SAndroid Build Coastguard Worker continue;
180*9880d681SAndroid Build Coastguard Worker }
181*9880d681SAndroid Build Coastguard Worker }
182*9880d681SAndroid Build Coastguard Worker // Different or no known return value? Don't propagate this return
183*9880d681SAndroid Build Coastguard Worker // value.
184*9880d681SAndroid Build Coastguard Worker RetVals[i] = nullptr;
185*9880d681SAndroid Build Coastguard Worker // All values non-constant? Stop looking.
186*9880d681SAndroid Build Coastguard Worker if (++NumNonConstant == RetVals.size())
187*9880d681SAndroid Build Coastguard Worker return false;
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker }
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker // If we got here, the function returns at least one constant value. Loop
192*9880d681SAndroid Build Coastguard Worker // over all users, replacing any uses of the return value with the returned
193*9880d681SAndroid Build Coastguard Worker // constant.
194*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
195*9880d681SAndroid Build Coastguard Worker for (Use &U : F.uses()) {
196*9880d681SAndroid Build Coastguard Worker CallSite CS(U.getUser());
197*9880d681SAndroid Build Coastguard Worker Instruction* Call = CS.getInstruction();
198*9880d681SAndroid Build Coastguard Worker
199*9880d681SAndroid Build Coastguard Worker // Not a call instruction or a call instruction that's not calling F
200*9880d681SAndroid Build Coastguard Worker // directly?
201*9880d681SAndroid Build Coastguard Worker if (!Call || !CS.isCallee(&U))
202*9880d681SAndroid Build Coastguard Worker continue;
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker // Call result not used?
205*9880d681SAndroid Build Coastguard Worker if (Call->use_empty())
206*9880d681SAndroid Build Coastguard Worker continue;
207*9880d681SAndroid Build Coastguard Worker
208*9880d681SAndroid Build Coastguard Worker MadeChange = true;
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker if (!STy) {
211*9880d681SAndroid Build Coastguard Worker Value* New = RetVals[0];
212*9880d681SAndroid Build Coastguard Worker if (Argument *A = dyn_cast<Argument>(New))
213*9880d681SAndroid Build Coastguard Worker // Was an argument returned? Then find the corresponding argument in
214*9880d681SAndroid Build Coastguard Worker // the call instruction and use that.
215*9880d681SAndroid Build Coastguard Worker New = CS.getArgument(A->getArgNo());
216*9880d681SAndroid Build Coastguard Worker Call->replaceAllUsesWith(New);
217*9880d681SAndroid Build Coastguard Worker continue;
218*9880d681SAndroid Build Coastguard Worker }
219*9880d681SAndroid Build Coastguard Worker
220*9880d681SAndroid Build Coastguard Worker for (auto I = Call->user_begin(), E = Call->user_end(); I != E;) {
221*9880d681SAndroid Build Coastguard Worker Instruction *Ins = cast<Instruction>(*I);
222*9880d681SAndroid Build Coastguard Worker
223*9880d681SAndroid Build Coastguard Worker // Increment now, so we can remove the use
224*9880d681SAndroid Build Coastguard Worker ++I;
225*9880d681SAndroid Build Coastguard Worker
226*9880d681SAndroid Build Coastguard Worker // Find the index of the retval to replace with
227*9880d681SAndroid Build Coastguard Worker int index = -1;
228*9880d681SAndroid Build Coastguard Worker if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Ins))
229*9880d681SAndroid Build Coastguard Worker if (EV->hasIndices())
230*9880d681SAndroid Build Coastguard Worker index = *EV->idx_begin();
231*9880d681SAndroid Build Coastguard Worker
232*9880d681SAndroid Build Coastguard Worker // If this use uses a specific return value, and we have a replacement,
233*9880d681SAndroid Build Coastguard Worker // replace it.
234*9880d681SAndroid Build Coastguard Worker if (index != -1) {
235*9880d681SAndroid Build Coastguard Worker Value *New = RetVals[index];
236*9880d681SAndroid Build Coastguard Worker if (New) {
237*9880d681SAndroid Build Coastguard Worker if (Argument *A = dyn_cast<Argument>(New))
238*9880d681SAndroid Build Coastguard Worker // Was an argument returned? Then find the corresponding argument in
239*9880d681SAndroid Build Coastguard Worker // the call instruction and use that.
240*9880d681SAndroid Build Coastguard Worker New = CS.getArgument(A->getArgNo());
241*9880d681SAndroid Build Coastguard Worker Ins->replaceAllUsesWith(New);
242*9880d681SAndroid Build Coastguard Worker Ins->eraseFromParent();
243*9880d681SAndroid Build Coastguard Worker }
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker }
246*9880d681SAndroid Build Coastguard Worker }
247*9880d681SAndroid Build Coastguard Worker
248*9880d681SAndroid Build Coastguard Worker if (MadeChange) ++NumReturnValProped;
249*9880d681SAndroid Build Coastguard Worker return MadeChange;
250*9880d681SAndroid Build Coastguard Worker }
251*9880d681SAndroid Build Coastguard Worker
252*9880d681SAndroid Build Coastguard Worker char IPCP::ID = 0;
253*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(IPCP, "ipconstprop",
254*9880d681SAndroid Build Coastguard Worker "Interprocedural constant propagation", false, false)
255*9880d681SAndroid Build Coastguard Worker
createIPConstantPropagationPass()256*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); }
257*9880d681SAndroid Build Coastguard Worker
runOnModule(Module & M)258*9880d681SAndroid Build Coastguard Worker bool IPCP::runOnModule(Module &M) {
259*9880d681SAndroid Build Coastguard Worker if (skipModule(M))
260*9880d681SAndroid Build Coastguard Worker return false;
261*9880d681SAndroid Build Coastguard Worker
262*9880d681SAndroid Build Coastguard Worker bool Changed = false;
263*9880d681SAndroid Build Coastguard Worker bool LocalChange = true;
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker // FIXME: instead of using smart algorithms, we just iterate until we stop
266*9880d681SAndroid Build Coastguard Worker // making changes.
267*9880d681SAndroid Build Coastguard Worker while (LocalChange) {
268*9880d681SAndroid Build Coastguard Worker LocalChange = false;
269*9880d681SAndroid Build Coastguard Worker for (Function &F : M)
270*9880d681SAndroid Build Coastguard Worker if (!F.isDeclaration()) {
271*9880d681SAndroid Build Coastguard Worker // Delete any klingons.
272*9880d681SAndroid Build Coastguard Worker F.removeDeadConstantUsers();
273*9880d681SAndroid Build Coastguard Worker if (F.hasLocalLinkage())
274*9880d681SAndroid Build Coastguard Worker LocalChange |= PropagateConstantsIntoArguments(F);
275*9880d681SAndroid Build Coastguard Worker Changed |= PropagateConstantReturn(F);
276*9880d681SAndroid Build Coastguard Worker }
277*9880d681SAndroid Build Coastguard Worker Changed |= LocalChange;
278*9880d681SAndroid Build Coastguard Worker }
279*9880d681SAndroid Build Coastguard Worker return Changed;
280*9880d681SAndroid Build Coastguard Worker }
281