Home | History | Annotate | Line # | Download | only in CodeGen
      1 //===- StackSlotColoring.cpp - Stack slot coloring pass. ------------------===//
      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 stack slot coloring pass.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "llvm/ADT/BitVector.h"
     14 #include "llvm/ADT/SmallVector.h"
     15 #include "llvm/ADT/Statistic.h"
     16 #include "llvm/CodeGen/LiveInterval.h"
     17 #include "llvm/CodeGen/LiveIntervals.h"
     18 #include "llvm/CodeGen/LiveStacks.h"
     19 #include "llvm/CodeGen/MachineBasicBlock.h"
     20 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
     21 #include "llvm/CodeGen/MachineFrameInfo.h"
     22 #include "llvm/CodeGen/MachineFunction.h"
     23 #include "llvm/CodeGen/MachineFunctionPass.h"
     24 #include "llvm/CodeGen/MachineInstr.h"
     25 #include "llvm/CodeGen/MachineMemOperand.h"
     26 #include "llvm/CodeGen/MachineOperand.h"
     27 #include "llvm/CodeGen/Passes.h"
     28 #include "llvm/CodeGen/PseudoSourceValue.h"
     29 #include "llvm/CodeGen/SlotIndexes.h"
     30 #include "llvm/CodeGen/TargetInstrInfo.h"
     31 #include "llvm/CodeGen/TargetRegisterInfo.h"
     32 #include "llvm/CodeGen/TargetSubtargetInfo.h"
     33 #include "llvm/InitializePasses.h"
     34 #include "llvm/Pass.h"
     35 #include "llvm/Support/Casting.h"
     36 #include "llvm/Support/CommandLine.h"
     37 #include "llvm/Support/Debug.h"
     38 #include "llvm/Support/raw_ostream.h"
     39 #include <algorithm>
     40 #include <cassert>
     41 #include <cstdint>
     42 #include <iterator>
     43 #include <vector>
     44 
     45 using namespace llvm;
     46 
     47 #define DEBUG_TYPE "stack-slot-coloring"
     48 
     49 static cl::opt<bool>
     50 DisableSharing("no-stack-slot-sharing",
     51              cl::init(false), cl::Hidden,
     52              cl::desc("Suppress slot sharing during stack coloring"));
     53 
     54 static cl::opt<int> DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden);
     55 
     56 STATISTIC(NumEliminated, "Number of stack slots eliminated due to coloring");
     57 STATISTIC(NumDead,       "Number of trivially dead stack accesses eliminated");
     58 
     59 namespace {
     60 
     61   class StackSlotColoring : public MachineFunctionPass {
     62     LiveStacks* LS;
     63     MachineFrameInfo *MFI;
     64     const TargetInstrInfo  *TII;
     65     const MachineBlockFrequencyInfo *MBFI;
     66 
     67     // SSIntervals - Spill slot intervals.
     68     std::vector<LiveInterval*> SSIntervals;
     69 
     70     // SSRefs - Keep a list of MachineMemOperands for each spill slot.
     71     // MachineMemOperands can be shared between instructions, so we need
     72     // to be careful that renames like [FI0, FI1] -> [FI1, FI2] do not
     73     // become FI0 -> FI1 -> FI2.
     74     SmallVector<SmallVector<MachineMemOperand *, 8>, 16> SSRefs;
     75 
     76     // OrigAlignments - Alignments of stack objects before coloring.
     77     SmallVector<Align, 16> OrigAlignments;
     78 
     79     // OrigSizes - Sizess of stack objects before coloring.
     80     SmallVector<unsigned, 16> OrigSizes;
     81 
     82     // AllColors - If index is set, it's a spill slot, i.e. color.
     83     // FIXME: This assumes PEI locate spill slot with smaller indices
     84     // closest to stack pointer / frame pointer. Therefore, smaller
     85     // index == better color. This is per stack ID.
     86     SmallVector<BitVector, 2> AllColors;
     87 
     88     // NextColor - Next "color" that's not yet used. This is per stack ID.
     89     SmallVector<int, 2> NextColors = { -1 };
     90 
     91     // UsedColors - "Colors" that have been assigned. This is per stack ID
     92     SmallVector<BitVector, 2> UsedColors;
     93 
     94     // Assignments - Color to intervals mapping.
     95     SmallVector<SmallVector<LiveInterval*,4>, 16> Assignments;
     96 
     97   public:
     98     static char ID; // Pass identification
     99 
    100     StackSlotColoring() : MachineFunctionPass(ID) {
    101       initializeStackSlotColoringPass(*PassRegistry::getPassRegistry());
    102     }
    103 
    104     void getAnalysisUsage(AnalysisUsage &AU) const override {
    105       AU.setPreservesCFG();
    106       AU.addRequired<SlotIndexes>();
    107       AU.addPreserved<SlotIndexes>();
    108       AU.addRequired<LiveStacks>();
    109       AU.addRequired<MachineBlockFrequencyInfo>();
    110       AU.addPreserved<MachineBlockFrequencyInfo>();
    111       AU.addPreservedID(MachineDominatorsID);
    112       MachineFunctionPass::getAnalysisUsage(AU);
    113     }
    114 
    115     bool runOnMachineFunction(MachineFunction &MF) override;
    116 
    117   private:
    118     void InitializeSlots();
    119     void ScanForSpillSlotRefs(MachineFunction &MF);
    120     bool OverlapWithAssignments(LiveInterval *li, int Color) const;
    121     int ColorSlot(LiveInterval *li);
    122     bool ColorSlots(MachineFunction &MF);
    123     void RewriteInstruction(MachineInstr &MI, SmallVectorImpl<int> &SlotMapping,
    124                             MachineFunction &MF);
    125     bool RemoveDeadStores(MachineBasicBlock* MBB);
    126   };
    127 
    128 } // end anonymous namespace
    129 
    130 char StackSlotColoring::ID = 0;
    131 
    132 char &llvm::StackSlotColoringID = StackSlotColoring::ID;
    133 
    134 INITIALIZE_PASS_BEGIN(StackSlotColoring, DEBUG_TYPE,
    135                 "Stack Slot Coloring", false, false)
    136 INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
    137 INITIALIZE_PASS_DEPENDENCY(LiveStacks)
    138 INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
    139 INITIALIZE_PASS_END(StackSlotColoring, DEBUG_TYPE,
    140                 "Stack Slot Coloring", false, false)
    141 
    142 namespace {
    143 
    144 // IntervalSorter - Comparison predicate that sort live intervals by
    145 // their weight.
    146 struct IntervalSorter {
    147   bool operator()(LiveInterval* LHS, LiveInterval* RHS) const {
    148     return LHS->weight() > RHS->weight();
    149   }
    150 };
    151 
    152 } // end anonymous namespace
    153 
    154 /// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot
    155 /// references and update spill slot weights.
    156 void StackSlotColoring::ScanForSpillSlotRefs(MachineFunction &MF) {
    157   SSRefs.resize(MFI->getObjectIndexEnd());
    158 
    159   // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands.
    160   for (MachineBasicBlock &MBB : MF) {
    161     for (MachineInstr &MI : MBB) {
    162       for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
    163         MachineOperand &MO = MI.getOperand(i);
    164         if (!MO.isFI())
    165           continue;
    166         int FI = MO.getIndex();
    167         if (FI < 0)
    168           continue;
    169         if (!LS->hasInterval(FI))
    170           continue;
    171         LiveInterval &li = LS->getInterval(FI);
    172         if (!MI.isDebugValue())
    173           li.incrementWeight(
    174               LiveIntervals::getSpillWeight(false, true, MBFI, MI));
    175       }
    176       for (MachineInstr::mmo_iterator MMOI = MI.memoperands_begin(),
    177                                       EE = MI.memoperands_end();
    178            MMOI != EE; ++MMOI) {
    179         MachineMemOperand *MMO = *MMOI;
    180         if (const FixedStackPseudoSourceValue *FSV =
    181             dyn_cast_or_null<FixedStackPseudoSourceValue>(
    182                 MMO->getPseudoValue())) {
    183           int FI = FSV->getFrameIndex();
    184           if (FI >= 0)
    185             SSRefs[FI].push_back(MMO);
    186         }
    187       }
    188     }
    189   }
    190 }
    191 
    192 /// InitializeSlots - Process all spill stack slot liveintervals and add them
    193 /// to a sorted (by weight) list.
    194 void StackSlotColoring::InitializeSlots() {
    195   int LastFI = MFI->getObjectIndexEnd();
    196 
    197   // There is always at least one stack ID.
    198   AllColors.resize(1);
    199   UsedColors.resize(1);
    200 
    201   OrigAlignments.resize(LastFI);
    202   OrigSizes.resize(LastFI);
    203   AllColors[0].resize(LastFI);
    204   UsedColors[0].resize(LastFI);
    205   Assignments.resize(LastFI);
    206 
    207   using Pair = std::iterator_traits<LiveStacks::iterator>::value_type;
    208 
    209   SmallVector<Pair *, 16> Intervals;
    210 
    211   Intervals.reserve(LS->getNumIntervals());
    212   for (auto &I : *LS)
    213     Intervals.push_back(&I);
    214   llvm::sort(Intervals,
    215              [](Pair *LHS, Pair *RHS) { return LHS->first < RHS->first; });
    216 
    217   // Gather all spill slots into a list.
    218   LLVM_DEBUG(dbgs() << "Spill slot intervals:\n");
    219   for (auto *I : Intervals) {
    220     LiveInterval &li = I->second;
    221     LLVM_DEBUG(li.dump());
    222     int FI = Register::stackSlot2Index(li.reg());
    223     if (MFI->isDeadObjectIndex(FI))
    224       continue;
    225 
    226     SSIntervals.push_back(&li);
    227     OrigAlignments[FI] = MFI->getObjectAlign(FI);
    228     OrigSizes[FI]      = MFI->getObjectSize(FI);
    229 
    230     auto StackID = MFI->getStackID(FI);
    231     if (StackID != 0) {
    232       AllColors.resize(StackID + 1);
    233       UsedColors.resize(StackID + 1);
    234       AllColors[StackID].resize(LastFI);
    235       UsedColors[StackID].resize(LastFI);
    236     }
    237 
    238     AllColors[StackID].set(FI);
    239   }
    240   LLVM_DEBUG(dbgs() << '\n');
    241 
    242   // Sort them by weight.
    243   llvm::stable_sort(SSIntervals, IntervalSorter());
    244 
    245   NextColors.resize(AllColors.size());
    246 
    247   // Get first "color".
    248   for (unsigned I = 0, E = AllColors.size(); I != E; ++I)
    249     NextColors[I] = AllColors[I].find_first();
    250 }
    251 
    252 /// OverlapWithAssignments - Return true if LiveInterval overlaps with any
    253 /// LiveIntervals that have already been assigned to the specified color.
    254 bool
    255 StackSlotColoring::OverlapWithAssignments(LiveInterval *li, int Color) const {
    256   const SmallVectorImpl<LiveInterval *> &OtherLIs = Assignments[Color];
    257   for (unsigned i = 0, e = OtherLIs.size(); i != e; ++i) {
    258     LiveInterval *OtherLI = OtherLIs[i];
    259     if (OtherLI->overlaps(*li))
    260       return true;
    261   }
    262   return false;
    263 }
    264 
    265 /// ColorSlot - Assign a "color" (stack slot) to the specified stack slot.
    266 int StackSlotColoring::ColorSlot(LiveInterval *li) {
    267   int Color = -1;
    268   bool Share = false;
    269   int FI = Register::stackSlot2Index(li->reg());
    270   uint8_t StackID = MFI->getStackID(FI);
    271 
    272   if (!DisableSharing) {
    273 
    274     // Check if it's possible to reuse any of the used colors.
    275     Color = UsedColors[StackID].find_first();
    276     while (Color != -1) {
    277       if (!OverlapWithAssignments(li, Color)) {
    278         Share = true;
    279         ++NumEliminated;
    280         break;
    281       }
    282       Color = UsedColors[StackID].find_next(Color);
    283     }
    284   }
    285 
    286   if (Color != -1 && MFI->getStackID(Color) != MFI->getStackID(FI)) {
    287     LLVM_DEBUG(dbgs() << "cannot share FIs with different stack IDs\n");
    288     Share = false;
    289   }
    290 
    291   // Assign it to the first available color (assumed to be the best) if it's
    292   // not possible to share a used color with other objects.
    293   if (!Share) {
    294     assert(NextColors[StackID] != -1 && "No more spill slots?");
    295     Color = NextColors[StackID];
    296     UsedColors[StackID].set(Color);
    297     NextColors[StackID] = AllColors[StackID].find_next(NextColors[StackID]);
    298   }
    299 
    300   assert(MFI->getStackID(Color) == MFI->getStackID(FI));
    301 
    302   // Record the assignment.
    303   Assignments[Color].push_back(li);
    304   LLVM_DEBUG(dbgs() << "Assigning fi#" << FI << " to fi#" << Color << "\n");
    305 
    306   // Change size and alignment of the allocated slot. If there are multiple
    307   // objects sharing the same slot, then make sure the size and alignment
    308   // are large enough for all.
    309   Align Alignment = OrigAlignments[FI];
    310   if (!Share || Alignment > MFI->getObjectAlign(Color))
    311     MFI->setObjectAlignment(Color, Alignment);
    312   int64_t Size = OrigSizes[FI];
    313   if (!Share || Size > MFI->getObjectSize(Color))
    314     MFI->setObjectSize(Color, Size);
    315   return Color;
    316 }
    317 
    318 /// Colorslots - Color all spill stack slots and rewrite all frameindex machine
    319 /// operands in the function.
    320 bool StackSlotColoring::ColorSlots(MachineFunction &MF) {
    321   unsigned NumObjs = MFI->getObjectIndexEnd();
    322   SmallVector<int, 16> SlotMapping(NumObjs, -1);
    323   SmallVector<float, 16> SlotWeights(NumObjs, 0.0);
    324   SmallVector<SmallVector<int, 4>, 16> RevMap(NumObjs);
    325   BitVector UsedColors(NumObjs);
    326 
    327   LLVM_DEBUG(dbgs() << "Color spill slot intervals:\n");
    328   bool Changed = false;
    329   for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) {
    330     LiveInterval *li = SSIntervals[i];
    331     int SS = Register::stackSlot2Index(li->reg());
    332     int NewSS = ColorSlot(li);
    333     assert(NewSS >= 0 && "Stack coloring failed?");
    334     SlotMapping[SS] = NewSS;
    335     RevMap[NewSS].push_back(SS);
    336     SlotWeights[NewSS] += li->weight();
    337     UsedColors.set(NewSS);
    338     Changed |= (SS != NewSS);
    339   }
    340 
    341   LLVM_DEBUG(dbgs() << "\nSpill slots after coloring:\n");
    342   for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) {
    343     LiveInterval *li = SSIntervals[i];
    344     int SS = Register::stackSlot2Index(li->reg());
    345     li->setWeight(SlotWeights[SS]);
    346   }
    347   // Sort them by new weight.
    348   llvm::stable_sort(SSIntervals, IntervalSorter());
    349 
    350 #ifndef NDEBUG
    351   for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i)
    352     LLVM_DEBUG(SSIntervals[i]->dump());
    353   LLVM_DEBUG(dbgs() << '\n');
    354 #endif
    355 
    356   if (!Changed)
    357     return false;
    358 
    359   // Rewrite all MachineMemOperands.
    360   for (unsigned SS = 0, SE = SSRefs.size(); SS != SE; ++SS) {
    361     int NewFI = SlotMapping[SS];
    362     if (NewFI == -1 || (NewFI == (int)SS))
    363       continue;
    364 
    365     const PseudoSourceValue *NewSV = MF.getPSVManager().getFixedStack(NewFI);
    366     SmallVectorImpl<MachineMemOperand *> &RefMMOs = SSRefs[SS];
    367     for (unsigned i = 0, e = RefMMOs.size(); i != e; ++i)
    368       RefMMOs[i]->setValue(NewSV);
    369   }
    370 
    371   // Rewrite all MO_FrameIndex operands.  Look for dead stores.
    372   for (MachineBasicBlock &MBB : MF) {
    373     for (MachineInstr &MI : MBB)
    374       RewriteInstruction(MI, SlotMapping, MF);
    375     RemoveDeadStores(&MBB);
    376   }
    377 
    378   // Delete unused stack slots.
    379   for (int StackID = 0, E = AllColors.size(); StackID != E; ++StackID) {
    380     int NextColor = NextColors[StackID];
    381     while (NextColor != -1) {
    382       LLVM_DEBUG(dbgs() << "Removing unused stack object fi#" << NextColor << "\n");
    383       MFI->RemoveStackObject(NextColor);
    384       NextColor = AllColors[StackID].find_next(NextColor);
    385     }
    386   }
    387 
    388   return true;
    389 }
    390 
    391 /// RewriteInstruction - Rewrite specified instruction by replacing references
    392 /// to old frame index with new one.
    393 void StackSlotColoring::RewriteInstruction(MachineInstr &MI,
    394                                            SmallVectorImpl<int> &SlotMapping,
    395                                            MachineFunction &MF) {
    396   // Update the operands.
    397   for (unsigned i = 0, ee = MI.getNumOperands(); i != ee; ++i) {
    398     MachineOperand &MO = MI.getOperand(i);
    399     if (!MO.isFI())
    400       continue;
    401     int OldFI = MO.getIndex();
    402     if (OldFI < 0)
    403       continue;
    404     int NewFI = SlotMapping[OldFI];
    405     if (NewFI == -1 || NewFI == OldFI)
    406       continue;
    407 
    408     assert(MFI->getStackID(OldFI) == MFI->getStackID(NewFI));
    409     MO.setIndex(NewFI);
    410   }
    411 
    412   // The MachineMemOperands have already been updated.
    413 }
    414 
    415 /// RemoveDeadStores - Scan through a basic block and look for loads followed
    416 /// by stores.  If they're both using the same stack slot, then the store is
    417 /// definitely dead.  This could obviously be much more aggressive (consider
    418 /// pairs with instructions between them), but such extensions might have a
    419 /// considerable compile time impact.
    420 bool StackSlotColoring::RemoveDeadStores(MachineBasicBlock* MBB) {
    421   // FIXME: This could be much more aggressive, but we need to investigate
    422   // the compile time impact of doing so.
    423   bool changed = false;
    424 
    425   SmallVector<MachineInstr*, 4> toErase;
    426 
    427   for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
    428        I != E; ++I) {
    429     if (DCELimit != -1 && (int)NumDead >= DCELimit)
    430       break;
    431     int FirstSS, SecondSS;
    432     if (TII->isStackSlotCopy(*I, FirstSS, SecondSS) && FirstSS == SecondSS &&
    433         FirstSS != -1) {
    434       ++NumDead;
    435       changed = true;
    436       toErase.push_back(&*I);
    437       continue;
    438     }
    439 
    440     MachineBasicBlock::iterator NextMI = std::next(I);
    441     MachineBasicBlock::iterator ProbableLoadMI = I;
    442 
    443     unsigned LoadReg = 0;
    444     unsigned StoreReg = 0;
    445     unsigned LoadSize = 0;
    446     unsigned StoreSize = 0;
    447     if (!(LoadReg = TII->isLoadFromStackSlot(*I, FirstSS, LoadSize)))
    448       continue;
    449     // Skip the ...pseudo debugging... instructions between a load and store.
    450     while ((NextMI != E) && NextMI->isDebugInstr()) {
    451       ++NextMI;
    452       ++I;
    453     }
    454     if (NextMI == E) continue;
    455     if (!(StoreReg = TII->isStoreToStackSlot(*NextMI, SecondSS, StoreSize)))
    456       continue;
    457     if (FirstSS != SecondSS || LoadReg != StoreReg || FirstSS == -1 ||
    458         LoadSize != StoreSize)
    459       continue;
    460 
    461     ++NumDead;
    462     changed = true;
    463 
    464     if (NextMI->findRegisterUseOperandIdx(LoadReg, true, nullptr) != -1) {
    465       ++NumDead;
    466       toErase.push_back(&*ProbableLoadMI);
    467     }
    468 
    469     toErase.push_back(&*NextMI);
    470     ++I;
    471   }
    472 
    473   for (MachineInstr *MI : toErase)
    474     MI->eraseFromParent();
    475 
    476   return changed;
    477 }
    478 
    479 bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) {
    480   LLVM_DEBUG({
    481     dbgs() << "********** Stack Slot Coloring **********\n"
    482            << "********** Function: " << MF.getName() << '\n';
    483   });
    484 
    485   if (skipFunction(MF.getFunction()))
    486     return false;
    487 
    488   MFI = &MF.getFrameInfo();
    489   TII = MF.getSubtarget().getInstrInfo();
    490   LS = &getAnalysis<LiveStacks>();
    491   MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
    492 
    493   bool Changed = false;
    494 
    495   unsigned NumSlots = LS->getNumIntervals();
    496   if (NumSlots == 0)
    497     // Nothing to do!
    498     return false;
    499 
    500   // If there are calls to setjmp or sigsetjmp, don't perform stack slot
    501   // coloring. The stack could be modified before the longjmp is executed,
    502   // resulting in the wrong value being used afterwards. (See
    503   // <rdar://problem/8007500>.)
    504   if (MF.exposesReturnsTwice())
    505     return false;
    506 
    507   // Gather spill slot references
    508   ScanForSpillSlotRefs(MF);
    509   InitializeSlots();
    510   Changed = ColorSlots(MF);
    511 
    512   for (int &Next : NextColors)
    513     Next = -1;
    514 
    515   SSIntervals.clear();
    516   for (unsigned i = 0, e = SSRefs.size(); i != e; ++i)
    517     SSRefs[i].clear();
    518   SSRefs.clear();
    519   OrigAlignments.clear();
    520   OrigSizes.clear();
    521   AllColors.clear();
    522   UsedColors.clear();
    523   for (unsigned i = 0, e = Assignments.size(); i != e; ++i)
    524     Assignments[i].clear();
    525   Assignments.clear();
    526 
    527   return Changed;
    528 }
    529