10b57cec5SDimitry Andric //===- ConstantHoisting.cpp - Prepare code for expensive constants --------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass identifies expensive constants to hoist and coalesces them to 100b57cec5SDimitry Andric // better prepare it for SelectionDAG-based code generation. This works around 110b57cec5SDimitry Andric // the limitations of the basic-block-at-a-time approach. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric // First it scans all instructions for integer constants and calculates its 140b57cec5SDimitry Andric // cost. If the constant can be folded into the instruction (the cost is 150b57cec5SDimitry Andric // TCC_Free) or the cost is just a simple operation (TCC_BASIC), then we don't 160b57cec5SDimitry Andric // consider it expensive and leave it alone. This is the default behavior and 17480093f4SDimitry Andric // the default implementation of getIntImmCostInst will always return TCC_Free. 180b57cec5SDimitry Andric // 190b57cec5SDimitry Andric // If the cost is more than TCC_BASIC, then the integer constant can't be folded 200b57cec5SDimitry Andric // into the instruction and it might be beneficial to hoist the constant. 210b57cec5SDimitry Andric // Similar constants are coalesced to reduce register pressure and 220b57cec5SDimitry Andric // materialization code. 230b57cec5SDimitry Andric // 240b57cec5SDimitry Andric // When a constant is hoisted, it is also hidden behind a bitcast to force it to 250b57cec5SDimitry Andric // be live-out of the basic block. Otherwise the constant would be just 260b57cec5SDimitry Andric // duplicated and each basic block would have its own copy in the SelectionDAG. 270b57cec5SDimitry Andric // The SelectionDAG recognizes such constants as opaque and doesn't perform 280b57cec5SDimitry Andric // certain transformations on them, which would create a new expensive constant. 290b57cec5SDimitry Andric // 300b57cec5SDimitry Andric // This optimization is only applied to integer constants in instructions and 310b57cec5SDimitry Andric // simple (this means not nested) constant cast expressions. For example: 320b57cec5SDimitry Andric // %0 = load i64* inttoptr (i64 big_constant to i64*) 330b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/ConstantHoisting.h" 360b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 370b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 380b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 390b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 400b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 410b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h" 420b57cec5SDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h" 430b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 440b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 450b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 46*0fca6ea1SDimitry Andric #include "llvm/IR/DataLayout.h" 470b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 480b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 490b57cec5SDimitry Andric #include "llvm/IR/Function.h" 500b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 510b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 520b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 530b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 5481ad6265SDimitry Andric #include "llvm/IR/Operator.h" 550b57cec5SDimitry Andric #include "llvm/IR/Value.h" 56480093f4SDimitry Andric #include "llvm/InitializePasses.h" 570b57cec5SDimitry Andric #include "llvm/Pass.h" 580b57cec5SDimitry Andric #include "llvm/Support/BlockFrequency.h" 590b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 600b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 610b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 620b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 630b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h" 64480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 650b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SizeOpts.h" 660b57cec5SDimitry Andric #include <algorithm> 670b57cec5SDimitry Andric #include <cassert> 680b57cec5SDimitry Andric #include <cstdint> 690b57cec5SDimitry Andric #include <iterator> 700b57cec5SDimitry Andric #include <tuple> 710b57cec5SDimitry Andric #include <utility> 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric using namespace llvm; 740b57cec5SDimitry Andric using namespace consthoist; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric #define DEBUG_TYPE "consthoist" 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric STATISTIC(NumConstantsHoisted, "Number of constants hoisted"); 790b57cec5SDimitry Andric STATISTIC(NumConstantsRebased, "Number of constants rebased"); 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric static cl::opt<bool> ConstHoistWithBlockFrequency( 820b57cec5SDimitry Andric "consthoist-with-block-frequency", cl::init(true), cl::Hidden, 830b57cec5SDimitry Andric cl::desc("Enable the use of the block frequency analysis to reduce the " 840b57cec5SDimitry Andric "chance to execute const materialization more frequently than " 850b57cec5SDimitry Andric "without hoisting.")); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric static cl::opt<bool> ConstHoistGEP( 880b57cec5SDimitry Andric "consthoist-gep", cl::init(false), cl::Hidden, 890b57cec5SDimitry Andric cl::desc("Try hoisting constant gep expressions")); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric static cl::opt<unsigned> 920b57cec5SDimitry Andric MinNumOfDependentToRebase("consthoist-min-num-to-rebase", 930b57cec5SDimitry Andric cl::desc("Do not rebase if number of dependent constants of a Base is less " 940b57cec5SDimitry Andric "than this number."), 950b57cec5SDimitry Andric cl::init(0), cl::Hidden); 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric namespace { 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric /// The constant hoisting pass. 1000b57cec5SDimitry Andric class ConstantHoistingLegacyPass : public FunctionPass { 1010b57cec5SDimitry Andric public: 1020b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric ConstantHoistingLegacyPass() : FunctionPass(ID) { 1050b57cec5SDimitry Andric initializeConstantHoistingLegacyPassPass(*PassRegistry::getPassRegistry()); 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric bool runOnFunction(Function &Fn) override; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric StringRef getPassName() const override { return "Constant Hoisting"; } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 1130b57cec5SDimitry Andric AU.setPreservesCFG(); 1140b57cec5SDimitry Andric if (ConstHoistWithBlockFrequency) 1150b57cec5SDimitry Andric AU.addRequired<BlockFrequencyInfoWrapperPass>(); 1160b57cec5SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>(); 1170b57cec5SDimitry Andric AU.addRequired<ProfileSummaryInfoWrapperPass>(); 1180b57cec5SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric private: 1220b57cec5SDimitry Andric ConstantHoistingPass Impl; 1230b57cec5SDimitry Andric }; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric } // end anonymous namespace 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric char ConstantHoistingLegacyPass::ID = 0; 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(ConstantHoistingLegacyPass, "consthoist", 1300b57cec5SDimitry Andric "Constant Hoisting", false, false) 1310b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) 1320b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 1330b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass) 1340b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 1350b57cec5SDimitry Andric INITIALIZE_PASS_END(ConstantHoistingLegacyPass, "consthoist", 1360b57cec5SDimitry Andric "Constant Hoisting", false, false) 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric FunctionPass *llvm::createConstantHoistingPass() { 1390b57cec5SDimitry Andric return new ConstantHoistingLegacyPass(); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric /// Perform the constant hoisting optimization for the given function. 1430b57cec5SDimitry Andric bool ConstantHoistingLegacyPass::runOnFunction(Function &Fn) { 1440b57cec5SDimitry Andric if (skipFunction(Fn)) 1450b57cec5SDimitry Andric return false; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** Begin Constant Hoisting **********\n"); 1480b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** Function: " << Fn.getName() << '\n'); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric bool MadeChange = 1510b57cec5SDimitry Andric Impl.runImpl(Fn, getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn), 1520b57cec5SDimitry Andric getAnalysis<DominatorTreeWrapperPass>().getDomTree(), 1530b57cec5SDimitry Andric ConstHoistWithBlockFrequency 1540b57cec5SDimitry Andric ? &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI() 1550b57cec5SDimitry Andric : nullptr, 1560b57cec5SDimitry Andric Fn.getEntryBlock(), 1570b57cec5SDimitry Andric &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI()); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** End Constant Hoisting **********\n"); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric return MadeChange; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 16406c3fb27SDimitry Andric void ConstantHoistingPass::collectMatInsertPts( 16506c3fb27SDimitry Andric const RebasedConstantListType &RebasedConstants, 166*0fca6ea1SDimitry Andric SmallVectorImpl<BasicBlock::iterator> &MatInsertPts) const { 16706c3fb27SDimitry Andric for (const RebasedConstantInfo &RCI : RebasedConstants) 16806c3fb27SDimitry Andric for (const ConstantUser &U : RCI.Uses) 16906c3fb27SDimitry Andric MatInsertPts.emplace_back(findMatInsertPt(U.Inst, U.OpndIdx)); 17006c3fb27SDimitry Andric } 17106c3fb27SDimitry Andric 1720b57cec5SDimitry Andric /// Find the constant materialization insertion point. 173*0fca6ea1SDimitry Andric BasicBlock::iterator ConstantHoistingPass::findMatInsertPt(Instruction *Inst, 1740b57cec5SDimitry Andric unsigned Idx) const { 1750b57cec5SDimitry Andric // If the operand is a cast instruction, then we have to materialize the 1760b57cec5SDimitry Andric // constant before the cast instruction. 1770b57cec5SDimitry Andric if (Idx != ~0U) { 1780b57cec5SDimitry Andric Value *Opnd = Inst->getOperand(Idx); 1790b57cec5SDimitry Andric if (auto CastInst = dyn_cast<Instruction>(Opnd)) 1800b57cec5SDimitry Andric if (CastInst->isCast()) 181*0fca6ea1SDimitry Andric return CastInst->getIterator(); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // The simple and common case. This also includes constant expressions. 1850b57cec5SDimitry Andric if (!isa<PHINode>(Inst) && !Inst->isEHPad()) 186*0fca6ea1SDimitry Andric return Inst->getIterator(); 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric // We can't insert directly before a phi node or an eh pad. Insert before 1890b57cec5SDimitry Andric // the terminator of the incoming or dominating block. 1900b57cec5SDimitry Andric assert(Entry != Inst->getParent() && "PHI or landing pad in entry block!"); 191fe6060f1SDimitry Andric BasicBlock *InsertionBlock = nullptr; 192fe6060f1SDimitry Andric if (Idx != ~0U && isa<PHINode>(Inst)) { 193fe6060f1SDimitry Andric InsertionBlock = cast<PHINode>(Inst)->getIncomingBlock(Idx); 194fe6060f1SDimitry Andric if (!InsertionBlock->isEHPad()) { 195*0fca6ea1SDimitry Andric return InsertionBlock->getTerminator()->getIterator(); 196fe6060f1SDimitry Andric } 197fe6060f1SDimitry Andric } else { 198fe6060f1SDimitry Andric InsertionBlock = Inst->getParent(); 199fe6060f1SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric // This must be an EH pad. Iterate over immediate dominators until we find a 2020b57cec5SDimitry Andric // non-EH pad. We need to skip over catchswitch blocks, which are both EH pads 2030b57cec5SDimitry Andric // and terminators. 204fe6060f1SDimitry Andric auto *IDom = DT->getNode(InsertionBlock)->getIDom(); 2050b57cec5SDimitry Andric while (IDom->getBlock()->isEHPad()) { 2060b57cec5SDimitry Andric assert(Entry != IDom->getBlock() && "eh pad in entry block"); 2070b57cec5SDimitry Andric IDom = IDom->getIDom(); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 210*0fca6ea1SDimitry Andric return IDom->getBlock()->getTerminator()->getIterator(); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric /// Given \p BBs as input, find another set of BBs which collectively 2140b57cec5SDimitry Andric /// dominates \p BBs and have the minimal sum of frequencies. Return the BB 2150b57cec5SDimitry Andric /// set found in \p BBs. 2160b57cec5SDimitry Andric static void findBestInsertionSet(DominatorTree &DT, BlockFrequencyInfo &BFI, 2170b57cec5SDimitry Andric BasicBlock *Entry, 2188bcb0991SDimitry Andric SetVector<BasicBlock *> &BBs) { 2190b57cec5SDimitry Andric assert(!BBs.count(Entry) && "Assume Entry is not in BBs"); 2200b57cec5SDimitry Andric // Nodes on the current path to the root. 2210b57cec5SDimitry Andric SmallPtrSet<BasicBlock *, 8> Path; 2220b57cec5SDimitry Andric // Candidates includes any block 'BB' in set 'BBs' that is not strictly 2230b57cec5SDimitry Andric // dominated by any other blocks in set 'BBs', and all nodes in the path 2240b57cec5SDimitry Andric // in the dominator tree from Entry to 'BB'. 2250b57cec5SDimitry Andric SmallPtrSet<BasicBlock *, 16> Candidates; 226bdd1243dSDimitry Andric for (auto *BB : BBs) { 2270b57cec5SDimitry Andric // Ignore unreachable basic blocks. 2280b57cec5SDimitry Andric if (!DT.isReachableFromEntry(BB)) 2290b57cec5SDimitry Andric continue; 2300b57cec5SDimitry Andric Path.clear(); 2310b57cec5SDimitry Andric // Walk up the dominator tree until Entry or another BB in BBs 2320b57cec5SDimitry Andric // is reached. Insert the nodes on the way to the Path. 2330b57cec5SDimitry Andric BasicBlock *Node = BB; 2340b57cec5SDimitry Andric // The "Path" is a candidate path to be added into Candidates set. 2350b57cec5SDimitry Andric bool isCandidate = false; 2360b57cec5SDimitry Andric do { 2370b57cec5SDimitry Andric Path.insert(Node); 2380b57cec5SDimitry Andric if (Node == Entry || Candidates.count(Node)) { 2390b57cec5SDimitry Andric isCandidate = true; 2400b57cec5SDimitry Andric break; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric assert(DT.getNode(Node)->getIDom() && 2430b57cec5SDimitry Andric "Entry doens't dominate current Node"); 2440b57cec5SDimitry Andric Node = DT.getNode(Node)->getIDom()->getBlock(); 2450b57cec5SDimitry Andric } while (!BBs.count(Node)); 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric // If isCandidate is false, Node is another Block in BBs dominating 2480b57cec5SDimitry Andric // current 'BB'. Drop the nodes on the Path. 2490b57cec5SDimitry Andric if (!isCandidate) 2500b57cec5SDimitry Andric continue; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric // Add nodes on the Path into Candidates. 2530b57cec5SDimitry Andric Candidates.insert(Path.begin(), Path.end()); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric // Sort the nodes in Candidates in top-down order and save the nodes 2570b57cec5SDimitry Andric // in Orders. 2580b57cec5SDimitry Andric unsigned Idx = 0; 2590b57cec5SDimitry Andric SmallVector<BasicBlock *, 16> Orders; 2600b57cec5SDimitry Andric Orders.push_back(Entry); 2610b57cec5SDimitry Andric while (Idx != Orders.size()) { 2620b57cec5SDimitry Andric BasicBlock *Node = Orders[Idx++]; 263bdd1243dSDimitry Andric for (auto *ChildDomNode : DT.getNode(Node)->children()) { 2640b57cec5SDimitry Andric if (Candidates.count(ChildDomNode->getBlock())) 2650b57cec5SDimitry Andric Orders.push_back(ChildDomNode->getBlock()); 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric // Visit Orders in bottom-up order. 2700b57cec5SDimitry Andric using InsertPtsCostPair = 2718bcb0991SDimitry Andric std::pair<SetVector<BasicBlock *>, BlockFrequency>; 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric // InsertPtsMap is a map from a BB to the best insertion points for the 2740b57cec5SDimitry Andric // subtree of BB (subtree not including the BB itself). 2750b57cec5SDimitry Andric DenseMap<BasicBlock *, InsertPtsCostPair> InsertPtsMap; 2760b57cec5SDimitry Andric InsertPtsMap.reserve(Orders.size() + 1); 2770eae32dcSDimitry Andric for (BasicBlock *Node : llvm::reverse(Orders)) { 2780b57cec5SDimitry Andric bool NodeInBBs = BBs.count(Node); 2798bcb0991SDimitry Andric auto &InsertPts = InsertPtsMap[Node].first; 2800b57cec5SDimitry Andric BlockFrequency &InsertPtsFreq = InsertPtsMap[Node].second; 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric // Return the optimal insert points in BBs. 2830b57cec5SDimitry Andric if (Node == Entry) { 2840b57cec5SDimitry Andric BBs.clear(); 2850b57cec5SDimitry Andric if (InsertPtsFreq > BFI.getBlockFreq(Node) || 2860b57cec5SDimitry Andric (InsertPtsFreq == BFI.getBlockFreq(Node) && InsertPts.size() > 1)) 2870b57cec5SDimitry Andric BBs.insert(Entry); 2880b57cec5SDimitry Andric else 2890b57cec5SDimitry Andric BBs.insert(InsertPts.begin(), InsertPts.end()); 2900b57cec5SDimitry Andric break; 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric BasicBlock *Parent = DT.getNode(Node)->getIDom()->getBlock(); 2940b57cec5SDimitry Andric // Initially, ParentInsertPts is empty and ParentPtsFreq is 0. Every child 2950b57cec5SDimitry Andric // will update its parent's ParentInsertPts and ParentPtsFreq. 2968bcb0991SDimitry Andric auto &ParentInsertPts = InsertPtsMap[Parent].first; 2970b57cec5SDimitry Andric BlockFrequency &ParentPtsFreq = InsertPtsMap[Parent].second; 2980b57cec5SDimitry Andric // Choose to insert in Node or in subtree of Node. 2990b57cec5SDimitry Andric // Don't hoist to EHPad because we may not find a proper place to insert 3000b57cec5SDimitry Andric // in EHPad. 3010b57cec5SDimitry Andric // If the total frequency of InsertPts is the same as the frequency of the 3020b57cec5SDimitry Andric // target Node, and InsertPts contains more than one nodes, choose hoisting 3030b57cec5SDimitry Andric // to reduce code size. 3040b57cec5SDimitry Andric if (NodeInBBs || 3050b57cec5SDimitry Andric (!Node->isEHPad() && 3060b57cec5SDimitry Andric (InsertPtsFreq > BFI.getBlockFreq(Node) || 3070b57cec5SDimitry Andric (InsertPtsFreq == BFI.getBlockFreq(Node) && InsertPts.size() > 1)))) { 3080b57cec5SDimitry Andric ParentInsertPts.insert(Node); 3090b57cec5SDimitry Andric ParentPtsFreq += BFI.getBlockFreq(Node); 3100b57cec5SDimitry Andric } else { 3110b57cec5SDimitry Andric ParentInsertPts.insert(InsertPts.begin(), InsertPts.end()); 3120b57cec5SDimitry Andric ParentPtsFreq += InsertPtsFreq; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric /// Find an insertion point that dominates all uses. 318*0fca6ea1SDimitry Andric SetVector<BasicBlock::iterator> 319*0fca6ea1SDimitry Andric ConstantHoistingPass::findConstantInsertionPoint( 32006c3fb27SDimitry Andric const ConstantInfo &ConstInfo, 321*0fca6ea1SDimitry Andric const ArrayRef<BasicBlock::iterator> MatInsertPts) const { 3220b57cec5SDimitry Andric assert(!ConstInfo.RebasedConstants.empty() && "Invalid constant info entry."); 3230b57cec5SDimitry Andric // Collect all basic blocks. 3248bcb0991SDimitry Andric SetVector<BasicBlock *> BBs; 325*0fca6ea1SDimitry Andric SetVector<BasicBlock::iterator> InsertPts; 32606c3fb27SDimitry Andric 327*0fca6ea1SDimitry Andric for (BasicBlock::iterator MatInsertPt : MatInsertPts) 32806c3fb27SDimitry Andric BBs.insert(MatInsertPt->getParent()); 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric if (BBs.count(Entry)) { 331*0fca6ea1SDimitry Andric InsertPts.insert(Entry->begin()); 3320b57cec5SDimitry Andric return InsertPts; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric if (BFI) { 3360b57cec5SDimitry Andric findBestInsertionSet(*DT, *BFI, Entry, BBs); 33706c3fb27SDimitry Andric for (BasicBlock *BB : BBs) 338*0fca6ea1SDimitry Andric InsertPts.insert(BB->getFirstInsertionPt()); 3390b57cec5SDimitry Andric return InsertPts; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric while (BBs.size() >= 2) { 3430b57cec5SDimitry Andric BasicBlock *BB, *BB1, *BB2; 3448bcb0991SDimitry Andric BB1 = BBs.pop_back_val(); 3458bcb0991SDimitry Andric BB2 = BBs.pop_back_val(); 3460b57cec5SDimitry Andric BB = DT->findNearestCommonDominator(BB1, BB2); 3470b57cec5SDimitry Andric if (BB == Entry) { 348*0fca6ea1SDimitry Andric InsertPts.insert(Entry->begin()); 3490b57cec5SDimitry Andric return InsertPts; 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric BBs.insert(BB); 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric assert((BBs.size() == 1) && "Expected only one element."); 3540b57cec5SDimitry Andric Instruction &FirstInst = (*BBs.begin())->front(); 3550b57cec5SDimitry Andric InsertPts.insert(findMatInsertPt(&FirstInst)); 3560b57cec5SDimitry Andric return InsertPts; 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric /// Record constant integer ConstInt for instruction Inst at operand 3600b57cec5SDimitry Andric /// index Idx. 3610b57cec5SDimitry Andric /// 3620b57cec5SDimitry Andric /// The operand at index Idx is not necessarily the constant integer itself. It 3630b57cec5SDimitry Andric /// could also be a cast instruction or a constant expression that uses the 3640b57cec5SDimitry Andric /// constant integer. 3650b57cec5SDimitry Andric void ConstantHoistingPass::collectConstantCandidates( 3660b57cec5SDimitry Andric ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx, 3670b57cec5SDimitry Andric ConstantInt *ConstInt) { 368*0fca6ea1SDimitry Andric if (ConstInt->getType()->isVectorTy()) 369*0fca6ea1SDimitry Andric return; 370*0fca6ea1SDimitry Andric 371fe6060f1SDimitry Andric InstructionCost Cost; 3720b57cec5SDimitry Andric // Ask the target about the cost of materializing the constant for the given 3730b57cec5SDimitry Andric // instruction and operand index. 3740b57cec5SDimitry Andric if (auto IntrInst = dyn_cast<IntrinsicInst>(Inst)) 375480093f4SDimitry Andric Cost = TTI->getIntImmCostIntrin(IntrInst->getIntrinsicID(), Idx, 3765ffd83dbSDimitry Andric ConstInt->getValue(), ConstInt->getType(), 3775ffd83dbSDimitry Andric TargetTransformInfo::TCK_SizeAndLatency); 3780b57cec5SDimitry Andric else 379e8d8bef9SDimitry Andric Cost = TTI->getIntImmCostInst( 380e8d8bef9SDimitry Andric Inst->getOpcode(), Idx, ConstInt->getValue(), ConstInt->getType(), 381e8d8bef9SDimitry Andric TargetTransformInfo::TCK_SizeAndLatency, Inst); 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric // Ignore cheap integer constants. 3840b57cec5SDimitry Andric if (Cost > TargetTransformInfo::TCC_Basic) { 3850b57cec5SDimitry Andric ConstCandMapType::iterator Itr; 3860b57cec5SDimitry Andric bool Inserted; 3870b57cec5SDimitry Andric ConstPtrUnionType Cand = ConstInt; 3880b57cec5SDimitry Andric std::tie(Itr, Inserted) = ConstCandMap.insert(std::make_pair(Cand, 0)); 3890b57cec5SDimitry Andric if (Inserted) { 3900b57cec5SDimitry Andric ConstIntCandVec.push_back(ConstantCandidate(ConstInt)); 3910b57cec5SDimitry Andric Itr->second = ConstIntCandVec.size() - 1; 3920b57cec5SDimitry Andric } 393fe6060f1SDimitry Andric ConstIntCandVec[Itr->second].addUser(Inst, Idx, *Cost.getValue()); 3940b57cec5SDimitry Andric LLVM_DEBUG(if (isa<ConstantInt>(Inst->getOperand(Idx))) dbgs() 3950b57cec5SDimitry Andric << "Collect constant " << *ConstInt << " from " << *Inst 3960b57cec5SDimitry Andric << " with cost " << Cost << '\n'; 3970b57cec5SDimitry Andric else dbgs() << "Collect constant " << *ConstInt 3980b57cec5SDimitry Andric << " indirectly from " << *Inst << " via " 3990b57cec5SDimitry Andric << *Inst->getOperand(Idx) << " with cost " << Cost 4000b57cec5SDimitry Andric << '\n';); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric /// Record constant GEP expression for instruction Inst at operand index Idx. 4050b57cec5SDimitry Andric void ConstantHoistingPass::collectConstantCandidates( 4060b57cec5SDimitry Andric ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx, 4070b57cec5SDimitry Andric ConstantExpr *ConstExpr) { 4080b57cec5SDimitry Andric // TODO: Handle vector GEPs 4090b57cec5SDimitry Andric if (ConstExpr->getType()->isVectorTy()) 4100b57cec5SDimitry Andric return; 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric GlobalVariable *BaseGV = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0)); 4130b57cec5SDimitry Andric if (!BaseGV) 4140b57cec5SDimitry Andric return; 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric // Get offset from the base GV. 4178bcb0991SDimitry Andric PointerType *GVPtrTy = cast<PointerType>(BaseGV->getType()); 41806c3fb27SDimitry Andric IntegerType *OffsetTy = DL->getIndexType(*Ctx, GVPtrTy->getAddressSpace()); 41906c3fb27SDimitry Andric APInt Offset(DL->getTypeSizeInBits(OffsetTy), /*val*/ 0, /*isSigned*/ true); 4200b57cec5SDimitry Andric auto *GEPO = cast<GEPOperator>(ConstExpr); 42104eeddc0SDimitry Andric 42204eeddc0SDimitry Andric // TODO: If we have a mix of inbounds and non-inbounds GEPs, then basing a 42304eeddc0SDimitry Andric // non-inbounds GEP on an inbounds GEP is potentially incorrect. Restrict to 42404eeddc0SDimitry Andric // inbounds GEP for now -- alternatively, we could drop inbounds from the 42504eeddc0SDimitry Andric // constant expression, 42604eeddc0SDimitry Andric if (!GEPO->isInBounds()) 42704eeddc0SDimitry Andric return; 42804eeddc0SDimitry Andric 4290b57cec5SDimitry Andric if (!GEPO->accumulateConstantOffset(*DL, Offset)) 4300b57cec5SDimitry Andric return; 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric if (!Offset.isIntN(32)) 4330b57cec5SDimitry Andric return; 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric // A constant GEP expression that has a GlobalVariable as base pointer is 4360b57cec5SDimitry Andric // usually lowered to a load from constant pool. Such operation is unlikely 4370b57cec5SDimitry Andric // to be cheaper than compute it by <Base + Offset>, which can be lowered to 4380b57cec5SDimitry Andric // an ADD instruction or folded into Load/Store instruction. 439fe6060f1SDimitry Andric InstructionCost Cost = 44006c3fb27SDimitry Andric TTI->getIntImmCostInst(Instruction::Add, 1, Offset, OffsetTy, 441e8d8bef9SDimitry Andric TargetTransformInfo::TCK_SizeAndLatency, Inst); 4420b57cec5SDimitry Andric ConstCandVecType &ExprCandVec = ConstGEPCandMap[BaseGV]; 4430b57cec5SDimitry Andric ConstCandMapType::iterator Itr; 4440b57cec5SDimitry Andric bool Inserted; 4450b57cec5SDimitry Andric ConstPtrUnionType Cand = ConstExpr; 4460b57cec5SDimitry Andric std::tie(Itr, Inserted) = ConstCandMap.insert(std::make_pair(Cand, 0)); 4470b57cec5SDimitry Andric if (Inserted) { 4480b57cec5SDimitry Andric ExprCandVec.push_back(ConstantCandidate( 4490b57cec5SDimitry Andric ConstantInt::get(Type::getInt32Ty(*Ctx), Offset.getLimitedValue()), 4500b57cec5SDimitry Andric ConstExpr)); 4510b57cec5SDimitry Andric Itr->second = ExprCandVec.size() - 1; 4520b57cec5SDimitry Andric } 453fe6060f1SDimitry Andric ExprCandVec[Itr->second].addUser(Inst, Idx, *Cost.getValue()); 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric /// Check the operand for instruction Inst at index Idx. 4570b57cec5SDimitry Andric void ConstantHoistingPass::collectConstantCandidates( 4580b57cec5SDimitry Andric ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx) { 4590b57cec5SDimitry Andric Value *Opnd = Inst->getOperand(Idx); 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric // Visit constant integers. 4620b57cec5SDimitry Andric if (auto ConstInt = dyn_cast<ConstantInt>(Opnd)) { 4630b57cec5SDimitry Andric collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt); 4640b57cec5SDimitry Andric return; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric // Visit cast instructions that have constant integers. 4680b57cec5SDimitry Andric if (auto CastInst = dyn_cast<Instruction>(Opnd)) { 4690b57cec5SDimitry Andric // Only visit cast instructions, which have been skipped. All other 4700b57cec5SDimitry Andric // instructions should have already been visited. 4710b57cec5SDimitry Andric if (!CastInst->isCast()) 4720b57cec5SDimitry Andric return; 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric if (auto *ConstInt = dyn_cast<ConstantInt>(CastInst->getOperand(0))) { 4750b57cec5SDimitry Andric // Pretend the constant is directly used by the instruction and ignore 4760b57cec5SDimitry Andric // the cast instruction. 4770b57cec5SDimitry Andric collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt); 4780b57cec5SDimitry Andric return; 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric // Visit constant expressions that have constant integers. 4830b57cec5SDimitry Andric if (auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) { 4840b57cec5SDimitry Andric // Handle constant gep expressions. 48504eeddc0SDimitry Andric if (ConstHoistGEP && isa<GEPOperator>(ConstExpr)) 4860b57cec5SDimitry Andric collectConstantCandidates(ConstCandMap, Inst, Idx, ConstExpr); 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric // Only visit constant cast expressions. 4890b57cec5SDimitry Andric if (!ConstExpr->isCast()) 4900b57cec5SDimitry Andric return; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric if (auto ConstInt = dyn_cast<ConstantInt>(ConstExpr->getOperand(0))) { 4930b57cec5SDimitry Andric // Pretend the constant is directly used by the instruction and ignore 4940b57cec5SDimitry Andric // the constant expression. 4950b57cec5SDimitry Andric collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt); 4960b57cec5SDimitry Andric return; 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric /// Scan the instruction for expensive integer constants and record them 5020b57cec5SDimitry Andric /// in the constant candidate vector. 5030b57cec5SDimitry Andric void ConstantHoistingPass::collectConstantCandidates( 5040b57cec5SDimitry Andric ConstCandMapType &ConstCandMap, Instruction *Inst) { 5050b57cec5SDimitry Andric // Skip all cast instructions. They are visited indirectly later on. 5060b57cec5SDimitry Andric if (Inst->isCast()) 5070b57cec5SDimitry Andric return; 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric // Scan all operands. 5100b57cec5SDimitry Andric for (unsigned Idx = 0, E = Inst->getNumOperands(); Idx != E; ++Idx) { 5110b57cec5SDimitry Andric // The cost of materializing the constants (defined in 512480093f4SDimitry Andric // `TargetTransformInfo::getIntImmCostInst`) for instructions which only 513480093f4SDimitry Andric // take constant variables is lower than `TargetTransformInfo::TCC_Basic`. 514480093f4SDimitry Andric // So it's safe for us to collect constant candidates from all 515480093f4SDimitry Andric // IntrinsicInsts. 5165ffd83dbSDimitry Andric if (canReplaceOperandWithVariable(Inst, Idx)) { 5170b57cec5SDimitry Andric collectConstantCandidates(ConstCandMap, Inst, Idx); 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric } // end of for all operands 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric /// Collect all integer constants in the function that cannot be folded 5230b57cec5SDimitry Andric /// into an instruction itself. 5240b57cec5SDimitry Andric void ConstantHoistingPass::collectConstantCandidates(Function &Fn) { 5250b57cec5SDimitry Andric ConstCandMapType ConstCandMap; 526480093f4SDimitry Andric for (BasicBlock &BB : Fn) { 527480093f4SDimitry Andric // Ignore unreachable basic blocks. 528480093f4SDimitry Andric if (!DT->isReachableFromEntry(&BB)) 529480093f4SDimitry Andric continue; 5300b57cec5SDimitry Andric for (Instruction &Inst : BB) 5315f757f3fSDimitry Andric if (!TTI->preferToKeepConstantsAttached(Inst, Fn)) 5320b57cec5SDimitry Andric collectConstantCandidates(ConstCandMap, &Inst); 5330b57cec5SDimitry Andric } 534480093f4SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric // This helper function is necessary to deal with values that have different 5370b57cec5SDimitry Andric // bit widths (APInt Operator- does not like that). If the value cannot be 5380b57cec5SDimitry Andric // represented in uint64 we return an "empty" APInt. This is then interpreted 5390b57cec5SDimitry Andric // as the value is not in range. 540bdd1243dSDimitry Andric static std::optional<APInt> calculateOffsetDiff(const APInt &V1, 541bdd1243dSDimitry Andric const APInt &V2) { 542bdd1243dSDimitry Andric std::optional<APInt> Res; 5430b57cec5SDimitry Andric unsigned BW = V1.getBitWidth() > V2.getBitWidth() ? 5440b57cec5SDimitry Andric V1.getBitWidth() : V2.getBitWidth(); 5450b57cec5SDimitry Andric uint64_t LimVal1 = V1.getLimitedValue(); 5460b57cec5SDimitry Andric uint64_t LimVal2 = V2.getLimitedValue(); 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric if (LimVal1 == ~0ULL || LimVal2 == ~0ULL) 5490b57cec5SDimitry Andric return Res; 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric uint64_t Diff = LimVal1 - LimVal2; 5520b57cec5SDimitry Andric return APInt(BW, Diff, true); 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric // From a list of constants, one needs to picked as the base and the other 5560b57cec5SDimitry Andric // constants will be transformed into an offset from that base constant. The 5570b57cec5SDimitry Andric // question is which we can pick best? For example, consider these constants 5580b57cec5SDimitry Andric // and their number of uses: 5590b57cec5SDimitry Andric // 5600b57cec5SDimitry Andric // Constants| 2 | 4 | 12 | 42 | 5610b57cec5SDimitry Andric // NumUses | 3 | 2 | 8 | 7 | 5620b57cec5SDimitry Andric // 5630b57cec5SDimitry Andric // Selecting constant 12 because it has the most uses will generate negative 5640b57cec5SDimitry Andric // offsets for constants 2 and 4 (i.e. -10 and -8 respectively). If negative 5650b57cec5SDimitry Andric // offsets lead to less optimal code generation, then there might be better 5660b57cec5SDimitry Andric // solutions. Suppose immediates in the range of 0..35 are most optimally 5670b57cec5SDimitry Andric // supported by the architecture, then selecting constant 2 is most optimal 5680b57cec5SDimitry Andric // because this will generate offsets: 0, 2, 10, 40. Offsets 0, 2 and 10 are in 5690b57cec5SDimitry Andric // range 0..35, and thus 3 + 2 + 8 = 13 uses are in range. Selecting 12 would 5700b57cec5SDimitry Andric // have only 8 uses in range, so choosing 2 as a base is more optimal. Thus, in 5710b57cec5SDimitry Andric // selecting the base constant the range of the offsets is a very important 5720b57cec5SDimitry Andric // factor too that we take into account here. This algorithm calculates a total 5730b57cec5SDimitry Andric // costs for selecting a constant as the base and substract the costs if 5740b57cec5SDimitry Andric // immediates are out of range. It has quadratic complexity, so we call this 5750b57cec5SDimitry Andric // function only when we're optimising for size and there are less than 100 5760b57cec5SDimitry Andric // constants, we fall back to the straightforward algorithm otherwise 5770b57cec5SDimitry Andric // which does not do all the offset calculations. 5780b57cec5SDimitry Andric unsigned 5790b57cec5SDimitry Andric ConstantHoistingPass::maximizeConstantsInRange(ConstCandVecType::iterator S, 5800b57cec5SDimitry Andric ConstCandVecType::iterator E, 5810b57cec5SDimitry Andric ConstCandVecType::iterator &MaxCostItr) { 5820b57cec5SDimitry Andric unsigned NumUses = 0; 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric if (!OptForSize || std::distance(S,E) > 100) { 5850b57cec5SDimitry Andric for (auto ConstCand = S; ConstCand != E; ++ConstCand) { 5860b57cec5SDimitry Andric NumUses += ConstCand->Uses.size(); 5870b57cec5SDimitry Andric if (ConstCand->CumulativeCost > MaxCostItr->CumulativeCost) 5880b57cec5SDimitry Andric MaxCostItr = ConstCand; 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric return NumUses; 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "== Maximize constants in range ==\n"); 594fe6060f1SDimitry Andric InstructionCost MaxCost = -1; 5950b57cec5SDimitry Andric for (auto ConstCand = S; ConstCand != E; ++ConstCand) { 5960b57cec5SDimitry Andric auto Value = ConstCand->ConstInt->getValue(); 5970b57cec5SDimitry Andric Type *Ty = ConstCand->ConstInt->getType(); 598fe6060f1SDimitry Andric InstructionCost Cost = 0; 5990b57cec5SDimitry Andric NumUses += ConstCand->Uses.size(); 6000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "= Constant: " << ConstCand->ConstInt->getValue() 6010b57cec5SDimitry Andric << "\n"); 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric for (auto User : ConstCand->Uses) { 6040b57cec5SDimitry Andric unsigned Opcode = User.Inst->getOpcode(); 6050b57cec5SDimitry Andric unsigned OpndIdx = User.OpndIdx; 6065ffd83dbSDimitry Andric Cost += TTI->getIntImmCostInst(Opcode, OpndIdx, Value, Ty, 6075ffd83dbSDimitry Andric TargetTransformInfo::TCK_SizeAndLatency); 6080b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Cost: " << Cost << "\n"); 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric for (auto C2 = S; C2 != E; ++C2) { 611bdd1243dSDimitry Andric std::optional<APInt> Diff = calculateOffsetDiff( 612bdd1243dSDimitry Andric C2->ConstInt->getValue(), ConstCand->ConstInt->getValue()); 6130b57cec5SDimitry Andric if (Diff) { 614fe6060f1SDimitry Andric const InstructionCost ImmCosts = 615bdd1243dSDimitry Andric TTI->getIntImmCodeSizeCost(Opcode, OpndIdx, *Diff, Ty); 6160b57cec5SDimitry Andric Cost -= ImmCosts; 617bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Offset " << *Diff << " " 6180b57cec5SDimitry Andric << "has penalty: " << ImmCosts << "\n" 6190b57cec5SDimitry Andric << "Adjusted cost: " << Cost << "\n"); 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Cumulative cost: " << Cost << "\n"); 6240b57cec5SDimitry Andric if (Cost > MaxCost) { 6250b57cec5SDimitry Andric MaxCost = Cost; 6260b57cec5SDimitry Andric MaxCostItr = ConstCand; 6270b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "New candidate: " << MaxCostItr->ConstInt->getValue() 6280b57cec5SDimitry Andric << "\n"); 6290b57cec5SDimitry Andric } 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric return NumUses; 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric /// Find the base constant within the given range and rebase all other 6350b57cec5SDimitry Andric /// constants with respect to the base constant. 6360b57cec5SDimitry Andric void ConstantHoistingPass::findAndMakeBaseConstant( 6370b57cec5SDimitry Andric ConstCandVecType::iterator S, ConstCandVecType::iterator E, 6380b57cec5SDimitry Andric SmallVectorImpl<consthoist::ConstantInfo> &ConstInfoVec) { 6390b57cec5SDimitry Andric auto MaxCostItr = S; 6400b57cec5SDimitry Andric unsigned NumUses = maximizeConstantsInRange(S, E, MaxCostItr); 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric // Don't hoist constants that have only one use. 6430b57cec5SDimitry Andric if (NumUses <= 1) 6440b57cec5SDimitry Andric return; 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric ConstantInt *ConstInt = MaxCostItr->ConstInt; 6470b57cec5SDimitry Andric ConstantExpr *ConstExpr = MaxCostItr->ConstExpr; 6480b57cec5SDimitry Andric ConstantInfo ConstInfo; 6490b57cec5SDimitry Andric ConstInfo.BaseInt = ConstInt; 6500b57cec5SDimitry Andric ConstInfo.BaseExpr = ConstExpr; 6510b57cec5SDimitry Andric Type *Ty = ConstInt->getType(); 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric // Rebase the constants with respect to the base constant. 6540b57cec5SDimitry Andric for (auto ConstCand = S; ConstCand != E; ++ConstCand) { 6550b57cec5SDimitry Andric APInt Diff = ConstCand->ConstInt->getValue() - ConstInt->getValue(); 6560b57cec5SDimitry Andric Constant *Offset = Diff == 0 ? nullptr : ConstantInt::get(Ty, Diff); 6570b57cec5SDimitry Andric Type *ConstTy = 6580b57cec5SDimitry Andric ConstCand->ConstExpr ? ConstCand->ConstExpr->getType() : nullptr; 6590b57cec5SDimitry Andric ConstInfo.RebasedConstants.push_back( 6600b57cec5SDimitry Andric RebasedConstantInfo(std::move(ConstCand->Uses), Offset, ConstTy)); 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric ConstInfoVec.push_back(std::move(ConstInfo)); 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric /// Finds and combines constant candidates that can be easily 6660b57cec5SDimitry Andric /// rematerialized with an add from a common base constant. 6670b57cec5SDimitry Andric void ConstantHoistingPass::findBaseConstants(GlobalVariable *BaseGV) { 6680b57cec5SDimitry Andric // If BaseGV is nullptr, find base among candidate constant integers; 6690b57cec5SDimitry Andric // Otherwise find base among constant GEPs that share the same BaseGV. 6700b57cec5SDimitry Andric ConstCandVecType &ConstCandVec = BaseGV ? 6710b57cec5SDimitry Andric ConstGEPCandMap[BaseGV] : ConstIntCandVec; 6720b57cec5SDimitry Andric ConstInfoVecType &ConstInfoVec = BaseGV ? 6730b57cec5SDimitry Andric ConstGEPInfoMap[BaseGV] : ConstIntInfoVec; 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric // Sort the constants by value and type. This invalidates the mapping! 6760b57cec5SDimitry Andric llvm::stable_sort(ConstCandVec, [](const ConstantCandidate &LHS, 6770b57cec5SDimitry Andric const ConstantCandidate &RHS) { 6780b57cec5SDimitry Andric if (LHS.ConstInt->getType() != RHS.ConstInt->getType()) 679cb14a3feSDimitry Andric return LHS.ConstInt->getBitWidth() < RHS.ConstInt->getBitWidth(); 6800b57cec5SDimitry Andric return LHS.ConstInt->getValue().ult(RHS.ConstInt->getValue()); 6810b57cec5SDimitry Andric }); 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric // Simple linear scan through the sorted constant candidate vector for viable 6840b57cec5SDimitry Andric // merge candidates. 6850b57cec5SDimitry Andric auto MinValItr = ConstCandVec.begin(); 6860b57cec5SDimitry Andric for (auto CC = std::next(ConstCandVec.begin()), E = ConstCandVec.end(); 6870b57cec5SDimitry Andric CC != E; ++CC) { 6880b57cec5SDimitry Andric if (MinValItr->ConstInt->getType() == CC->ConstInt->getType()) { 6890b57cec5SDimitry Andric Type *MemUseValTy = nullptr; 6900b57cec5SDimitry Andric for (auto &U : CC->Uses) { 6910b57cec5SDimitry Andric auto *UI = U.Inst; 6920b57cec5SDimitry Andric if (LoadInst *LI = dyn_cast<LoadInst>(UI)) { 6930b57cec5SDimitry Andric MemUseValTy = LI->getType(); 6940b57cec5SDimitry Andric break; 6950b57cec5SDimitry Andric } else if (StoreInst *SI = dyn_cast<StoreInst>(UI)) { 6960b57cec5SDimitry Andric // Make sure the constant is used as pointer operand of the StoreInst. 6970b57cec5SDimitry Andric if (SI->getPointerOperand() == SI->getOperand(U.OpndIdx)) { 6980b57cec5SDimitry Andric MemUseValTy = SI->getValueOperand()->getType(); 6990b57cec5SDimitry Andric break; 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric // Check if the constant is in range of an add with immediate. 7050b57cec5SDimitry Andric APInt Diff = CC->ConstInt->getValue() - MinValItr->ConstInt->getValue(); 7060b57cec5SDimitry Andric if ((Diff.getBitWidth() <= 64) && 7070b57cec5SDimitry Andric TTI->isLegalAddImmediate(Diff.getSExtValue()) && 7080b57cec5SDimitry Andric // Check if Diff can be used as offset in addressing mode of the user 7090b57cec5SDimitry Andric // memory instruction. 7100b57cec5SDimitry Andric (!MemUseValTy || TTI->isLegalAddressingMode(MemUseValTy, 7110b57cec5SDimitry Andric /*BaseGV*/nullptr, /*BaseOffset*/Diff.getSExtValue(), 7120b57cec5SDimitry Andric /*HasBaseReg*/true, /*Scale*/0))) 7130b57cec5SDimitry Andric continue; 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric // We either have now a different constant type or the constant is not in 7160b57cec5SDimitry Andric // range of an add with immediate anymore. 7170b57cec5SDimitry Andric findAndMakeBaseConstant(MinValItr, CC, ConstInfoVec); 7180b57cec5SDimitry Andric // Start a new base constant search. 7190b57cec5SDimitry Andric MinValItr = CC; 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric // Finalize the last base constant search. 7220b57cec5SDimitry Andric findAndMakeBaseConstant(MinValItr, ConstCandVec.end(), ConstInfoVec); 7230b57cec5SDimitry Andric } 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric /// Updates the operand at Idx in instruction Inst with the result of 7260b57cec5SDimitry Andric /// instruction Mat. If the instruction is a PHI node then special 727bdd1243dSDimitry Andric /// handling for duplicate values from the same incoming basic block is 7280b57cec5SDimitry Andric /// required. 7290b57cec5SDimitry Andric /// \return The update will always succeed, but the return value indicated if 7300b57cec5SDimitry Andric /// Mat was used for the update or not. 7310b57cec5SDimitry Andric static bool updateOperand(Instruction *Inst, unsigned Idx, Instruction *Mat) { 7320b57cec5SDimitry Andric if (auto PHI = dyn_cast<PHINode>(Inst)) { 7330b57cec5SDimitry Andric // Check if any previous operand of the PHI node has the same incoming basic 7340b57cec5SDimitry Andric // block. This is a very odd case that happens when the incoming basic block 7350b57cec5SDimitry Andric // has a switch statement. In this case use the same value as the previous 7360b57cec5SDimitry Andric // operand(s), otherwise we will fail verification due to different values. 7370b57cec5SDimitry Andric // The values are actually the same, but the variable names are different 7380b57cec5SDimitry Andric // and the verifier doesn't like that. 7390b57cec5SDimitry Andric BasicBlock *IncomingBB = PHI->getIncomingBlock(Idx); 7400b57cec5SDimitry Andric for (unsigned i = 0; i < Idx; ++i) { 7410b57cec5SDimitry Andric if (PHI->getIncomingBlock(i) == IncomingBB) { 7420b57cec5SDimitry Andric Value *IncomingVal = PHI->getIncomingValue(i); 7430b57cec5SDimitry Andric Inst->setOperand(Idx, IncomingVal); 7440b57cec5SDimitry Andric return false; 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric Inst->setOperand(Idx, Mat); 7500b57cec5SDimitry Andric return true; 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric /// Emit materialization code for all rebased constants and update their 7540b57cec5SDimitry Andric /// users. 7550b57cec5SDimitry Andric void ConstantHoistingPass::emitBaseConstants(Instruction *Base, 75606c3fb27SDimitry Andric UserAdjustment *Adj) { 7570b57cec5SDimitry Andric Instruction *Mat = Base; 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric // The same offset can be dereferenced to different types in nested struct. 76006c3fb27SDimitry Andric if (!Adj->Offset && Adj->Ty && Adj->Ty != Base->getType()) 76106c3fb27SDimitry Andric Adj->Offset = ConstantInt::get(Type::getInt32Ty(*Ctx), 0); 7620b57cec5SDimitry Andric 76306c3fb27SDimitry Andric if (Adj->Offset) { 76406c3fb27SDimitry Andric if (Adj->Ty) { 7650b57cec5SDimitry Andric // Constant being rebased is a ConstantExpr. 76606c3fb27SDimitry Andric Mat = GetElementPtrInst::Create(Type::getInt8Ty(*Ctx), Base, Adj->Offset, 76706c3fb27SDimitry Andric "mat_gep", Adj->MatInsertPt); 7685f757f3fSDimitry Andric // Hide it behind a bitcast. 769*0fca6ea1SDimitry Andric Mat = new BitCastInst(Mat, Adj->Ty, "mat_bitcast", 770*0fca6ea1SDimitry Andric Adj->MatInsertPt->getIterator()); 7710b57cec5SDimitry Andric } else 7720b57cec5SDimitry Andric // Constant being rebased is a ConstantInt. 773*0fca6ea1SDimitry Andric Mat = 774*0fca6ea1SDimitry Andric BinaryOperator::Create(Instruction::Add, Base, Adj->Offset, 775*0fca6ea1SDimitry Andric "const_mat", Adj->MatInsertPt->getIterator()); 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Materialize constant (" << *Base->getOperand(0) 77806c3fb27SDimitry Andric << " + " << *Adj->Offset << ") in BB " 7790b57cec5SDimitry Andric << Mat->getParent()->getName() << '\n' 7800b57cec5SDimitry Andric << *Mat << '\n'); 78106c3fb27SDimitry Andric Mat->setDebugLoc(Adj->User.Inst->getDebugLoc()); 7820b57cec5SDimitry Andric } 78306c3fb27SDimitry Andric Value *Opnd = Adj->User.Inst->getOperand(Adj->User.OpndIdx); 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric // Visit constant integer. 7860b57cec5SDimitry Andric if (isa<ConstantInt>(Opnd)) { 78706c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Update: " << *Adj->User.Inst << '\n'); 78806c3fb27SDimitry Andric if (!updateOperand(Adj->User.Inst, Adj->User.OpndIdx, Mat) && Adj->Offset) 7890b57cec5SDimitry Andric Mat->eraseFromParent(); 79006c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "To : " << *Adj->User.Inst << '\n'); 7910b57cec5SDimitry Andric return; 7920b57cec5SDimitry Andric } 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric // Visit cast instruction. 7950b57cec5SDimitry Andric if (auto CastInst = dyn_cast<Instruction>(Opnd)) { 7960b57cec5SDimitry Andric assert(CastInst->isCast() && "Expected an cast instruction!"); 7970b57cec5SDimitry Andric // Check if we already have visited this cast instruction before to avoid 7980b57cec5SDimitry Andric // unnecessary cloning. 7990b57cec5SDimitry Andric Instruction *&ClonedCastInst = ClonedCastMap[CastInst]; 8000b57cec5SDimitry Andric if (!ClonedCastInst) { 8010b57cec5SDimitry Andric ClonedCastInst = CastInst->clone(); 8020b57cec5SDimitry Andric ClonedCastInst->setOperand(0, Mat); 8030b57cec5SDimitry Andric ClonedCastInst->insertAfter(CastInst); 8040b57cec5SDimitry Andric // Use the same debug location as the original cast instruction. 8050b57cec5SDimitry Andric ClonedCastInst->setDebugLoc(CastInst->getDebugLoc()); 8060b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Clone instruction: " << *CastInst << '\n' 8070b57cec5SDimitry Andric << "To : " << *ClonedCastInst << '\n'); 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric 81006c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Update: " << *Adj->User.Inst << '\n'); 81106c3fb27SDimitry Andric updateOperand(Adj->User.Inst, Adj->User.OpndIdx, ClonedCastInst); 81206c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "To : " << *Adj->User.Inst << '\n'); 8130b57cec5SDimitry Andric return; 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric // Visit constant expression. 8170b57cec5SDimitry Andric if (auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) { 81804eeddc0SDimitry Andric if (isa<GEPOperator>(ConstExpr)) { 8190b57cec5SDimitry Andric // Operand is a ConstantGEP, replace it. 82006c3fb27SDimitry Andric updateOperand(Adj->User.Inst, Adj->User.OpndIdx, Mat); 8210b57cec5SDimitry Andric return; 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric // Aside from constant GEPs, only constant cast expressions are collected. 8250b57cec5SDimitry Andric assert(ConstExpr->isCast() && "ConstExpr should be a cast"); 826*0fca6ea1SDimitry Andric Instruction *ConstExprInst = ConstExpr->getAsInstruction(); 827*0fca6ea1SDimitry Andric ConstExprInst->insertBefore(Adj->MatInsertPt); 8280b57cec5SDimitry Andric ConstExprInst->setOperand(0, Mat); 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric // Use the same debug location as the instruction we are about to update. 83106c3fb27SDimitry Andric ConstExprInst->setDebugLoc(Adj->User.Inst->getDebugLoc()); 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Create instruction: " << *ConstExprInst << '\n' 8340b57cec5SDimitry Andric << "From : " << *ConstExpr << '\n'); 83506c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Update: " << *Adj->User.Inst << '\n'); 83606c3fb27SDimitry Andric if (!updateOperand(Adj->User.Inst, Adj->User.OpndIdx, ConstExprInst)) { 8370b57cec5SDimitry Andric ConstExprInst->eraseFromParent(); 83806c3fb27SDimitry Andric if (Adj->Offset) 8390b57cec5SDimitry Andric Mat->eraseFromParent(); 8400b57cec5SDimitry Andric } 84106c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "To : " << *Adj->User.Inst << '\n'); 8420b57cec5SDimitry Andric return; 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric /// Hoist and hide the base constant behind a bitcast and emit 8470b57cec5SDimitry Andric /// materialization code for derived constants. 8480b57cec5SDimitry Andric bool ConstantHoistingPass::emitBaseConstants(GlobalVariable *BaseGV) { 8490b57cec5SDimitry Andric bool MadeChange = false; 8500b57cec5SDimitry Andric SmallVectorImpl<consthoist::ConstantInfo> &ConstInfoVec = 8510b57cec5SDimitry Andric BaseGV ? ConstGEPInfoMap[BaseGV] : ConstIntInfoVec; 85206c3fb27SDimitry Andric for (const consthoist::ConstantInfo &ConstInfo : ConstInfoVec) { 853*0fca6ea1SDimitry Andric SmallVector<BasicBlock::iterator, 4> MatInsertPts; 85406c3fb27SDimitry Andric collectMatInsertPts(ConstInfo.RebasedConstants, MatInsertPts); 855*0fca6ea1SDimitry Andric SetVector<BasicBlock::iterator> IPSet = 85606c3fb27SDimitry Andric findConstantInsertionPoint(ConstInfo, MatInsertPts); 8570b57cec5SDimitry Andric // We can have an empty set if the function contains unreachable blocks. 8580b57cec5SDimitry Andric if (IPSet.empty()) 8590b57cec5SDimitry Andric continue; 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric unsigned UsesNum = 0; 8620b57cec5SDimitry Andric unsigned ReBasesNum = 0; 8630b57cec5SDimitry Andric unsigned NotRebasedNum = 0; 864*0fca6ea1SDimitry Andric for (const BasicBlock::iterator &IP : IPSet) { 8650b57cec5SDimitry Andric // First, collect constants depending on this IP of the base. 86606c3fb27SDimitry Andric UsesNum = 0; 86706c3fb27SDimitry Andric SmallVector<UserAdjustment, 4> ToBeRebased; 86806c3fb27SDimitry Andric unsigned MatCtr = 0; 8690b57cec5SDimitry Andric for (auto const &RCI : ConstInfo.RebasedConstants) { 87006c3fb27SDimitry Andric UsesNum += RCI.Uses.size(); 8710b57cec5SDimitry Andric for (auto const &U : RCI.Uses) { 872*0fca6ea1SDimitry Andric const BasicBlock::iterator &MatInsertPt = MatInsertPts[MatCtr++]; 87306c3fb27SDimitry Andric BasicBlock *OrigMatInsertBB = MatInsertPt->getParent(); 8740b57cec5SDimitry Andric // If Base constant is to be inserted in multiple places, 8750b57cec5SDimitry Andric // generate rebase for U using the Base dominating U. 8760b57cec5SDimitry Andric if (IPSet.size() == 1 || 8770b57cec5SDimitry Andric DT->dominates(IP->getParent(), OrigMatInsertBB)) 87806c3fb27SDimitry Andric ToBeRebased.emplace_back(RCI.Offset, RCI.Ty, MatInsertPt, U); 8790b57cec5SDimitry Andric } 8800b57cec5SDimitry Andric } 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric // If only few constants depend on this IP of base, skip rebasing, 8830b57cec5SDimitry Andric // assuming the base and the rebased have the same materialization cost. 8840b57cec5SDimitry Andric if (ToBeRebased.size() < MinNumOfDependentToRebase) { 8850b57cec5SDimitry Andric NotRebasedNum += ToBeRebased.size(); 8860b57cec5SDimitry Andric continue; 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric // Emit an instance of the base at this IP. 8900b57cec5SDimitry Andric Instruction *Base = nullptr; 8910b57cec5SDimitry Andric // Hoist and hide the base constant behind a bitcast. 8920b57cec5SDimitry Andric if (ConstInfo.BaseExpr) { 8930b57cec5SDimitry Andric assert(BaseGV && "A base constant expression must have an base GV"); 8940b57cec5SDimitry Andric Type *Ty = ConstInfo.BaseExpr->getType(); 8950b57cec5SDimitry Andric Base = new BitCastInst(ConstInfo.BaseExpr, Ty, "const", IP); 8960b57cec5SDimitry Andric } else { 897cb14a3feSDimitry Andric IntegerType *Ty = ConstInfo.BaseInt->getIntegerType(); 8980b57cec5SDimitry Andric Base = new BitCastInst(ConstInfo.BaseInt, Ty, "const", IP); 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric Base->setDebugLoc(IP->getDebugLoc()); 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Hoist constant (" << *ConstInfo.BaseInt 9040b57cec5SDimitry Andric << ") to BB " << IP->getParent()->getName() << '\n' 9050b57cec5SDimitry Andric << *Base << '\n'); 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric // Emit materialization code for rebased constants depending on this IP. 90806c3fb27SDimitry Andric for (UserAdjustment &R : ToBeRebased) { 90906c3fb27SDimitry Andric emitBaseConstants(Base, &R); 9100b57cec5SDimitry Andric ReBasesNum++; 9110b57cec5SDimitry Andric // Use the same debug location as the last user of the constant. 9120b57cec5SDimitry Andric Base->setDebugLoc(DILocation::getMergedLocation( 91306c3fb27SDimitry Andric Base->getDebugLoc(), R.User.Inst->getDebugLoc())); 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric assert(!Base->use_empty() && "The use list is empty!?"); 9160b57cec5SDimitry Andric assert(isa<Instruction>(Base->user_back()) && 9170b57cec5SDimitry Andric "All uses should be instructions."); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric (void)UsesNum; 9200b57cec5SDimitry Andric (void)ReBasesNum; 9210b57cec5SDimitry Andric (void)NotRebasedNum; 9220b57cec5SDimitry Andric // Expect all uses are rebased after rebase is done. 9230b57cec5SDimitry Andric assert(UsesNum == (ReBasesNum + NotRebasedNum) && 9240b57cec5SDimitry Andric "Not all uses are rebased"); 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric NumConstantsHoisted++; 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric // Base constant is also included in ConstInfo.RebasedConstants, so 9290b57cec5SDimitry Andric // deduct 1 from ConstInfo.RebasedConstants.size(). 9300b57cec5SDimitry Andric NumConstantsRebased += ConstInfo.RebasedConstants.size() - 1; 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric MadeChange = true; 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric return MadeChange; 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric /// Check all cast instructions we made a copy of and remove them if they 9380b57cec5SDimitry Andric /// have no more users. 9390b57cec5SDimitry Andric void ConstantHoistingPass::deleteDeadCastInst() const { 9400b57cec5SDimitry Andric for (auto const &I : ClonedCastMap) 9410b57cec5SDimitry Andric if (I.first->use_empty()) 9420b57cec5SDimitry Andric I.first->eraseFromParent(); 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric /// Optimize expensive integer constants in the given function. 9460b57cec5SDimitry Andric bool ConstantHoistingPass::runImpl(Function &Fn, TargetTransformInfo &TTI, 9470b57cec5SDimitry Andric DominatorTree &DT, BlockFrequencyInfo *BFI, 9480b57cec5SDimitry Andric BasicBlock &Entry, ProfileSummaryInfo *PSI) { 9490b57cec5SDimitry Andric this->TTI = &TTI; 9500b57cec5SDimitry Andric this->DT = &DT; 9510b57cec5SDimitry Andric this->BFI = BFI; 952*0fca6ea1SDimitry Andric this->DL = &Fn.getDataLayout(); 9530b57cec5SDimitry Andric this->Ctx = &Fn.getContext(); 9540b57cec5SDimitry Andric this->Entry = &Entry; 9550b57cec5SDimitry Andric this->PSI = PSI; 9567a6dacacSDimitry Andric this->OptForSize = Entry.getParent()->hasOptSize() || 9577a6dacacSDimitry Andric llvm::shouldOptimizeForSize(Entry.getParent(), PSI, BFI, 9587a6dacacSDimitry Andric PGSOQueryType::IRPass); 9597a6dacacSDimitry Andric 9600b57cec5SDimitry Andric // Collect all constant candidates. 9610b57cec5SDimitry Andric collectConstantCandidates(Fn); 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric // Combine constants that can be easily materialized with an add from a common 9640b57cec5SDimitry Andric // base constant. 9650b57cec5SDimitry Andric if (!ConstIntCandVec.empty()) 9660b57cec5SDimitry Andric findBaseConstants(nullptr); 967e8d8bef9SDimitry Andric for (const auto &MapEntry : ConstGEPCandMap) 9680b57cec5SDimitry Andric if (!MapEntry.second.empty()) 9690b57cec5SDimitry Andric findBaseConstants(MapEntry.first); 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric // Finally hoist the base constant and emit materialization code for dependent 9720b57cec5SDimitry Andric // constants. 9730b57cec5SDimitry Andric bool MadeChange = false; 9740b57cec5SDimitry Andric if (!ConstIntInfoVec.empty()) 9750b57cec5SDimitry Andric MadeChange = emitBaseConstants(nullptr); 976e8d8bef9SDimitry Andric for (const auto &MapEntry : ConstGEPInfoMap) 9770b57cec5SDimitry Andric if (!MapEntry.second.empty()) 9780b57cec5SDimitry Andric MadeChange |= emitBaseConstants(MapEntry.first); 9790b57cec5SDimitry Andric 9800b57cec5SDimitry Andric 9810b57cec5SDimitry Andric // Cleanup dead instructions. 9820b57cec5SDimitry Andric deleteDeadCastInst(); 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric cleanup(); 9850b57cec5SDimitry Andric 9860b57cec5SDimitry Andric return MadeChange; 9870b57cec5SDimitry Andric } 9880b57cec5SDimitry Andric 9890b57cec5SDimitry Andric PreservedAnalyses ConstantHoistingPass::run(Function &F, 9900b57cec5SDimitry Andric FunctionAnalysisManager &AM) { 9910b57cec5SDimitry Andric auto &DT = AM.getResult<DominatorTreeAnalysis>(F); 9920b57cec5SDimitry Andric auto &TTI = AM.getResult<TargetIRAnalysis>(F); 9930b57cec5SDimitry Andric auto BFI = ConstHoistWithBlockFrequency 9940b57cec5SDimitry Andric ? &AM.getResult<BlockFrequencyAnalysis>(F) 9950b57cec5SDimitry Andric : nullptr; 9965ffd83dbSDimitry Andric auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); 9975ffd83dbSDimitry Andric auto *PSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent()); 9980b57cec5SDimitry Andric if (!runImpl(F, TTI, DT, BFI, F.getEntryBlock(), PSI)) 9990b57cec5SDimitry Andric return PreservedAnalyses::all(); 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric PreservedAnalyses PA; 10020b57cec5SDimitry Andric PA.preserveSet<CFGAnalyses>(); 10030b57cec5SDimitry Andric return PA; 10040b57cec5SDimitry Andric } 1005