1*9880d681SAndroid Build Coastguard Worker //=- AArch64PromoteConstant.cpp --- Promote constant to global for AArch64 -==//
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 file implements the AArch64PromoteConstant pass which promotes constants
11*9880d681SAndroid Build Coastguard Worker // to global variables when this is likely to be more efficient. Currently only
12*9880d681SAndroid Build Coastguard Worker // types related to constant vector (i.e., constant vector, array of constant
13*9880d681SAndroid Build Coastguard Worker // vectors, constant structure with a constant vector field, etc.) are promoted
14*9880d681SAndroid Build Coastguard Worker // to global variables. Constant vectors are likely to be lowered in target
15*9880d681SAndroid Build Coastguard Worker // constant pool during instruction selection already; therefore, the access
16*9880d681SAndroid Build Coastguard Worker // will remain the same (memory load), but the structure types are not split
17*9880d681SAndroid Build Coastguard Worker // into different constant pool accesses for each field. A bonus side effect is
18*9880d681SAndroid Build Coastguard Worker // that created globals may be merged by the global merge pass.
19*9880d681SAndroid Build Coastguard Worker //
20*9880d681SAndroid Build Coastguard Worker // FIXME: This pass may be useful for other targets too.
21*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker #include "AArch64.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Dominators.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalVariable.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InlineAsm.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstIterator.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker using namespace llvm;
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "aarch64-promote-const"
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker // Stress testing mode - disable heuristics.
48*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> Stress("aarch64-stress-promote-const", cl::Hidden,
49*9880d681SAndroid Build Coastguard Worker cl::desc("Promote all vector constants"));
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker STATISTIC(NumPromoted, "Number of promoted constants");
52*9880d681SAndroid Build Coastguard Worker STATISTIC(NumPromotedUses, "Number of promoted constants uses");
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
55*9880d681SAndroid Build Coastguard Worker // AArch64PromoteConstant
56*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker namespace {
59*9880d681SAndroid Build Coastguard Worker /// Promotes interesting constant into global variables.
60*9880d681SAndroid Build Coastguard Worker /// The motivating example is:
61*9880d681SAndroid Build Coastguard Worker /// static const uint16_t TableA[32] = {
62*9880d681SAndroid Build Coastguard Worker /// 41944, 40330, 38837, 37450, 36158, 34953, 33826, 32768,
63*9880d681SAndroid Build Coastguard Worker /// 31776, 30841, 29960, 29128, 28340, 27595, 26887, 26215,
64*9880d681SAndroid Build Coastguard Worker /// 25576, 24967, 24386, 23832, 23302, 22796, 22311, 21846,
65*9880d681SAndroid Build Coastguard Worker /// 21400, 20972, 20561, 20165, 19785, 19419, 19066, 18725,
66*9880d681SAndroid Build Coastguard Worker /// };
67*9880d681SAndroid Build Coastguard Worker ///
68*9880d681SAndroid Build Coastguard Worker /// uint8x16x4_t LoadStatic(void) {
69*9880d681SAndroid Build Coastguard Worker /// uint8x16x4_t ret;
70*9880d681SAndroid Build Coastguard Worker /// ret.val[0] = vld1q_u16(TableA + 0);
71*9880d681SAndroid Build Coastguard Worker /// ret.val[1] = vld1q_u16(TableA + 8);
72*9880d681SAndroid Build Coastguard Worker /// ret.val[2] = vld1q_u16(TableA + 16);
73*9880d681SAndroid Build Coastguard Worker /// ret.val[3] = vld1q_u16(TableA + 24);
74*9880d681SAndroid Build Coastguard Worker /// return ret;
75*9880d681SAndroid Build Coastguard Worker /// }
76*9880d681SAndroid Build Coastguard Worker ///
77*9880d681SAndroid Build Coastguard Worker /// The constants in this example are folded into the uses. Thus, 4 different
78*9880d681SAndroid Build Coastguard Worker /// constants are created.
79*9880d681SAndroid Build Coastguard Worker ///
80*9880d681SAndroid Build Coastguard Worker /// As their type is vector the cheapest way to create them is to load them
81*9880d681SAndroid Build Coastguard Worker /// for the memory.
82*9880d681SAndroid Build Coastguard Worker ///
83*9880d681SAndroid Build Coastguard Worker /// Therefore the final assembly final has 4 different loads. With this pass
84*9880d681SAndroid Build Coastguard Worker /// enabled, only one load is issued for the constants.
85*9880d681SAndroid Build Coastguard Worker class AArch64PromoteConstant : public ModulePass {
86*9880d681SAndroid Build Coastguard Worker
87*9880d681SAndroid Build Coastguard Worker public:
88*9880d681SAndroid Build Coastguard Worker struct PromotedConstant {
89*9880d681SAndroid Build Coastguard Worker bool ShouldConvert = false;
90*9880d681SAndroid Build Coastguard Worker GlobalVariable *GV = nullptr;
91*9880d681SAndroid Build Coastguard Worker };
92*9880d681SAndroid Build Coastguard Worker typedef SmallDenseMap<Constant *, PromotedConstant, 16> PromotionCacheTy;
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker struct UpdateRecord {
95*9880d681SAndroid Build Coastguard Worker Constant *C;
96*9880d681SAndroid Build Coastguard Worker Instruction *User;
97*9880d681SAndroid Build Coastguard Worker unsigned Op;
98*9880d681SAndroid Build Coastguard Worker
UpdateRecord__anon375ae52f0111::AArch64PromoteConstant::UpdateRecord99*9880d681SAndroid Build Coastguard Worker UpdateRecord(Constant *C, Instruction *User, unsigned Op)
100*9880d681SAndroid Build Coastguard Worker : C(C), User(User), Op(Op) {}
101*9880d681SAndroid Build Coastguard Worker };
102*9880d681SAndroid Build Coastguard Worker
103*9880d681SAndroid Build Coastguard Worker static char ID;
AArch64PromoteConstant()104*9880d681SAndroid Build Coastguard Worker AArch64PromoteConstant() : ModulePass(ID) {}
105*9880d681SAndroid Build Coastguard Worker
getPassName() const106*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override { return "AArch64 Promote Constant"; }
107*9880d681SAndroid Build Coastguard Worker
108*9880d681SAndroid Build Coastguard Worker /// Iterate over the functions and promote the interesting constants into
109*9880d681SAndroid Build Coastguard Worker /// global variables with module scope.
runOnModule(Module & M)110*9880d681SAndroid Build Coastguard Worker bool runOnModule(Module &M) override {
111*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << getPassName() << '\n');
112*9880d681SAndroid Build Coastguard Worker if (skipModule(M))
113*9880d681SAndroid Build Coastguard Worker return false;
114*9880d681SAndroid Build Coastguard Worker bool Changed = false;
115*9880d681SAndroid Build Coastguard Worker PromotionCacheTy PromotionCache;
116*9880d681SAndroid Build Coastguard Worker for (auto &MF : M) {
117*9880d681SAndroid Build Coastguard Worker Changed |= runOnFunction(MF, PromotionCache);
118*9880d681SAndroid Build Coastguard Worker }
119*9880d681SAndroid Build Coastguard Worker return Changed;
120*9880d681SAndroid Build Coastguard Worker }
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker private:
123*9880d681SAndroid Build Coastguard Worker /// Look for interesting constants used within the given function.
124*9880d681SAndroid Build Coastguard Worker /// Promote them into global variables, load these global variables within
125*9880d681SAndroid Build Coastguard Worker /// the related function, so that the number of inserted load is minimal.
126*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F, PromotionCacheTy &PromotionCache);
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker // This transformation requires dominator info
getAnalysisUsage(AnalysisUsage & AU) const129*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
130*9880d681SAndroid Build Coastguard Worker AU.setPreservesCFG();
131*9880d681SAndroid Build Coastguard Worker AU.addRequired<DominatorTreeWrapperPass>();
132*9880d681SAndroid Build Coastguard Worker AU.addPreserved<DominatorTreeWrapperPass>();
133*9880d681SAndroid Build Coastguard Worker }
134*9880d681SAndroid Build Coastguard Worker
135*9880d681SAndroid Build Coastguard Worker /// Type to store a list of Uses.
136*9880d681SAndroid Build Coastguard Worker typedef SmallVector<std::pair<Instruction *, unsigned>, 4> Uses;
137*9880d681SAndroid Build Coastguard Worker /// Map an insertion point to all the uses it dominates.
138*9880d681SAndroid Build Coastguard Worker typedef DenseMap<Instruction *, Uses> InsertionPoints;
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker /// Find the closest point that dominates the given Use.
141*9880d681SAndroid Build Coastguard Worker Instruction *findInsertionPoint(Instruction &User, unsigned OpNo);
142*9880d681SAndroid Build Coastguard Worker
143*9880d681SAndroid Build Coastguard Worker /// Check if the given insertion point is dominated by an existing
144*9880d681SAndroid Build Coastguard Worker /// insertion point.
145*9880d681SAndroid Build Coastguard Worker /// If true, the given use is added to the list of dominated uses for
146*9880d681SAndroid Build Coastguard Worker /// the related existing point.
147*9880d681SAndroid Build Coastguard Worker /// \param NewPt the insertion point to be checked
148*9880d681SAndroid Build Coastguard Worker /// \param User the user of the constant
149*9880d681SAndroid Build Coastguard Worker /// \param OpNo the operand number of the use
150*9880d681SAndroid Build Coastguard Worker /// \param InsertPts existing insertion points
151*9880d681SAndroid Build Coastguard Worker /// \pre NewPt and all instruction in InsertPts belong to the same function
152*9880d681SAndroid Build Coastguard Worker /// \return true if one of the insertion point in InsertPts dominates NewPt,
153*9880d681SAndroid Build Coastguard Worker /// false otherwise
154*9880d681SAndroid Build Coastguard Worker bool isDominated(Instruction *NewPt, Instruction *User, unsigned OpNo,
155*9880d681SAndroid Build Coastguard Worker InsertionPoints &InsertPts);
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker /// Check if the given insertion point can be merged with an existing
158*9880d681SAndroid Build Coastguard Worker /// insertion point in a common dominator.
159*9880d681SAndroid Build Coastguard Worker /// If true, the given use is added to the list of the created insertion
160*9880d681SAndroid Build Coastguard Worker /// point.
161*9880d681SAndroid Build Coastguard Worker /// \param NewPt the insertion point to be checked
162*9880d681SAndroid Build Coastguard Worker /// \param User the user of the constant
163*9880d681SAndroid Build Coastguard Worker /// \param OpNo the operand number of the use
164*9880d681SAndroid Build Coastguard Worker /// \param InsertPts existing insertion points
165*9880d681SAndroid Build Coastguard Worker /// \pre NewPt and all instruction in InsertPts belong to the same function
166*9880d681SAndroid Build Coastguard Worker /// \pre isDominated returns false for the exact same parameters.
167*9880d681SAndroid Build Coastguard Worker /// \return true if it exists an insertion point in InsertPts that could
168*9880d681SAndroid Build Coastguard Worker /// have been merged with NewPt in a common dominator,
169*9880d681SAndroid Build Coastguard Worker /// false otherwise
170*9880d681SAndroid Build Coastguard Worker bool tryAndMerge(Instruction *NewPt, Instruction *User, unsigned OpNo,
171*9880d681SAndroid Build Coastguard Worker InsertionPoints &InsertPts);
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker /// Compute the minimal insertion points to dominates all the interesting
174*9880d681SAndroid Build Coastguard Worker /// uses of value.
175*9880d681SAndroid Build Coastguard Worker /// Insertion points are group per function and each insertion point
176*9880d681SAndroid Build Coastguard Worker /// contains a list of all the uses it dominates within the related function
177*9880d681SAndroid Build Coastguard Worker /// \param User the user of the constant
178*9880d681SAndroid Build Coastguard Worker /// \param OpNo the operand number of the constant
179*9880d681SAndroid Build Coastguard Worker /// \param[out] InsertPts output storage of the analysis
180*9880d681SAndroid Build Coastguard Worker void computeInsertionPoint(Instruction *User, unsigned OpNo,
181*9880d681SAndroid Build Coastguard Worker InsertionPoints &InsertPts);
182*9880d681SAndroid Build Coastguard Worker
183*9880d681SAndroid Build Coastguard Worker /// Insert a definition of a new global variable at each point contained in
184*9880d681SAndroid Build Coastguard Worker /// InsPtsPerFunc and update the related uses (also contained in
185*9880d681SAndroid Build Coastguard Worker /// InsPtsPerFunc).
186*9880d681SAndroid Build Coastguard Worker void insertDefinitions(Function &F, GlobalVariable &GV,
187*9880d681SAndroid Build Coastguard Worker InsertionPoints &InsertPts);
188*9880d681SAndroid Build Coastguard Worker
189*9880d681SAndroid Build Coastguard Worker /// Do the constant promotion indicated by the Updates records, keeping track
190*9880d681SAndroid Build Coastguard Worker /// of globals in PromotionCache.
191*9880d681SAndroid Build Coastguard Worker void promoteConstants(Function &F, SmallVectorImpl<UpdateRecord> &Updates,
192*9880d681SAndroid Build Coastguard Worker PromotionCacheTy &PromotionCache);
193*9880d681SAndroid Build Coastguard Worker
194*9880d681SAndroid Build Coastguard Worker /// Transfer the list of dominated uses of IPI to NewPt in InsertPts.
195*9880d681SAndroid Build Coastguard Worker /// Append Use to this list and delete the entry of IPI in InsertPts.
appendAndTransferDominatedUses(Instruction * NewPt,Instruction * User,unsigned OpNo,InsertionPoints::iterator & IPI,InsertionPoints & InsertPts)196*9880d681SAndroid Build Coastguard Worker static void appendAndTransferDominatedUses(Instruction *NewPt,
197*9880d681SAndroid Build Coastguard Worker Instruction *User, unsigned OpNo,
198*9880d681SAndroid Build Coastguard Worker InsertionPoints::iterator &IPI,
199*9880d681SAndroid Build Coastguard Worker InsertionPoints &InsertPts) {
200*9880d681SAndroid Build Coastguard Worker // Record the dominated use.
201*9880d681SAndroid Build Coastguard Worker IPI->second.emplace_back(User, OpNo);
202*9880d681SAndroid Build Coastguard Worker // Transfer the dominated uses of IPI to NewPt
203*9880d681SAndroid Build Coastguard Worker // Inserting into the DenseMap may invalidate existing iterator.
204*9880d681SAndroid Build Coastguard Worker // Keep a copy of the key to find the iterator to erase. Keep a copy of the
205*9880d681SAndroid Build Coastguard Worker // value so that we don't have to dereference IPI->second.
206*9880d681SAndroid Build Coastguard Worker Instruction *OldInstr = IPI->first;
207*9880d681SAndroid Build Coastguard Worker Uses OldUses = std::move(IPI->second);
208*9880d681SAndroid Build Coastguard Worker InsertPts[NewPt] = std::move(OldUses);
209*9880d681SAndroid Build Coastguard Worker // Erase IPI.
210*9880d681SAndroid Build Coastguard Worker InsertPts.erase(OldInstr);
211*9880d681SAndroid Build Coastguard Worker }
212*9880d681SAndroid Build Coastguard Worker };
213*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
214*9880d681SAndroid Build Coastguard Worker
215*9880d681SAndroid Build Coastguard Worker char AArch64PromoteConstant::ID = 0;
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Worker namespace llvm {
218*9880d681SAndroid Build Coastguard Worker void initializeAArch64PromoteConstantPass(PassRegistry &);
219*9880d681SAndroid Build Coastguard Worker }
220*9880d681SAndroid Build Coastguard Worker
221*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(AArch64PromoteConstant, "aarch64-promote-const",
222*9880d681SAndroid Build Coastguard Worker "AArch64 Promote Constant Pass", false, false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)223*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
224*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(AArch64PromoteConstant, "aarch64-promote-const",
225*9880d681SAndroid Build Coastguard Worker "AArch64 Promote Constant Pass", false, false)
226*9880d681SAndroid Build Coastguard Worker
227*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createAArch64PromoteConstantPass() {
228*9880d681SAndroid Build Coastguard Worker return new AArch64PromoteConstant();
229*9880d681SAndroid Build Coastguard Worker }
230*9880d681SAndroid Build Coastguard Worker
231*9880d681SAndroid Build Coastguard Worker /// Check if the given type uses a vector type.
isConstantUsingVectorTy(const Type * CstTy)232*9880d681SAndroid Build Coastguard Worker static bool isConstantUsingVectorTy(const Type *CstTy) {
233*9880d681SAndroid Build Coastguard Worker if (CstTy->isVectorTy())
234*9880d681SAndroid Build Coastguard Worker return true;
235*9880d681SAndroid Build Coastguard Worker if (CstTy->isStructTy()) {
236*9880d681SAndroid Build Coastguard Worker for (unsigned EltIdx = 0, EndEltIdx = CstTy->getStructNumElements();
237*9880d681SAndroid Build Coastguard Worker EltIdx < EndEltIdx; ++EltIdx)
238*9880d681SAndroid Build Coastguard Worker if (isConstantUsingVectorTy(CstTy->getStructElementType(EltIdx)))
239*9880d681SAndroid Build Coastguard Worker return true;
240*9880d681SAndroid Build Coastguard Worker } else if (CstTy->isArrayTy())
241*9880d681SAndroid Build Coastguard Worker return isConstantUsingVectorTy(CstTy->getArrayElementType());
242*9880d681SAndroid Build Coastguard Worker return false;
243*9880d681SAndroid Build Coastguard Worker }
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker /// Check if the given use (Instruction + OpIdx) of Cst should be converted into
246*9880d681SAndroid Build Coastguard Worker /// a load of a global variable initialized with Cst.
247*9880d681SAndroid Build Coastguard Worker /// A use should be converted if it is legal to do so.
248*9880d681SAndroid Build Coastguard Worker /// For instance, it is not legal to turn the mask operand of a shuffle vector
249*9880d681SAndroid Build Coastguard Worker /// into a load of a global variable.
shouldConvertUse(const Constant * Cst,const Instruction * Instr,unsigned OpIdx)250*9880d681SAndroid Build Coastguard Worker static bool shouldConvertUse(const Constant *Cst, const Instruction *Instr,
251*9880d681SAndroid Build Coastguard Worker unsigned OpIdx) {
252*9880d681SAndroid Build Coastguard Worker // shufflevector instruction expects a const for the mask argument, i.e., the
253*9880d681SAndroid Build Coastguard Worker // third argument. Do not promote this use in that case.
254*9880d681SAndroid Build Coastguard Worker if (isa<const ShuffleVectorInst>(Instr) && OpIdx == 2)
255*9880d681SAndroid Build Coastguard Worker return false;
256*9880d681SAndroid Build Coastguard Worker
257*9880d681SAndroid Build Coastguard Worker // extractvalue instruction expects a const idx.
258*9880d681SAndroid Build Coastguard Worker if (isa<const ExtractValueInst>(Instr) && OpIdx > 0)
259*9880d681SAndroid Build Coastguard Worker return false;
260*9880d681SAndroid Build Coastguard Worker
261*9880d681SAndroid Build Coastguard Worker // extractvalue instruction expects a const idx.
262*9880d681SAndroid Build Coastguard Worker if (isa<const InsertValueInst>(Instr) && OpIdx > 1)
263*9880d681SAndroid Build Coastguard Worker return false;
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker if (isa<const AllocaInst>(Instr) && OpIdx > 0)
266*9880d681SAndroid Build Coastguard Worker return false;
267*9880d681SAndroid Build Coastguard Worker
268*9880d681SAndroid Build Coastguard Worker // Alignment argument must be constant.
269*9880d681SAndroid Build Coastguard Worker if (isa<const LoadInst>(Instr) && OpIdx > 0)
270*9880d681SAndroid Build Coastguard Worker return false;
271*9880d681SAndroid Build Coastguard Worker
272*9880d681SAndroid Build Coastguard Worker // Alignment argument must be constant.
273*9880d681SAndroid Build Coastguard Worker if (isa<const StoreInst>(Instr) && OpIdx > 1)
274*9880d681SAndroid Build Coastguard Worker return false;
275*9880d681SAndroid Build Coastguard Worker
276*9880d681SAndroid Build Coastguard Worker // Index must be constant.
277*9880d681SAndroid Build Coastguard Worker if (isa<const GetElementPtrInst>(Instr) && OpIdx > 0)
278*9880d681SAndroid Build Coastguard Worker return false;
279*9880d681SAndroid Build Coastguard Worker
280*9880d681SAndroid Build Coastguard Worker // Personality function and filters must be constant.
281*9880d681SAndroid Build Coastguard Worker // Give up on that instruction.
282*9880d681SAndroid Build Coastguard Worker if (isa<const LandingPadInst>(Instr))
283*9880d681SAndroid Build Coastguard Worker return false;
284*9880d681SAndroid Build Coastguard Worker
285*9880d681SAndroid Build Coastguard Worker // Switch instruction expects constants to compare to.
286*9880d681SAndroid Build Coastguard Worker if (isa<const SwitchInst>(Instr))
287*9880d681SAndroid Build Coastguard Worker return false;
288*9880d681SAndroid Build Coastguard Worker
289*9880d681SAndroid Build Coastguard Worker // Expected address must be a constant.
290*9880d681SAndroid Build Coastguard Worker if (isa<const IndirectBrInst>(Instr))
291*9880d681SAndroid Build Coastguard Worker return false;
292*9880d681SAndroid Build Coastguard Worker
293*9880d681SAndroid Build Coastguard Worker // Do not mess with intrinsics.
294*9880d681SAndroid Build Coastguard Worker if (isa<const IntrinsicInst>(Instr))
295*9880d681SAndroid Build Coastguard Worker return false;
296*9880d681SAndroid Build Coastguard Worker
297*9880d681SAndroid Build Coastguard Worker // Do not mess with inline asm.
298*9880d681SAndroid Build Coastguard Worker const CallInst *CI = dyn_cast<const CallInst>(Instr);
299*9880d681SAndroid Build Coastguard Worker return !(CI && isa<const InlineAsm>(CI->getCalledValue()));
300*9880d681SAndroid Build Coastguard Worker }
301*9880d681SAndroid Build Coastguard Worker
302*9880d681SAndroid Build Coastguard Worker /// Check if the given Cst should be converted into
303*9880d681SAndroid Build Coastguard Worker /// a load of a global variable initialized with Cst.
304*9880d681SAndroid Build Coastguard Worker /// A constant should be converted if it is likely that the materialization of
305*9880d681SAndroid Build Coastguard Worker /// the constant will be tricky. Thus, we give up on zero or undef values.
306*9880d681SAndroid Build Coastguard Worker ///
307*9880d681SAndroid Build Coastguard Worker /// \todo Currently, accept only vector related types.
308*9880d681SAndroid Build Coastguard Worker /// Also we give up on all simple vector type to keep the existing
309*9880d681SAndroid Build Coastguard Worker /// behavior. Otherwise, we should push here all the check of the lowering of
310*9880d681SAndroid Build Coastguard Worker /// BUILD_VECTOR. By giving up, we lose the potential benefit of merging
311*9880d681SAndroid Build Coastguard Worker /// constant via global merge and the fact that the same constant is stored
312*9880d681SAndroid Build Coastguard Worker /// only once with this method (versus, as many function that uses the constant
313*9880d681SAndroid Build Coastguard Worker /// for the regular approach, even for float).
314*9880d681SAndroid Build Coastguard Worker /// Again, the simplest solution would be to promote every
315*9880d681SAndroid Build Coastguard Worker /// constant and rematerialize them when they are actually cheap to create.
shouldConvertImpl(const Constant * Cst)316*9880d681SAndroid Build Coastguard Worker static bool shouldConvertImpl(const Constant *Cst) {
317*9880d681SAndroid Build Coastguard Worker if (isa<const UndefValue>(Cst))
318*9880d681SAndroid Build Coastguard Worker return false;
319*9880d681SAndroid Build Coastguard Worker
320*9880d681SAndroid Build Coastguard Worker // FIXME: In some cases, it may be interesting to promote in memory
321*9880d681SAndroid Build Coastguard Worker // a zero initialized constant.
322*9880d681SAndroid Build Coastguard Worker // E.g., when the type of Cst require more instructions than the
323*9880d681SAndroid Build Coastguard Worker // adrp/add/load sequence or when this sequence can be shared by several
324*9880d681SAndroid Build Coastguard Worker // instances of Cst.
325*9880d681SAndroid Build Coastguard Worker // Ideally, we could promote this into a global and rematerialize the constant
326*9880d681SAndroid Build Coastguard Worker // when it was a bad idea.
327*9880d681SAndroid Build Coastguard Worker if (Cst->isZeroValue())
328*9880d681SAndroid Build Coastguard Worker return false;
329*9880d681SAndroid Build Coastguard Worker
330*9880d681SAndroid Build Coastguard Worker if (Stress)
331*9880d681SAndroid Build Coastguard Worker return true;
332*9880d681SAndroid Build Coastguard Worker
333*9880d681SAndroid Build Coastguard Worker // FIXME: see function \todo
334*9880d681SAndroid Build Coastguard Worker if (Cst->getType()->isVectorTy())
335*9880d681SAndroid Build Coastguard Worker return false;
336*9880d681SAndroid Build Coastguard Worker return isConstantUsingVectorTy(Cst->getType());
337*9880d681SAndroid Build Coastguard Worker }
338*9880d681SAndroid Build Coastguard Worker
339*9880d681SAndroid Build Coastguard Worker static bool
shouldConvert(Constant & C,AArch64PromoteConstant::PromotionCacheTy & PromotionCache)340*9880d681SAndroid Build Coastguard Worker shouldConvert(Constant &C,
341*9880d681SAndroid Build Coastguard Worker AArch64PromoteConstant::PromotionCacheTy &PromotionCache) {
342*9880d681SAndroid Build Coastguard Worker auto Converted = PromotionCache.insert(
343*9880d681SAndroid Build Coastguard Worker std::make_pair(&C, AArch64PromoteConstant::PromotedConstant()));
344*9880d681SAndroid Build Coastguard Worker if (Converted.second)
345*9880d681SAndroid Build Coastguard Worker Converted.first->second.ShouldConvert = shouldConvertImpl(&C);
346*9880d681SAndroid Build Coastguard Worker return Converted.first->second.ShouldConvert;
347*9880d681SAndroid Build Coastguard Worker }
348*9880d681SAndroid Build Coastguard Worker
findInsertionPoint(Instruction & User,unsigned OpNo)349*9880d681SAndroid Build Coastguard Worker Instruction *AArch64PromoteConstant::findInsertionPoint(Instruction &User,
350*9880d681SAndroid Build Coastguard Worker unsigned OpNo) {
351*9880d681SAndroid Build Coastguard Worker // If this user is a phi, the insertion point is in the related
352*9880d681SAndroid Build Coastguard Worker // incoming basic block.
353*9880d681SAndroid Build Coastguard Worker if (PHINode *PhiInst = dyn_cast<PHINode>(&User))
354*9880d681SAndroid Build Coastguard Worker return PhiInst->getIncomingBlock(OpNo)->getTerminator();
355*9880d681SAndroid Build Coastguard Worker
356*9880d681SAndroid Build Coastguard Worker return &User;
357*9880d681SAndroid Build Coastguard Worker }
358*9880d681SAndroid Build Coastguard Worker
isDominated(Instruction * NewPt,Instruction * User,unsigned OpNo,InsertionPoints & InsertPts)359*9880d681SAndroid Build Coastguard Worker bool AArch64PromoteConstant::isDominated(Instruction *NewPt, Instruction *User,
360*9880d681SAndroid Build Coastguard Worker unsigned OpNo,
361*9880d681SAndroid Build Coastguard Worker InsertionPoints &InsertPts) {
362*9880d681SAndroid Build Coastguard Worker
363*9880d681SAndroid Build Coastguard Worker DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(
364*9880d681SAndroid Build Coastguard Worker *NewPt->getParent()->getParent()).getDomTree();
365*9880d681SAndroid Build Coastguard Worker
366*9880d681SAndroid Build Coastguard Worker // Traverse all the existing insertion points and check if one is dominating
367*9880d681SAndroid Build Coastguard Worker // NewPt. If it is, remember that.
368*9880d681SAndroid Build Coastguard Worker for (auto &IPI : InsertPts) {
369*9880d681SAndroid Build Coastguard Worker if (NewPt == IPI.first || DT.dominates(IPI.first, NewPt) ||
370*9880d681SAndroid Build Coastguard Worker // When IPI.first is a terminator instruction, DT may think that
371*9880d681SAndroid Build Coastguard Worker // the result is defined on the edge.
372*9880d681SAndroid Build Coastguard Worker // Here we are testing the insertion point, not the definition.
373*9880d681SAndroid Build Coastguard Worker (IPI.first->getParent() != NewPt->getParent() &&
374*9880d681SAndroid Build Coastguard Worker DT.dominates(IPI.first->getParent(), NewPt->getParent()))) {
375*9880d681SAndroid Build Coastguard Worker // No need to insert this point. Just record the dominated use.
376*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Insertion point dominated by:\n");
377*9880d681SAndroid Build Coastguard Worker DEBUG(IPI.first->print(dbgs()));
378*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << '\n');
379*9880d681SAndroid Build Coastguard Worker IPI.second.emplace_back(User, OpNo);
380*9880d681SAndroid Build Coastguard Worker return true;
381*9880d681SAndroid Build Coastguard Worker }
382*9880d681SAndroid Build Coastguard Worker }
383*9880d681SAndroid Build Coastguard Worker return false;
384*9880d681SAndroid Build Coastguard Worker }
385*9880d681SAndroid Build Coastguard Worker
tryAndMerge(Instruction * NewPt,Instruction * User,unsigned OpNo,InsertionPoints & InsertPts)386*9880d681SAndroid Build Coastguard Worker bool AArch64PromoteConstant::tryAndMerge(Instruction *NewPt, Instruction *User,
387*9880d681SAndroid Build Coastguard Worker unsigned OpNo,
388*9880d681SAndroid Build Coastguard Worker InsertionPoints &InsertPts) {
389*9880d681SAndroid Build Coastguard Worker DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(
390*9880d681SAndroid Build Coastguard Worker *NewPt->getParent()->getParent()).getDomTree();
391*9880d681SAndroid Build Coastguard Worker BasicBlock *NewBB = NewPt->getParent();
392*9880d681SAndroid Build Coastguard Worker
393*9880d681SAndroid Build Coastguard Worker // Traverse all the existing insertion point and check if one is dominated by
394*9880d681SAndroid Build Coastguard Worker // NewPt and thus useless or can be combined with NewPt into a common
395*9880d681SAndroid Build Coastguard Worker // dominator.
396*9880d681SAndroid Build Coastguard Worker for (InsertionPoints::iterator IPI = InsertPts.begin(),
397*9880d681SAndroid Build Coastguard Worker EndIPI = InsertPts.end();
398*9880d681SAndroid Build Coastguard Worker IPI != EndIPI; ++IPI) {
399*9880d681SAndroid Build Coastguard Worker BasicBlock *CurBB = IPI->first->getParent();
400*9880d681SAndroid Build Coastguard Worker if (NewBB == CurBB) {
401*9880d681SAndroid Build Coastguard Worker // Instructions are in the same block.
402*9880d681SAndroid Build Coastguard Worker // By construction, NewPt is dominating the other.
403*9880d681SAndroid Build Coastguard Worker // Indeed, isDominated returned false with the exact same arguments.
404*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Merge insertion point with:\n");
405*9880d681SAndroid Build Coastguard Worker DEBUG(IPI->first->print(dbgs()));
406*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\nat considered insertion point.\n");
407*9880d681SAndroid Build Coastguard Worker appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts);
408*9880d681SAndroid Build Coastguard Worker return true;
409*9880d681SAndroid Build Coastguard Worker }
410*9880d681SAndroid Build Coastguard Worker
411*9880d681SAndroid Build Coastguard Worker // Look for a common dominator
412*9880d681SAndroid Build Coastguard Worker BasicBlock *CommonDominator = DT.findNearestCommonDominator(NewBB, CurBB);
413*9880d681SAndroid Build Coastguard Worker // If none exists, we cannot merge these two points.
414*9880d681SAndroid Build Coastguard Worker if (!CommonDominator)
415*9880d681SAndroid Build Coastguard Worker continue;
416*9880d681SAndroid Build Coastguard Worker
417*9880d681SAndroid Build Coastguard Worker if (CommonDominator != NewBB) {
418*9880d681SAndroid Build Coastguard Worker // By construction, the CommonDominator cannot be CurBB.
419*9880d681SAndroid Build Coastguard Worker assert(CommonDominator != CurBB &&
420*9880d681SAndroid Build Coastguard Worker "Instruction has not been rejected during isDominated check!");
421*9880d681SAndroid Build Coastguard Worker // Take the last instruction of the CommonDominator as insertion point
422*9880d681SAndroid Build Coastguard Worker NewPt = CommonDominator->getTerminator();
423*9880d681SAndroid Build Coastguard Worker }
424*9880d681SAndroid Build Coastguard Worker // else, CommonDominator is the block of NewBB, hence NewBB is the last
425*9880d681SAndroid Build Coastguard Worker // possible insertion point in that block.
426*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Merge insertion point with:\n");
427*9880d681SAndroid Build Coastguard Worker DEBUG(IPI->first->print(dbgs()));
428*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << '\n');
429*9880d681SAndroid Build Coastguard Worker DEBUG(NewPt->print(dbgs()));
430*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << '\n');
431*9880d681SAndroid Build Coastguard Worker appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts);
432*9880d681SAndroid Build Coastguard Worker return true;
433*9880d681SAndroid Build Coastguard Worker }
434*9880d681SAndroid Build Coastguard Worker return false;
435*9880d681SAndroid Build Coastguard Worker }
436*9880d681SAndroid Build Coastguard Worker
computeInsertionPoint(Instruction * User,unsigned OpNo,InsertionPoints & InsertPts)437*9880d681SAndroid Build Coastguard Worker void AArch64PromoteConstant::computeInsertionPoint(
438*9880d681SAndroid Build Coastguard Worker Instruction *User, unsigned OpNo, InsertionPoints &InsertPts) {
439*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Considered use, opidx " << OpNo << ":\n");
440*9880d681SAndroid Build Coastguard Worker DEBUG(User->print(dbgs()));
441*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << '\n');
442*9880d681SAndroid Build Coastguard Worker
443*9880d681SAndroid Build Coastguard Worker Instruction *InsertionPoint = findInsertionPoint(*User, OpNo);
444*9880d681SAndroid Build Coastguard Worker
445*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Considered insertion point:\n");
446*9880d681SAndroid Build Coastguard Worker DEBUG(InsertionPoint->print(dbgs()));
447*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << '\n');
448*9880d681SAndroid Build Coastguard Worker
449*9880d681SAndroid Build Coastguard Worker if (isDominated(InsertionPoint, User, OpNo, InsertPts))
450*9880d681SAndroid Build Coastguard Worker return;
451*9880d681SAndroid Build Coastguard Worker // This insertion point is useful, check if we can merge some insertion
452*9880d681SAndroid Build Coastguard Worker // point in a common dominator or if NewPt dominates an existing one.
453*9880d681SAndroid Build Coastguard Worker if (tryAndMerge(InsertionPoint, User, OpNo, InsertPts))
454*9880d681SAndroid Build Coastguard Worker return;
455*9880d681SAndroid Build Coastguard Worker
456*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Keep considered insertion point\n");
457*9880d681SAndroid Build Coastguard Worker
458*9880d681SAndroid Build Coastguard Worker // It is definitely useful by its own
459*9880d681SAndroid Build Coastguard Worker InsertPts[InsertionPoint].emplace_back(User, OpNo);
460*9880d681SAndroid Build Coastguard Worker }
461*9880d681SAndroid Build Coastguard Worker
ensurePromotedGV(Function & F,Constant & C,AArch64PromoteConstant::PromotedConstant & PC)462*9880d681SAndroid Build Coastguard Worker static void ensurePromotedGV(Function &F, Constant &C,
463*9880d681SAndroid Build Coastguard Worker AArch64PromoteConstant::PromotedConstant &PC) {
464*9880d681SAndroid Build Coastguard Worker assert(PC.ShouldConvert &&
465*9880d681SAndroid Build Coastguard Worker "Expected that we should convert this to a global");
466*9880d681SAndroid Build Coastguard Worker if (PC.GV)
467*9880d681SAndroid Build Coastguard Worker return;
468*9880d681SAndroid Build Coastguard Worker PC.GV = new GlobalVariable(
469*9880d681SAndroid Build Coastguard Worker *F.getParent(), C.getType(), true, GlobalValue::InternalLinkage, nullptr,
470*9880d681SAndroid Build Coastguard Worker "_PromotedConst", nullptr, GlobalVariable::NotThreadLocal);
471*9880d681SAndroid Build Coastguard Worker PC.GV->setInitializer(&C);
472*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Global replacement: ");
473*9880d681SAndroid Build Coastguard Worker DEBUG(PC.GV->print(dbgs()));
474*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << '\n');
475*9880d681SAndroid Build Coastguard Worker ++NumPromoted;
476*9880d681SAndroid Build Coastguard Worker }
477*9880d681SAndroid Build Coastguard Worker
insertDefinitions(Function & F,GlobalVariable & PromotedGV,InsertionPoints & InsertPts)478*9880d681SAndroid Build Coastguard Worker void AArch64PromoteConstant::insertDefinitions(Function &F,
479*9880d681SAndroid Build Coastguard Worker GlobalVariable &PromotedGV,
480*9880d681SAndroid Build Coastguard Worker InsertionPoints &InsertPts) {
481*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
482*9880d681SAndroid Build Coastguard Worker // Do more checking for debug purposes.
483*9880d681SAndroid Build Coastguard Worker DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
484*9880d681SAndroid Build Coastguard Worker #endif
485*9880d681SAndroid Build Coastguard Worker assert(!InsertPts.empty() && "Empty uses does not need a definition");
486*9880d681SAndroid Build Coastguard Worker
487*9880d681SAndroid Build Coastguard Worker for (const auto &IPI : InsertPts) {
488*9880d681SAndroid Build Coastguard Worker // Create the load of the global variable.
489*9880d681SAndroid Build Coastguard Worker IRBuilder<> Builder(IPI.first);
490*9880d681SAndroid Build Coastguard Worker LoadInst *LoadedCst = Builder.CreateLoad(&PromotedGV);
491*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "**********\n");
492*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "New def: ");
493*9880d681SAndroid Build Coastguard Worker DEBUG(LoadedCst->print(dbgs()));
494*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << '\n');
495*9880d681SAndroid Build Coastguard Worker
496*9880d681SAndroid Build Coastguard Worker // Update the dominated uses.
497*9880d681SAndroid Build Coastguard Worker for (auto Use : IPI.second) {
498*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
499*9880d681SAndroid Build Coastguard Worker assert(DT.dominates(LoadedCst,
500*9880d681SAndroid Build Coastguard Worker findInsertionPoint(*Use.first, Use.second)) &&
501*9880d681SAndroid Build Coastguard Worker "Inserted definition does not dominate all its uses!");
502*9880d681SAndroid Build Coastguard Worker #endif
503*9880d681SAndroid Build Coastguard Worker DEBUG({
504*9880d681SAndroid Build Coastguard Worker dbgs() << "Use to update " << Use.second << ":";
505*9880d681SAndroid Build Coastguard Worker Use.first->print(dbgs());
506*9880d681SAndroid Build Coastguard Worker dbgs() << '\n';
507*9880d681SAndroid Build Coastguard Worker });
508*9880d681SAndroid Build Coastguard Worker Use.first->setOperand(Use.second, LoadedCst);
509*9880d681SAndroid Build Coastguard Worker ++NumPromotedUses;
510*9880d681SAndroid Build Coastguard Worker }
511*9880d681SAndroid Build Coastguard Worker }
512*9880d681SAndroid Build Coastguard Worker }
513*9880d681SAndroid Build Coastguard Worker
promoteConstants(Function & F,SmallVectorImpl<UpdateRecord> & Updates,PromotionCacheTy & PromotionCache)514*9880d681SAndroid Build Coastguard Worker void AArch64PromoteConstant::promoteConstants(
515*9880d681SAndroid Build Coastguard Worker Function &F, SmallVectorImpl<UpdateRecord> &Updates,
516*9880d681SAndroid Build Coastguard Worker PromotionCacheTy &PromotionCache) {
517*9880d681SAndroid Build Coastguard Worker // Promote the constants.
518*9880d681SAndroid Build Coastguard Worker for (auto U = Updates.begin(), E = Updates.end(); U != E;) {
519*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "** Compute insertion points **\n");
520*9880d681SAndroid Build Coastguard Worker auto First = U;
521*9880d681SAndroid Build Coastguard Worker Constant *C = First->C;
522*9880d681SAndroid Build Coastguard Worker InsertionPoints InsertPts;
523*9880d681SAndroid Build Coastguard Worker do {
524*9880d681SAndroid Build Coastguard Worker computeInsertionPoint(U->User, U->Op, InsertPts);
525*9880d681SAndroid Build Coastguard Worker } while (++U != E && U->C == C);
526*9880d681SAndroid Build Coastguard Worker
527*9880d681SAndroid Build Coastguard Worker auto &Promotion = PromotionCache[C];
528*9880d681SAndroid Build Coastguard Worker ensurePromotedGV(F, *C, Promotion);
529*9880d681SAndroid Build Coastguard Worker insertDefinitions(F, *Promotion.GV, InsertPts);
530*9880d681SAndroid Build Coastguard Worker }
531*9880d681SAndroid Build Coastguard Worker }
532*9880d681SAndroid Build Coastguard Worker
runOnFunction(Function & F,PromotionCacheTy & PromotionCache)533*9880d681SAndroid Build Coastguard Worker bool AArch64PromoteConstant::runOnFunction(Function &F,
534*9880d681SAndroid Build Coastguard Worker PromotionCacheTy &PromotionCache) {
535*9880d681SAndroid Build Coastguard Worker // Look for instructions using constant vector. Promote that constant to a
536*9880d681SAndroid Build Coastguard Worker // global variable. Create as few loads of this variable as possible and
537*9880d681SAndroid Build Coastguard Worker // update the uses accordingly.
538*9880d681SAndroid Build Coastguard Worker SmallVector<UpdateRecord, 64> Updates;
539*9880d681SAndroid Build Coastguard Worker for (Instruction &I : instructions(&F)) {
540*9880d681SAndroid Build Coastguard Worker // Traverse the operand, looking for constant vectors. Replace them by a
541*9880d681SAndroid Build Coastguard Worker // load of a global variable of constant vector type.
542*9880d681SAndroid Build Coastguard Worker for (Use &U : I.operands()) {
543*9880d681SAndroid Build Coastguard Worker Constant *Cst = dyn_cast<Constant>(U);
544*9880d681SAndroid Build Coastguard Worker // There is no point in promoting global values as they are already
545*9880d681SAndroid Build Coastguard Worker // global. Do not promote constant expressions either, as they may
546*9880d681SAndroid Build Coastguard Worker // require some code expansion.
547*9880d681SAndroid Build Coastguard Worker if (!Cst || isa<GlobalValue>(Cst) || isa<ConstantExpr>(Cst))
548*9880d681SAndroid Build Coastguard Worker continue;
549*9880d681SAndroid Build Coastguard Worker
550*9880d681SAndroid Build Coastguard Worker // Check if this constant is worth promoting.
551*9880d681SAndroid Build Coastguard Worker if (!shouldConvert(*Cst, PromotionCache))
552*9880d681SAndroid Build Coastguard Worker continue;
553*9880d681SAndroid Build Coastguard Worker
554*9880d681SAndroid Build Coastguard Worker // Check if this use should be promoted.
555*9880d681SAndroid Build Coastguard Worker unsigned OpNo = &U - I.op_begin();
556*9880d681SAndroid Build Coastguard Worker if (!shouldConvertUse(Cst, &I, OpNo))
557*9880d681SAndroid Build Coastguard Worker continue;
558*9880d681SAndroid Build Coastguard Worker
559*9880d681SAndroid Build Coastguard Worker Updates.emplace_back(Cst, &I, OpNo);
560*9880d681SAndroid Build Coastguard Worker }
561*9880d681SAndroid Build Coastguard Worker }
562*9880d681SAndroid Build Coastguard Worker
563*9880d681SAndroid Build Coastguard Worker if (Updates.empty())
564*9880d681SAndroid Build Coastguard Worker return false;
565*9880d681SAndroid Build Coastguard Worker
566*9880d681SAndroid Build Coastguard Worker promoteConstants(F, Updates, PromotionCache);
567*9880d681SAndroid Build Coastguard Worker return true;
568*9880d681SAndroid Build Coastguard Worker }
569