12cab237bSDimitry Andric //===- StackSlotColoring.cpp - Stack slot coloring pass. ------------------===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky //                     The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
10f22ef01cSRoman Divacky // This file implements the stack slot coloring pass.
11f22ef01cSRoman Divacky //
12f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
13f22ef01cSRoman Divacky 
14139f7f9bSDimitry Andric #include "llvm/ADT/BitVector.h"
15139f7f9bSDimitry Andric #include "llvm/ADT/SmallVector.h"
16139f7f9bSDimitry Andric #include "llvm/ADT/Statistic.h"
172cab237bSDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
182cab237bSDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
19da09e106SDimitry Andric #include "llvm/CodeGen/LiveStacks.h"
202cab237bSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
21f785676fSDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
22f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineFrameInfo.h"
232cab237bSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
242cab237bSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
252cab237bSDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
26f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineMemOperand.h"
272cab237bSDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
28db17bf38SDimitry Andric #include "llvm/CodeGen/Passes.h"
29f22ef01cSRoman Divacky #include "llvm/CodeGen/PseudoSourceValue.h"
302cab237bSDimitry Andric #include "llvm/CodeGen/SlotIndexes.h"
312cab237bSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
322cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
332cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
342cab237bSDimitry Andric #include "llvm/Pass.h"
352cab237bSDimitry Andric #include "llvm/Support/Casting.h"
36f22ef01cSRoman Divacky #include "llvm/Support/CommandLine.h"
37f22ef01cSRoman Divacky #include "llvm/Support/Debug.h"
38f785676fSDimitry Andric #include "llvm/Support/raw_ostream.h"
392cab237bSDimitry Andric #include <algorithm>
402cab237bSDimitry Andric #include <cassert>
412cab237bSDimitry Andric #include <cstdint>
422cab237bSDimitry Andric #include <iterator>
43f22ef01cSRoman Divacky #include <vector>
442cab237bSDimitry Andric 
45f22ef01cSRoman Divacky using namespace llvm;
46f22ef01cSRoman Divacky 
47302affcbSDimitry Andric #define DEBUG_TYPE "stack-slot-coloring"
4891bc56edSDimitry Andric 
49f22ef01cSRoman Divacky static cl::opt<bool>
50f22ef01cSRoman Divacky DisableSharing("no-stack-slot-sharing",
51f22ef01cSRoman Divacky              cl::init(false), cl::Hidden,
52f22ef01cSRoman Divacky              cl::desc("Suppress slot sharing during stack coloring"));
53f22ef01cSRoman Divacky 
54f22ef01cSRoman Divacky static cl::opt<int> DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden);
55f22ef01cSRoman Divacky 
56f22ef01cSRoman Divacky STATISTIC(NumEliminated, "Number of stack slots eliminated due to coloring");
57f22ef01cSRoman Divacky STATISTIC(NumDead,       "Number of trivially dead stack accesses eliminated");
58f22ef01cSRoman Divacky 
59f22ef01cSRoman Divacky namespace {
602cab237bSDimitry Andric 
61f22ef01cSRoman Divacky   class StackSlotColoring : public MachineFunctionPass {
62f22ef01cSRoman Divacky     LiveStacks* LS;
63f22ef01cSRoman Divacky     MachineFrameInfo *MFI;
64f22ef01cSRoman Divacky     const TargetInstrInfo  *TII;
65f785676fSDimitry Andric     const MachineBlockFrequencyInfo *MBFI;
66f22ef01cSRoman Divacky 
67f22ef01cSRoman Divacky     // SSIntervals - Spill slot intervals.
68f22ef01cSRoman Divacky     std::vector<LiveInterval*> SSIntervals;
69f22ef01cSRoman Divacky 
70f785676fSDimitry Andric     // SSRefs - Keep a list of MachineMemOperands for each spill slot.
71f785676fSDimitry Andric     // MachineMemOperands can be shared between instructions, so we need
72f785676fSDimitry Andric     // to be careful that renames like [FI0, FI1] -> [FI1, FI2] do not
73f785676fSDimitry Andric     // become FI0 -> FI1 -> FI2.
74f785676fSDimitry Andric     SmallVector<SmallVector<MachineMemOperand *, 8>, 16> SSRefs;
75f22ef01cSRoman Divacky 
76f22ef01cSRoman Divacky     // OrigAlignments - Alignments of stack objects before coloring.
77f22ef01cSRoman Divacky     SmallVector<unsigned, 16> OrigAlignments;
78f22ef01cSRoman Divacky 
79f22ef01cSRoman Divacky     // OrigSizes - Sizess of stack objects before coloring.
80f22ef01cSRoman Divacky     SmallVector<unsigned, 16> OrigSizes;
81f22ef01cSRoman Divacky 
82f22ef01cSRoman Divacky     // AllColors - If index is set, it's a spill slot, i.e. color.
83f22ef01cSRoman Divacky     // FIXME: This assumes PEI locate spill slot with smaller indices
84f22ef01cSRoman Divacky     // closest to stack pointer / frame pointer. Therefore, smaller
854ba319b5SDimitry Andric     // index == better color. This is per stack ID.
864ba319b5SDimitry Andric     SmallVector<BitVector, 2> AllColors;
87f22ef01cSRoman Divacky 
884ba319b5SDimitry Andric     // NextColor - Next "color" that's not yet used. This is per stack ID.
894ba319b5SDimitry Andric     SmallVector<int, 2> NextColors = { -1 };
90f22ef01cSRoman Divacky 
914ba319b5SDimitry Andric     // UsedColors - "Colors" that have been assigned. This is per stack ID
924ba319b5SDimitry Andric     SmallVector<BitVector, 2> UsedColors;
93f22ef01cSRoman Divacky 
94f22ef01cSRoman Divacky     // Assignments - Color to intervals mapping.
95f22ef01cSRoman Divacky     SmallVector<SmallVector<LiveInterval*,4>, 16> Assignments;
96f22ef01cSRoman Divacky 
97f22ef01cSRoman Divacky   public:
98f22ef01cSRoman Divacky     static char ID; // Pass identification
992cab237bSDimitry Andric 
StackSlotColoring()1002cab237bSDimitry Andric     StackSlotColoring() : MachineFunctionPass(ID) {
1012754fe60SDimitry Andric       initializeStackSlotColoringPass(*PassRegistry::getPassRegistry());
1022754fe60SDimitry Andric     }
103f22ef01cSRoman Divacky 
getAnalysisUsage(AnalysisUsage & AU) const10491bc56edSDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
105f22ef01cSRoman Divacky       AU.setPreservesCFG();
106f22ef01cSRoman Divacky       AU.addRequired<SlotIndexes>();
107f22ef01cSRoman Divacky       AU.addPreserved<SlotIndexes>();
108f22ef01cSRoman Divacky       AU.addRequired<LiveStacks>();
109f785676fSDimitry Andric       AU.addRequired<MachineBlockFrequencyInfo>();
110f785676fSDimitry Andric       AU.addPreserved<MachineBlockFrequencyInfo>();
111f22ef01cSRoman Divacky       AU.addPreservedID(MachineDominatorsID);
112f22ef01cSRoman Divacky       MachineFunctionPass::getAnalysisUsage(AU);
113f22ef01cSRoman Divacky     }
114f22ef01cSRoman Divacky 
11591bc56edSDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
116f22ef01cSRoman Divacky 
117f22ef01cSRoman Divacky   private:
118f22ef01cSRoman Divacky     void InitializeSlots();
119f22ef01cSRoman Divacky     void ScanForSpillSlotRefs(MachineFunction &MF);
120f22ef01cSRoman Divacky     bool OverlapWithAssignments(LiveInterval *li, int Color) const;
121f22ef01cSRoman Divacky     int ColorSlot(LiveInterval *li);
122f22ef01cSRoman Divacky     bool ColorSlots(MachineFunction &MF);
1233ca95b02SDimitry Andric     void RewriteInstruction(MachineInstr &MI, SmallVectorImpl<int> &SlotMapping,
124f22ef01cSRoman Divacky                             MachineFunction &MF);
125f22ef01cSRoman Divacky     bool RemoveDeadStores(MachineBasicBlock* MBB);
126f22ef01cSRoman Divacky   };
1272cab237bSDimitry Andric 
128f22ef01cSRoman Divacky } // end anonymous namespace
129f22ef01cSRoman Divacky 
130f22ef01cSRoman Divacky char StackSlotColoring::ID = 0;
1312cab237bSDimitry Andric 
132dff0c46cSDimitry Andric char &llvm::StackSlotColoringID = StackSlotColoring::ID;
133f22ef01cSRoman Divacky 
134302affcbSDimitry Andric INITIALIZE_PASS_BEGIN(StackSlotColoring, DEBUG_TYPE,
1352754fe60SDimitry Andric                 "Stack Slot Coloring", false, false)
1362754fe60SDimitry Andric INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
1372754fe60SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveStacks)
1382754fe60SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
139302affcbSDimitry Andric INITIALIZE_PASS_END(StackSlotColoring, DEBUG_TYPE,
1402754fe60SDimitry Andric                 "Stack Slot Coloring", false, false)
141f22ef01cSRoman Divacky 
142f22ef01cSRoman Divacky namespace {
1432cab237bSDimitry Andric 
144f22ef01cSRoman Divacky // IntervalSorter - Comparison predicate that sort live intervals by
145f22ef01cSRoman Divacky // their weight.
146f22ef01cSRoman Divacky struct IntervalSorter {
operator ()__anona4ed5fee0211::IntervalSorter147f22ef01cSRoman Divacky   bool operator()(LiveInterval* LHS, LiveInterval* RHS) const {
148f22ef01cSRoman Divacky     return LHS->weight > RHS->weight;
149f22ef01cSRoman Divacky   }
150f22ef01cSRoman Divacky };
1512cab237bSDimitry Andric 
1522cab237bSDimitry Andric } // end anonymous namespace
153f22ef01cSRoman Divacky 
154f22ef01cSRoman Divacky /// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot
155f22ef01cSRoman Divacky /// references and update spill slot weights.
ScanForSpillSlotRefs(MachineFunction & MF)156f22ef01cSRoman Divacky void StackSlotColoring::ScanForSpillSlotRefs(MachineFunction &MF) {
157f22ef01cSRoman Divacky   SSRefs.resize(MFI->getObjectIndexEnd());
158f22ef01cSRoman Divacky 
159f22ef01cSRoman Divacky   // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands.
160f22ef01cSRoman Divacky   for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end();
161f22ef01cSRoman Divacky        MBBI != E; ++MBBI) {
162f22ef01cSRoman Divacky     MachineBasicBlock *MBB = &*MBBI;
163f22ef01cSRoman Divacky     for (MachineBasicBlock::iterator MII = MBB->begin(), EE = MBB->end();
164f22ef01cSRoman Divacky          MII != EE; ++MII) {
1653ca95b02SDimitry Andric       MachineInstr &MI = *MII;
1663ca95b02SDimitry Andric       for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
1673ca95b02SDimitry Andric         MachineOperand &MO = MI.getOperand(i);
168f22ef01cSRoman Divacky         if (!MO.isFI())
169f22ef01cSRoman Divacky           continue;
170f22ef01cSRoman Divacky         int FI = MO.getIndex();
171f22ef01cSRoman Divacky         if (FI < 0)
172f22ef01cSRoman Divacky           continue;
173f22ef01cSRoman Divacky         if (!LS->hasInterval(FI))
174f22ef01cSRoman Divacky           continue;
175f22ef01cSRoman Divacky         LiveInterval &li = LS->getInterval(FI);
1763ca95b02SDimitry Andric         if (!MI.isDebugValue())
17791bc56edSDimitry Andric           li.weight += LiveIntervals::getSpillWeight(false, true, MBFI, MI);
178f785676fSDimitry Andric       }
1793ca95b02SDimitry Andric       for (MachineInstr::mmo_iterator MMOI = MI.memoperands_begin(),
1803ca95b02SDimitry Andric                                       EE = MI.memoperands_end();
1813ca95b02SDimitry Andric            MMOI != EE; ++MMOI) {
182f785676fSDimitry Andric         MachineMemOperand *MMO = *MMOI;
183f785676fSDimitry Andric         if (const FixedStackPseudoSourceValue *FSV =
18491bc56edSDimitry Andric             dyn_cast_or_null<FixedStackPseudoSourceValue>(
18591bc56edSDimitry Andric                 MMO->getPseudoValue())) {
186f785676fSDimitry Andric           int FI = FSV->getFrameIndex();
187f785676fSDimitry Andric           if (FI >= 0)
188f785676fSDimitry Andric             SSRefs[FI].push_back(MMO);
189f785676fSDimitry Andric         }
190f785676fSDimitry Andric       }
191f22ef01cSRoman Divacky     }
192f22ef01cSRoman Divacky   }
193f22ef01cSRoman Divacky }
194f22ef01cSRoman Divacky 
195f22ef01cSRoman Divacky /// InitializeSlots - Process all spill stack slot liveintervals and add them
196f22ef01cSRoman Divacky /// to a sorted (by weight) list.
InitializeSlots()197f22ef01cSRoman Divacky void StackSlotColoring::InitializeSlots() {
198f22ef01cSRoman Divacky   int LastFI = MFI->getObjectIndexEnd();
1994ba319b5SDimitry Andric 
2004ba319b5SDimitry Andric   // There is always at least one stack ID.
2014ba319b5SDimitry Andric   AllColors.resize(1);
2024ba319b5SDimitry Andric   UsedColors.resize(1);
2034ba319b5SDimitry Andric 
204f22ef01cSRoman Divacky   OrigAlignments.resize(LastFI);
205f22ef01cSRoman Divacky   OrigSizes.resize(LastFI);
2064ba319b5SDimitry Andric   AllColors[0].resize(LastFI);
2074ba319b5SDimitry Andric   UsedColors[0].resize(LastFI);
208f22ef01cSRoman Divacky   Assignments.resize(LastFI);
209f22ef01cSRoman Divacky 
2102cab237bSDimitry Andric   using Pair = std::iterator_traits<LiveStacks::iterator>::value_type;
2112cab237bSDimitry Andric 
212ff0cc061SDimitry Andric   SmallVector<Pair *, 16> Intervals;
2132cab237bSDimitry Andric 
214ff0cc061SDimitry Andric   Intervals.reserve(LS->getNumIntervals());
215ff0cc061SDimitry Andric   for (auto &I : *LS)
216ff0cc061SDimitry Andric     Intervals.push_back(&I);
217*b5893f02SDimitry Andric   llvm::sort(Intervals,
218ff0cc061SDimitry Andric              [](Pair *LHS, Pair *RHS) { return LHS->first < RHS->first; });
219ff0cc061SDimitry Andric 
220f22ef01cSRoman Divacky   // Gather all spill slots into a list.
2214ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Spill slot intervals:\n");
222ff0cc061SDimitry Andric   for (auto *I : Intervals) {
223ff0cc061SDimitry Andric     LiveInterval &li = I->second;
2244ba319b5SDimitry Andric     LLVM_DEBUG(li.dump());
2252754fe60SDimitry Andric     int FI = TargetRegisterInfo::stackSlot2Index(li.reg);
226f22ef01cSRoman Divacky     if (MFI->isDeadObjectIndex(FI))
227f22ef01cSRoman Divacky       continue;
2284ba319b5SDimitry Andric 
229f22ef01cSRoman Divacky     SSIntervals.push_back(&li);
230f22ef01cSRoman Divacky     OrigAlignments[FI] = MFI->getObjectAlignment(FI);
231f22ef01cSRoman Divacky     OrigSizes[FI]      = MFI->getObjectSize(FI);
2324ba319b5SDimitry Andric 
2334ba319b5SDimitry Andric     auto StackID = MFI->getStackID(FI);
2344ba319b5SDimitry Andric     if (StackID != 0) {
2354ba319b5SDimitry Andric       AllColors.resize(StackID + 1);
2364ba319b5SDimitry Andric       UsedColors.resize(StackID + 1);
2374ba319b5SDimitry Andric       AllColors[StackID].resize(LastFI);
2384ba319b5SDimitry Andric       UsedColors[StackID].resize(LastFI);
239f22ef01cSRoman Divacky     }
2404ba319b5SDimitry Andric 
2414ba319b5SDimitry Andric     AllColors[StackID].set(FI);
2424ba319b5SDimitry Andric   }
2434ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << '\n');
244f22ef01cSRoman Divacky 
245f22ef01cSRoman Divacky   // Sort them by weight.
246f22ef01cSRoman Divacky   std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter());
247f22ef01cSRoman Divacky 
2484ba319b5SDimitry Andric   NextColors.resize(AllColors.size());
2494ba319b5SDimitry Andric 
250f22ef01cSRoman Divacky   // Get first "color".
2514ba319b5SDimitry Andric   for (unsigned I = 0, E = AllColors.size(); I != E; ++I)
2524ba319b5SDimitry Andric     NextColors[I] = AllColors[I].find_first();
253f22ef01cSRoman Divacky }
254f22ef01cSRoman Divacky 
255f22ef01cSRoman Divacky /// OverlapWithAssignments - Return true if LiveInterval overlaps with any
256f22ef01cSRoman Divacky /// LiveIntervals that have already been assigned to the specified color.
257f22ef01cSRoman Divacky bool
OverlapWithAssignments(LiveInterval * li,int Color) const258f22ef01cSRoman Divacky StackSlotColoring::OverlapWithAssignments(LiveInterval *li, int Color) const {
259f785676fSDimitry Andric   const SmallVectorImpl<LiveInterval *> &OtherLIs = Assignments[Color];
260f22ef01cSRoman Divacky   for (unsigned i = 0, e = OtherLIs.size(); i != e; ++i) {
261f22ef01cSRoman Divacky     LiveInterval *OtherLI = OtherLIs[i];
262f22ef01cSRoman Divacky     if (OtherLI->overlaps(*li))
263f22ef01cSRoman Divacky       return true;
264f22ef01cSRoman Divacky   }
265f22ef01cSRoman Divacky   return false;
266f22ef01cSRoman Divacky }
267f22ef01cSRoman Divacky 
268f22ef01cSRoman Divacky /// ColorSlot - Assign a "color" (stack slot) to the specified stack slot.
ColorSlot(LiveInterval * li)269f22ef01cSRoman Divacky int StackSlotColoring::ColorSlot(LiveInterval *li) {
270f22ef01cSRoman Divacky   int Color = -1;
271f22ef01cSRoman Divacky   bool Share = false;
2722cab237bSDimitry Andric   int FI = TargetRegisterInfo::stackSlot2Index(li->reg);
2734ba319b5SDimitry Andric   uint8_t StackID = MFI->getStackID(FI);
2742cab237bSDimitry Andric 
275f22ef01cSRoman Divacky   if (!DisableSharing) {
2764ba319b5SDimitry Andric 
277f22ef01cSRoman Divacky     // Check if it's possible to reuse any of the used colors.
2784ba319b5SDimitry Andric     Color = UsedColors[StackID].find_first();
279f22ef01cSRoman Divacky     while (Color != -1) {
280f22ef01cSRoman Divacky       if (!OverlapWithAssignments(li, Color)) {
281f22ef01cSRoman Divacky         Share = true;
282f22ef01cSRoman Divacky         ++NumEliminated;
283f22ef01cSRoman Divacky         break;
284f22ef01cSRoman Divacky       }
2854ba319b5SDimitry Andric       Color = UsedColors[StackID].find_next(Color);
286f22ef01cSRoman Divacky     }
287f22ef01cSRoman Divacky   }
288f22ef01cSRoman Divacky 
2892cab237bSDimitry Andric   if (Color != -1 && MFI->getStackID(Color) != MFI->getStackID(FI)) {
2904ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "cannot share FIs with different stack IDs\n");
2912cab237bSDimitry Andric     Share = false;
2922cab237bSDimitry Andric   }
2932cab237bSDimitry Andric 
294f22ef01cSRoman Divacky   // Assign it to the first available color (assumed to be the best) if it's
295f22ef01cSRoman Divacky   // not possible to share a used color with other objects.
296f22ef01cSRoman Divacky   if (!Share) {
2974ba319b5SDimitry Andric     assert(NextColors[StackID] != -1 && "No more spill slots?");
2984ba319b5SDimitry Andric     Color = NextColors[StackID];
2994ba319b5SDimitry Andric     UsedColors[StackID].set(Color);
3004ba319b5SDimitry Andric     NextColors[StackID] = AllColors[StackID].find_next(NextColors[StackID]);
301f22ef01cSRoman Divacky   }
302f22ef01cSRoman Divacky 
3034ba319b5SDimitry Andric   assert(MFI->getStackID(Color) == MFI->getStackID(FI));
3044ba319b5SDimitry Andric 
305f22ef01cSRoman Divacky   // Record the assignment.
306f22ef01cSRoman Divacky   Assignments[Color].push_back(li);
3074ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Assigning fi#" << FI << " to fi#" << Color << "\n");
308f22ef01cSRoman Divacky 
309f22ef01cSRoman Divacky   // Change size and alignment of the allocated slot. If there are multiple
310f22ef01cSRoman Divacky   // objects sharing the same slot, then make sure the size and alignment
311f22ef01cSRoman Divacky   // are large enough for all.
312f22ef01cSRoman Divacky   unsigned Align = OrigAlignments[FI];
313f22ef01cSRoman Divacky   if (!Share || Align > MFI->getObjectAlignment(Color))
314f22ef01cSRoman Divacky     MFI->setObjectAlignment(Color, Align);
315f22ef01cSRoman Divacky   int64_t Size = OrigSizes[FI];
316f22ef01cSRoman Divacky   if (!Share || Size > MFI->getObjectSize(Color))
317f22ef01cSRoman Divacky     MFI->setObjectSize(Color, Size);
318f22ef01cSRoman Divacky   return Color;
319f22ef01cSRoman Divacky }
320f22ef01cSRoman Divacky 
321f22ef01cSRoman Divacky /// Colorslots - Color all spill stack slots and rewrite all frameindex machine
322f22ef01cSRoman Divacky /// operands in the function.
ColorSlots(MachineFunction & MF)323f22ef01cSRoman Divacky bool StackSlotColoring::ColorSlots(MachineFunction &MF) {
324f22ef01cSRoman Divacky   unsigned NumObjs = MFI->getObjectIndexEnd();
325f22ef01cSRoman Divacky   SmallVector<int, 16> SlotMapping(NumObjs, -1);
326f22ef01cSRoman Divacky   SmallVector<float, 16> SlotWeights(NumObjs, 0.0);
327f22ef01cSRoman Divacky   SmallVector<SmallVector<int, 4>, 16> RevMap(NumObjs);
328f22ef01cSRoman Divacky   BitVector UsedColors(NumObjs);
329f22ef01cSRoman Divacky 
3304ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Color spill slot intervals:\n");
331f22ef01cSRoman Divacky   bool Changed = false;
332f22ef01cSRoman Divacky   for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) {
333f22ef01cSRoman Divacky     LiveInterval *li = SSIntervals[i];
3342754fe60SDimitry Andric     int SS = TargetRegisterInfo::stackSlot2Index(li->reg);
335f22ef01cSRoman Divacky     int NewSS = ColorSlot(li);
336f22ef01cSRoman Divacky     assert(NewSS >= 0 && "Stack coloring failed?");
337f22ef01cSRoman Divacky     SlotMapping[SS] = NewSS;
338f22ef01cSRoman Divacky     RevMap[NewSS].push_back(SS);
339f22ef01cSRoman Divacky     SlotWeights[NewSS] += li->weight;
340f22ef01cSRoman Divacky     UsedColors.set(NewSS);
341f22ef01cSRoman Divacky     Changed |= (SS != NewSS);
342f22ef01cSRoman Divacky   }
343f22ef01cSRoman Divacky 
3444ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "\nSpill slots after coloring:\n");
345f22ef01cSRoman Divacky   for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) {
346f22ef01cSRoman Divacky     LiveInterval *li = SSIntervals[i];
3472754fe60SDimitry Andric     int SS = TargetRegisterInfo::stackSlot2Index(li->reg);
348f22ef01cSRoman Divacky     li->weight = SlotWeights[SS];
349f22ef01cSRoman Divacky   }
350f22ef01cSRoman Divacky   // Sort them by new weight.
351f22ef01cSRoman Divacky   std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter());
352f22ef01cSRoman Divacky 
353f22ef01cSRoman Divacky #ifndef NDEBUG
354f22ef01cSRoman Divacky   for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i)
3554ba319b5SDimitry Andric     LLVM_DEBUG(SSIntervals[i]->dump());
3564ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << '\n');
357f22ef01cSRoman Divacky #endif
358f22ef01cSRoman Divacky 
359f22ef01cSRoman Divacky   if (!Changed)
360f22ef01cSRoman Divacky     return false;
361f22ef01cSRoman Divacky 
362f785676fSDimitry Andric   // Rewrite all MachineMemOperands.
363f22ef01cSRoman Divacky   for (unsigned SS = 0, SE = SSRefs.size(); SS != SE; ++SS) {
364f22ef01cSRoman Divacky     int NewFI = SlotMapping[SS];
365dff0c46cSDimitry Andric     if (NewFI == -1 || (NewFI == (int)SS))
366f22ef01cSRoman Divacky       continue;
367f22ef01cSRoman Divacky 
3687d523365SDimitry Andric     const PseudoSourceValue *NewSV = MF.getPSVManager().getFixedStack(NewFI);
369f785676fSDimitry Andric     SmallVectorImpl<MachineMemOperand *> &RefMMOs = SSRefs[SS];
370f785676fSDimitry Andric     for (unsigned i = 0, e = RefMMOs.size(); i != e; ++i)
371f785676fSDimitry Andric       RefMMOs[i]->setValue(NewSV);
372f785676fSDimitry Andric   }
373f785676fSDimitry Andric 
374f785676fSDimitry Andric   // Rewrite all MO_FrameIndex operands.  Look for dead stores.
3753ca95b02SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
3763ca95b02SDimitry Andric     for (MachineInstr &MI : MBB)
3773ca95b02SDimitry Andric       RewriteInstruction(MI, SlotMapping, MF);
3783ca95b02SDimitry Andric     RemoveDeadStores(&MBB);
379f22ef01cSRoman Divacky   }
380f22ef01cSRoman Divacky 
381f22ef01cSRoman Divacky   // Delete unused stack slots.
3824ba319b5SDimitry Andric   for (int StackID = 0, E = AllColors.size(); StackID != E; ++StackID) {
3834ba319b5SDimitry Andric     int NextColor = NextColors[StackID];
384f22ef01cSRoman Divacky     while (NextColor != -1) {
3854ba319b5SDimitry Andric       LLVM_DEBUG(dbgs() << "Removing unused stack object fi#" << NextColor << "\n");
386f22ef01cSRoman Divacky       MFI->RemoveStackObject(NextColor);
3874ba319b5SDimitry Andric       NextColor = AllColors[StackID].find_next(NextColor);
3884ba319b5SDimitry Andric     }
389f22ef01cSRoman Divacky   }
390f22ef01cSRoman Divacky 
391f22ef01cSRoman Divacky   return true;
392f22ef01cSRoman Divacky }
393f22ef01cSRoman Divacky 
394f22ef01cSRoman Divacky /// RewriteInstruction - Rewrite specified instruction by replacing references
395f22ef01cSRoman Divacky /// to old frame index with new one.
RewriteInstruction(MachineInstr & MI,SmallVectorImpl<int> & SlotMapping,MachineFunction & MF)3963ca95b02SDimitry Andric void StackSlotColoring::RewriteInstruction(MachineInstr &MI,
397f785676fSDimitry Andric                                            SmallVectorImpl<int> &SlotMapping,
398f785676fSDimitry Andric                                            MachineFunction &MF) {
399f22ef01cSRoman Divacky   // Update the operands.
4003ca95b02SDimitry Andric   for (unsigned i = 0, ee = MI.getNumOperands(); i != ee; ++i) {
4013ca95b02SDimitry Andric     MachineOperand &MO = MI.getOperand(i);
402f22ef01cSRoman Divacky     if (!MO.isFI())
403f22ef01cSRoman Divacky       continue;
404f785676fSDimitry Andric     int OldFI = MO.getIndex();
405f785676fSDimitry Andric     if (OldFI < 0)
406f785676fSDimitry Andric       continue;
407f785676fSDimitry Andric     int NewFI = SlotMapping[OldFI];
408f785676fSDimitry Andric     if (NewFI == -1 || NewFI == OldFI)
409f22ef01cSRoman Divacky       continue;
4104ba319b5SDimitry Andric 
4114ba319b5SDimitry Andric     assert(MFI->getStackID(OldFI) == MFI->getStackID(NewFI));
412f22ef01cSRoman Divacky     MO.setIndex(NewFI);
413f22ef01cSRoman Divacky   }
414f22ef01cSRoman Divacky 
415f785676fSDimitry Andric   // The MachineMemOperands have already been updated.
416f22ef01cSRoman Divacky }
417f22ef01cSRoman Divacky 
418f22ef01cSRoman Divacky /// RemoveDeadStores - Scan through a basic block and look for loads followed
419f22ef01cSRoman Divacky /// by stores.  If they're both using the same stack slot, then the store is
420f22ef01cSRoman Divacky /// definitely dead.  This could obviously be much more aggressive (consider
421f22ef01cSRoman Divacky /// pairs with instructions between them), but such extensions might have a
422f22ef01cSRoman Divacky /// considerable compile time impact.
RemoveDeadStores(MachineBasicBlock * MBB)423f22ef01cSRoman Divacky bool StackSlotColoring::RemoveDeadStores(MachineBasicBlock* MBB) {
424f22ef01cSRoman Divacky   // FIXME: This could be much more aggressive, but we need to investigate
425f22ef01cSRoman Divacky   // the compile time impact of doing so.
426f22ef01cSRoman Divacky   bool changed = false;
427f22ef01cSRoman Divacky 
428f22ef01cSRoman Divacky   SmallVector<MachineInstr*, 4> toErase;
429f22ef01cSRoman Divacky 
430f22ef01cSRoman Divacky   for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
431f22ef01cSRoman Divacky        I != E; ++I) {
432f22ef01cSRoman Divacky     if (DCELimit != -1 && (int)NumDead >= DCELimit)
433f22ef01cSRoman Divacky       break;
434f785676fSDimitry Andric     int FirstSS, SecondSS;
4353ca95b02SDimitry Andric     if (TII->isStackSlotCopy(*I, FirstSS, SecondSS) && FirstSS == SecondSS &&
436f785676fSDimitry Andric         FirstSS != -1) {
437f785676fSDimitry Andric       ++NumDead;
438f785676fSDimitry Andric       changed = true;
4393ca95b02SDimitry Andric       toErase.push_back(&*I);
440f785676fSDimitry Andric       continue;
441f785676fSDimitry Andric     }
442f785676fSDimitry Andric 
44391bc56edSDimitry Andric     MachineBasicBlock::iterator NextMI = std::next(I);
44424e2fe98SDimitry Andric     MachineBasicBlock::iterator ProbableLoadMI = I;
445f22ef01cSRoman Divacky 
446f22ef01cSRoman Divacky     unsigned LoadReg = 0;
447f22ef01cSRoman Divacky     unsigned StoreReg = 0;
4484ba319b5SDimitry Andric     unsigned LoadSize = 0;
4494ba319b5SDimitry Andric     unsigned StoreSize = 0;
4504ba319b5SDimitry Andric     if (!(LoadReg = TII->isLoadFromStackSlot(*I, FirstSS, LoadSize)))
4513ca95b02SDimitry Andric       continue;
45224e2fe98SDimitry Andric     // Skip the ...pseudo debugging... instructions between a load and store.
4534ba319b5SDimitry Andric     while ((NextMI != E) && NextMI->isDebugInstr()) {
45424e2fe98SDimitry Andric       ++NextMI;
45524e2fe98SDimitry Andric       ++I;
45624e2fe98SDimitry Andric     }
45724e2fe98SDimitry Andric     if (NextMI == E) continue;
4584ba319b5SDimitry Andric     if (!(StoreReg = TII->isStoreToStackSlot(*NextMI, SecondSS, StoreSize)))
4593ca95b02SDimitry Andric       continue;
4604ba319b5SDimitry Andric     if (FirstSS != SecondSS || LoadReg != StoreReg || FirstSS == -1 ||
4614ba319b5SDimitry Andric         LoadSize != StoreSize)
4624ba319b5SDimitry Andric       continue;
463f22ef01cSRoman Divacky 
464f22ef01cSRoman Divacky     ++NumDead;
465f22ef01cSRoman Divacky     changed = true;
466f22ef01cSRoman Divacky 
46791bc56edSDimitry Andric     if (NextMI->findRegisterUseOperandIdx(LoadReg, true, nullptr) != -1) {
468f22ef01cSRoman Divacky       ++NumDead;
46924e2fe98SDimitry Andric       toErase.push_back(&*ProbableLoadMI);
470f22ef01cSRoman Divacky     }
471f22ef01cSRoman Divacky 
4723ca95b02SDimitry Andric     toErase.push_back(&*NextMI);
473f22ef01cSRoman Divacky     ++I;
474f22ef01cSRoman Divacky   }
475f22ef01cSRoman Divacky 
476f785676fSDimitry Andric   for (SmallVectorImpl<MachineInstr *>::iterator I = toErase.begin(),
477f22ef01cSRoman Divacky        E = toErase.end(); I != E; ++I)
478f22ef01cSRoman Divacky     (*I)->eraseFromParent();
479f22ef01cSRoman Divacky 
480f22ef01cSRoman Divacky   return changed;
481f22ef01cSRoman Divacky }
482f22ef01cSRoman Divacky 
runOnMachineFunction(MachineFunction & MF)483f22ef01cSRoman Divacky bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) {
4844ba319b5SDimitry Andric   LLVM_DEBUG({
485f22ef01cSRoman Divacky     dbgs() << "********** Stack Slot Coloring **********\n"
4863861d79fSDimitry Andric            << "********** Function: " << MF.getName() << '\n';
487f22ef01cSRoman Divacky   });
488f22ef01cSRoman Divacky 
4894ba319b5SDimitry Andric   if (skipFunction(MF.getFunction()))
4904ba319b5SDimitry Andric     return false;
4914ba319b5SDimitry Andric 
492d88c1a5aSDimitry Andric   MFI = &MF.getFrameInfo();
49339d628a0SDimitry Andric   TII = MF.getSubtarget().getInstrInfo();
494f22ef01cSRoman Divacky   LS = &getAnalysis<LiveStacks>();
495f785676fSDimitry Andric   MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
496f22ef01cSRoman Divacky 
497f22ef01cSRoman Divacky   bool Changed = false;
498f22ef01cSRoman Divacky 
499f22ef01cSRoman Divacky   unsigned NumSlots = LS->getNumIntervals();
500dff0c46cSDimitry Andric   if (NumSlots == 0)
501f22ef01cSRoman Divacky     // Nothing to do!
502f22ef01cSRoman Divacky     return false;
503f22ef01cSRoman Divacky 
504f22ef01cSRoman Divacky   // If there are calls to setjmp or sigsetjmp, don't perform stack slot
505f22ef01cSRoman Divacky   // coloring. The stack could be modified before the longjmp is executed,
506f22ef01cSRoman Divacky   // resulting in the wrong value being used afterwards. (See
507f22ef01cSRoman Divacky   // <rdar://problem/8007500>.)
508dff0c46cSDimitry Andric   if (MF.exposesReturnsTwice())
509f22ef01cSRoman Divacky     return false;
510f22ef01cSRoman Divacky 
511f22ef01cSRoman Divacky   // Gather spill slot references
512f22ef01cSRoman Divacky   ScanForSpillSlotRefs(MF);
513f22ef01cSRoman Divacky   InitializeSlots();
514f22ef01cSRoman Divacky   Changed = ColorSlots(MF);
515f22ef01cSRoman Divacky 
5164ba319b5SDimitry Andric   for (int &Next : NextColors)
5174ba319b5SDimitry Andric     Next = -1;
5184ba319b5SDimitry Andric 
519f22ef01cSRoman Divacky   SSIntervals.clear();
520f22ef01cSRoman Divacky   for (unsigned i = 0, e = SSRefs.size(); i != e; ++i)
521f22ef01cSRoman Divacky     SSRefs[i].clear();
522f22ef01cSRoman Divacky   SSRefs.clear();
523f22ef01cSRoman Divacky   OrigAlignments.clear();
524f22ef01cSRoman Divacky   OrigSizes.clear();
525f22ef01cSRoman Divacky   AllColors.clear();
526f22ef01cSRoman Divacky   UsedColors.clear();
527f22ef01cSRoman Divacky   for (unsigned i = 0, e = Assignments.size(); i != e; ++i)
528f22ef01cSRoman Divacky     Assignments[i].clear();
529f22ef01cSRoman Divacky   Assignments.clear();
530f22ef01cSRoman Divacky 
531f22ef01cSRoman Divacky   return Changed;
532f22ef01cSRoman Divacky }
533