1 | //===- ConstantHoisting.cpp - Prepare code for expensive constants --------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This pass identifies expensive constants to hoist and coalesces them to |
10 | // better prepare it for SelectionDAG-based code generation. This works around |
11 | // the limitations of the basic-block-at-a-time approach. |
12 | // |
13 | // First it scans all instructions for integer constants and calculates its |
14 | // cost. If the constant can be folded into the instruction (the cost is |
15 | // TCC_Free) or the cost is just a simple operation (TCC_BASIC), then we don't |
16 | // consider it expensive and leave it alone. This is the default behavior and |
17 | // the default implementation of getIntImmCostInst will always return TCC_Free. |
18 | // |
19 | // If the cost is more than TCC_BASIC, then the integer constant can't be folded |
20 | // into the instruction and it might be beneficial to hoist the constant. |
21 | // Similar constants are coalesced to reduce register pressure and |
22 | // materialization code. |
23 | // |
24 | // When a constant is hoisted, it is also hidden behind a bitcast to force it to |
25 | // be live-out of the basic block. Otherwise the constant would be just |
26 | // duplicated and each basic block would have its own copy in the SelectionDAG. |
27 | // The SelectionDAG recognizes such constants as opaque and doesn't perform |
28 | // certain transformations on them, which would create a new expensive constant. |
29 | // |
30 | // This optimization is only applied to integer constants in instructions and |
31 | // simple (this means not nested) constant cast expressions. For example: |
32 | // %0 = load i64* inttoptr (i64 big_constant to i64*) |
33 | //===----------------------------------------------------------------------===// |
34 | |
35 | #include "llvm/Transforms/Scalar/ConstantHoisting.h" |
36 | #include "llvm/ADT/APInt.h" |
37 | #include "llvm/ADT/DenseMap.h" |
38 | #include "llvm/ADT/SmallPtrSet.h" |
39 | #include "llvm/ADT/SmallVector.h" |
40 | #include "llvm/ADT/Statistic.h" |
41 | #include "llvm/Analysis/BlockFrequencyInfo.h" |
42 | #include "llvm/Analysis/ProfileSummaryInfo.h" |
43 | #include "llvm/Analysis/TargetTransformInfo.h" |
44 | #include "llvm/IR/BasicBlock.h" |
45 | #include "llvm/IR/Constants.h" |
46 | #include "llvm/IR/DataLayout.h" |
47 | #include "llvm/IR/Dominators.h" |
48 | #include "llvm/IR/Function.h" |
49 | #include "llvm/IR/InstrTypes.h" |
50 | #include "llvm/IR/Instruction.h" |
51 | #include "llvm/IR/Instructions.h" |
52 | #include "llvm/IR/IntrinsicInst.h" |
53 | #include "llvm/IR/Operator.h" |
54 | #include "llvm/IR/Value.h" |
55 | #include "llvm/InitializePasses.h" |
56 | #include "llvm/Pass.h" |
57 | #include "llvm/Support/BlockFrequency.h" |
58 | #include "llvm/Support/Casting.h" |
59 | #include "llvm/Support/CommandLine.h" |
60 | #include "llvm/Support/Debug.h" |
61 | #include "llvm/Support/raw_ostream.h" |
62 | #include "llvm/Transforms/Scalar.h" |
63 | #include "llvm/Transforms/Utils/Local.h" |
64 | #include "llvm/Transforms/Utils/SizeOpts.h" |
65 | #include <cassert> |
66 | #include <iterator> |
67 | #include <tuple> |
68 | #include <utility> |
69 | |
70 | using namespace llvm; |
71 | using namespace consthoist; |
72 | |
73 | #define DEBUG_TYPE "consthoist" |
74 | |
75 | STATISTIC(NumConstantsHoisted, "Number of constants hoisted" ); |
76 | STATISTIC(NumConstantsRebased, "Number of constants rebased" ); |
77 | |
78 | static cl::opt<bool> ConstHoistWithBlockFrequency( |
79 | "consthoist-with-block-frequency" , cl::init(Val: true), cl::Hidden, |
80 | cl::desc("Enable the use of the block frequency analysis to reduce the " |
81 | "chance to execute const materialization more frequently than " |
82 | "without hoisting." )); |
83 | |
84 | static cl::opt<bool> ConstHoistGEP( |
85 | "consthoist-gep" , cl::init(Val: false), cl::Hidden, |
86 | cl::desc("Try hoisting constant gep expressions" )); |
87 | |
88 | static cl::opt<unsigned> |
89 | MinNumOfDependentToRebase("consthoist-min-num-to-rebase" , |
90 | cl::desc("Do not rebase if number of dependent constants of a Base is less " |
91 | "than this number." ), |
92 | cl::init(Val: 0), cl::Hidden); |
93 | |
94 | namespace { |
95 | |
96 | /// The constant hoisting pass. |
97 | class ConstantHoistingLegacyPass : public FunctionPass { |
98 | public: |
99 | static char ID; // Pass identification, replacement for typeid |
100 | |
101 | ConstantHoistingLegacyPass() : FunctionPass(ID) { |
102 | initializeConstantHoistingLegacyPassPass(*PassRegistry::getPassRegistry()); |
103 | } |
104 | |
105 | bool runOnFunction(Function &Fn) override; |
106 | |
107 | StringRef getPassName() const override { return "Constant Hoisting" ; } |
108 | |
109 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
110 | AU.setPreservesCFG(); |
111 | if (ConstHoistWithBlockFrequency) |
112 | AU.addRequired<BlockFrequencyInfoWrapperPass>(); |
113 | AU.addRequired<DominatorTreeWrapperPass>(); |
114 | AU.addRequired<ProfileSummaryInfoWrapperPass>(); |
115 | AU.addRequired<TargetTransformInfoWrapperPass>(); |
116 | } |
117 | |
118 | private: |
119 | ConstantHoistingPass Impl; |
120 | }; |
121 | |
122 | } // end anonymous namespace |
123 | |
124 | char ConstantHoistingLegacyPass::ID = 0; |
125 | |
126 | INITIALIZE_PASS_BEGIN(ConstantHoistingLegacyPass, "consthoist" , |
127 | "Constant Hoisting" , false, false) |
128 | INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) |
129 | INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) |
130 | INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass) |
131 | INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) |
132 | INITIALIZE_PASS_END(ConstantHoistingLegacyPass, "consthoist" , |
133 | "Constant Hoisting" , false, false) |
134 | |
135 | FunctionPass *llvm::createConstantHoistingPass() { |
136 | return new ConstantHoistingLegacyPass(); |
137 | } |
138 | |
139 | /// Perform the constant hoisting optimization for the given function. |
140 | bool ConstantHoistingLegacyPass::runOnFunction(Function &Fn) { |
141 | if (skipFunction(F: Fn)) |
142 | return false; |
143 | |
144 | LLVM_DEBUG(dbgs() << "********** Begin Constant Hoisting **********\n" ); |
145 | LLVM_DEBUG(dbgs() << "********** Function: " << Fn.getName() << '\n'); |
146 | |
147 | bool MadeChange = |
148 | Impl.runImpl(F&: Fn, TTI&: getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F: Fn), |
149 | DT&: getAnalysis<DominatorTreeWrapperPass>().getDomTree(), |
150 | BFI: ConstHoistWithBlockFrequency |
151 | ? &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI() |
152 | : nullptr, |
153 | Entry&: Fn.getEntryBlock(), |
154 | PSI: &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI()); |
155 | |
156 | LLVM_DEBUG(dbgs() << "********** End Constant Hoisting **********\n" ); |
157 | |
158 | return MadeChange; |
159 | } |
160 | |
161 | void ConstantHoistingPass::collectMatInsertPts( |
162 | const RebasedConstantListType &RebasedConstants, |
163 | SmallVectorImpl<BasicBlock::iterator> &MatInsertPts) const { |
164 | for (const RebasedConstantInfo &RCI : RebasedConstants) |
165 | for (const ConstantUser &U : RCI.Uses) |
166 | MatInsertPts.emplace_back(Args: findMatInsertPt(Inst: U.Inst, Idx: U.OpndIdx)); |
167 | } |
168 | |
169 | /// Find the constant materialization insertion point. |
170 | BasicBlock::iterator ConstantHoistingPass::findMatInsertPt(Instruction *Inst, |
171 | unsigned Idx) const { |
172 | // If the operand is a cast instruction, then we have to materialize the |
173 | // constant before the cast instruction. |
174 | if (Idx != ~0U) { |
175 | Value *Opnd = Inst->getOperand(i: Idx); |
176 | if (auto CastInst = dyn_cast<Instruction>(Val: Opnd)) |
177 | if (CastInst->isCast()) |
178 | return CastInst->getIterator(); |
179 | } |
180 | |
181 | // The simple and common case. This also includes constant expressions. |
182 | if (!isa<PHINode>(Val: Inst) && !Inst->isEHPad()) |
183 | return Inst->getIterator(); |
184 | |
185 | // We can't insert directly before a phi node or an eh pad. Insert before |
186 | // the terminator of the incoming or dominating block. |
187 | assert(Entry != Inst->getParent() && "PHI or landing pad in entry block!" ); |
188 | BasicBlock *InsertionBlock = nullptr; |
189 | if (Idx != ~0U && isa<PHINode>(Val: Inst)) { |
190 | InsertionBlock = cast<PHINode>(Val: Inst)->getIncomingBlock(i: Idx); |
191 | if (!InsertionBlock->isEHPad()) { |
192 | return InsertionBlock->getTerminator()->getIterator(); |
193 | } |
194 | } else { |
195 | InsertionBlock = Inst->getParent(); |
196 | } |
197 | |
198 | // This must be an EH pad. Iterate over immediate dominators until we find a |
199 | // non-EH pad. We need to skip over catchswitch blocks, which are both EH pads |
200 | // and terminators. |
201 | auto *IDom = DT->getNode(BB: InsertionBlock)->getIDom(); |
202 | while (IDom->getBlock()->isEHPad()) { |
203 | assert(Entry != IDom->getBlock() && "eh pad in entry block" ); |
204 | IDom = IDom->getIDom(); |
205 | } |
206 | |
207 | return IDom->getBlock()->getTerminator()->getIterator(); |
208 | } |
209 | |
210 | /// Given \p BBs as input, find another set of BBs which collectively |
211 | /// dominates \p BBs and have the minimal sum of frequencies. Return the BB |
212 | /// set found in \p BBs. |
213 | static void findBestInsertionSet(DominatorTree &DT, BlockFrequencyInfo &BFI, |
214 | BasicBlock *Entry, |
215 | SetVector<BasicBlock *> &BBs) { |
216 | assert(!BBs.count(Entry) && "Assume Entry is not in BBs" ); |
217 | // Nodes on the current path to the root. |
218 | SmallPtrSet<BasicBlock *, 8> Path; |
219 | // Candidates includes any block 'BB' in set 'BBs' that is not strictly |
220 | // dominated by any other blocks in set 'BBs', and all nodes in the path |
221 | // in the dominator tree from Entry to 'BB'. |
222 | SmallPtrSet<BasicBlock *, 16> Candidates; |
223 | for (auto *BB : BBs) { |
224 | // Ignore unreachable basic blocks. |
225 | if (!DT.isReachableFromEntry(A: BB)) |
226 | continue; |
227 | Path.clear(); |
228 | // Walk up the dominator tree until Entry or another BB in BBs |
229 | // is reached. Insert the nodes on the way to the Path. |
230 | BasicBlock *Node = BB; |
231 | // The "Path" is a candidate path to be added into Candidates set. |
232 | bool isCandidate = false; |
233 | do { |
234 | Path.insert(Ptr: Node); |
235 | if (Node == Entry || Candidates.count(Ptr: Node)) { |
236 | isCandidate = true; |
237 | break; |
238 | } |
239 | assert(DT.getNode(Node)->getIDom() && |
240 | "Entry doens't dominate current Node" ); |
241 | Node = DT.getNode(BB: Node)->getIDom()->getBlock(); |
242 | } while (!BBs.count(key: Node)); |
243 | |
244 | // If isCandidate is false, Node is another Block in BBs dominating |
245 | // current 'BB'. Drop the nodes on the Path. |
246 | if (!isCandidate) |
247 | continue; |
248 | |
249 | // Add nodes on the Path into Candidates. |
250 | Candidates.insert_range(R&: Path); |
251 | } |
252 | |
253 | // Sort the nodes in Candidates in top-down order and save the nodes |
254 | // in Orders. |
255 | unsigned Idx = 0; |
256 | SmallVector<BasicBlock *, 16> Orders; |
257 | Orders.push_back(Elt: Entry); |
258 | while (Idx != Orders.size()) { |
259 | BasicBlock *Node = Orders[Idx++]; |
260 | for (auto *ChildDomNode : DT.getNode(BB: Node)->children()) { |
261 | if (Candidates.count(Ptr: ChildDomNode->getBlock())) |
262 | Orders.push_back(Elt: ChildDomNode->getBlock()); |
263 | } |
264 | } |
265 | |
266 | // Visit Orders in bottom-up order. |
267 | using InsertPtsCostPair = |
268 | std::pair<SetVector<BasicBlock *>, BlockFrequency>; |
269 | |
270 | // InsertPtsMap is a map from a BB to the best insertion points for the |
271 | // subtree of BB (subtree not including the BB itself). |
272 | DenseMap<BasicBlock *, InsertPtsCostPair> InsertPtsMap; |
273 | InsertPtsMap.reserve(NumEntries: Orders.size() + 1); |
274 | for (BasicBlock *Node : llvm::reverse(C&: Orders)) { |
275 | bool NodeInBBs = BBs.count(key: Node); |
276 | auto &[InsertPts, InsertPtsFreq] = InsertPtsMap[Node]; |
277 | |
278 | // Return the optimal insert points in BBs. |
279 | if (Node == Entry) { |
280 | BBs.clear(); |
281 | if (InsertPtsFreq > BFI.getBlockFreq(BB: Node) || |
282 | (InsertPtsFreq == BFI.getBlockFreq(BB: Node) && InsertPts.size() > 1)) |
283 | BBs.insert(X: Entry); |
284 | else |
285 | BBs.insert_range(R&: InsertPts); |
286 | break; |
287 | } |
288 | |
289 | BasicBlock *Parent = DT.getNode(BB: Node)->getIDom()->getBlock(); |
290 | // Initially, ParentInsertPts is empty and ParentPtsFreq is 0. Every child |
291 | // will update its parent's ParentInsertPts and ParentPtsFreq. |
292 | auto &[ParentInsertPts, ParentPtsFreq] = InsertPtsMap[Parent]; |
293 | // Choose to insert in Node or in subtree of Node. |
294 | // Don't hoist to EHPad because we may not find a proper place to insert |
295 | // in EHPad. |
296 | // If the total frequency of InsertPts is the same as the frequency of the |
297 | // target Node, and InsertPts contains more than one nodes, choose hoisting |
298 | // to reduce code size. |
299 | if (NodeInBBs || |
300 | (!Node->isEHPad() && |
301 | (InsertPtsFreq > BFI.getBlockFreq(BB: Node) || |
302 | (InsertPtsFreq == BFI.getBlockFreq(BB: Node) && InsertPts.size() > 1)))) { |
303 | ParentInsertPts.insert(X: Node); |
304 | ParentPtsFreq += BFI.getBlockFreq(BB: Node); |
305 | } else { |
306 | ParentInsertPts.insert_range(R&: InsertPts); |
307 | ParentPtsFreq += InsertPtsFreq; |
308 | } |
309 | } |
310 | } |
311 | |
312 | /// Find an insertion point that dominates all uses. |
313 | SetVector<BasicBlock::iterator> |
314 | ConstantHoistingPass::findConstantInsertionPoint( |
315 | const ConstantInfo &ConstInfo, |
316 | const ArrayRef<BasicBlock::iterator> MatInsertPts) const { |
317 | assert(!ConstInfo.RebasedConstants.empty() && "Invalid constant info entry." ); |
318 | // Collect all basic blocks. |
319 | SetVector<BasicBlock *> BBs; |
320 | SetVector<BasicBlock::iterator> InsertPts; |
321 | |
322 | for (BasicBlock::iterator MatInsertPt : MatInsertPts) |
323 | BBs.insert(X: MatInsertPt->getParent()); |
324 | |
325 | if (BBs.count(key: Entry)) { |
326 | InsertPts.insert(X: Entry->begin()); |
327 | return InsertPts; |
328 | } |
329 | |
330 | if (BFI) { |
331 | findBestInsertionSet(DT&: *DT, BFI&: *BFI, Entry, BBs); |
332 | for (BasicBlock *BB : BBs) |
333 | InsertPts.insert(X: BB->getFirstInsertionPt()); |
334 | return InsertPts; |
335 | } |
336 | |
337 | while (BBs.size() >= 2) { |
338 | BasicBlock *BB, *BB1, *BB2; |
339 | BB1 = BBs.pop_back_val(); |
340 | BB2 = BBs.pop_back_val(); |
341 | BB = DT->findNearestCommonDominator(A: BB1, B: BB2); |
342 | if (BB == Entry) { |
343 | InsertPts.insert(X: Entry->begin()); |
344 | return InsertPts; |
345 | } |
346 | BBs.insert(X: BB); |
347 | } |
348 | assert((BBs.size() == 1) && "Expected only one element." ); |
349 | Instruction &FirstInst = (*BBs.begin())->front(); |
350 | InsertPts.insert(X: findMatInsertPt(Inst: &FirstInst)); |
351 | return InsertPts; |
352 | } |
353 | |
354 | /// Record constant integer ConstInt for instruction Inst at operand |
355 | /// index Idx. |
356 | /// |
357 | /// The operand at index Idx is not necessarily the constant integer itself. It |
358 | /// could also be a cast instruction or a constant expression that uses the |
359 | /// constant integer. |
360 | void ConstantHoistingPass::collectConstantCandidates( |
361 | ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx, |
362 | ConstantInt *ConstInt) { |
363 | if (ConstInt->getType()->isVectorTy()) |
364 | return; |
365 | |
366 | InstructionCost Cost; |
367 | // Ask the target about the cost of materializing the constant for the given |
368 | // instruction and operand index. |
369 | if (auto IntrInst = dyn_cast<IntrinsicInst>(Val: Inst)) |
370 | Cost = TTI->getIntImmCostIntrin(IID: IntrInst->getIntrinsicID(), Idx, |
371 | Imm: ConstInt->getValue(), Ty: ConstInt->getType(), |
372 | CostKind: TargetTransformInfo::TCK_SizeAndLatency); |
373 | else |
374 | Cost = TTI->getIntImmCostInst( |
375 | Opc: Inst->getOpcode(), Idx, Imm: ConstInt->getValue(), Ty: ConstInt->getType(), |
376 | CostKind: TargetTransformInfo::TCK_SizeAndLatency, Inst); |
377 | |
378 | // Ignore cheap integer constants. |
379 | if (Cost > TargetTransformInfo::TCC_Basic) { |
380 | ConstCandMapType::iterator Itr; |
381 | bool Inserted; |
382 | ConstPtrUnionType Cand = ConstInt; |
383 | std::tie(args&: Itr, args&: Inserted) = ConstCandMap.try_emplace(Key: Cand); |
384 | if (Inserted) { |
385 | ConstIntCandVec.push_back(x: ConstantCandidate(ConstInt)); |
386 | Itr->second = ConstIntCandVec.size() - 1; |
387 | } |
388 | ConstIntCandVec[Itr->second].addUser(Inst, Idx, Cost: Cost.getValue()); |
389 | LLVM_DEBUG(if (isa<ConstantInt>(Inst->getOperand(Idx))) dbgs() |
390 | << "Collect constant " << *ConstInt << " from " << *Inst |
391 | << " with cost " << Cost << '\n'; |
392 | else dbgs() << "Collect constant " << *ConstInt |
393 | << " indirectly from " << *Inst << " via " |
394 | << *Inst->getOperand(Idx) << " with cost " << Cost |
395 | << '\n';); |
396 | } |
397 | } |
398 | |
399 | /// Record constant GEP expression for instruction Inst at operand index Idx. |
400 | void ConstantHoistingPass::collectConstantCandidates( |
401 | ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx, |
402 | ConstantExpr *ConstExpr) { |
403 | // TODO: Handle vector GEPs |
404 | if (ConstExpr->getType()->isVectorTy()) |
405 | return; |
406 | |
407 | GlobalVariable *BaseGV = dyn_cast<GlobalVariable>(Val: ConstExpr->getOperand(i_nocapture: 0)); |
408 | if (!BaseGV) |
409 | return; |
410 | |
411 | // Get offset from the base GV. |
412 | PointerType *GVPtrTy = cast<PointerType>(Val: BaseGV->getType()); |
413 | IntegerType *OffsetTy = DL->getIndexType(C&: *Ctx, AddressSpace: GVPtrTy->getAddressSpace()); |
414 | APInt Offset(DL->getTypeSizeInBits(Ty: OffsetTy), /*val*/ 0, /*isSigned*/ true); |
415 | auto *GEPO = cast<GEPOperator>(Val: ConstExpr); |
416 | |
417 | // TODO: If we have a mix of inbounds and non-inbounds GEPs, then basing a |
418 | // non-inbounds GEP on an inbounds GEP is potentially incorrect. Restrict to |
419 | // inbounds GEP for now -- alternatively, we could drop inbounds from the |
420 | // constant expression, |
421 | if (!GEPO->isInBounds()) |
422 | return; |
423 | |
424 | if (!GEPO->accumulateConstantOffset(DL: *DL, Offset)) |
425 | return; |
426 | |
427 | if (!Offset.isIntN(N: 32)) |
428 | return; |
429 | |
430 | // A constant GEP expression that has a GlobalVariable as base pointer is |
431 | // usually lowered to a load from constant pool. Such operation is unlikely |
432 | // to be cheaper than compute it by <Base + Offset>, which can be lowered to |
433 | // an ADD instruction or folded into Load/Store instruction. |
434 | InstructionCost Cost = |
435 | TTI->getIntImmCostInst(Opc: Instruction::Add, Idx: 1, Imm: Offset, Ty: OffsetTy, |
436 | CostKind: TargetTransformInfo::TCK_SizeAndLatency, Inst); |
437 | ConstCandVecType &ExprCandVec = ConstGEPCandMap[BaseGV]; |
438 | ConstCandMapType::iterator Itr; |
439 | bool Inserted; |
440 | ConstPtrUnionType Cand = ConstExpr; |
441 | std::tie(args&: Itr, args&: Inserted) = ConstCandMap.try_emplace(Key: Cand); |
442 | if (Inserted) { |
443 | ExprCandVec.push_back(x: ConstantCandidate( |
444 | ConstantInt::get(Ty: Type::getInt32Ty(C&: *Ctx), V: Offset.getLimitedValue()), |
445 | ConstExpr)); |
446 | Itr->second = ExprCandVec.size() - 1; |
447 | } |
448 | ExprCandVec[Itr->second].addUser(Inst, Idx, Cost: Cost.getValue()); |
449 | } |
450 | |
451 | /// Check the operand for instruction Inst at index Idx. |
452 | void ConstantHoistingPass::collectConstantCandidates( |
453 | ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx) { |
454 | Value *Opnd = Inst->getOperand(i: Idx); |
455 | |
456 | // Visit constant integers. |
457 | if (auto ConstInt = dyn_cast<ConstantInt>(Val: Opnd)) { |
458 | collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt); |
459 | return; |
460 | } |
461 | |
462 | // Visit cast instructions that have constant integers. |
463 | if (auto CastInst = dyn_cast<Instruction>(Val: Opnd)) { |
464 | // Only visit cast instructions, which have been skipped. All other |
465 | // instructions should have already been visited. |
466 | if (!CastInst->isCast()) |
467 | return; |
468 | |
469 | if (auto *ConstInt = dyn_cast<ConstantInt>(Val: CastInst->getOperand(i: 0))) { |
470 | // Pretend the constant is directly used by the instruction and ignore |
471 | // the cast instruction. |
472 | collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt); |
473 | return; |
474 | } |
475 | } |
476 | |
477 | // Visit constant expressions that have constant integers. |
478 | if (auto ConstExpr = dyn_cast<ConstantExpr>(Val: Opnd)) { |
479 | // Handle constant gep expressions. |
480 | if (ConstHoistGEP && isa<GEPOperator>(Val: ConstExpr)) |
481 | collectConstantCandidates(ConstCandMap, Inst, Idx, ConstExpr); |
482 | |
483 | // Only visit constant cast expressions. |
484 | if (!ConstExpr->isCast()) |
485 | return; |
486 | |
487 | if (auto ConstInt = dyn_cast<ConstantInt>(Val: ConstExpr->getOperand(i_nocapture: 0))) { |
488 | // Pretend the constant is directly used by the instruction and ignore |
489 | // the constant expression. |
490 | collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt); |
491 | return; |
492 | } |
493 | } |
494 | } |
495 | |
496 | /// Scan the instruction for expensive integer constants and record them |
497 | /// in the constant candidate vector. |
498 | void ConstantHoistingPass::collectConstantCandidates( |
499 | ConstCandMapType &ConstCandMap, Instruction *Inst) { |
500 | // Skip all cast instructions. They are visited indirectly later on. |
501 | if (Inst->isCast()) |
502 | return; |
503 | |
504 | // Scan all operands. |
505 | for (unsigned Idx = 0, E = Inst->getNumOperands(); Idx != E; ++Idx) { |
506 | // The cost of materializing the constants (defined in |
507 | // `TargetTransformInfo::getIntImmCostInst`) for instructions which only |
508 | // take constant variables is lower than `TargetTransformInfo::TCC_Basic`. |
509 | // So it's safe for us to collect constant candidates from all |
510 | // IntrinsicInsts. |
511 | if (canReplaceOperandWithVariable(I: Inst, OpIdx: Idx)) { |
512 | collectConstantCandidates(ConstCandMap, Inst, Idx); |
513 | } |
514 | } // end of for all operands |
515 | } |
516 | |
517 | /// Collect all integer constants in the function that cannot be folded |
518 | /// into an instruction itself. |
519 | void ConstantHoistingPass::collectConstantCandidates(Function &Fn) { |
520 | ConstCandMapType ConstCandMap; |
521 | for (BasicBlock &BB : Fn) { |
522 | // Ignore unreachable basic blocks. |
523 | if (!DT->isReachableFromEntry(A: &BB)) |
524 | continue; |
525 | for (Instruction &Inst : BB) |
526 | if (!TTI->preferToKeepConstantsAttached(Inst, Fn)) |
527 | collectConstantCandidates(ConstCandMap, Inst: &Inst); |
528 | } |
529 | } |
530 | |
531 | // From a list of constants, one needs to picked as the base and the other |
532 | // constants will be transformed into an offset from that base constant. The |
533 | // question is which we can pick best? For example, consider these constants |
534 | // and their number of uses: |
535 | // |
536 | // Constants| 2 | 4 | 12 | 42 | |
537 | // NumUses | 3 | 2 | 8 | 7 | |
538 | // |
539 | // Selecting constant 12 because it has the most uses will generate negative |
540 | // offsets for constants 2 and 4 (i.e. -10 and -8 respectively). If negative |
541 | // offsets lead to less optimal code generation, then there might be better |
542 | // solutions. Suppose immediates in the range of 0..35 are most optimally |
543 | // supported by the architecture, then selecting constant 2 is most optimal |
544 | // because this will generate offsets: 0, 2, 10, 40. Offsets 0, 2 and 10 are in |
545 | // range 0..35, and thus 3 + 2 + 8 = 13 uses are in range. Selecting 12 would |
546 | // have only 8 uses in range, so choosing 2 as a base is more optimal. Thus, in |
547 | // selecting the base constant the range of the offsets is a very important |
548 | // factor too that we take into account here. This algorithm calculates a total |
549 | // costs for selecting a constant as the base and substract the costs if |
550 | // immediates are out of range. It has quadratic complexity, so we call this |
551 | // function only when we're optimising for size and there are less than 100 |
552 | // constants, we fall back to the straightforward algorithm otherwise |
553 | // which does not do all the offset calculations. |
554 | unsigned |
555 | ConstantHoistingPass::maximizeConstantsInRange(ConstCandVecType::iterator S, |
556 | ConstCandVecType::iterator E, |
557 | ConstCandVecType::iterator &MaxCostItr) { |
558 | unsigned NumUses = 0; |
559 | |
560 | if (!OptForSize || std::distance(first: S,last: E) > 100) { |
561 | for (auto ConstCand = S; ConstCand != E; ++ConstCand) { |
562 | NumUses += ConstCand->Uses.size(); |
563 | if (ConstCand->CumulativeCost > MaxCostItr->CumulativeCost) |
564 | MaxCostItr = ConstCand; |
565 | } |
566 | return NumUses; |
567 | } |
568 | |
569 | LLVM_DEBUG(dbgs() << "== Maximize constants in range ==\n" ); |
570 | InstructionCost MaxCost = -1; |
571 | for (auto ConstCand = S; ConstCand != E; ++ConstCand) { |
572 | auto Value = ConstCand->ConstInt->getValue(); |
573 | Type *Ty = ConstCand->ConstInt->getType(); |
574 | InstructionCost Cost = 0; |
575 | NumUses += ConstCand->Uses.size(); |
576 | LLVM_DEBUG(dbgs() << "= Constant: " << ConstCand->ConstInt->getValue() |
577 | << "\n" ); |
578 | |
579 | for (auto User : ConstCand->Uses) { |
580 | unsigned Opcode = User.Inst->getOpcode(); |
581 | unsigned OpndIdx = User.OpndIdx; |
582 | Cost += TTI->getIntImmCostInst(Opc: Opcode, Idx: OpndIdx, Imm: Value, Ty, |
583 | CostKind: TargetTransformInfo::TCK_SizeAndLatency); |
584 | LLVM_DEBUG(dbgs() << "Cost: " << Cost << "\n" ); |
585 | |
586 | for (auto C2 = S; C2 != E; ++C2) { |
587 | APInt Diff = C2->ConstInt->getValue() - ConstCand->ConstInt->getValue(); |
588 | const InstructionCost ImmCosts = |
589 | TTI->getIntImmCodeSizeCost(Opc: Opcode, Idx: OpndIdx, Imm: Diff, Ty); |
590 | Cost -= ImmCosts; |
591 | LLVM_DEBUG(dbgs() << "Offset " << Diff << " " |
592 | << "has penalty: " << ImmCosts << "\n" |
593 | << "Adjusted cost: " << Cost << "\n" ); |
594 | } |
595 | } |
596 | LLVM_DEBUG(dbgs() << "Cumulative cost: " << Cost << "\n" ); |
597 | if (Cost > MaxCost) { |
598 | MaxCost = Cost; |
599 | MaxCostItr = ConstCand; |
600 | LLVM_DEBUG(dbgs() << "New candidate: " << MaxCostItr->ConstInt->getValue() |
601 | << "\n" ); |
602 | } |
603 | } |
604 | return NumUses; |
605 | } |
606 | |
607 | /// Find the base constant within the given range and rebase all other |
608 | /// constants with respect to the base constant. |
609 | void ConstantHoistingPass::findAndMakeBaseConstant( |
610 | ConstCandVecType::iterator S, ConstCandVecType::iterator E, |
611 | SmallVectorImpl<consthoist::ConstantInfo> &ConstInfoVec) { |
612 | auto MaxCostItr = S; |
613 | unsigned NumUses = maximizeConstantsInRange(S, E, MaxCostItr); |
614 | |
615 | // Don't hoist constants that have only one use. |
616 | if (NumUses <= 1) |
617 | return; |
618 | |
619 | ConstantInt *ConstInt = MaxCostItr->ConstInt; |
620 | ConstantExpr *ConstExpr = MaxCostItr->ConstExpr; |
621 | ConstantInfo ConstInfo; |
622 | ConstInfo.BaseInt = ConstInt; |
623 | ConstInfo.BaseExpr = ConstExpr; |
624 | Type *Ty = ConstInt->getType(); |
625 | |
626 | // Rebase the constants with respect to the base constant. |
627 | for (auto ConstCand = S; ConstCand != E; ++ConstCand) { |
628 | APInt Diff = ConstCand->ConstInt->getValue() - ConstInt->getValue(); |
629 | Constant *Offset = Diff == 0 ? nullptr : ConstantInt::get(Ty, V: Diff); |
630 | Type *ConstTy = |
631 | ConstCand->ConstExpr ? ConstCand->ConstExpr->getType() : nullptr; |
632 | ConstInfo.RebasedConstants.push_back( |
633 | Elt: RebasedConstantInfo(std::move(ConstCand->Uses), Offset, ConstTy)); |
634 | } |
635 | ConstInfoVec.push_back(Elt: std::move(ConstInfo)); |
636 | } |
637 | |
638 | /// Finds and combines constant candidates that can be easily |
639 | /// rematerialized with an add from a common base constant. |
640 | void ConstantHoistingPass::findBaseConstants(GlobalVariable *BaseGV) { |
641 | // If BaseGV is nullptr, find base among candidate constant integers; |
642 | // Otherwise find base among constant GEPs that share the same BaseGV. |
643 | ConstCandVecType &ConstCandVec = BaseGV ? |
644 | ConstGEPCandMap[BaseGV] : ConstIntCandVec; |
645 | ConstInfoVecType &ConstInfoVec = BaseGV ? |
646 | ConstGEPInfoMap[BaseGV] : ConstIntInfoVec; |
647 | |
648 | // Sort the constants by value and type. This invalidates the mapping! |
649 | llvm::stable_sort(Range&: ConstCandVec, C: [](const ConstantCandidate &LHS, |
650 | const ConstantCandidate &RHS) { |
651 | if (LHS.ConstInt->getType() != RHS.ConstInt->getType()) |
652 | return LHS.ConstInt->getBitWidth() < RHS.ConstInt->getBitWidth(); |
653 | return LHS.ConstInt->getValue().ult(RHS: RHS.ConstInt->getValue()); |
654 | }); |
655 | |
656 | // Simple linear scan through the sorted constant candidate vector for viable |
657 | // merge candidates. |
658 | auto MinValItr = ConstCandVec.begin(); |
659 | for (auto CC = std::next(x: ConstCandVec.begin()), E = ConstCandVec.end(); |
660 | CC != E; ++CC) { |
661 | if (MinValItr->ConstInt->getType() == CC->ConstInt->getType()) { |
662 | Type *MemUseValTy = nullptr; |
663 | for (auto &U : CC->Uses) { |
664 | auto *UI = U.Inst; |
665 | if (LoadInst *LI = dyn_cast<LoadInst>(Val: UI)) { |
666 | MemUseValTy = LI->getType(); |
667 | break; |
668 | } else if (StoreInst *SI = dyn_cast<StoreInst>(Val: UI)) { |
669 | // Make sure the constant is used as pointer operand of the StoreInst. |
670 | if (SI->getPointerOperand() == SI->getOperand(i_nocapture: U.OpndIdx)) { |
671 | MemUseValTy = SI->getValueOperand()->getType(); |
672 | break; |
673 | } |
674 | } |
675 | } |
676 | |
677 | // Check if the constant is in range of an add with immediate. |
678 | APInt Diff = CC->ConstInt->getValue() - MinValItr->ConstInt->getValue(); |
679 | if ((Diff.getBitWidth() <= 64) && |
680 | TTI->isLegalAddImmediate(Imm: Diff.getSExtValue()) && |
681 | // Check if Diff can be used as offset in addressing mode of the user |
682 | // memory instruction. |
683 | (!MemUseValTy || TTI->isLegalAddressingMode(Ty: MemUseValTy, |
684 | /*BaseGV*/nullptr, /*BaseOffset*/Diff.getSExtValue(), |
685 | /*HasBaseReg*/true, /*Scale*/0))) |
686 | continue; |
687 | } |
688 | // We either have now a different constant type or the constant is not in |
689 | // range of an add with immediate anymore. |
690 | findAndMakeBaseConstant(S: MinValItr, E: CC, ConstInfoVec); |
691 | // Start a new base constant search. |
692 | MinValItr = CC; |
693 | } |
694 | // Finalize the last base constant search. |
695 | findAndMakeBaseConstant(S: MinValItr, E: ConstCandVec.end(), ConstInfoVec); |
696 | } |
697 | |
698 | /// Updates the operand at Idx in instruction Inst with the result of |
699 | /// instruction Mat. If the instruction is a PHI node then special |
700 | /// handling for duplicate values from the same incoming basic block is |
701 | /// required. |
702 | /// \return The update will always succeed, but the return value indicated if |
703 | /// Mat was used for the update or not. |
704 | static bool updateOperand(Instruction *Inst, unsigned Idx, Instruction *Mat) { |
705 | if (auto PHI = dyn_cast<PHINode>(Val: Inst)) { |
706 | // Check if any previous operand of the PHI node has the same incoming basic |
707 | // block. This is a very odd case that happens when the incoming basic block |
708 | // has a switch statement. In this case use the same value as the previous |
709 | // operand(s), otherwise we will fail verification due to different values. |
710 | // The values are actually the same, but the variable names are different |
711 | // and the verifier doesn't like that. |
712 | BasicBlock *IncomingBB = PHI->getIncomingBlock(i: Idx); |
713 | for (unsigned i = 0; i < Idx; ++i) { |
714 | if (PHI->getIncomingBlock(i) == IncomingBB) { |
715 | Value *IncomingVal = PHI->getIncomingValue(i); |
716 | Inst->setOperand(i: Idx, Val: IncomingVal); |
717 | return false; |
718 | } |
719 | } |
720 | } |
721 | |
722 | Inst->setOperand(i: Idx, Val: Mat); |
723 | return true; |
724 | } |
725 | |
726 | /// Emit materialization code for all rebased constants and update their |
727 | /// users. |
728 | void ConstantHoistingPass::emitBaseConstants(Instruction *Base, |
729 | UserAdjustment *Adj) { |
730 | Instruction *Mat = Base; |
731 | |
732 | // The same offset can be dereferenced to different types in nested struct. |
733 | if (!Adj->Offset && Adj->Ty && Adj->Ty != Base->getType()) |
734 | Adj->Offset = ConstantInt::get(Ty: Type::getInt32Ty(C&: *Ctx), V: 0); |
735 | |
736 | if (Adj->Offset) { |
737 | if (Adj->Ty) { |
738 | // Constant being rebased is a ConstantExpr. |
739 | Mat = GetElementPtrInst::Create(PointeeType: Type::getInt8Ty(C&: *Ctx), Ptr: Base, IdxList: Adj->Offset, |
740 | NameStr: "mat_gep" , InsertBefore: Adj->MatInsertPt); |
741 | // Hide it behind a bitcast. |
742 | Mat = new BitCastInst(Mat, Adj->Ty, "mat_bitcast" , |
743 | Adj->MatInsertPt->getIterator()); |
744 | } else |
745 | // Constant being rebased is a ConstantInt. |
746 | Mat = |
747 | BinaryOperator::Create(Op: Instruction::Add, S1: Base, S2: Adj->Offset, |
748 | Name: "const_mat" , InsertBefore: Adj->MatInsertPt->getIterator()); |
749 | |
750 | LLVM_DEBUG(dbgs() << "Materialize constant (" << *Base->getOperand(0) |
751 | << " + " << *Adj->Offset << ") in BB " |
752 | << Mat->getParent()->getName() << '\n' |
753 | << *Mat << '\n'); |
754 | Mat->setDebugLoc(Adj->User.Inst->getDebugLoc()); |
755 | } |
756 | Value *Opnd = Adj->User.Inst->getOperand(i: Adj->User.OpndIdx); |
757 | |
758 | // Visit constant integer. |
759 | if (isa<ConstantInt>(Val: Opnd)) { |
760 | LLVM_DEBUG(dbgs() << "Update: " << *Adj->User.Inst << '\n'); |
761 | if (!updateOperand(Inst: Adj->User.Inst, Idx: Adj->User.OpndIdx, Mat) && Adj->Offset) |
762 | Mat->eraseFromParent(); |
763 | LLVM_DEBUG(dbgs() << "To : " << *Adj->User.Inst << '\n'); |
764 | return; |
765 | } |
766 | |
767 | // Visit cast instruction. |
768 | if (auto CastInst = dyn_cast<Instruction>(Val: Opnd)) { |
769 | assert(CastInst->isCast() && "Expected an cast instruction!" ); |
770 | // Check if we already have visited this cast instruction before to avoid |
771 | // unnecessary cloning. |
772 | Instruction *&ClonedCastInst = ClonedCastMap[CastInst]; |
773 | if (!ClonedCastInst) { |
774 | ClonedCastInst = CastInst->clone(); |
775 | ClonedCastInst->setOperand(i: 0, Val: Mat); |
776 | ClonedCastInst->insertAfter(InsertPos: CastInst->getIterator()); |
777 | // Use the same debug location as the original cast instruction. |
778 | ClonedCastInst->setDebugLoc(CastInst->getDebugLoc()); |
779 | LLVM_DEBUG(dbgs() << "Clone instruction: " << *CastInst << '\n' |
780 | << "To : " << *ClonedCastInst << '\n'); |
781 | } |
782 | |
783 | LLVM_DEBUG(dbgs() << "Update: " << *Adj->User.Inst << '\n'); |
784 | updateOperand(Inst: Adj->User.Inst, Idx: Adj->User.OpndIdx, Mat: ClonedCastInst); |
785 | LLVM_DEBUG(dbgs() << "To : " << *Adj->User.Inst << '\n'); |
786 | return; |
787 | } |
788 | |
789 | // Visit constant expression. |
790 | if (auto ConstExpr = dyn_cast<ConstantExpr>(Val: Opnd)) { |
791 | if (isa<GEPOperator>(Val: ConstExpr)) { |
792 | // Operand is a ConstantGEP, replace it. |
793 | updateOperand(Inst: Adj->User.Inst, Idx: Adj->User.OpndIdx, Mat); |
794 | return; |
795 | } |
796 | |
797 | // Aside from constant GEPs, only constant cast expressions are collected. |
798 | assert(ConstExpr->isCast() && "ConstExpr should be a cast" ); |
799 | Instruction *ConstExprInst = ConstExpr->getAsInstruction(); |
800 | ConstExprInst->insertBefore(InsertPos: Adj->MatInsertPt); |
801 | ConstExprInst->setOperand(i: 0, Val: Mat); |
802 | |
803 | // Use the same debug location as the instruction we are about to update. |
804 | ConstExprInst->setDebugLoc(Adj->User.Inst->getDebugLoc()); |
805 | |
806 | LLVM_DEBUG(dbgs() << "Create instruction: " << *ConstExprInst << '\n' |
807 | << "From : " << *ConstExpr << '\n'); |
808 | LLVM_DEBUG(dbgs() << "Update: " << *Adj->User.Inst << '\n'); |
809 | if (!updateOperand(Inst: Adj->User.Inst, Idx: Adj->User.OpndIdx, Mat: ConstExprInst)) { |
810 | ConstExprInst->eraseFromParent(); |
811 | if (Adj->Offset) |
812 | Mat->eraseFromParent(); |
813 | } |
814 | LLVM_DEBUG(dbgs() << "To : " << *Adj->User.Inst << '\n'); |
815 | return; |
816 | } |
817 | } |
818 | |
819 | /// Hoist and hide the base constant behind a bitcast and emit |
820 | /// materialization code for derived constants. |
821 | bool ConstantHoistingPass::emitBaseConstants(GlobalVariable *BaseGV) { |
822 | bool MadeChange = false; |
823 | SmallVectorImpl<consthoist::ConstantInfo> &ConstInfoVec = |
824 | BaseGV ? ConstGEPInfoMap[BaseGV] : ConstIntInfoVec; |
825 | for (const consthoist::ConstantInfo &ConstInfo : ConstInfoVec) { |
826 | SmallVector<BasicBlock::iterator, 4> MatInsertPts; |
827 | collectMatInsertPts(RebasedConstants: ConstInfo.RebasedConstants, MatInsertPts); |
828 | SetVector<BasicBlock::iterator> IPSet = |
829 | findConstantInsertionPoint(ConstInfo, MatInsertPts); |
830 | // We can have an empty set if the function contains unreachable blocks. |
831 | if (IPSet.empty()) |
832 | continue; |
833 | |
834 | unsigned UsesNum = 0; |
835 | unsigned ReBasesNum = 0; |
836 | unsigned NotRebasedNum = 0; |
837 | for (const BasicBlock::iterator &IP : IPSet) { |
838 | // First, collect constants depending on this IP of the base. |
839 | UsesNum = 0; |
840 | SmallVector<UserAdjustment, 4> ToBeRebased; |
841 | unsigned MatCtr = 0; |
842 | for (auto const &RCI : ConstInfo.RebasedConstants) { |
843 | UsesNum += RCI.Uses.size(); |
844 | for (auto const &U : RCI.Uses) { |
845 | const BasicBlock::iterator &MatInsertPt = MatInsertPts[MatCtr++]; |
846 | BasicBlock *OrigMatInsertBB = MatInsertPt->getParent(); |
847 | // If Base constant is to be inserted in multiple places, |
848 | // generate rebase for U using the Base dominating U. |
849 | if (IPSet.size() == 1 || |
850 | DT->dominates(A: IP->getParent(), B: OrigMatInsertBB)) |
851 | ToBeRebased.emplace_back(Args: RCI.Offset, Args: RCI.Ty, Args: MatInsertPt, Args: U); |
852 | } |
853 | } |
854 | |
855 | // If only few constants depend on this IP of base, skip rebasing, |
856 | // assuming the base and the rebased have the same materialization cost. |
857 | if (ToBeRebased.size() < MinNumOfDependentToRebase) { |
858 | NotRebasedNum += ToBeRebased.size(); |
859 | continue; |
860 | } |
861 | |
862 | // Emit an instance of the base at this IP. |
863 | Instruction *Base = nullptr; |
864 | // Hoist and hide the base constant behind a bitcast. |
865 | if (ConstInfo.BaseExpr) { |
866 | assert(BaseGV && "A base constant expression must have an base GV" ); |
867 | Type *Ty = ConstInfo.BaseExpr->getType(); |
868 | Base = new BitCastInst(ConstInfo.BaseExpr, Ty, "const" , IP); |
869 | } else { |
870 | IntegerType *Ty = ConstInfo.BaseInt->getIntegerType(); |
871 | Base = new BitCastInst(ConstInfo.BaseInt, Ty, "const" , IP); |
872 | } |
873 | |
874 | Base->setDebugLoc(IP->getDebugLoc()); |
875 | |
876 | LLVM_DEBUG(dbgs() << "Hoist constant (" << *ConstInfo.BaseInt |
877 | << ") to BB " << IP->getParent()->getName() << '\n' |
878 | << *Base << '\n'); |
879 | |
880 | // Emit materialization code for rebased constants depending on this IP. |
881 | for (UserAdjustment &R : ToBeRebased) { |
882 | emitBaseConstants(Base, Adj: &R); |
883 | ReBasesNum++; |
884 | // Use the same debug location as the last user of the constant. |
885 | Base->setDebugLoc(DebugLoc::getMergedLocation( |
886 | LocA: Base->getDebugLoc(), LocB: R.User.Inst->getDebugLoc())); |
887 | } |
888 | assert(!Base->use_empty() && "The use list is empty!?" ); |
889 | assert(isa<Instruction>(Base->user_back()) && |
890 | "All uses should be instructions." ); |
891 | } |
892 | (void)UsesNum; |
893 | (void)ReBasesNum; |
894 | (void)NotRebasedNum; |
895 | // Expect all uses are rebased after rebase is done. |
896 | assert(UsesNum == (ReBasesNum + NotRebasedNum) && |
897 | "Not all uses are rebased" ); |
898 | |
899 | NumConstantsHoisted++; |
900 | |
901 | // Base constant is also included in ConstInfo.RebasedConstants, so |
902 | // deduct 1 from ConstInfo.RebasedConstants.size(). |
903 | NumConstantsRebased += ConstInfo.RebasedConstants.size() - 1; |
904 | |
905 | MadeChange = true; |
906 | } |
907 | return MadeChange; |
908 | } |
909 | |
910 | /// Check all cast instructions we made a copy of and remove them if they |
911 | /// have no more users. |
912 | void ConstantHoistingPass::deleteDeadCastInst() const { |
913 | for (auto const &I : ClonedCastMap) |
914 | if (I.first->use_empty()) |
915 | I.first->eraseFromParent(); |
916 | } |
917 | |
918 | /// Optimize expensive integer constants in the given function. |
919 | bool ConstantHoistingPass::runImpl(Function &Fn, TargetTransformInfo &TTI, |
920 | DominatorTree &DT, BlockFrequencyInfo *BFI, |
921 | BasicBlock &Entry, ProfileSummaryInfo *PSI) { |
922 | this->TTI = &TTI; |
923 | this->DT = &DT; |
924 | this->BFI = BFI; |
925 | this->DL = &Fn.getDataLayout(); |
926 | this->Ctx = &Fn.getContext(); |
927 | this->Entry = &Entry; |
928 | this->PSI = PSI; |
929 | this->OptForSize = llvm::shouldOptimizeForSize(F: Entry.getParent(), PSI, BFI, |
930 | QueryType: PGSOQueryType::IRPass); |
931 | |
932 | // Collect all constant candidates. |
933 | collectConstantCandidates(Fn); |
934 | |
935 | // Combine constants that can be easily materialized with an add from a common |
936 | // base constant. |
937 | if (!ConstIntCandVec.empty()) |
938 | findBaseConstants(BaseGV: nullptr); |
939 | for (const auto &MapEntry : ConstGEPCandMap) |
940 | if (!MapEntry.second.empty()) |
941 | findBaseConstants(BaseGV: MapEntry.first); |
942 | |
943 | // Finally hoist the base constant and emit materialization code for dependent |
944 | // constants. |
945 | bool MadeChange = false; |
946 | if (!ConstIntInfoVec.empty()) |
947 | MadeChange = emitBaseConstants(BaseGV: nullptr); |
948 | for (const auto &MapEntry : ConstGEPInfoMap) |
949 | if (!MapEntry.second.empty()) |
950 | MadeChange |= emitBaseConstants(BaseGV: MapEntry.first); |
951 | |
952 | |
953 | // Cleanup dead instructions. |
954 | deleteDeadCastInst(); |
955 | |
956 | cleanup(); |
957 | |
958 | return MadeChange; |
959 | } |
960 | |
961 | PreservedAnalyses ConstantHoistingPass::run(Function &F, |
962 | FunctionAnalysisManager &AM) { |
963 | auto &DT = AM.getResult<DominatorTreeAnalysis>(IR&: F); |
964 | auto &TTI = AM.getResult<TargetIRAnalysis>(IR&: F); |
965 | auto BFI = ConstHoistWithBlockFrequency |
966 | ? &AM.getResult<BlockFrequencyAnalysis>(IR&: F) |
967 | : nullptr; |
968 | auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(IR&: F); |
969 | auto *PSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(IR&: *F.getParent()); |
970 | if (!runImpl(Fn&: F, TTI, DT, BFI, Entry&: F.getEntryBlock(), PSI)) |
971 | return PreservedAnalyses::all(); |
972 | |
973 | PreservedAnalyses PA; |
974 | PA.preserveSet<CFGAnalyses>(); |
975 | return PA; |
976 | } |
977 | |