xref: /aosp_15_r20/external/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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