1 //===- bolt/Passes/ShrinkWrapping.cpp -------------------------------------===//
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 file implements the ShrinkWrapping class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "bolt/Passes/ShrinkWrapping.h"
14 #include "bolt/Core/MCPlus.h"
15 #include "bolt/Passes/DataflowInfoManager.h"
16 #include <numeric>
17 #include <stack>
18 
19 #define DEBUG_TYPE "shrinkwrapping"
20 
21 using namespace llvm;
22 
23 namespace opts {
24 
25 extern cl::opt<bool> TimeOpts;
26 extern cl::OptionCategory BoltOptCategory;
27 
28 static cl::opt<unsigned> ShrinkWrappingThreshold(
29     "shrink-wrapping-threshold",
30     cl::desc("Percentage of prologue execution count to use as threshold when"
31              " evaluating whether a block is cold enough to be profitable to"
32              " move eligible spills there"),
33     cl::init(30), cl::ZeroOrMore, cl::cat(BoltOptCategory));
34 } // namespace opts
35 
36 namespace llvm {
37 namespace bolt {
38 
39 void CalleeSavedAnalysis::analyzeSaves() {
40   ReachingDefOrUse</*Def=*/true> &RD = Info.getReachingDefs();
41   StackReachingUses &SRU = Info.getStackReachingUses();
42   auto &InsnToBB = Info.getInsnToBBMap();
43   BitVector BlacklistedRegs(BC.MRI->getNumRegs(), false);
44 
45   LLVM_DEBUG(dbgs() << "Checking spill locations\n");
46   for (BinaryBasicBlock &BB : BF) {
47     LLVM_DEBUG(dbgs() << "\tNow at BB " << BB.getName() << "\n");
48     const MCInst *Prev = nullptr;
49     for (MCInst &Inst : BB) {
50       if (ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Inst)) {
51         // Blacklist weird stores we don't understand
52         if ((!FIE->IsSimple || FIE->StackOffset >= 0) && FIE->IsStore &&
53             FIE->IsStoreFromReg) {
54           BlacklistedRegs.set(FIE->RegOrImm);
55           CalleeSaved.reset(FIE->RegOrImm);
56           Prev = &Inst;
57           continue;
58         }
59 
60         if (!FIE->IsStore || !FIE->IsStoreFromReg ||
61             BlacklistedRegs[FIE->RegOrImm]) {
62           Prev = &Inst;
63           continue;
64         }
65 
66         // If this reg is defined locally, it is not a callee-saved reg
67         if (RD.isReachedBy(FIE->RegOrImm,
68                            Prev ? RD.expr_begin(*Prev) : RD.expr_begin(BB))) {
69           BlacklistedRegs.set(FIE->RegOrImm);
70           CalleeSaved.reset(FIE->RegOrImm);
71           Prev = &Inst;
72           continue;
73         }
74 
75         // If this stack position is accessed in another function, we are
76         // probably dealing with a parameter passed in a stack -- do not mess
77         // with it
78         if (SRU.isStoreUsed(*FIE,
79                             Prev ? SRU.expr_begin(*Prev) : SRU.expr_begin(BB)),
80             /*IncludeLocalAccesses=*/false) {
81           BlacklistedRegs.set(FIE->RegOrImm);
82           CalleeSaved.reset(FIE->RegOrImm);
83           Prev = &Inst;
84           continue;
85         }
86 
87         // If this stack position is loaded elsewhere in another reg, we can't
88         // update it, so blacklist it.
89         if (SRU.isLoadedInDifferentReg(*FIE, Prev ? SRU.expr_begin(*Prev)
90                                                   : SRU.expr_begin(BB))) {
91           BlacklistedRegs.set(FIE->RegOrImm);
92           CalleeSaved.reset(FIE->RegOrImm);
93           Prev = &Inst;
94           continue;
95         }
96 
97         // Ignore regs with multiple saves
98         if (CalleeSaved[FIE->RegOrImm]) {
99           BlacklistedRegs.set(FIE->RegOrImm);
100           CalleeSaved.reset(FIE->RegOrImm);
101           Prev = &Inst;
102           continue;
103         }
104 
105         CalleeSaved.set(FIE->RegOrImm);
106         SaveFIEByReg[FIE->RegOrImm] = &*FIE;
107         SavingCost[FIE->RegOrImm] += InsnToBB[&Inst]->getKnownExecutionCount();
108         BC.MIB->addAnnotation(Inst, getSaveTag(), FIE->RegOrImm, AllocatorId);
109         OffsetsByReg[FIE->RegOrImm] = FIE->StackOffset;
110         LLVM_DEBUG(dbgs() << "Logging new candidate for Callee-Saved Reg: "
111                           << FIE->RegOrImm << "\n");
112       }
113       Prev = &Inst;
114     }
115   }
116 }
117 
118 void CalleeSavedAnalysis::analyzeRestores() {
119   ReachingDefOrUse</*Def=*/false> &RU = Info.getReachingUses();
120 
121   // Now compute all restores of these callee-saved regs
122   for (BinaryBasicBlock &BB : BF) {
123     const MCInst *Prev = nullptr;
124     for (auto I = BB.rbegin(), E = BB.rend(); I != E; ++I) {
125       MCInst &Inst = *I;
126       if (ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Inst)) {
127         if (!FIE->IsLoad || !CalleeSaved[FIE->RegOrImm]) {
128           Prev = &Inst;
129           continue;
130         }
131 
132         // If this reg is used locally after a restore, then we are probably
133         // not dealing with a callee-saved reg. Except if this use is by
134         // another store, but we don't cover this case yet.
135         // Also not callee-saved if this load accesses caller stack or isn't
136         // simple.
137         if (!FIE->IsSimple || FIE->StackOffset >= 0 ||
138             RU.isReachedBy(FIE->RegOrImm,
139                            Prev ? RU.expr_begin(*Prev) : RU.expr_begin(BB))) {
140           CalleeSaved.reset(FIE->RegOrImm);
141           Prev = &Inst;
142           continue;
143         }
144         // If stack offsets between saves/store don't agree with each other,
145         // we don't completely understand what's happening here
146         if (FIE->StackOffset != OffsetsByReg[FIE->RegOrImm]) {
147           CalleeSaved.reset(FIE->RegOrImm);
148           LLVM_DEBUG(dbgs() << "Dismissing Callee-Saved Reg because we found a "
149                                "mismatching restore: "
150                             << FIE->RegOrImm << "\n");
151           Prev = &Inst;
152           continue;
153         }
154 
155         LLVM_DEBUG(dbgs() << "Adding matching restore for: " << FIE->RegOrImm
156                           << "\n");
157         if (LoadFIEByReg[FIE->RegOrImm] == nullptr)
158           LoadFIEByReg[FIE->RegOrImm] = &*FIE;
159         BC.MIB->addAnnotation(Inst, getRestoreTag(), FIE->RegOrImm,
160                               AllocatorId);
161         HasRestores.set(FIE->RegOrImm);
162       }
163       Prev = &Inst;
164     }
165   }
166 }
167 
168 std::vector<MCInst *> CalleeSavedAnalysis::getSavesByReg(uint16_t Reg) {
169   std::vector<MCInst *> Results;
170   for (BinaryBasicBlock &BB : BF)
171     for (MCInst &Inst : BB)
172       if (getSavedReg(Inst) == Reg)
173         Results.push_back(&Inst);
174   return Results;
175 }
176 
177 std::vector<MCInst *> CalleeSavedAnalysis::getRestoresByReg(uint16_t Reg) {
178   std::vector<MCInst *> Results;
179   for (BinaryBasicBlock &BB : BF)
180     for (MCInst &Inst : BB)
181       if (getRestoredReg(Inst) == Reg)
182         Results.push_back(&Inst);
183   return Results;
184 }
185 
186 CalleeSavedAnalysis::~CalleeSavedAnalysis() {
187   for (BinaryBasicBlock &BB : BF) {
188     for (MCInst &Inst : BB) {
189       BC.MIB->removeAnnotation(Inst, getSaveTag());
190       BC.MIB->removeAnnotation(Inst, getRestoreTag());
191     }
192   }
193 }
194 
195 void StackLayoutModifier::blacklistRegion(int64_t Offset, int64_t Size) {
196   if (BlacklistedRegions[Offset] < Size)
197     BlacklistedRegions[Offset] = Size;
198 }
199 
200 bool StackLayoutModifier::isRegionBlacklisted(int64_t Offset, int64_t Size) {
201   for (std::pair<const int64_t, int64_t> Elem : BlacklistedRegions)
202     if (Offset + Size > Elem.first && Offset < Elem.first + Elem.second)
203       return true;
204   return false;
205 }
206 
207 bool StackLayoutModifier::blacklistAllInConflictWith(int64_t Offset,
208                                                      int64_t Size) {
209   bool HasConflict = false;
210   for (auto Iter = AvailableRegions.begin(); Iter != AvailableRegions.end();) {
211     std::pair<const int64_t, int64_t> &Elem = *Iter;
212     if (Offset + Size > Elem.first && Offset < Elem.first + Elem.second &&
213         (Offset != Elem.first || Size != Elem.second)) {
214       Iter = AvailableRegions.erase(Iter);
215       HasConflict = true;
216       continue;
217     }
218     ++Iter;
219   }
220   if (HasConflict) {
221     blacklistRegion(Offset, Size);
222     return true;
223   }
224   return false;
225 }
226 
227 void StackLayoutModifier::checkFramePointerInitialization(MCInst &Point) {
228   StackPointerTracking &SPT = Info.getStackPointerTracking();
229   if (!BC.MII->get(Point.getOpcode())
230            .hasDefOfPhysReg(Point, BC.MIB->getFramePointer(), *BC.MRI))
231     return;
232 
233   int SPVal, FPVal;
234   std::tie(SPVal, FPVal) = *SPT.getStateBefore(Point);
235   std::pair<MCPhysReg, int64_t> FP;
236 
237   if (FPVal != SPT.EMPTY && FPVal != SPT.SUPERPOSITION)
238     FP = std::make_pair(BC.MIB->getFramePointer(), FPVal);
239   else
240     FP = std::make_pair(0, 0);
241   std::pair<MCPhysReg, int64_t> SP;
242 
243   if (SPVal != SPT.EMPTY && SPVal != SPT.SUPERPOSITION)
244     SP = std::make_pair(BC.MIB->getStackPointer(), SPVal);
245   else
246     SP = std::make_pair(0, 0);
247 
248   int64_t Output;
249   if (!BC.MIB->evaluateStackOffsetExpr(Point, Output, SP, FP))
250     return;
251 
252   // Not your regular frame pointer initialization... bail
253   if (Output != SPVal)
254     blacklistRegion(0, 0);
255 }
256 
257 void StackLayoutModifier::checkStackPointerRestore(MCInst &Point) {
258   StackPointerTracking &SPT = Info.getStackPointerTracking();
259   if (!BC.MII->get(Point.getOpcode())
260            .hasDefOfPhysReg(Point, BC.MIB->getStackPointer(), *BC.MRI))
261     return;
262   // Check if the definition of SP comes from FP -- in this case, this
263   // value may need to be updated depending on our stack layout changes
264   const MCInstrDesc &InstInfo = BC.MII->get(Point.getOpcode());
265   unsigned NumDefs = InstInfo.getNumDefs();
266   bool UsesFP = false;
267   for (unsigned I = NumDefs, E = MCPlus::getNumPrimeOperands(Point); I < E;
268        ++I) {
269     MCOperand &Operand = Point.getOperand(I);
270     if (!Operand.isReg())
271       continue;
272     if (Operand.getReg() == BC.MIB->getFramePointer()) {
273       UsesFP = true;
274       break;
275     }
276   }
277   if (!UsesFP)
278     return;
279 
280   // Setting up evaluation
281   int SPVal, FPVal;
282   std::tie(SPVal, FPVal) = *SPT.getStateBefore(Point);
283   std::pair<MCPhysReg, int64_t> FP;
284 
285   if (FPVal != SPT.EMPTY && FPVal != SPT.SUPERPOSITION)
286     FP = std::make_pair(BC.MIB->getFramePointer(), FPVal);
287   else
288     FP = std::make_pair(0, 0);
289   std::pair<MCPhysReg, int64_t> SP;
290 
291   if (SPVal != SPT.EMPTY && SPVal != SPT.SUPERPOSITION)
292     SP = std::make_pair(BC.MIB->getStackPointer(), SPVal);
293   else
294     SP = std::make_pair(0, 0);
295 
296   int64_t Output;
297   if (!BC.MIB->evaluateStackOffsetExpr(Point, Output, SP, FP))
298     return;
299 
300   // If the value is the same of FP, no need to adjust it
301   if (Output == FPVal)
302     return;
303 
304   // If an allocation happened through FP, bail
305   if (Output <= SPVal) {
306     blacklistRegion(0, 0);
307     return;
308   }
309 
310   // We are restoring SP to an old value based on FP. Mark it as a stack
311   // access to be fixed later.
312   BC.MIB->addAnnotation(Point, getSlotTag(), Output, AllocatorId);
313 }
314 
315 void StackLayoutModifier::classifyStackAccesses() {
316   // Understand when stack slots are being used non-locally
317   StackReachingUses &SRU = Info.getStackReachingUses();
318 
319   for (BinaryBasicBlock &BB : BF) {
320     const MCInst *Prev = nullptr;
321     for (auto I = BB.rbegin(), E = BB.rend(); I != E; ++I) {
322       MCInst &Inst = *I;
323       checkFramePointerInitialization(Inst);
324       checkStackPointerRestore(Inst);
325       ErrorOr<const FrameIndexEntry &> FIEX = FA.getFIEFor(Inst);
326       if (!FIEX) {
327         Prev = &Inst;
328         continue;
329       }
330       if (!FIEX->IsSimple || (FIEX->IsStore && !FIEX->IsStoreFromReg)) {
331         blacklistRegion(FIEX->StackOffset, FIEX->Size);
332         Prev = &Inst;
333         continue;
334       }
335       // If this stack position is accessed in another function, we are
336       // probably dealing with a parameter passed in a stack -- do not mess
337       // with it
338       if (SRU.isStoreUsed(*FIEX,
339                           Prev ? SRU.expr_begin(*Prev) : SRU.expr_begin(BB),
340                           /*IncludeLocalAccesses=*/false)) {
341         blacklistRegion(FIEX->StackOffset, FIEX->Size);
342         Prev = &Inst;
343         continue;
344       }
345       // Now we have a clear stack slot access. Check if its blacklisted or if
346       // it conflicts with another chunk.
347       if (isRegionBlacklisted(FIEX->StackOffset, FIEX->Size) ||
348           blacklistAllInConflictWith(FIEX->StackOffset, FIEX->Size)) {
349         Prev = &Inst;
350         continue;
351       }
352       // We are free to go. Add it as available stack slot which we know how
353       // to move it.
354       AvailableRegions[FIEX->StackOffset] = FIEX->Size;
355       BC.MIB->addAnnotation(Inst, getSlotTag(), FIEX->StackOffset, AllocatorId);
356       RegionToRegMap[FIEX->StackOffset].insert(FIEX->RegOrImm);
357       RegToRegionMap[FIEX->RegOrImm].insert(FIEX->StackOffset);
358       LLVM_DEBUG(dbgs() << "Adding region " << FIEX->StackOffset << " size "
359                         << (int)FIEX->Size << "\n");
360     }
361   }
362 }
363 
364 void StackLayoutModifier::classifyCFIs() {
365   std::stack<std::pair<int64_t, uint16_t>> CFIStack;
366   int64_t CfaOffset = -8;
367   uint16_t CfaReg = 7;
368 
369   auto recordAccess = [&](MCInst *Inst, int64_t Offset) {
370     const uint16_t Reg = *BC.MRI->getLLVMRegNum(CfaReg, /*isEH=*/false);
371     if (Reg == BC.MIB->getStackPointer() || Reg == BC.MIB->getFramePointer()) {
372       BC.MIB->addAnnotation(*Inst, getSlotTag(), Offset, AllocatorId);
373       LLVM_DEBUG(dbgs() << "Recording CFI " << Offset << "\n");
374     } else {
375       IsSimple = false;
376       return;
377     }
378   };
379 
380   for (BinaryBasicBlock *&BB : BF.layout()) {
381     for (MCInst &Inst : *BB) {
382       if (!BC.MIB->isCFI(Inst))
383         continue;
384       const MCCFIInstruction *CFI = BF.getCFIFor(Inst);
385       switch (CFI->getOperation()) {
386       case MCCFIInstruction::OpDefCfa:
387         CfaOffset = -CFI->getOffset();
388         recordAccess(&Inst, CfaOffset);
389         LLVM_FALLTHROUGH;
390       case MCCFIInstruction::OpDefCfaRegister:
391         CfaReg = CFI->getRegister();
392         break;
393       case MCCFIInstruction::OpDefCfaOffset:
394         CfaOffset = -CFI->getOffset();
395         recordAccess(&Inst, CfaOffset);
396         break;
397       case MCCFIInstruction::OpOffset:
398         recordAccess(&Inst, CFI->getOffset());
399         BC.MIB->addAnnotation(Inst, getOffsetCFIRegTag(),
400                               BC.MRI->getLLVMRegNum(CFI->getRegister(),
401                                                     /*isEH=*/false),
402                               AllocatorId);
403         break;
404       case MCCFIInstruction::OpSameValue:
405         BC.MIB->addAnnotation(Inst, getOffsetCFIRegTag(),
406                               BC.MRI->getLLVMRegNum(CFI->getRegister(),
407                                                     /*isEH=*/false),
408                               AllocatorId);
409         break;
410       case MCCFIInstruction::OpRememberState:
411         CFIStack.push(std::make_pair(CfaOffset, CfaReg));
412         break;
413       case MCCFIInstruction::OpRestoreState: {
414         assert(!CFIStack.empty() && "Corrupt CFI stack");
415         std::pair<int64_t, uint16_t> &Elem = CFIStack.top();
416         CFIStack.pop();
417         CfaOffset = Elem.first;
418         CfaReg = Elem.second;
419         break;
420       }
421       case MCCFIInstruction::OpRelOffset:
422       case MCCFIInstruction::OpAdjustCfaOffset:
423         llvm_unreachable("Unhandled AdjustCfaOffset");
424         break;
425       default:
426         break;
427       }
428     }
429   }
430 }
431 
432 void StackLayoutModifier::scheduleChange(
433     MCInst &Inst, StackLayoutModifier::WorklistItem Item) {
434   auto &WList = BC.MIB->getOrCreateAnnotationAs<std::vector<WorklistItem>>(
435       Inst, getTodoTag(), AllocatorId);
436   WList.push_back(Item);
437 }
438 
439 bool StackLayoutModifier::canCollapseRegion(MCInst *DeletedPush) {
440   if (!IsSimple || !BC.MIB->isPush(*DeletedPush))
441     return false;
442 
443   ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(*DeletedPush);
444   if (!FIE)
445     return false;
446 
447   return canCollapseRegion(FIE->StackOffset);
448 }
449 
450 bool StackLayoutModifier::canCollapseRegion(int64_t RegionAddr) {
451   if (!IsInitialized)
452     initialize();
453   if (!IsSimple)
454     return false;
455 
456   if (CollapsedRegions.count(RegionAddr))
457     return true;
458 
459   // Check if it is possible to readjust all accesses below RegionAddr
460   if (!BlacklistedRegions.empty())
461     return false;
462 
463   return true;
464 }
465 
466 bool StackLayoutModifier::collapseRegion(MCInst *DeletedPush) {
467   ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(*DeletedPush);
468   if (!FIE)
469     return false;
470   int64_t RegionAddr = FIE->StackOffset;
471   int64_t RegionSz = FIE->Size;
472   return collapseRegion(DeletedPush, RegionAddr, RegionSz);
473 }
474 
475 bool StackLayoutModifier::collapseRegion(MCInst *Alloc, int64_t RegionAddr,
476                                          int64_t RegionSz) {
477   if (!canCollapseRegion(RegionAddr))
478     return false;
479 
480   assert(IsInitialized);
481   StackAllocationAnalysis &SAA = Info.getStackAllocationAnalysis();
482 
483   for (BinaryBasicBlock &BB : BF) {
484     for (MCInst &Inst : BB) {
485       if (!BC.MIB->hasAnnotation(Inst, getSlotTag()))
486         continue;
487       auto Slot =
488           BC.MIB->getAnnotationAs<decltype(FrameIndexEntry::StackOffset)>(
489               Inst, getSlotTag());
490       if (!AvailableRegions.count(Slot))
491         continue;
492       // We need to ensure this access is affected by the deleted push
493       if (!(*SAA.getStateBefore(Inst))[SAA.ExprToIdx[Alloc]])
494         continue;
495 
496       if (BC.MIB->isCFI(Inst)) {
497         if (Slot > RegionAddr)
498           continue;
499         scheduleChange(Inst, WorklistItem(WorklistItem::AdjustCFI, RegionSz));
500         continue;
501       }
502       ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Inst);
503       if (!FIE) {
504         if (Slot > RegionAddr)
505           continue;
506         // SP update based on frame pointer
507         scheduleChange(
508             Inst, WorklistItem(WorklistItem::AdjustLoadStoreOffset, RegionSz));
509         continue;
510       }
511 
512       if (Slot == RegionAddr) {
513         BC.MIB->addAnnotation(Inst, "AccessesDeletedPos", 0U, AllocatorId);
514         continue;
515       }
516       if (BC.MIB->isPush(Inst) || BC.MIB->isPop(Inst))
517         continue;
518 
519       if (FIE->StackPtrReg == BC.MIB->getStackPointer() && Slot < RegionAddr)
520         continue;
521 
522       if (FIE->StackPtrReg == BC.MIB->getFramePointer() && Slot > RegionAddr)
523         continue;
524 
525       scheduleChange(
526           Inst, WorklistItem(WorklistItem::AdjustLoadStoreOffset, RegionSz));
527     }
528   }
529 
530   CollapsedRegions.insert(RegionAddr);
531   return true;
532 }
533 
534 void StackLayoutModifier::setOffsetForCollapsedAccesses(int64_t NewOffset) {
535   for (BinaryBasicBlock &BB : BF) {
536     for (MCInst &Inst : BB) {
537       if (!BC.MIB->hasAnnotation(Inst, "AccessesDeletedPos"))
538         continue;
539       BC.MIB->removeAnnotation(Inst, "AccessesDeletedPos");
540       scheduleChange(
541           Inst, WorklistItem(WorklistItem::AdjustLoadStoreOffset, NewOffset));
542     }
543   }
544 }
545 
546 bool StackLayoutModifier::canInsertRegion(ProgramPoint P) {
547   if (!IsInitialized)
548     initialize();
549   if (!IsSimple)
550     return false;
551 
552   StackPointerTracking &SPT = Info.getStackPointerTracking();
553   int64_t RegionAddr = SPT.getStateBefore(P)->first;
554   if (RegionAddr == SPT.SUPERPOSITION || RegionAddr == SPT.EMPTY)
555     return false;
556 
557   if (InsertedRegions.count(RegionAddr))
558     return true;
559 
560   // Check if we are going to screw up stack accesses at call sites that
561   // pass parameters via stack
562   if (!BlacklistedRegions.empty())
563     return false;
564 
565   return true;
566 }
567 
568 bool StackLayoutModifier::insertRegion(ProgramPoint P, int64_t RegionSz) {
569   if (!canInsertRegion(P))
570     return false;
571 
572   assert(IsInitialized);
573   StackPointerTracking &SPT = Info.getStackPointerTracking();
574   // This RegionAddr is slightly different from the one seen in collapseRegion
575   // This is the value of SP before the allocation the user wants to make.
576   int64_t RegionAddr = SPT.getStateBefore(P)->first;
577   if (RegionAddr == SPT.SUPERPOSITION || RegionAddr == SPT.EMPTY)
578     return false;
579 
580   DominatorAnalysis<false> &DA = Info.getDominatorAnalysis();
581 
582   for (BinaryBasicBlock &BB : BF) {
583     for (MCInst &Inst : BB) {
584       if (!BC.MIB->hasAnnotation(Inst, getSlotTag()))
585         continue;
586       auto Slot =
587           BC.MIB->getAnnotationAs<decltype(FrameIndexEntry::StackOffset)>(
588               Inst, getSlotTag());
589       if (!AvailableRegions.count(Slot))
590         continue;
591 
592       if (!(DA.doesADominateB(P, Inst)))
593         continue;
594 
595       if (BC.MIB->isCFI(Inst)) {
596         if (Slot >= RegionAddr)
597           continue;
598         scheduleChange(Inst, WorklistItem(WorklistItem::AdjustCFI, -RegionSz));
599         continue;
600       }
601       ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Inst);
602       if (!FIE) {
603         if (Slot >= RegionAddr)
604           continue;
605         scheduleChange(
606             Inst, WorklistItem(WorklistItem::AdjustLoadStoreOffset, -RegionSz));
607         continue;
608       }
609 
610       if (FIE->StackPtrReg == BC.MIB->getStackPointer() && Slot < RegionAddr)
611         continue;
612       if (FIE->StackPtrReg == BC.MIB->getFramePointer() && Slot >= RegionAddr)
613         continue;
614       if (BC.MIB->isPush(Inst) || BC.MIB->isPop(Inst))
615         continue;
616       scheduleChange(
617           Inst, WorklistItem(WorklistItem::AdjustLoadStoreOffset, -RegionSz));
618     }
619   }
620 
621   InsertedRegions.insert(RegionAddr);
622   return true;
623 }
624 
625 void StackLayoutModifier::performChanges() {
626   std::set<uint32_t> ModifiedCFIIndices;
627   for (BinaryBasicBlock &BB : BF) {
628     for (auto I = BB.rbegin(), E = BB.rend(); I != E; ++I) {
629       MCInst &Inst = *I;
630       if (BC.MIB->hasAnnotation(Inst, "AccessesDeletedPos")) {
631         assert(BC.MIB->isPop(Inst) || BC.MIB->isPush(Inst));
632         BC.MIB->removeAnnotation(Inst, "AccessesDeletedPos");
633       }
634       if (!BC.MIB->hasAnnotation(Inst, getTodoTag()))
635         continue;
636       auto &WList = BC.MIB->getAnnotationAs<std::vector<WorklistItem>>(
637           Inst, getTodoTag());
638       int64_t Adjustment = 0;
639       WorklistItem::ActionType AdjustmentType = WorklistItem::None;
640       for (WorklistItem &WI : WList) {
641         if (WI.Action == WorklistItem::None)
642           continue;
643         assert(WI.Action == WorklistItem::AdjustLoadStoreOffset ||
644                WI.Action == WorklistItem::AdjustCFI);
645         assert((AdjustmentType == WorklistItem::None ||
646                 AdjustmentType == WI.Action) &&
647                "Conflicting actions requested at the same program point");
648         AdjustmentType = WI.Action;
649         Adjustment += WI.OffsetUpdate;
650       }
651       if (!Adjustment)
652         continue;
653       if (AdjustmentType != WorklistItem::AdjustLoadStoreOffset) {
654         assert(BC.MIB->isCFI(Inst));
655         uint32_t CFINum = Inst.getOperand(0).getImm();
656         if (ModifiedCFIIndices.count(CFINum))
657           continue;
658         ModifiedCFIIndices.insert(CFINum);
659         const MCCFIInstruction *CFI = BF.getCFIFor(Inst);
660         const MCCFIInstruction::OpType Operation = CFI->getOperation();
661         if (Operation == MCCFIInstruction::OpDefCfa ||
662             Operation == MCCFIInstruction::OpDefCfaOffset)
663           Adjustment = 0 - Adjustment;
664         LLVM_DEBUG(dbgs() << "Changing CFI offset from " << CFI->getOffset()
665                           << " to " << (CFI->getOffset() + Adjustment) << "\n");
666         BF.mutateCFIOffsetFor(Inst, CFI->getOffset() + Adjustment);
667         continue;
668       }
669       int32_t SrcImm = 0;
670       MCPhysReg Reg = 0;
671       MCPhysReg StackPtrReg = 0;
672       int64_t StackOffset = 0;
673       bool IsIndexed = false;
674       bool IsLoad = false;
675       bool IsStore = false;
676       bool IsSimple = false;
677       bool IsStoreFromReg = false;
678       uint8_t Size = 0;
679       bool Success = false;
680       Success = BC.MIB->isStackAccess(Inst, IsLoad, IsStore, IsStoreFromReg,
681                                       Reg, SrcImm, StackPtrReg, StackOffset,
682                                       Size, IsSimple, IsIndexed);
683       if (!Success) {
684         // SP update based on FP value
685         Success = BC.MIB->addToImm(Inst, Adjustment, &*BC.Ctx);
686         assert(Success);
687         continue;
688       }
689       assert(Success && IsSimple && !IsIndexed && (!IsStore || IsStoreFromReg));
690       if (StackPtrReg != BC.MIB->getFramePointer())
691         Adjustment = -Adjustment;
692       if (IsLoad)
693         Success = BC.MIB->createRestoreFromStack(
694             Inst, StackPtrReg, StackOffset + Adjustment, Reg, Size);
695       else if (IsStore)
696         Success = BC.MIB->createSaveToStack(
697             Inst, StackPtrReg, StackOffset + Adjustment, Reg, Size);
698       LLVM_DEBUG({
699         dbgs() << "Adjusted instruction: ";
700         Inst.dump();
701       });
702       assert(Success);
703     }
704   }
705 }
706 
707 void StackLayoutModifier::initialize() {
708   classifyStackAccesses();
709   classifyCFIs();
710   IsInitialized = true;
711 }
712 
713 std::atomic_uint64_t ShrinkWrapping::SpillsMovedRegularMode{0};
714 std::atomic_uint64_t ShrinkWrapping::SpillsMovedPushPopMode{0};
715 std::atomic_uint64_t ShrinkWrapping::SpillsMovedDynamicCount{0};
716 std::atomic_uint64_t ShrinkWrapping::SpillsFailedDynamicCount{0};
717 std::atomic_uint64_t ShrinkWrapping::InstrDynamicCount{0};
718 std::atomic_uint64_t ShrinkWrapping::StoreDynamicCount{0};
719 
720 using BBIterTy = BinaryBasicBlock::iterator;
721 
722 void ShrinkWrapping::classifyCSRUses() {
723   DominatorAnalysis<false> &DA = Info.getDominatorAnalysis();
724   StackPointerTracking &SPT = Info.getStackPointerTracking();
725   UsesByReg = std::vector<BitVector>(BC.MRI->getNumRegs(),
726                                      BitVector(DA.NumInstrs, false));
727 
728   const BitVector &FPAliases = BC.MIB->getAliases(BC.MIB->getFramePointer());
729   for (BinaryBasicBlock &BB : BF) {
730     for (MCInst &Inst : BB) {
731       if (BC.MIB->isCFI(Inst))
732         continue;
733       BitVector BV = BitVector(BC.MRI->getNumRegs(), false);
734       BC.MIB->getTouchedRegs(Inst, BV);
735       BV &= CSA.CalleeSaved;
736       for (int I : BV.set_bits()) {
737         if (I == 0)
738           continue;
739         if (CSA.getSavedReg(Inst) != I && CSA.getRestoredReg(Inst) != I)
740           UsesByReg[I].set(DA.ExprToIdx[&Inst]);
741       }
742       if (!SPT.HasFramePointer || !BC.MIB->isCall(Inst))
743         continue;
744       BV = CSA.CalleeSaved;
745       BV &= FPAliases;
746       for (int I : BV.set_bits())
747         UsesByReg[I].set(DA.ExprToIdx[&Inst]);
748     }
749   }
750 }
751 
752 void ShrinkWrapping::pruneUnwantedCSRs() {
753   BitVector ParamRegs = BC.MIB->getRegsUsedAsParams();
754   for (unsigned I = 0, E = BC.MRI->getNumRegs(); I != E; ++I) {
755     if (!CSA.CalleeSaved[I])
756       continue;
757     if (ParamRegs[I]) {
758       CSA.CalleeSaved.reset(I);
759       continue;
760     }
761     if (UsesByReg[I].empty()) {
762       LLVM_DEBUG(
763           dbgs()
764           << "Dismissing Callee-Saved Reg because we found no uses of it:" << I
765           << "\n");
766       CSA.CalleeSaved.reset(I);
767       continue;
768     }
769     if (!CSA.HasRestores[I]) {
770       LLVM_DEBUG(
771           dbgs() << "Dismissing Callee-Saved Reg because it does not have "
772                     "restores:"
773                  << I << "\n");
774       CSA.CalleeSaved.reset(I);
775     }
776   }
777 }
778 
779 void ShrinkWrapping::computeSaveLocations() {
780   SavePos = std::vector<SmallSetVector<MCInst *, 4>>(BC.MRI->getNumRegs());
781   ReachingInsns<true> &RI = Info.getReachingInsnsBackwards();
782   DominatorAnalysis<false> &DA = Info.getDominatorAnalysis();
783   StackPointerTracking &SPT = Info.getStackPointerTracking();
784 
785   LLVM_DEBUG(dbgs() << "Checking save/restore possibilities\n");
786   for (BinaryBasicBlock &BB : BF) {
787     LLVM_DEBUG(dbgs() << "\tNow at BB " << BB.getName() << "\n");
788 
789     MCInst *First = BB.begin() != BB.end() ? &*BB.begin() : nullptr;
790     if (!First)
791       continue;
792 
793     // Use reaching instructions to detect if we are inside a loop - if we
794     // are, do not consider this BB as valid placement for saves.
795     if (RI.isInLoop(BB))
796       continue;
797 
798     const std::pair<int, int> SPFP = *SPT.getStateBefore(*First);
799     // If we don't know stack state at this point, bail
800     if ((SPFP.first == SPT.SUPERPOSITION || SPFP.first == SPT.EMPTY) &&
801         (SPFP.second == SPT.SUPERPOSITION || SPFP.second == SPT.EMPTY))
802       continue;
803 
804     for (unsigned I = 0, E = BC.MRI->getNumRegs(); I != E; ++I) {
805       if (!CSA.CalleeSaved[I])
806         continue;
807 
808       BitVector BBDominatedUses = BitVector(DA.NumInstrs, false);
809       for (int J : UsesByReg[I].set_bits())
810         if (DA.doesADominateB(*First, J))
811           BBDominatedUses.set(J);
812       LLVM_DEBUG(dbgs() << "\t\tBB " << BB.getName() << " dominates "
813                         << BBDominatedUses.count() << " uses for reg " << I
814                         << ". Total uses for reg is " << UsesByReg[I].count()
815                         << "\n");
816       BBDominatedUses &= UsesByReg[I];
817       if (BBDominatedUses == UsesByReg[I]) {
818         LLVM_DEBUG(dbgs() << "\t\t\tAdded " << BB.getName()
819                           << " as a save pos for " << I << "\n");
820         SavePos[I].insert(First);
821         LLVM_DEBUG({
822           dbgs() << "Dominated uses are:\n";
823           for (int J : UsesByReg[I].set_bits()) {
824             dbgs() << "Idx " << J << ": ";
825             DA.Expressions[J]->dump();
826           }
827         });
828       }
829     }
830   }
831 
832   BestSaveCount = std::vector<uint64_t>(BC.MRI->getNumRegs(),
833                                         std::numeric_limits<uint64_t>::max());
834   BestSavePos = std::vector<MCInst *>(BC.MRI->getNumRegs(), nullptr);
835   auto &InsnToBB = Info.getInsnToBBMap();
836   for (unsigned I = 0, E = BC.MRI->getNumRegs(); I != E; ++I) {
837     if (!CSA.CalleeSaved[I])
838       continue;
839 
840     for (MCInst *Pos : SavePos[I]) {
841       BinaryBasicBlock *BB = InsnToBB[Pos];
842       uint64_t Count = BB->getExecutionCount();
843       if (Count != BinaryBasicBlock::COUNT_NO_PROFILE &&
844           Count < BestSaveCount[I]) {
845         BestSavePos[I] = Pos;
846         BestSaveCount[I] = Count;
847       }
848     }
849   }
850 }
851 
852 void ShrinkWrapping::computeDomOrder() {
853   std::vector<MCPhysReg> Order;
854   for (MCPhysReg I = 0, E = BC.MRI->getNumRegs(); I != E; ++I) {
855     Order.push_back(I);
856   }
857 
858   DominatorAnalysis<false> &DA = Info.getDominatorAnalysis();
859   auto &InsnToBB = Info.getInsnToBBMap();
860   llvm::sort(Order, [&](const MCPhysReg &A, const MCPhysReg &B) {
861     BinaryBasicBlock *BBA = BestSavePos[A] ? InsnToBB[BestSavePos[A]] : nullptr;
862     BinaryBasicBlock *BBB = BestSavePos[B] ? InsnToBB[BestSavePos[B]] : nullptr;
863     if (BBA == BBB)
864       return A < B;
865     if (!BBA && BBB)
866       return false;
867     if (BBA && !BBB)
868       return true;
869     if (DA.doesADominateB(*BestSavePos[A], *BestSavePos[B]))
870       return true;
871     if (DA.doesADominateB(*BestSavePos[B], *BestSavePos[A]))
872       return false;
873     return A < B;
874   });
875 
876   for (MCPhysReg I = 0, E = BC.MRI->getNumRegs(); I != E; ++I)
877     DomOrder[Order[I]] = I;
878 }
879 
880 bool ShrinkWrapping::isBestSavePosCold(unsigned CSR, MCInst *&BestPosSave,
881                                        uint64_t &TotalEstimatedWin) {
882   const uint64_t CurSavingCost = CSA.SavingCost[CSR];
883   if (!CSA.CalleeSaved[CSR])
884     return false;
885 
886   uint64_t BestCount = BestSaveCount[CSR];
887   BestPosSave = BestSavePos[CSR];
888   bool ShouldMove = false;
889   if (BestCount != std::numeric_limits<uint64_t>::max() &&
890       BestCount < (opts::ShrinkWrappingThreshold / 100.0) * CurSavingCost) {
891     LLVM_DEBUG({
892       auto &InsnToBB = Info.getInsnToBBMap();
893       dbgs() << "Better position for saves found in func " << BF.getPrintName()
894              << " count << " << BF.getKnownExecutionCount() << "\n";
895       dbgs() << "Reg: " << CSR
896              << "; New BB: " << InsnToBB[BestPosSave]->getName()
897              << " Freq reduction: " << (CurSavingCost - BestCount) << "\n";
898     });
899     TotalEstimatedWin += CurSavingCost - BestCount;
900     ShouldMove = true;
901   }
902 
903   if (!ShouldMove)
904     return false;
905   if (!BestPosSave) {
906     LLVM_DEBUG({
907       dbgs() << "Dropping opportunity because we don't know where to put "
908                 "stores -- total est. freq reduc: "
909              << TotalEstimatedWin << "\n";
910     });
911     return false;
912   }
913   return true;
914 }
915 
916 /// Auxiliar function used to create basic blocks for critical edges and update
917 /// the dominance frontier with these new locations
918 void ShrinkWrapping::splitFrontierCritEdges(
919     BinaryFunction *Func, SmallVector<ProgramPoint, 4> &Frontier,
920     const SmallVector<bool, 4> &IsCritEdge,
921     const SmallVector<BinaryBasicBlock *, 4> &From,
922     const SmallVector<SmallVector<BinaryBasicBlock *, 4>, 4> &To) {
923   LLVM_DEBUG(dbgs() << "splitFrontierCritEdges: Now handling func "
924                     << BF.getPrintName() << "\n");
925   // For every FromBB, there might be one or more critical edges, with
926   // To[I] containing destination BBs. It's important to memorize
927   // the original size of the Frontier as we may append to it while splitting
928   // critical edges originating with blocks with multiple destinations.
929   for (size_t I = 0, IE = Frontier.size(); I < IE; ++I) {
930     if (!IsCritEdge[I])
931       continue;
932     if (To[I].empty())
933       continue;
934     BinaryBasicBlock *FromBB = From[I];
935     LLVM_DEBUG(dbgs() << " - Now handling FrontierBB " << FromBB->getName()
936                       << "\n");
937     // Split edge for every DestinationBBs
938     for (size_t DI = 0, DIE = To[I].size(); DI < DIE; ++DI) {
939       BinaryBasicBlock *DestinationBB = To[I][DI];
940       LLVM_DEBUG(dbgs() << "   - Dest : " << DestinationBB->getName() << "\n");
941       BinaryBasicBlock *NewBB = Func->splitEdge(FromBB, DestinationBB);
942       // Insert dummy instruction so this BB is never empty (we need this for
943       // PredictiveStackPointerTracking to work, since it annotates instructions
944       // and not BBs).
945       if (NewBB->empty()) {
946         MCInst NewInst;
947         BC.MIB->createNoop(NewInst);
948         NewBB->addInstruction(std::move(NewInst));
949         scheduleChange(&*NewBB->begin(), WorklistItem(WorklistItem::Erase, 0));
950       }
951 
952       // Update frontier
953       ProgramPoint NewFrontierPP = ProgramPoint::getLastPointAt(*NewBB);
954       if (DI == 0) {
955         // Update frontier inplace
956         Frontier[I] = NewFrontierPP;
957         LLVM_DEBUG(dbgs() << "   - Update frontier with " << NewBB->getName()
958                           << '\n');
959       } else {
960         // Append new frontier to the end of the list
961         Frontier.push_back(NewFrontierPP);
962         LLVM_DEBUG(dbgs() << "   - Append frontier " << NewBB->getName()
963                           << '\n');
964       }
965     }
966   }
967 }
968 
969 SmallVector<ProgramPoint, 4>
970 ShrinkWrapping::doRestorePlacement(MCInst *BestPosSave, unsigned CSR,
971                                    uint64_t TotalEstimatedWin) {
972   SmallVector<ProgramPoint, 4> Frontier;
973   SmallVector<bool, 4> IsCritEdge;
974   bool CannotPlace = false;
975   DominatorAnalysis<false> &DA = Info.getDominatorAnalysis();
976 
977   SmallVector<BinaryBasicBlock *, 4> CritEdgesFrom;
978   SmallVector<SmallVector<BinaryBasicBlock *, 4>, 4> CritEdgesTo;
979   // In case of a critical edge, we need to create extra BBs to host restores
980   // into edges transitioning to the dominance frontier, otherwise we pull these
981   // restores to inside the dominated area.
982   Frontier = DA.getDominanceFrontierFor(*BestPosSave).takeVector();
983   LLVM_DEBUG({
984     dbgs() << "Dumping dominance frontier for ";
985     BC.printInstruction(dbgs(), *BestPosSave);
986     for (ProgramPoint &PP : Frontier)
987       if (PP.isInst())
988         BC.printInstruction(dbgs(), *PP.getInst());
989       else
990         dbgs() << PP.getBB()->getName() << "\n";
991   });
992   for (ProgramPoint &PP : Frontier) {
993     bool HasCritEdges = false;
994     if (PP.isInst() && BC.MIB->isTerminator(*PP.getInst()) &&
995         doesInstUsesCSR(*PP.getInst(), CSR))
996       CannotPlace = true;
997     BinaryBasicBlock *FrontierBB = Info.getParentBB(PP);
998     CritEdgesFrom.emplace_back(FrontierBB);
999     CritEdgesTo.emplace_back(0);
1000     SmallVector<BinaryBasicBlock *, 4> &Dests = CritEdgesTo.back();
1001     // Check for invoke instructions at the dominance frontier, which indicates
1002     // the landing pad is not dominated.
1003     if (PP.isInst() && BC.MIB->isInvoke(*PP.getInst())) {
1004       LLVM_DEBUG(
1005           dbgs() << "Bailing on restore placement to avoid LP splitting\n");
1006       Frontier.clear();
1007       return Frontier;
1008     }
1009     doForAllSuccs(*FrontierBB, [&](ProgramPoint P) {
1010       if (!DA.doesADominateB(*BestPosSave, P)) {
1011         Dests.emplace_back(Info.getParentBB(P));
1012         return;
1013       }
1014       HasCritEdges = true;
1015     });
1016     IsCritEdge.push_back(HasCritEdges);
1017   }
1018   // Restores cannot be placed in empty BBs because we have a dataflow
1019   // analysis that depends on insertions happening before real instructions
1020   // (PredictiveStackPointerTracking). Detect now for empty BBs and add a
1021   // dummy nop that is scheduled to be removed later.
1022   bool InvalidateRequired = false;
1023   for (BinaryBasicBlock *&BB : BF.layout()) {
1024     if (BB->size() != 0)
1025       continue;
1026     MCInst NewInst;
1027     BC.MIB->createNoop(NewInst);
1028     auto II = BB->addInstruction(std::move(NewInst));
1029     scheduleChange(&*II, WorklistItem(WorklistItem::Erase, 0));
1030     InvalidateRequired = true;
1031   }
1032   if (std::accumulate(IsCritEdge.begin(), IsCritEdge.end(), 0)) {
1033     LLVM_DEBUG({
1034       dbgs() << "Now detected critical edges in the following frontier:\n";
1035       for (ProgramPoint &PP : Frontier) {
1036         if (PP.isBB()) {
1037           dbgs() << "  BB: " << PP.getBB()->getName() << "\n";
1038         } else {
1039           dbgs() << "  Inst: ";
1040           PP.getInst()->dump();
1041         }
1042       }
1043     });
1044     splitFrontierCritEdges(&BF, Frontier, IsCritEdge, CritEdgesFrom,
1045                            CritEdgesTo);
1046     InvalidateRequired = true;
1047   }
1048   if (InvalidateRequired) {
1049     // BitVectors that represent all insns of the function are invalid now
1050     // since we changed BBs/Insts. Re-run steps that depend on pointers being
1051     // valid
1052     Info.invalidateAll();
1053     classifyCSRUses();
1054   }
1055   if (CannotPlace) {
1056     LLVM_DEBUG({
1057       dbgs() << "Dropping opportunity because restore placement failed"
1058                 " -- total est. freq reduc: "
1059              << TotalEstimatedWin << "\n";
1060     });
1061     Frontier.clear();
1062     return Frontier;
1063   }
1064   return Frontier;
1065 }
1066 
1067 bool ShrinkWrapping::validatePushPopsMode(unsigned CSR, MCInst *BestPosSave,
1068                                           int64_t SaveOffset) {
1069   if (FA.requiresAlignment(BF)) {
1070     LLVM_DEBUG({
1071       dbgs() << "Reg " << CSR
1072              << " is not using push/pops due to function "
1073                 "alignment requirements.\n";
1074     });
1075     return false;
1076   }
1077   for (MCInst *Save : CSA.getSavesByReg(CSR)) {
1078     if (!SLM.canCollapseRegion(Save)) {
1079       LLVM_DEBUG(dbgs() << "Reg " << CSR << " cannot collapse region.\n");
1080       return false;
1081     }
1082   }
1083   // Abort if one of the restores for this CSR is not a POP.
1084   for (MCInst *Load : CSA.getRestoresByReg(CSR)) {
1085     if (!BC.MIB->isPop(*Load)) {
1086       LLVM_DEBUG(dbgs() << "Reg " << CSR << " has a mismatching restore.\n");
1087       return false;
1088     }
1089   }
1090 
1091   StackPointerTracking &SPT = Info.getStackPointerTracking();
1092   // Abort if we are inserting a push into an entry BB (offset -8) and this
1093   // func sets up a frame pointer.
1094   if (!SLM.canInsertRegion(BestPosSave) || SaveOffset == SPT.SUPERPOSITION ||
1095       SaveOffset == SPT.EMPTY || (SaveOffset == -8 && SPT.HasFramePointer)) {
1096     LLVM_DEBUG({
1097       dbgs() << "Reg " << CSR
1098              << " cannot insert region or we are "
1099                 "trying to insert a push into entry bb.\n";
1100     });
1101     return false;
1102   }
1103   return true;
1104 }
1105 
1106 SmallVector<ProgramPoint, 4> ShrinkWrapping::fixPopsPlacements(
1107     const SmallVector<ProgramPoint, 4> &RestorePoints, int64_t SaveOffset,
1108     unsigned CSR) {
1109   SmallVector<ProgramPoint, 4> FixedRestorePoints = RestorePoints;
1110   // Moving pop locations to the correct sp offset
1111   ReachingInsns<true> &RI = Info.getReachingInsnsBackwards();
1112   StackPointerTracking &SPT = Info.getStackPointerTracking();
1113   for (ProgramPoint &PP : FixedRestorePoints) {
1114     BinaryBasicBlock *BB = Info.getParentBB(PP);
1115     bool Found = false;
1116     if (SPT.getStateAt(ProgramPoint::getLastPointAt(*BB))->first ==
1117         SaveOffset) {
1118       BitVector BV = *RI.getStateAt(ProgramPoint::getLastPointAt(*BB));
1119       BV &= UsesByReg[CSR];
1120       if (!BV.any()) {
1121         Found = true;
1122         PP = BB;
1123         continue;
1124       }
1125     }
1126     for (auto RIt = BB->rbegin(), End = BB->rend(); RIt != End; ++RIt) {
1127       if (SPT.getStateBefore(*RIt)->first == SaveOffset) {
1128         BitVector BV = *RI.getStateAt(*RIt);
1129         BV &= UsesByReg[CSR];
1130         if (!BV.any()) {
1131           Found = true;
1132           PP = &*RIt;
1133           break;
1134         }
1135       }
1136     }
1137     if (!Found) {
1138       LLVM_DEBUG({
1139         dbgs() << "Could not find restore insertion point for " << CSR
1140                << ", falling back to load/store mode\n";
1141       });
1142       FixedRestorePoints.clear();
1143       return FixedRestorePoints;
1144     }
1145   }
1146   return FixedRestorePoints;
1147 }
1148 
1149 void ShrinkWrapping::scheduleOldSaveRestoresRemoval(unsigned CSR,
1150                                                     bool UsePushPops) {
1151 
1152   for (BinaryBasicBlock *&BB : BF.layout()) {
1153     std::vector<MCInst *> CFIs;
1154     for (auto I = BB->rbegin(), E = BB->rend(); I != E; ++I) {
1155       MCInst &Inst = *I;
1156       if (BC.MIB->isCFI(Inst)) {
1157         // Delete all offset CFIs related to this CSR
1158         if (SLM.getOffsetCFIReg(Inst) == CSR) {
1159           HasDeletedOffsetCFIs[CSR] = true;
1160           scheduleChange(&Inst, WorklistItem(WorklistItem::Erase, CSR));
1161           continue;
1162         }
1163         CFIs.push_back(&Inst);
1164         continue;
1165       }
1166 
1167       uint16_t SavedReg = CSA.getSavedReg(Inst);
1168       uint16_t RestoredReg = CSA.getRestoredReg(Inst);
1169       if (SavedReg != CSR && RestoredReg != CSR) {
1170         CFIs.clear();
1171         continue;
1172       }
1173 
1174       scheduleChange(&Inst, WorklistItem(UsePushPops
1175                                              ? WorklistItem::Erase
1176                                              : WorklistItem::ChangeToAdjustment,
1177                                          CSR));
1178 
1179       // Delete associated CFIs
1180       const bool RecordDeletedPushCFIs =
1181           SavedReg == CSR && DeletedPushCFIs[CSR].empty();
1182       const bool RecordDeletedPopCFIs =
1183           RestoredReg == CSR && DeletedPopCFIs[CSR].empty();
1184       for (MCInst *CFI : CFIs) {
1185         const MCCFIInstruction *MCCFI = BF.getCFIFor(*CFI);
1186         // Do not touch these...
1187         if (MCCFI->getOperation() == MCCFIInstruction::OpRestoreState ||
1188             MCCFI->getOperation() == MCCFIInstruction::OpRememberState)
1189           continue;
1190         scheduleChange(CFI, WorklistItem(WorklistItem::Erase, CSR));
1191         if (RecordDeletedPushCFIs) {
1192           // Do not record this to be replayed later because we are going to
1193           // rebuild it.
1194           if (MCCFI->getOperation() == MCCFIInstruction::OpDefCfaOffset)
1195             continue;
1196           DeletedPushCFIs[CSR].push_back(CFI->getOperand(0).getImm());
1197         }
1198         if (RecordDeletedPopCFIs) {
1199           if (MCCFI->getOperation() == MCCFIInstruction::OpDefCfaOffset)
1200             continue;
1201           DeletedPopCFIs[CSR].push_back(CFI->getOperand(0).getImm());
1202         }
1203       }
1204       CFIs.clear();
1205     }
1206   }
1207 }
1208 
1209 bool ShrinkWrapping::doesInstUsesCSR(const MCInst &Inst, uint16_t CSR) {
1210   if (BC.MIB->isCFI(Inst) || CSA.getSavedReg(Inst) == CSR ||
1211       CSA.getRestoredReg(Inst) == CSR)
1212     return false;
1213   BitVector BV = BitVector(BC.MRI->getNumRegs(), false);
1214   BC.MIB->getTouchedRegs(Inst, BV);
1215   return BV[CSR];
1216 }
1217 
1218 void ShrinkWrapping::scheduleSaveRestoreInsertions(
1219     unsigned CSR, MCInst *BestPosSave,
1220     SmallVector<ProgramPoint, 4> &RestorePoints, bool UsePushPops) {
1221   auto &InsnToBB = Info.getInsnToBBMap();
1222   const FrameIndexEntry *FIESave = CSA.SaveFIEByReg[CSR];
1223   const FrameIndexEntry *FIELoad = CSA.LoadFIEByReg[CSR];
1224   assert(FIESave && FIELoad && "Invalid CSR");
1225 
1226   LLVM_DEBUG({
1227     dbgs() << "Scheduling save insertion at: ";
1228     BestPosSave->dump();
1229   });
1230 
1231   scheduleChange(BestPosSave,
1232                  UsePushPops ? WorklistItem::InsertPushOrPop
1233                              : WorklistItem::InsertLoadOrStore,
1234                  *FIESave, CSR);
1235 
1236   for (ProgramPoint &PP : RestorePoints) {
1237     BinaryBasicBlock *FrontierBB = Info.getParentBB(PP);
1238     LLVM_DEBUG({
1239       dbgs() << "Scheduling restore insertion at: ";
1240       if (PP.isInst())
1241         PP.getInst()->dump();
1242       else
1243         dbgs() << PP.getBB()->getName() << "\n";
1244     });
1245     MCInst *Term =
1246         FrontierBB->getTerminatorBefore(PP.isInst() ? PP.getInst() : nullptr);
1247     if (Term)
1248       PP = Term;
1249     bool PrecededByPrefix = false;
1250     if (PP.isInst()) {
1251       auto Iter = FrontierBB->findInstruction(PP.getInst());
1252       if (Iter != FrontierBB->end() && Iter != FrontierBB->begin()) {
1253         --Iter;
1254         PrecededByPrefix = BC.MIB->isPrefix(*Iter);
1255       }
1256     }
1257     if (PP.isInst() &&
1258         (doesInstUsesCSR(*PP.getInst(), CSR) || PrecededByPrefix)) {
1259       assert(!InsnToBB[PP.getInst()]->hasTerminatorAfter(PP.getInst()) &&
1260              "cannot move to end of bb");
1261       scheduleChange(InsnToBB[PP.getInst()],
1262                      UsePushPops ? WorklistItem::InsertPushOrPop
1263                                  : WorklistItem::InsertLoadOrStore,
1264                      *FIELoad, CSR);
1265       continue;
1266     }
1267     scheduleChange(PP,
1268                    UsePushPops ? WorklistItem::InsertPushOrPop
1269                                : WorklistItem::InsertLoadOrStore,
1270                    *FIELoad, CSR);
1271   }
1272 }
1273 
1274 void ShrinkWrapping::moveSaveRestores() {
1275   bool DisablePushPopMode = false;
1276   bool UsedPushPopMode = false;
1277   // Keeps info about successfully moved regs: reg index, save position and
1278   // save size
1279   std::vector<std::tuple<unsigned, MCInst *, size_t>> MovedRegs;
1280   uint64_t TotalEstimatedWin = 0;
1281 
1282   for (unsigned I = 0, E = BC.MRI->getNumRegs(); I != E; ++I) {
1283     MCInst *BestPosSave = nullptr;
1284     uint64_t EstimatedWin = 0;
1285     if (!isBestSavePosCold(I, BestPosSave, EstimatedWin))
1286       continue;
1287     SmallVector<ProgramPoint, 4> RestorePoints =
1288         doRestorePlacement(BestPosSave, I, EstimatedWin);
1289     if (RestorePoints.empty()) {
1290       SpillsFailedDynamicCount += EstimatedWin;
1291       continue;
1292     }
1293 
1294     const FrameIndexEntry *FIESave = CSA.SaveFIEByReg[I];
1295     const FrameIndexEntry *FIELoad = CSA.LoadFIEByReg[I];
1296     (void)FIELoad;
1297     assert(FIESave && FIELoad);
1298     StackPointerTracking &SPT = Info.getStackPointerTracking();
1299     const std::pair<int, int> SPFP = *SPT.getStateBefore(*BestPosSave);
1300     int SaveOffset = SPFP.first;
1301     uint8_t SaveSize = FIESave->Size;
1302 
1303     // If we don't know stack state at this point, bail
1304     if ((SPFP.first == SPT.SUPERPOSITION || SPFP.first == SPT.EMPTY) &&
1305         (SPFP.second == SPT.SUPERPOSITION || SPFP.second == SPT.EMPTY)) {
1306       SpillsFailedDynamicCount += EstimatedWin;
1307       continue;
1308     }
1309 
1310     // Operation mode: if true, will insert push/pops instead of loads/restores
1311     bool UsePushPops = validatePushPopsMode(I, BestPosSave, SaveOffset);
1312 
1313     if (UsePushPops) {
1314       SmallVector<ProgramPoint, 4> FixedRestorePoints =
1315           fixPopsPlacements(RestorePoints, SaveOffset, I);
1316       if (FixedRestorePoints.empty())
1317         UsePushPops = false;
1318       else
1319         RestorePoints = FixedRestorePoints;
1320     }
1321 
1322     // Disable push-pop mode for all CSRs in this function
1323     if (!UsePushPops)
1324       DisablePushPopMode = true;
1325     else
1326       UsedPushPopMode = true;
1327 
1328     scheduleOldSaveRestoresRemoval(I, UsePushPops);
1329     scheduleSaveRestoreInsertions(I, BestPosSave, RestorePoints, UsePushPops);
1330     MovedRegs.emplace_back(std::make_tuple(I, BestPosSave, SaveSize));
1331     TotalEstimatedWin += EstimatedWin;
1332   }
1333 
1334   // Revert push-pop mode if it failed for a single CSR
1335   if (DisablePushPopMode && UsedPushPopMode) {
1336     UsedPushPopMode = false;
1337     for (BinaryBasicBlock &BB : BF) {
1338       auto WRI = Todo.find(&BB);
1339       if (WRI != Todo.end()) {
1340         std::vector<WorklistItem> &TodoList = WRI->second;
1341         for (WorklistItem &Item : TodoList)
1342           if (Item.Action == WorklistItem::InsertPushOrPop)
1343             Item.Action = WorklistItem::InsertLoadOrStore;
1344       }
1345       for (auto I = BB.rbegin(), E = BB.rend(); I != E; ++I) {
1346         MCInst &Inst = *I;
1347         auto TodoList = BC.MIB->tryGetAnnotationAs<std::vector<WorklistItem>>(
1348             Inst, getAnnotationIndex());
1349         if (!TodoList)
1350           continue;
1351         bool isCFI = BC.MIB->isCFI(Inst);
1352         for (WorklistItem &Item : *TodoList) {
1353           if (Item.Action == WorklistItem::InsertPushOrPop)
1354             Item.Action = WorklistItem::InsertLoadOrStore;
1355           if (!isCFI && Item.Action == WorklistItem::Erase)
1356             Item.Action = WorklistItem::ChangeToAdjustment;
1357         }
1358       }
1359     }
1360   }
1361   SpillsMovedDynamicCount += TotalEstimatedWin;
1362 
1363   // Update statistics
1364   if (!UsedPushPopMode) {
1365     SpillsMovedRegularMode += MovedRegs.size();
1366     return;
1367   }
1368 
1369   // Schedule modifications to stack-accessing instructions via
1370   // StackLayoutModifier.
1371   SpillsMovedPushPopMode += MovedRegs.size();
1372   for (std::tuple<unsigned, MCInst *, size_t> &I : MovedRegs) {
1373     unsigned RegNdx;
1374     MCInst *SavePos;
1375     size_t SaveSize;
1376     std::tie(RegNdx, SavePos, SaveSize) = I;
1377     for (MCInst *Save : CSA.getSavesByReg(RegNdx))
1378       SLM.collapseRegion(Save);
1379     SLM.insertRegion(SavePos, SaveSize);
1380   }
1381 }
1382 
1383 namespace {
1384 /// Helper function to identify whether two basic blocks created by splitting
1385 /// a critical edge have the same contents.
1386 bool isIdenticalSplitEdgeBB(const BinaryContext &BC, const BinaryBasicBlock &A,
1387                             const BinaryBasicBlock &B) {
1388   if (A.succ_size() != B.succ_size())
1389     return false;
1390   if (A.succ_size() != 1)
1391     return false;
1392 
1393   if (*A.succ_begin() != *B.succ_begin())
1394     return false;
1395 
1396   if (A.size() != B.size())
1397     return false;
1398 
1399   // Compare instructions
1400   auto I = A.begin(), E = A.end();
1401   auto OtherI = B.begin(), OtherE = B.end();
1402   while (I != E && OtherI != OtherE) {
1403     if (I->getOpcode() != OtherI->getOpcode())
1404       return false;
1405     if (!BC.MIB->equals(*I, *OtherI, [](const MCSymbol *A, const MCSymbol *B) {
1406           return true;
1407         }))
1408       return false;
1409     ++I;
1410     ++OtherI;
1411   }
1412   return true;
1413 }
1414 } // namespace
1415 
1416 bool ShrinkWrapping::foldIdenticalSplitEdges() {
1417   bool Changed = false;
1418   for (auto Iter = BF.begin(); Iter != BF.end(); ++Iter) {
1419     BinaryBasicBlock &BB = *Iter;
1420     if (!BB.getName().startswith(".LSplitEdge"))
1421       continue;
1422     for (auto RIter = BF.rbegin(); RIter != BF.rend(); ++RIter) {
1423       BinaryBasicBlock &RBB = *RIter;
1424       if (&RBB == &BB)
1425         break;
1426       if (!RBB.getName().startswith(".LSplitEdge") || !RBB.isValid() ||
1427           !isIdenticalSplitEdgeBB(BC, *Iter, RBB))
1428         continue;
1429       assert(RBB.pred_size() == 1 && "Invalid split edge BB");
1430       BinaryBasicBlock *Pred = *RBB.pred_begin();
1431       uint64_t OrigCount = Pred->branch_info_begin()->Count;
1432       uint64_t OrigMispreds = Pred->branch_info_begin()->MispredictedCount;
1433       BF.replaceJumpTableEntryIn(Pred, &RBB, &BB);
1434       Pred->replaceSuccessor(&RBB, &BB, OrigCount, OrigMispreds);
1435       Changed = true;
1436       // Remove the block from CFG
1437       RBB.markValid(false);
1438     }
1439   }
1440 
1441   return Changed;
1442 }
1443 
1444 namespace {
1445 
1446 // A special StackPointerTracking that compensates for our future plans
1447 // in removing/adding insn.
1448 class PredictiveStackPointerTracking
1449     : public StackPointerTrackingBase<PredictiveStackPointerTracking> {
1450   friend class DataflowAnalysis<PredictiveStackPointerTracking,
1451                                 std::pair<int, int>>;
1452   decltype(ShrinkWrapping::Todo) &TodoMap;
1453   DataflowInfoManager &Info;
1454 
1455   Optional<unsigned> AnnotationIndex;
1456 
1457 protected:
1458   void compNextAux(const MCInst &Point,
1459                    const std::vector<ShrinkWrapping::WorklistItem> &TodoItems,
1460                    std::pair<int, int> &Res) {
1461     for (const ShrinkWrapping::WorklistItem &Item : TodoItems) {
1462       if (Item.Action == ShrinkWrapping::WorklistItem::Erase &&
1463           BC.MIB->isPush(Point)) {
1464         Res.first += BC.MIB->getPushSize(Point);
1465         continue;
1466       }
1467       if (Item.Action == ShrinkWrapping::WorklistItem::Erase &&
1468           BC.MIB->isPop(Point)) {
1469         Res.first -= BC.MIB->getPopSize(Point);
1470         continue;
1471       }
1472       if (Item.Action == ShrinkWrapping::WorklistItem::InsertPushOrPop &&
1473           Item.FIEToInsert.IsStore) {
1474         Res.first -= Item.FIEToInsert.Size;
1475         continue;
1476       }
1477       if (Item.Action == ShrinkWrapping::WorklistItem::InsertPushOrPop &&
1478           Item.FIEToInsert.IsLoad) {
1479         Res.first += Item.FIEToInsert.Size;
1480         continue;
1481       }
1482     }
1483   }
1484 
1485   std::pair<int, int> computeNext(const MCInst &Point,
1486                                   const std::pair<int, int> &Cur) {
1487     std::pair<int, int> Res =
1488         StackPointerTrackingBase<PredictiveStackPointerTracking>::computeNext(
1489             Point, Cur);
1490     if (Res.first == StackPointerTracking::SUPERPOSITION ||
1491         Res.first == StackPointerTracking::EMPTY)
1492       return Res;
1493     auto TodoItems =
1494         BC.MIB->tryGetAnnotationAs<std::vector<ShrinkWrapping::WorklistItem>>(
1495             Point, ShrinkWrapping::getAnnotationName());
1496     if (TodoItems)
1497       compNextAux(Point, *TodoItems, Res);
1498     auto &InsnToBBMap = Info.getInsnToBBMap();
1499     if (&*InsnToBBMap[&Point]->rbegin() != &Point)
1500       return Res;
1501     auto WRI = TodoMap.find(InsnToBBMap[&Point]);
1502     if (WRI == TodoMap.end())
1503       return Res;
1504     compNextAux(Point, WRI->second, Res);
1505     return Res;
1506   }
1507 
1508   StringRef getAnnotationName() const {
1509     return StringRef("PredictiveStackPointerTracking");
1510   }
1511 
1512 public:
1513   PredictiveStackPointerTracking(BinaryFunction &BF,
1514                                  decltype(ShrinkWrapping::Todo) &TodoMap,
1515                                  DataflowInfoManager &Info,
1516                                  MCPlusBuilder::AllocatorIdTy AllocatorId = 0)
1517       : StackPointerTrackingBase<PredictiveStackPointerTracking>(BF,
1518                                                                  AllocatorId),
1519         TodoMap(TodoMap), Info(Info) {}
1520 
1521   void run() {
1522     StackPointerTrackingBase<PredictiveStackPointerTracking>::run();
1523   }
1524 };
1525 
1526 } // end anonymous namespace
1527 
1528 void ShrinkWrapping::insertUpdatedCFI(unsigned CSR, int SPValPush,
1529                                       int SPValPop) {
1530   MCInst *SavePoint = nullptr;
1531   for (BinaryBasicBlock &BB : BF) {
1532     for (auto InstIter = BB.rbegin(), EndIter = BB.rend(); InstIter != EndIter;
1533          ++InstIter) {
1534       int32_t SrcImm = 0;
1535       MCPhysReg Reg = 0;
1536       MCPhysReg StackPtrReg = 0;
1537       int64_t StackOffset = 0;
1538       bool IsIndexed = false;
1539       bool IsLoad = false;
1540       bool IsStore = false;
1541       bool IsSimple = false;
1542       bool IsStoreFromReg = false;
1543       uint8_t Size = 0;
1544       if (!BC.MIB->isStackAccess(*InstIter, IsLoad, IsStore, IsStoreFromReg,
1545                                  Reg, SrcImm, StackPtrReg, StackOffset, Size,
1546                                  IsSimple, IsIndexed))
1547         continue;
1548       if (Reg != CSR || !IsStore || !IsSimple)
1549         continue;
1550       SavePoint = &*InstIter;
1551       break;
1552     }
1553     if (SavePoint)
1554       break;
1555   }
1556   assert(SavePoint);
1557   LLVM_DEBUG({
1558     dbgs() << "Now using as save point for reg " << CSR << " :";
1559     SavePoint->dump();
1560   });
1561   bool PrevAffectedZone = false;
1562   BinaryBasicBlock *PrevBB = nullptr;
1563   DominatorAnalysis<false> &DA = Info.getDominatorAnalysis();
1564   for (BinaryBasicBlock *BB : BF.layout()) {
1565     if (BB->size() == 0)
1566       continue;
1567     const bool InAffectedZoneAtEnd = DA.count(*BB->rbegin(), *SavePoint);
1568     const bool InAffectedZoneAtBegin =
1569         (*DA.getStateBefore(*BB->begin()))[DA.ExprToIdx[SavePoint]];
1570     bool InAffectedZone = InAffectedZoneAtBegin;
1571     for (auto InstIter = BB->begin(); InstIter != BB->end(); ++InstIter) {
1572       const bool CurZone = DA.count(*InstIter, *SavePoint);
1573       if (InAffectedZone != CurZone) {
1574         auto InsertionIter = InstIter;
1575         ++InsertionIter;
1576         InAffectedZone = CurZone;
1577         if (InAffectedZone)
1578           InstIter = insertCFIsForPushOrPop(*BB, InsertionIter, CSR, true, 0,
1579                                             SPValPop);
1580         else
1581           InstIter = insertCFIsForPushOrPop(*BB, InsertionIter, CSR, false, 0,
1582                                             SPValPush);
1583         --InstIter;
1584       }
1585     }
1586     // Are we at the first basic block or hot-cold split point?
1587     if (!PrevBB || (BF.isSplit() && BB->isCold() != PrevBB->isCold())) {
1588       if (InAffectedZoneAtBegin)
1589         insertCFIsForPushOrPop(*BB, BB->begin(), CSR, true, 0, SPValPush);
1590     } else if (InAffectedZoneAtBegin != PrevAffectedZone) {
1591       if (InAffectedZoneAtBegin)
1592         insertCFIsForPushOrPop(*PrevBB, PrevBB->end(), CSR, true, 0, SPValPush);
1593       else
1594         insertCFIsForPushOrPop(*PrevBB, PrevBB->end(), CSR, false, 0, SPValPop);
1595     }
1596     PrevAffectedZone = InAffectedZoneAtEnd;
1597     PrevBB = BB;
1598   }
1599 }
1600 
1601 void ShrinkWrapping::rebuildCFIForSP() {
1602   for (BinaryBasicBlock &BB : BF) {
1603     for (MCInst &Inst : BB) {
1604       if (!BC.MIB->isCFI(Inst))
1605         continue;
1606       const MCCFIInstruction *CFI = BF.getCFIFor(Inst);
1607       if (CFI->getOperation() == MCCFIInstruction::OpDefCfaOffset)
1608         BC.MIB->addAnnotation(Inst, "DeleteMe", 0U, AllocatorId);
1609     }
1610   }
1611 
1612   int PrevSPVal = -8;
1613   BinaryBasicBlock *PrevBB = nullptr;
1614   StackPointerTracking &SPT = Info.getStackPointerTracking();
1615   for (BinaryBasicBlock *BB : BF.layout()) {
1616     if (BB->size() == 0)
1617       continue;
1618     const int SPValAtEnd = SPT.getStateAt(*BB->rbegin())->first;
1619     const int SPValAtBegin = SPT.getStateBefore(*BB->begin())->first;
1620     int SPVal = SPValAtBegin;
1621     for (auto Iter = BB->begin(); Iter != BB->end(); ++Iter) {
1622       const int CurVal = SPT.getStateAt(*Iter)->first;
1623       if (SPVal != CurVal) {
1624         auto InsertionIter = Iter;
1625         ++InsertionIter;
1626         Iter = BF.addCFIInstruction(
1627             BB, InsertionIter,
1628             MCCFIInstruction::cfiDefCfaOffset(nullptr, -CurVal));
1629         SPVal = CurVal;
1630       }
1631     }
1632     if (BF.isSplit() && PrevBB && BB->isCold() != PrevBB->isCold())
1633       BF.addCFIInstruction(
1634           BB, BB->begin(),
1635           MCCFIInstruction::cfiDefCfaOffset(nullptr, -SPValAtBegin));
1636     else if (SPValAtBegin != PrevSPVal)
1637       BF.addCFIInstruction(
1638           PrevBB, PrevBB->end(),
1639           MCCFIInstruction::cfiDefCfaOffset(nullptr, -SPValAtBegin));
1640     PrevSPVal = SPValAtEnd;
1641     PrevBB = BB;
1642   }
1643 
1644   for (BinaryBasicBlock &BB : BF)
1645     for (auto I = BB.begin(); I != BB.end();)
1646       if (BC.MIB->hasAnnotation(*I, "DeleteMe"))
1647         I = BB.eraseInstruction(I);
1648       else
1649         ++I;
1650 }
1651 
1652 MCInst ShrinkWrapping::createStackAccess(int SPVal, int FPVal,
1653                                          const FrameIndexEntry &FIE,
1654                                          bool CreatePushOrPop) {
1655   MCInst NewInst;
1656   if (SPVal != StackPointerTracking::SUPERPOSITION &&
1657       SPVal != StackPointerTracking::EMPTY) {
1658     if (FIE.IsLoad) {
1659       if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getStackPointer(),
1660                                           FIE.StackOffset - SPVal, FIE.RegOrImm,
1661                                           FIE.Size)) {
1662         errs() << "createRestoreFromStack: not supported on this platform\n";
1663         abort();
1664       }
1665     } else {
1666       if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getStackPointer(),
1667                                      FIE.StackOffset - SPVal, FIE.RegOrImm,
1668                                      FIE.Size)) {
1669         errs() << "createSaveToStack: not supported on this platform\n";
1670         abort();
1671       }
1672     }
1673     if (CreatePushOrPop)
1674       BC.MIB->changeToPushOrPop(NewInst);
1675     return NewInst;
1676   }
1677   assert(FPVal != StackPointerTracking::SUPERPOSITION &&
1678          FPVal != StackPointerTracking::EMPTY);
1679 
1680   if (FIE.IsLoad) {
1681     if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getFramePointer(),
1682                                         FIE.StackOffset - FPVal, FIE.RegOrImm,
1683                                         FIE.Size)) {
1684       errs() << "createRestoreFromStack: not supported on this platform\n";
1685       abort();
1686     }
1687   } else {
1688     if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getFramePointer(),
1689                                    FIE.StackOffset - FPVal, FIE.RegOrImm,
1690                                    FIE.Size)) {
1691       errs() << "createSaveToStack: not supported on this platform\n";
1692       abort();
1693     }
1694   }
1695   return NewInst;
1696 }
1697 
1698 void ShrinkWrapping::updateCFIInstOffset(MCInst &Inst, int64_t NewOffset) {
1699   const MCCFIInstruction *CFI = BF.getCFIFor(Inst);
1700   if (UpdatedCFIs.count(CFI))
1701     return;
1702 
1703   switch (CFI->getOperation()) {
1704   case MCCFIInstruction::OpDefCfa:
1705   case MCCFIInstruction::OpDefCfaRegister:
1706   case MCCFIInstruction::OpDefCfaOffset:
1707     CFI = BF.mutateCFIOffsetFor(Inst, -NewOffset);
1708     break;
1709   case MCCFIInstruction::OpOffset:
1710   default:
1711     break;
1712   }
1713 
1714   UpdatedCFIs.insert(CFI);
1715 }
1716 
1717 BBIterTy ShrinkWrapping::insertCFIsForPushOrPop(BinaryBasicBlock &BB,
1718                                                 BBIterTy Pos, unsigned Reg,
1719                                                 bool isPush, int Sz,
1720                                                 int64_t NewOffset) {
1721   if (isPush) {
1722     for (uint32_t Idx : DeletedPushCFIs[Reg]) {
1723       Pos = BF.addCFIPseudo(&BB, Pos, Idx);
1724       updateCFIInstOffset(*Pos++, NewOffset);
1725     }
1726     if (HasDeletedOffsetCFIs[Reg]) {
1727       Pos = BF.addCFIInstruction(
1728           &BB, Pos,
1729           MCCFIInstruction::createOffset(
1730               nullptr, BC.MRI->getDwarfRegNum(Reg, false), NewOffset));
1731       ++Pos;
1732     }
1733   } else {
1734     for (uint32_t Idx : DeletedPopCFIs[Reg]) {
1735       Pos = BF.addCFIPseudo(&BB, Pos, Idx);
1736       updateCFIInstOffset(*Pos++, NewOffset);
1737     }
1738     if (HasDeletedOffsetCFIs[Reg]) {
1739       Pos = BF.addCFIInstruction(
1740           &BB, Pos,
1741           MCCFIInstruction::createSameValue(
1742               nullptr, BC.MRI->getDwarfRegNum(Reg, false)));
1743       ++Pos;
1744     }
1745   }
1746   return Pos;
1747 }
1748 
1749 BBIterTy ShrinkWrapping::processInsertion(BBIterTy InsertionPoint,
1750                                           BinaryBasicBlock *CurBB,
1751                                           const WorklistItem &Item,
1752                                           int64_t SPVal, int64_t FPVal) {
1753   // Trigger CFI reconstruction for this CSR if necessary - writing to
1754   // PushOffsetByReg/PopOffsetByReg *will* trigger CFI update
1755   if ((Item.FIEToInsert.IsStore &&
1756        !DeletedPushCFIs[Item.AffectedReg].empty()) ||
1757       (Item.FIEToInsert.IsLoad && !DeletedPopCFIs[Item.AffectedReg].empty()) ||
1758       HasDeletedOffsetCFIs[Item.AffectedReg]) {
1759     if (Item.Action == WorklistItem::InsertPushOrPop) {
1760       if (Item.FIEToInsert.IsStore)
1761         PushOffsetByReg[Item.AffectedReg] = SPVal - Item.FIEToInsert.Size;
1762       else
1763         PopOffsetByReg[Item.AffectedReg] = SPVal;
1764     } else {
1765       if (Item.FIEToInsert.IsStore)
1766         PushOffsetByReg[Item.AffectedReg] = Item.FIEToInsert.StackOffset;
1767       else
1768         PopOffsetByReg[Item.AffectedReg] = Item.FIEToInsert.StackOffset;
1769     }
1770   }
1771 
1772   LLVM_DEBUG({
1773     dbgs() << "Creating stack access with SPVal = " << SPVal
1774            << "; stack offset = " << Item.FIEToInsert.StackOffset
1775            << " Is push = " << (Item.Action == WorklistItem::InsertPushOrPop)
1776            << "\n";
1777   });
1778   MCInst NewInst =
1779       createStackAccess(SPVal, FPVal, Item.FIEToInsert,
1780                         Item.Action == WorklistItem::InsertPushOrPop);
1781   if (InsertionPoint != CurBB->end()) {
1782     LLVM_DEBUG({
1783       dbgs() << "Adding before Inst: ";
1784       InsertionPoint->dump();
1785       dbgs() << "the following inst: ";
1786       NewInst.dump();
1787     });
1788     BBIterTy Iter =
1789         CurBB->insertInstruction(InsertionPoint, std::move(NewInst));
1790     return ++Iter;
1791   }
1792   CurBB->addInstruction(std::move(NewInst));
1793   LLVM_DEBUG(dbgs() << "Adding to BB!\n");
1794   return CurBB->end();
1795 }
1796 
1797 BBIterTy ShrinkWrapping::processInsertionsList(
1798     BBIterTy InsertionPoint, BinaryBasicBlock *CurBB,
1799     std::vector<WorklistItem> &TodoList, int64_t SPVal, int64_t FPVal) {
1800   bool HasInsertions = false;
1801   for (WorklistItem &Item : TodoList) {
1802     if (Item.Action == WorklistItem::Erase ||
1803         Item.Action == WorklistItem::ChangeToAdjustment)
1804       continue;
1805     HasInsertions = true;
1806     break;
1807   }
1808 
1809   if (!HasInsertions)
1810     return InsertionPoint;
1811 
1812   assert(((SPVal != StackPointerTracking::SUPERPOSITION &&
1813            SPVal != StackPointerTracking::EMPTY) ||
1814           (FPVal != StackPointerTracking::SUPERPOSITION &&
1815            FPVal != StackPointerTracking::EMPTY)) &&
1816          "Cannot insert if we have no idea of the stack state here");
1817 
1818   // Revert the effect of PSPT for this location, we want SP Value before
1819   // insertions
1820   if (InsertionPoint == CurBB->end()) {
1821     for (WorklistItem &Item : TodoList) {
1822       if (Item.Action != WorklistItem::InsertPushOrPop)
1823         continue;
1824       if (Item.FIEToInsert.IsStore)
1825         SPVal += Item.FIEToInsert.Size;
1826       if (Item.FIEToInsert.IsLoad)
1827         SPVal -= Item.FIEToInsert.Size;
1828     }
1829   }
1830 
1831   // Reorder POPs to obey the correct dominance relation between them
1832   llvm::stable_sort(TodoList, [&](const WorklistItem &A,
1833                                   const WorklistItem &B) {
1834     if ((A.Action != WorklistItem::InsertPushOrPop || !A.FIEToInsert.IsLoad) &&
1835         (B.Action != WorklistItem::InsertPushOrPop || !B.FIEToInsert.IsLoad))
1836       return false;
1837     if ((A.Action != WorklistItem::InsertPushOrPop || !A.FIEToInsert.IsLoad))
1838       return true;
1839     if ((B.Action != WorklistItem::InsertPushOrPop || !B.FIEToInsert.IsLoad))
1840       return false;
1841     return DomOrder[B.AffectedReg] < DomOrder[A.AffectedReg];
1842   });
1843 
1844   // Process insertions
1845   for (WorklistItem &Item : TodoList) {
1846     if (Item.Action == WorklistItem::Erase ||
1847         Item.Action == WorklistItem::ChangeToAdjustment)
1848       continue;
1849 
1850     InsertionPoint =
1851         processInsertion(InsertionPoint, CurBB, Item, SPVal, FPVal);
1852     if (Item.Action == WorklistItem::InsertPushOrPop &&
1853         Item.FIEToInsert.IsStore)
1854       SPVal -= Item.FIEToInsert.Size;
1855     if (Item.Action == WorklistItem::InsertPushOrPop &&
1856         Item.FIEToInsert.IsLoad)
1857       SPVal += Item.FIEToInsert.Size;
1858   }
1859   return InsertionPoint;
1860 }
1861 
1862 bool ShrinkWrapping::processInsertions() {
1863   PredictiveStackPointerTracking PSPT(BF, Todo, Info, AllocatorId);
1864   PSPT.run();
1865 
1866   bool Changes = false;
1867   for (BinaryBasicBlock &BB : BF) {
1868     // Process insertions before some inst.
1869     for (auto I = BB.begin(); I != BB.end(); ++I) {
1870       MCInst &Inst = *I;
1871       auto TodoList = BC.MIB->tryGetAnnotationAs<std::vector<WorklistItem>>(
1872           Inst, getAnnotationIndex());
1873       if (!TodoList)
1874         continue;
1875       Changes = true;
1876       std::vector<WorklistItem> List = *TodoList;
1877       LLVM_DEBUG({
1878         dbgs() << "Now processing insertions in " << BB.getName()
1879                << " before inst: ";
1880         Inst.dump();
1881       });
1882       auto Iter = I;
1883       std::pair<int, int> SPTState =
1884           *PSPT.getStateAt(Iter == BB.begin() ? (ProgramPoint)&BB : &*(--Iter));
1885       I = processInsertionsList(I, &BB, List, SPTState.first, SPTState.second);
1886     }
1887     // Process insertions at the end of bb
1888     auto WRI = Todo.find(&BB);
1889     if (WRI != Todo.end()) {
1890       std::pair<int, int> SPTState = *PSPT.getStateAt(*BB.rbegin());
1891       processInsertionsList(BB.end(), &BB, WRI->second, SPTState.first,
1892                             SPTState.second);
1893       Changes = true;
1894     }
1895   }
1896   return Changes;
1897 }
1898 
1899 void ShrinkWrapping::processDeletions() {
1900   LivenessAnalysis &LA = Info.getLivenessAnalysis();
1901   for (BinaryBasicBlock &BB : BF) {
1902     for (auto II = BB.begin(); II != BB.end(); ++II) {
1903       MCInst &Inst = *II;
1904       auto TodoList = BC.MIB->tryGetAnnotationAs<std::vector<WorklistItem>>(
1905           Inst, getAnnotationIndex());
1906       if (!TodoList)
1907         continue;
1908       // Process all deletions
1909       for (WorklistItem &Item : *TodoList) {
1910         if (Item.Action != WorklistItem::Erase &&
1911             Item.Action != WorklistItem::ChangeToAdjustment)
1912           continue;
1913 
1914         if (Item.Action == WorklistItem::ChangeToAdjustment) {
1915           // Is flag reg alive across this func?
1916           bool DontClobberFlags = LA.isAlive(&Inst, BC.MIB->getFlagsReg());
1917           if (int Sz = BC.MIB->getPushSize(Inst)) {
1918             BC.MIB->createStackPointerIncrement(Inst, Sz, DontClobberFlags);
1919             continue;
1920           }
1921           if (int Sz = BC.MIB->getPopSize(Inst)) {
1922             BC.MIB->createStackPointerDecrement(Inst, Sz, DontClobberFlags);
1923             continue;
1924           }
1925         }
1926 
1927         LLVM_DEBUG({
1928           dbgs() << "Erasing: ";
1929           BC.printInstruction(dbgs(), Inst);
1930         });
1931         II = std::prev(BB.eraseInstruction(II));
1932         break;
1933       }
1934     }
1935   }
1936 }
1937 
1938 void ShrinkWrapping::rebuildCFI() {
1939   const bool FP = Info.getStackPointerTracking().HasFramePointer;
1940   Info.invalidateAll();
1941   if (!FP) {
1942     rebuildCFIForSP();
1943     Info.invalidateAll();
1944   }
1945   for (unsigned I = 0, E = BC.MRI->getNumRegs(); I != E; ++I) {
1946     if (PushOffsetByReg[I] == 0 || PopOffsetByReg[I] == 0)
1947       continue;
1948     const int64_t SPValPush = PushOffsetByReg[I];
1949     const int64_t SPValPop = PopOffsetByReg[I];
1950     insertUpdatedCFI(I, SPValPush, SPValPop);
1951     Info.invalidateAll();
1952   }
1953 }
1954 
1955 bool ShrinkWrapping::perform(bool HotOnly) {
1956   HasDeletedOffsetCFIs = BitVector(BC.MRI->getNumRegs(), false);
1957   PushOffsetByReg = std::vector<int64_t>(BC.MRI->getNumRegs(), 0LL);
1958   PopOffsetByReg = std::vector<int64_t>(BC.MRI->getNumRegs(), 0LL);
1959   DomOrder = std::vector<MCPhysReg>(BC.MRI->getNumRegs(), 0);
1960 
1961   // Update pass statistics
1962   uint64_t TotalInstrs = 0ULL;
1963   uint64_t TotalStoreInstrs = 0ULL;
1964   for (BinaryBasicBlock *BB : BF.layout()) {
1965     uint64_t BBExecCount = BB->getExecutionCount();
1966     if (!BBExecCount || BBExecCount == BinaryBasicBlock::COUNT_NO_PROFILE)
1967       continue;
1968     for (const auto &Instr : *BB) {
1969       if (BC.MIB->isPseudo(Instr))
1970         continue;
1971       if (BC.MIB->isStore(Instr))
1972         TotalStoreInstrs += BBExecCount;
1973       TotalInstrs += BBExecCount;
1974     }
1975   }
1976   InstrDynamicCount += TotalInstrs;
1977   StoreDynamicCount += TotalStoreInstrs;
1978 
1979   if (!FA.hasFrameInfo(BF))
1980     return false;
1981 
1982   if (HotOnly && (BF.getKnownExecutionCount() < BC.getHotThreshold()))
1983     return false;
1984 
1985   if (BF.checkForAmbiguousJumpTables()) {
1986     LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ambiguous JTs in " << BF.getPrintName()
1987                       << ".\n");
1988     // We could call disambiguateJumpTables here, but it is probably not worth
1989     // the cost (of duplicating potentially large jump tables that could regress
1990     // dcache misses). Moreover, ambiguous JTs are rare and coming from code
1991     // written in assembly language. Just bail.
1992     return false;
1993   }
1994   SLM.initialize();
1995   CSA.compute();
1996   classifyCSRUses();
1997   pruneUnwantedCSRs();
1998   computeSaveLocations();
1999   computeDomOrder();
2000   moveSaveRestores();
2001   LLVM_DEBUG({
2002     dbgs() << "Func before shrink-wrapping: \n";
2003     BF.dump();
2004   });
2005   SLM.performChanges();
2006   // Early exit if processInsertions doesn't detect any todo items
2007   if (!processInsertions())
2008     return false;
2009   processDeletions();
2010   if (foldIdenticalSplitEdges()) {
2011     const std::pair<unsigned, uint64_t> Stats = BF.eraseInvalidBBs();
2012     (void)Stats;
2013     LLVM_DEBUG(dbgs() << "Deleted " << Stats.first
2014                       << " redundant split edge BBs (" << Stats.second
2015                       << " bytes) for " << BF.getPrintName() << "\n");
2016   }
2017   rebuildCFI();
2018   // We may have split edges, creating BBs that need correct branching
2019   BF.fixBranches();
2020   LLVM_DEBUG({
2021     dbgs() << "Func after shrink-wrapping: \n";
2022     BF.dump();
2023   });
2024   return true;
2025 }
2026 
2027 void ShrinkWrapping::printStats() {
2028   outs() << "BOLT-INFO: Shrink wrapping moved " << SpillsMovedRegularMode
2029          << " spills inserting load/stores and " << SpillsMovedPushPopMode
2030          << " spills inserting push/pops\n";
2031   if (!InstrDynamicCount || !StoreDynamicCount)
2032     return;
2033   outs() << "BOLT-INFO: Shrink wrapping reduced " << SpillsMovedDynamicCount
2034          << " store executions ("
2035          << format("%.1lf%%",
2036                    (100.0 * SpillsMovedDynamicCount / InstrDynamicCount))
2037          << " total instructions executed, "
2038          << format("%.1lf%%",
2039                    (100.0 * SpillsMovedDynamicCount / StoreDynamicCount))
2040          << " store instructions)\n";
2041   outs() << "BOLT-INFO: Shrink wrapping failed at reducing "
2042          << SpillsFailedDynamicCount << " store executions ("
2043          << format("%.1lf%%",
2044                    (100.0 * SpillsFailedDynamicCount / InstrDynamicCount))
2045          << " total instructions executed, "
2046          << format("%.1lf%%",
2047                    (100.0 * SpillsFailedDynamicCount / StoreDynamicCount))
2048          << " store instructions)\n";
2049 }
2050 
2051 // Operators necessary as a result of using MCAnnotation
2052 raw_ostream &operator<<(raw_ostream &OS,
2053                         const std::vector<ShrinkWrapping::WorklistItem> &Vec) {
2054   OS << "SWTodo[";
2055   const char *Sep = "";
2056   for (const ShrinkWrapping::WorklistItem &Item : Vec) {
2057     OS << Sep;
2058     switch (Item.Action) {
2059     case ShrinkWrapping::WorklistItem::Erase:
2060       OS << "Erase";
2061       break;
2062     case ShrinkWrapping::WorklistItem::ChangeToAdjustment:
2063       OS << "ChangeToAdjustment";
2064       break;
2065     case ShrinkWrapping::WorklistItem::InsertLoadOrStore:
2066       OS << "InsertLoadOrStore";
2067       break;
2068     case ShrinkWrapping::WorklistItem::InsertPushOrPop:
2069       OS << "InsertPushOrPop";
2070       break;
2071     }
2072     Sep = ", ";
2073   }
2074   OS << "]";
2075   return OS;
2076 }
2077 
2078 raw_ostream &
2079 operator<<(raw_ostream &OS,
2080            const std::vector<StackLayoutModifier::WorklistItem> &Vec) {
2081   OS << "SLMTodo[";
2082   const char *Sep = "";
2083   for (const StackLayoutModifier::WorklistItem &Item : Vec) {
2084     OS << Sep;
2085     switch (Item.Action) {
2086     case StackLayoutModifier::WorklistItem::None:
2087       OS << "None";
2088       break;
2089     case StackLayoutModifier::WorklistItem::AdjustLoadStoreOffset:
2090       OS << "AdjustLoadStoreOffset";
2091       break;
2092     case StackLayoutModifier::WorklistItem::AdjustCFI:
2093       OS << "AdjustCFI";
2094       break;
2095     }
2096     Sep = ", ";
2097   }
2098   OS << "]";
2099   return OS;
2100 }
2101 
2102 bool operator==(const ShrinkWrapping::WorklistItem &A,
2103                 const ShrinkWrapping::WorklistItem &B) {
2104   return (A.Action == B.Action && A.AffectedReg == B.AffectedReg &&
2105           A.Adjustment == B.Adjustment &&
2106           A.FIEToInsert.IsLoad == B.FIEToInsert.IsLoad &&
2107           A.FIEToInsert.IsStore == B.FIEToInsert.IsStore &&
2108           A.FIEToInsert.RegOrImm == B.FIEToInsert.RegOrImm &&
2109           A.FIEToInsert.Size == B.FIEToInsert.Size &&
2110           A.FIEToInsert.IsSimple == B.FIEToInsert.IsSimple &&
2111           A.FIEToInsert.StackOffset == B.FIEToInsert.StackOffset);
2112 }
2113 
2114 bool operator==(const StackLayoutModifier::WorklistItem &A,
2115                 const StackLayoutModifier::WorklistItem &B) {
2116   return (A.Action == B.Action && A.OffsetUpdate == B.OffsetUpdate);
2117 }
2118 
2119 } // end namespace bolt
2120 } // end namespace llvm
2121