1*a34c753fSRafael Auler //===--- Passes/FrameOptimizer.cpp ----------------------------------------===// 2*a34c753fSRafael Auler // 3*a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information. 5*a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*a34c753fSRafael Auler // 7*a34c753fSRafael Auler //===----------------------------------------------------------------------===// 8*a34c753fSRafael Auler // 9*a34c753fSRafael Auler //===----------------------------------------------------------------------===// 10*a34c753fSRafael Auler 11*a34c753fSRafael Auler #include "bolt/Passes/FrameOptimizer.h" 12*a34c753fSRafael Auler #include "bolt/Core/ParallelUtilities.h" 13*a34c753fSRafael Auler #include "bolt/Passes/BinaryFunctionCallGraph.h" 14*a34c753fSRafael Auler #include "bolt/Passes/DataflowInfoManager.h" 15*a34c753fSRafael Auler #include "bolt/Passes/ShrinkWrapping.h" 16*a34c753fSRafael Auler #include "bolt/Passes/StackAvailableExpressions.h" 17*a34c753fSRafael Auler #include "bolt/Passes/StackReachingUses.h" 18*a34c753fSRafael Auler #include "llvm/Support/Timer.h" 19*a34c753fSRafael Auler #include <deque> 20*a34c753fSRafael Auler #include <unordered_map> 21*a34c753fSRafael Auler 22*a34c753fSRafael Auler #define DEBUG_TYPE "fop" 23*a34c753fSRafael Auler 24*a34c753fSRafael Auler using namespace llvm; 25*a34c753fSRafael Auler 26*a34c753fSRafael Auler namespace opts { 27*a34c753fSRafael Auler extern cl::opt<unsigned> Verbosity; 28*a34c753fSRafael Auler extern cl::opt<bool> TimeOpts; 29*a34c753fSRafael Auler extern cl::OptionCategory BoltOptCategory; 30*a34c753fSRafael Auler 31*a34c753fSRafael Auler using namespace bolt; 32*a34c753fSRafael Auler 33*a34c753fSRafael Auler cl::opt<FrameOptimizationType> 34*a34c753fSRafael Auler FrameOptimization("frame-opt", 35*a34c753fSRafael Auler cl::init(FOP_NONE), 36*a34c753fSRafael Auler cl::desc("optimize stack frame accesses"), 37*a34c753fSRafael Auler cl::values( 38*a34c753fSRafael Auler clEnumValN(FOP_NONE, "none", "do not perform frame optimization"), 39*a34c753fSRafael Auler clEnumValN(FOP_HOT, "hot", "perform FOP on hot functions"), 40*a34c753fSRafael Auler clEnumValN(FOP_ALL, "all", "perform FOP on all functions")), 41*a34c753fSRafael Auler cl::ZeroOrMore, 42*a34c753fSRafael Auler cl::cat(BoltOptCategory)); 43*a34c753fSRafael Auler 44*a34c753fSRafael Auler cl::opt<bool> 45*a34c753fSRafael Auler RemoveStores("frame-opt-rm-stores", 46*a34c753fSRafael Auler cl::init(FOP_NONE), 47*a34c753fSRafael Auler cl::desc("apply additional analysis to remove stores (experimental)"), 48*a34c753fSRafael Auler cl::init(false), 49*a34c753fSRafael Auler cl::ZeroOrMore, 50*a34c753fSRafael Auler cl::cat(BoltOptCategory)); 51*a34c753fSRafael Auler 52*a34c753fSRafael Auler } // namespace opts 53*a34c753fSRafael Auler 54*a34c753fSRafael Auler namespace llvm { 55*a34c753fSRafael Auler namespace bolt { 56*a34c753fSRafael Auler 57*a34c753fSRafael Auler void FrameOptimizerPass::removeUnnecessaryLoads(const RegAnalysis &RA, 58*a34c753fSRafael Auler const FrameAnalysis &FA, 59*a34c753fSRafael Auler const BinaryContext &BC, 60*a34c753fSRafael Auler BinaryFunction &BF) { 61*a34c753fSRafael Auler StackAvailableExpressions SAE(RA, FA, BC, BF); 62*a34c753fSRafael Auler SAE.run(); 63*a34c753fSRafael Auler 64*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Performing unnecessary loads removal\n"); 65*a34c753fSRafael Auler std::deque<std::pair<BinaryBasicBlock *, MCInst *>> ToErase; 66*a34c753fSRafael Auler bool Changed = false; 67*a34c753fSRafael Auler const auto ExprEnd = SAE.expr_end(); 68*a34c753fSRafael Auler for (BinaryBasicBlock &BB : BF) { 69*a34c753fSRafael Auler LLVM_DEBUG(dbgs() <<"\tNow at BB " << BB.getName() << "\n"); 70*a34c753fSRafael Auler const MCInst *Prev = nullptr; 71*a34c753fSRafael Auler for (MCInst &Inst : BB) { 72*a34c753fSRafael Auler LLVM_DEBUG({ 73*a34c753fSRafael Auler dbgs() << "\t\tNow at "; 74*a34c753fSRafael Auler Inst.dump(); 75*a34c753fSRafael Auler for (auto I = Prev ? SAE.expr_begin(*Prev) : SAE.expr_begin(BB); 76*a34c753fSRafael Auler I != ExprEnd; ++I) { 77*a34c753fSRafael Auler dbgs() << "\t\t\tReached by: "; 78*a34c753fSRafael Auler (*I)->dump(); 79*a34c753fSRafael Auler } 80*a34c753fSRafael Auler }); 81*a34c753fSRafael Auler // if Inst is a load from stack and the current available expressions show 82*a34c753fSRafael Auler // this value is available in a register or immediate, replace this load 83*a34c753fSRafael Auler // with move from register or from immediate. 84*a34c753fSRafael Auler ErrorOr<const FrameIndexEntry &> FIEX = FA.getFIEFor(Inst); 85*a34c753fSRafael Auler if (!FIEX) { 86*a34c753fSRafael Auler Prev = &Inst; 87*a34c753fSRafael Auler continue; 88*a34c753fSRafael Auler } 89*a34c753fSRafael Auler // FIXME: Change to remove IsSimple == 0. We're being conservative here, 90*a34c753fSRafael Auler // but once replaceMemOperandWithReg is ready, we should feed it with all 91*a34c753fSRafael Auler // sorts of complex instructions. 92*a34c753fSRafael Auler if (FIEX->IsLoad == false || FIEX->IsSimple == false || 93*a34c753fSRafael Auler FIEX->StackOffset >= 0) { 94*a34c753fSRafael Auler Prev = &Inst; 95*a34c753fSRafael Auler continue; 96*a34c753fSRafael Auler } 97*a34c753fSRafael Auler 98*a34c753fSRafael Auler for (auto I = Prev ? SAE.expr_begin(*Prev) : SAE.expr_begin(BB); 99*a34c753fSRafael Auler I != ExprEnd; ++I) { 100*a34c753fSRafael Auler const MCInst *AvailableInst = *I; 101*a34c753fSRafael Auler ErrorOr<const FrameIndexEntry &> FIEY = FA.getFIEFor(*AvailableInst); 102*a34c753fSRafael Auler if (!FIEY) 103*a34c753fSRafael Auler continue; 104*a34c753fSRafael Auler assert(FIEY->IsStore && FIEY->IsSimple); 105*a34c753fSRafael Auler if (FIEX->StackOffset != FIEY->StackOffset || FIEX->Size != FIEY->Size) 106*a34c753fSRafael Auler continue; 107*a34c753fSRafael Auler // TODO: Change push/pops to stack adjustment instruction 108*a34c753fSRafael Auler if (BC.MIB->isPop(Inst)) 109*a34c753fSRafael Auler continue; 110*a34c753fSRafael Auler 111*a34c753fSRafael Auler ++NumRedundantLoads; 112*a34c753fSRafael Auler Changed = true; 113*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Redundant load instruction: "); 114*a34c753fSRafael Auler LLVM_DEBUG(Inst.dump()); 115*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Related store instruction: "); 116*a34c753fSRafael Auler LLVM_DEBUG(AvailableInst->dump()); 117*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "@BB: " << BB.getName() << "\n"); 118*a34c753fSRafael Auler // Replace load 119*a34c753fSRafael Auler if (FIEY->IsStoreFromReg) { 120*a34c753fSRafael Auler if (!BC.MIB->replaceMemOperandWithReg(Inst, FIEY->RegOrImm)) { 121*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "FAILED to change operand to a reg\n"); 122*a34c753fSRafael Auler break; 123*a34c753fSRafael Auler } 124*a34c753fSRafael Auler ++NumLoadsChangedToReg; 125*a34c753fSRafael Auler BC.MIB->removeAnnotation(Inst, "FrameAccessEntry"); 126*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Changed operand to a reg\n"); 127*a34c753fSRafael Auler if (BC.MIB->isRedundantMove(Inst)) { 128*a34c753fSRafael Auler ++NumLoadsDeleted; 129*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Created a redundant move\n"); 130*a34c753fSRafael Auler // Delete it! 131*a34c753fSRafael Auler ToErase.push_front(std::make_pair(&BB, &Inst)); 132*a34c753fSRafael Auler } 133*a34c753fSRafael Auler } else { 134*a34c753fSRafael Auler char Buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 135*a34c753fSRafael Auler support::ulittle64_t::ref(Buf + 0) = FIEY->RegOrImm; 136*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Changing operand to an imm... "); 137*a34c753fSRafael Auler if (!BC.MIB->replaceMemOperandWithImm(Inst, StringRef(Buf, 8), 0)) { 138*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "FAILED\n"); 139*a34c753fSRafael Auler } else { 140*a34c753fSRafael Auler ++NumLoadsChangedToImm; 141*a34c753fSRafael Auler BC.MIB->removeAnnotation(Inst, "FrameAccessEntry"); 142*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Ok\n"); 143*a34c753fSRafael Auler } 144*a34c753fSRafael Auler } 145*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Changed to: "); 146*a34c753fSRafael Auler LLVM_DEBUG(Inst.dump()); 147*a34c753fSRafael Auler break; 148*a34c753fSRafael Auler } 149*a34c753fSRafael Auler Prev = &Inst; 150*a34c753fSRafael Auler } 151*a34c753fSRafael Auler } 152*a34c753fSRafael Auler if (Changed) { 153*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "FOP modified \"" << BF.getPrintName() << "\"\n"); 154*a34c753fSRafael Auler } 155*a34c753fSRafael Auler // TODO: Implement an interface of eraseInstruction that works out the 156*a34c753fSRafael Auler // complete list of elements to remove. 157*a34c753fSRafael Auler for (std::pair<BinaryBasicBlock *, MCInst *> I : ToErase) { 158*a34c753fSRafael Auler I.first->eraseInstruction(I.first->findInstruction(I.second)); 159*a34c753fSRafael Auler } 160*a34c753fSRafael Auler } 161*a34c753fSRafael Auler 162*a34c753fSRafael Auler void FrameOptimizerPass::removeUnusedStores(const FrameAnalysis &FA, 163*a34c753fSRafael Auler const BinaryContext &BC, 164*a34c753fSRafael Auler BinaryFunction &BF) { 165*a34c753fSRafael Auler StackReachingUses SRU(FA, BC, BF); 166*a34c753fSRafael Auler SRU.run(); 167*a34c753fSRafael Auler 168*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Performing unused stores removal\n"); 169*a34c753fSRafael Auler std::vector<std::pair<BinaryBasicBlock *, MCInst *>> ToErase; 170*a34c753fSRafael Auler bool Changed = false; 171*a34c753fSRafael Auler for (BinaryBasicBlock &BB : BF) { 172*a34c753fSRafael Auler LLVM_DEBUG(dbgs() <<"\tNow at BB " << BB.getName() << "\n"); 173*a34c753fSRafael Auler const MCInst *Prev = nullptr; 174*a34c753fSRafael Auler for (auto I = BB.rbegin(), E = BB.rend(); I != E; ++I) { 175*a34c753fSRafael Auler MCInst &Inst = *I; 176*a34c753fSRafael Auler LLVM_DEBUG({ 177*a34c753fSRafael Auler dbgs() << "\t\tNow at "; 178*a34c753fSRafael Auler Inst.dump(); 179*a34c753fSRafael Auler for (auto I = Prev ? SRU.expr_begin(*Prev) : SRU.expr_begin(BB); 180*a34c753fSRafael Auler I != SRU.expr_end(); ++I) { 181*a34c753fSRafael Auler dbgs() << "\t\t\tReached by: "; 182*a34c753fSRafael Auler (*I)->dump(); 183*a34c753fSRafael Auler } 184*a34c753fSRafael Auler }); 185*a34c753fSRafael Auler ErrorOr<const FrameIndexEntry &> FIEX = FA.getFIEFor(Inst); 186*a34c753fSRafael Auler if (!FIEX) { 187*a34c753fSRafael Auler Prev = &Inst; 188*a34c753fSRafael Auler continue; 189*a34c753fSRafael Auler } 190*a34c753fSRafael Auler if (FIEX->IsLoad || !FIEX->IsSimple || FIEX->StackOffset >= 0) { 191*a34c753fSRafael Auler Prev = &Inst; 192*a34c753fSRafael Auler continue; 193*a34c753fSRafael Auler } 194*a34c753fSRafael Auler 195*a34c753fSRafael Auler if (SRU.isStoreUsed(*FIEX, 196*a34c753fSRafael Auler Prev ? SRU.expr_begin(*Prev) : SRU.expr_begin(BB))) { 197*a34c753fSRafael Auler Prev = &Inst; 198*a34c753fSRafael Auler continue; 199*a34c753fSRafael Auler } 200*a34c753fSRafael Auler // TODO: Change push/pops to stack adjustment instruction 201*a34c753fSRafael Auler if (BC.MIB->isPush(Inst)) 202*a34c753fSRafael Auler continue; 203*a34c753fSRafael Auler 204*a34c753fSRafael Auler ++NumRedundantStores; 205*a34c753fSRafael Auler Changed = true; 206*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "Unused store instruction: "); 207*a34c753fSRafael Auler LLVM_DEBUG(Inst.dump()); 208*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "@BB: " << BB.getName() << "\n"); 209*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "FIE offset = " << FIEX->StackOffset 210*a34c753fSRafael Auler << " size = " << (int)FIEX->Size << "\n"); 211*a34c753fSRafael Auler // Delete it! 212*a34c753fSRafael Auler ToErase.emplace_back(&BB, &Inst); 213*a34c753fSRafael Auler Prev = &Inst; 214*a34c753fSRafael Auler } 215*a34c753fSRafael Auler } 216*a34c753fSRafael Auler 217*a34c753fSRafael Auler for (std::pair<BinaryBasicBlock *, MCInst *> I : ToErase) { 218*a34c753fSRafael Auler I.first->eraseInstruction(I.first->findInstruction(I.second)); 219*a34c753fSRafael Auler } 220*a34c753fSRafael Auler if (Changed) { 221*a34c753fSRafael Auler LLVM_DEBUG(dbgs() << "FOP modified \"" << BF.getPrintName() << "\"\n"); 222*a34c753fSRafael Auler } 223*a34c753fSRafael Auler } 224*a34c753fSRafael Auler 225*a34c753fSRafael Auler void FrameOptimizerPass::runOnFunctions(BinaryContext &BC) { 226*a34c753fSRafael Auler if (opts::FrameOptimization == FOP_NONE) 227*a34c753fSRafael Auler return; 228*a34c753fSRafael Auler 229*a34c753fSRafael Auler std::unique_ptr<BinaryFunctionCallGraph> CG; 230*a34c753fSRafael Auler std::unique_ptr<FrameAnalysis> FA; 231*a34c753fSRafael Auler std::unique_ptr<RegAnalysis> RA; 232*a34c753fSRafael Auler 233*a34c753fSRafael Auler { 234*a34c753fSRafael Auler NamedRegionTimer T1("callgraph", "create call graph", "FOP", 235*a34c753fSRafael Auler "FOP breakdown", opts::TimeOpts); 236*a34c753fSRafael Auler CG = std::make_unique<BinaryFunctionCallGraph>(buildCallGraph(BC)); 237*a34c753fSRafael Auler } 238*a34c753fSRafael Auler 239*a34c753fSRafael Auler { 240*a34c753fSRafael Auler NamedRegionTimer T1("frameanalysis", "frame analysis", "FOP", 241*a34c753fSRafael Auler "FOP breakdown", opts::TimeOpts); 242*a34c753fSRafael Auler FA = std::make_unique<FrameAnalysis>(BC, *CG); 243*a34c753fSRafael Auler } 244*a34c753fSRafael Auler 245*a34c753fSRafael Auler { 246*a34c753fSRafael Auler NamedRegionTimer T1("reganalysis", "reg analysis", "FOP", 247*a34c753fSRafael Auler "FOP breakdown", opts::TimeOpts); 248*a34c753fSRafael Auler RA = std::make_unique<RegAnalysis>(BC, &BC.getBinaryFunctions(), CG.get()); 249*a34c753fSRafael Auler } 250*a34c753fSRafael Auler 251*a34c753fSRafael Auler // Perform caller-saved register optimizations, then callee-saved register 252*a34c753fSRafael Auler // optimizations (shrink wrapping) 253*a34c753fSRafael Auler for (auto &I : BC.getBinaryFunctions()) { 254*a34c753fSRafael Auler if (!FA->hasFrameInfo(I.second)) 255*a34c753fSRafael Auler continue; 256*a34c753fSRafael Auler // Restrict pass execution if user asked to only run on hot functions 257*a34c753fSRafael Auler if (opts::FrameOptimization == FOP_HOT) { 258*a34c753fSRafael Auler if (I.second.getKnownExecutionCount() < BC.getHotThreshold()) 259*a34c753fSRafael Auler continue; 260*a34c753fSRafael Auler LLVM_DEBUG( 261*a34c753fSRafael Auler dbgs() << "Considering " << I.second.getPrintName() 262*a34c753fSRafael Auler << " for frame optimizations because its execution count ( " 263*a34c753fSRafael Auler << I.second.getKnownExecutionCount() 264*a34c753fSRafael Auler << " ) exceeds our hotness threshold ( " 265*a34c753fSRafael Auler << BC.getHotThreshold() << " )\n"); 266*a34c753fSRafael Auler } 267*a34c753fSRafael Auler 268*a34c753fSRafael Auler { 269*a34c753fSRafael Auler NamedRegionTimer T1("removeloads", "remove loads", "FOP", "FOP breakdown", 270*a34c753fSRafael Auler opts::TimeOpts); 271*a34c753fSRafael Auler removeUnnecessaryLoads(*RA, *FA, BC, I.second); 272*a34c753fSRafael Auler } 273*a34c753fSRafael Auler 274*a34c753fSRafael Auler if (opts::RemoveStores) { 275*a34c753fSRafael Auler NamedRegionTimer T1("removestores", "remove stores", "FOP", 276*a34c753fSRafael Auler "FOP breakdown", opts::TimeOpts); 277*a34c753fSRafael Auler removeUnusedStores(*FA, BC, I.second); 278*a34c753fSRafael Auler } 279*a34c753fSRafael Auler // Don't even start shrink wrapping if no profiling info is available 280*a34c753fSRafael Auler if (I.second.getKnownExecutionCount() == 0) 281*a34c753fSRafael Auler continue; 282*a34c753fSRafael Auler 283*a34c753fSRafael Auler } 284*a34c753fSRafael Auler 285*a34c753fSRafael Auler { 286*a34c753fSRafael Auler NamedRegionTimer T1("shrinkwrapping", "shrink wrapping", "FOP", 287*a34c753fSRafael Auler "FOP breakdown", opts::TimeOpts); 288*a34c753fSRafael Auler performShrinkWrapping(*RA, *FA, BC); 289*a34c753fSRafael Auler } 290*a34c753fSRafael Auler 291*a34c753fSRafael Auler outs() << "BOLT-INFO: FOP optimized " << NumRedundantLoads 292*a34c753fSRafael Auler << " redundant load(s) and " << NumRedundantStores 293*a34c753fSRafael Auler << " unused store(s)\n"; 294*a34c753fSRafael Auler outs() << "BOLT-INFO: FOP changed " << NumLoadsChangedToReg 295*a34c753fSRafael Auler << " load(s) to use a register instead of a stack access, and " 296*a34c753fSRafael Auler << NumLoadsChangedToImm << " to use an immediate.\n" 297*a34c753fSRafael Auler << "BOLT-INFO: FOP deleted " << NumLoadsDeleted << " load(s) and " 298*a34c753fSRafael Auler << NumRedundantStores << " store(s).\n"; 299*a34c753fSRafael Auler FA->printStats(); 300*a34c753fSRafael Auler ShrinkWrapping::printStats(); 301*a34c753fSRafael Auler } 302*a34c753fSRafael Auler 303*a34c753fSRafael Auler void FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA, 304*a34c753fSRafael Auler const FrameAnalysis &FA, 305*a34c753fSRafael Auler BinaryContext &BC) { 306*a34c753fSRafael Auler // Initialize necessary annotations to allow safe parallel accesses to 307*a34c753fSRafael Auler // annotation index in MIB 308*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex(CalleeSavedAnalysis::getSaveTagName()); 309*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex(CalleeSavedAnalysis::getRestoreTagName()); 310*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex(StackLayoutModifier::getTodoTagName()); 311*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex(StackLayoutModifier::getSlotTagName()); 312*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex( 313*a34c753fSRafael Auler StackLayoutModifier::getOffsetCFIRegTagName()); 314*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("ReachingDefs"); 315*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("ReachingUses"); 316*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("LivenessAnalysis"); 317*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("StackReachingUses"); 318*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("PostDominatorAnalysis"); 319*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("DominatorAnalysis"); 320*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("StackPointerTracking"); 321*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("StackPointerTrackingForInternalCalls"); 322*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("StackAvailableExpressions"); 323*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("StackAllocationAnalysis"); 324*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("ShrinkWrap-Todo"); 325*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("PredictiveStackPointerTracking"); 326*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("ReachingInsnsBackward"); 327*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("ReachingInsns"); 328*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("AccessesDeletedPos"); 329*a34c753fSRafael Auler BC.MIB->getOrCreateAnnotationIndex("DeleteMe"); 330*a34c753fSRafael Auler 331*a34c753fSRafael Auler ParallelUtilities::PredicateTy SkipPredicate = [&](const BinaryFunction &BF) { 332*a34c753fSRafael Auler if (!FA.hasFrameInfo(BF)) 333*a34c753fSRafael Auler return true; 334*a34c753fSRafael Auler 335*a34c753fSRafael Auler if (opts::FrameOptimization == FOP_HOT && 336*a34c753fSRafael Auler (BF.getKnownExecutionCount() < BC.getHotThreshold())) 337*a34c753fSRafael Auler return true; 338*a34c753fSRafael Auler 339*a34c753fSRafael Auler if (BF.getKnownExecutionCount() == 0) 340*a34c753fSRafael Auler return true; 341*a34c753fSRafael Auler 342*a34c753fSRafael Auler return false; 343*a34c753fSRafael Auler }; 344*a34c753fSRafael Auler 345*a34c753fSRafael Auler ParallelUtilities::WorkFuncWithAllocTy WorkFunction = 346*a34c753fSRafael Auler [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId) { 347*a34c753fSRafael Auler DataflowInfoManager Info(BC, BF, &RA, &FA, AllocatorId); 348*a34c753fSRafael Auler ShrinkWrapping SW(FA, BC, BF, Info, AllocatorId); 349*a34c753fSRafael Auler 350*a34c753fSRafael Auler if (SW.perform()) { 351*a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(FuncsChangedMutex); 352*a34c753fSRafael Auler FuncsChanged.insert(&BF); 353*a34c753fSRafael Auler } 354*a34c753fSRafael Auler }; 355*a34c753fSRafael Auler 356*a34c753fSRafael Auler ParallelUtilities::runOnEachFunctionWithUniqueAllocId( 357*a34c753fSRafael Auler BC, ParallelUtilities::SchedulingPolicy::SP_INST_QUADRATIC, WorkFunction, 358*a34c753fSRafael Auler SkipPredicate, "shrink-wrapping"); 359*a34c753fSRafael Auler } 360*a34c753fSRafael Auler 361*a34c753fSRafael Auler } // namespace bolt 362*a34c753fSRafael Auler } // namespace llvm 363