LLVM  4.0.0
StackSlotColoring.cpp
Go to the documentation of this file.
1 //===-- StackSlotColoring.cpp - Stack slot coloring pass. -----------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the stack slot coloring pass.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/CodeGen/Passes.h"
15 #include "llvm/ADT/BitVector.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/Statistic.h"
26 #include "llvm/IR/Module.h"
28 #include "llvm/Support/Debug.h"
32 #include <vector>
33 using namespace llvm;
34 
35 #define DEBUG_TYPE "stackslotcoloring"
36 
37 static cl::opt<bool>
38 DisableSharing("no-stack-slot-sharing",
39  cl::init(false), cl::Hidden,
40  cl::desc("Suppress slot sharing during stack coloring"));
41 
42 static cl::opt<int> DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden);
43 
44 STATISTIC(NumEliminated, "Number of stack slots eliminated due to coloring");
45 STATISTIC(NumDead, "Number of trivially dead stack accesses eliminated");
46 
47 namespace {
48  class StackSlotColoring : public MachineFunctionPass {
49  LiveStacks* LS;
50  MachineFrameInfo *MFI;
51  const TargetInstrInfo *TII;
52  const MachineBlockFrequencyInfo *MBFI;
53 
54  // SSIntervals - Spill slot intervals.
55  std::vector<LiveInterval*> SSIntervals;
56 
57  // SSRefs - Keep a list of MachineMemOperands for each spill slot.
58  // MachineMemOperands can be shared between instructions, so we need
59  // to be careful that renames like [FI0, FI1] -> [FI1, FI2] do not
60  // become FI0 -> FI1 -> FI2.
62 
63  // OrigAlignments - Alignments of stack objects before coloring.
64  SmallVector<unsigned, 16> OrigAlignments;
65 
66  // OrigSizes - Sizess of stack objects before coloring.
67  SmallVector<unsigned, 16> OrigSizes;
68 
69  // AllColors - If index is set, it's a spill slot, i.e. color.
70  // FIXME: This assumes PEI locate spill slot with smaller indices
71  // closest to stack pointer / frame pointer. Therefore, smaller
72  // index == better color.
73  BitVector AllColors;
74 
75  // NextColor - Next "color" that's not yet used.
76  int NextColor;
77 
78  // UsedColors - "Colors" that have been assigned.
79  BitVector UsedColors;
80 
81  // Assignments - Color to intervals mapping.
83 
84  public:
85  static char ID; // Pass identification
86  StackSlotColoring() :
87  MachineFunctionPass(ID), NextColor(-1) {
89  }
90 
91  void getAnalysisUsage(AnalysisUsage &AU) const override {
92  AU.setPreservesCFG();
95  AU.addRequired<LiveStacks>();
100  }
101 
102  bool runOnMachineFunction(MachineFunction &MF) override;
103 
104  private:
105  void InitializeSlots();
106  void ScanForSpillSlotRefs(MachineFunction &MF);
107  bool OverlapWithAssignments(LiveInterval *li, int Color) const;
108  int ColorSlot(LiveInterval *li);
109  bool ColorSlots(MachineFunction &MF);
110  void RewriteInstruction(MachineInstr &MI, SmallVectorImpl<int> &SlotMapping,
111  MachineFunction &MF);
112  bool RemoveDeadStores(MachineBasicBlock* MBB);
113  };
114 } // end anonymous namespace
115 
116 char StackSlotColoring::ID = 0;
118 
119 INITIALIZE_PASS_BEGIN(StackSlotColoring, "stack-slot-coloring",
120  "Stack Slot Coloring", false, false)
124 INITIALIZE_PASS_END(StackSlotColoring, "stack-slot-coloring",
125  "Stack Slot Coloring", false, false)
126 
127 namespace {
128  // IntervalSorter - Comparison predicate that sort live intervals by
129  // their weight.
130  struct IntervalSorter {
131  bool operator()(LiveInterval* LHS, LiveInterval* RHS) const {
132  return LHS->weight > RHS->weight;
133  }
134  };
135 }
136 
137 /// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot
138 /// references and update spill slot weights.
139 void StackSlotColoring::ScanForSpillSlotRefs(MachineFunction &MF) {
140  SSRefs.resize(MFI->getObjectIndexEnd());
141 
142  // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands.
143  for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end();
144  MBBI != E; ++MBBI) {
145  MachineBasicBlock *MBB = &*MBBI;
146  for (MachineBasicBlock::iterator MII = MBB->begin(), EE = MBB->end();
147  MII != EE; ++MII) {
148  MachineInstr &MI = *MII;
149  for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
150  MachineOperand &MO = MI.getOperand(i);
151  if (!MO.isFI())
152  continue;
153  int FI = MO.getIndex();
154  if (FI < 0)
155  continue;
156  if (!LS->hasInterval(FI))
157  continue;
158  LiveInterval &li = LS->getInterval(FI);
159  if (!MI.isDebugValue())
160  li.weight += LiveIntervals::getSpillWeight(false, true, MBFI, MI);
161  }
163  EE = MI.memoperands_end();
164  MMOI != EE; ++MMOI) {
165  MachineMemOperand *MMO = *MMOI;
166  if (const FixedStackPseudoSourceValue *FSV =
167  dyn_cast_or_null<FixedStackPseudoSourceValue>(
168  MMO->getPseudoValue())) {
169  int FI = FSV->getFrameIndex();
170  if (FI >= 0)
171  SSRefs[FI].push_back(MMO);
172  }
173  }
174  }
175  }
176 }
177 
178 /// InitializeSlots - Process all spill stack slot liveintervals and add them
179 /// to a sorted (by weight) list.
180 void StackSlotColoring::InitializeSlots() {
181  int LastFI = MFI->getObjectIndexEnd();
182  OrigAlignments.resize(LastFI);
183  OrigSizes.resize(LastFI);
184  AllColors.resize(LastFI);
185  UsedColors.resize(LastFI);
186  Assignments.resize(LastFI);
187 
188  typedef std::iterator_traits<LiveStacks::iterator>::value_type Pair;
190  Intervals.reserve(LS->getNumIntervals());
191  for (auto &I : *LS)
192  Intervals.push_back(&I);
193  std::sort(Intervals.begin(), Intervals.end(),
194  [](Pair *LHS, Pair *RHS) { return LHS->first < RHS->first; });
195 
196  // Gather all spill slots into a list.
197  DEBUG(dbgs() << "Spill slot intervals:\n");
198  for (auto *I : Intervals) {
199  LiveInterval &li = I->second;
200  DEBUG(li.dump());
202  if (MFI->isDeadObjectIndex(FI))
203  continue;
204  SSIntervals.push_back(&li);
205  OrigAlignments[FI] = MFI->getObjectAlignment(FI);
206  OrigSizes[FI] = MFI->getObjectSize(FI);
207  AllColors.set(FI);
208  }
209  DEBUG(dbgs() << '\n');
210 
211  // Sort them by weight.
212  std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter());
213 
214  // Get first "color".
215  NextColor = AllColors.find_first();
216 }
217 
218 /// OverlapWithAssignments - Return true if LiveInterval overlaps with any
219 /// LiveIntervals that have already been assigned to the specified color.
220 bool
221 StackSlotColoring::OverlapWithAssignments(LiveInterval *li, int Color) const {
222  const SmallVectorImpl<LiveInterval *> &OtherLIs = Assignments[Color];
223  for (unsigned i = 0, e = OtherLIs.size(); i != e; ++i) {
224  LiveInterval *OtherLI = OtherLIs[i];
225  if (OtherLI->overlaps(*li))
226  return true;
227  }
228  return false;
229 }
230 
231 /// ColorSlot - Assign a "color" (stack slot) to the specified stack slot.
232 ///
233 int StackSlotColoring::ColorSlot(LiveInterval *li) {
234  int Color = -1;
235  bool Share = false;
236  if (!DisableSharing) {
237  // Check if it's possible to reuse any of the used colors.
238  Color = UsedColors.find_first();
239  while (Color != -1) {
240  if (!OverlapWithAssignments(li, Color)) {
241  Share = true;
242  ++NumEliminated;
243  break;
244  }
245  Color = UsedColors.find_next(Color);
246  }
247  }
248 
249  // Assign it to the first available color (assumed to be the best) if it's
250  // not possible to share a used color with other objects.
251  if (!Share) {
252  assert(NextColor != -1 && "No more spill slots?");
253  Color = NextColor;
254  UsedColors.set(Color);
255  NextColor = AllColors.find_next(NextColor);
256  }
257 
258  // Record the assignment.
259  Assignments[Color].push_back(li);
261  DEBUG(dbgs() << "Assigning fi#" << FI << " to fi#" << Color << "\n");
262 
263  // Change size and alignment of the allocated slot. If there are multiple
264  // objects sharing the same slot, then make sure the size and alignment
265  // are large enough for all.
266  unsigned Align = OrigAlignments[FI];
267  if (!Share || Align > MFI->getObjectAlignment(Color))
268  MFI->setObjectAlignment(Color, Align);
269  int64_t Size = OrigSizes[FI];
270  if (!Share || Size > MFI->getObjectSize(Color))
271  MFI->setObjectSize(Color, Size);
272  return Color;
273 }
274 
275 /// Colorslots - Color all spill stack slots and rewrite all frameindex machine
276 /// operands in the function.
277 bool StackSlotColoring::ColorSlots(MachineFunction &MF) {
278  unsigned NumObjs = MFI->getObjectIndexEnd();
279  SmallVector<int, 16> SlotMapping(NumObjs, -1);
280  SmallVector<float, 16> SlotWeights(NumObjs, 0.0);
281  SmallVector<SmallVector<int, 4>, 16> RevMap(NumObjs);
282  BitVector UsedColors(NumObjs);
283 
284  DEBUG(dbgs() << "Color spill slot intervals:\n");
285  bool Changed = false;
286  for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) {
287  LiveInterval *li = SSIntervals[i];
289  int NewSS = ColorSlot(li);
290  assert(NewSS >= 0 && "Stack coloring failed?");
291  SlotMapping[SS] = NewSS;
292  RevMap[NewSS].push_back(SS);
293  SlotWeights[NewSS] += li->weight;
294  UsedColors.set(NewSS);
295  Changed |= (SS != NewSS);
296  }
297 
298  DEBUG(dbgs() << "\nSpill slots after coloring:\n");
299  for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) {
300  LiveInterval *li = SSIntervals[i];
302  li->weight = SlotWeights[SS];
303  }
304  // Sort them by new weight.
305  std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter());
306 
307 #ifndef NDEBUG
308  for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i)
309  DEBUG(SSIntervals[i]->dump());
310  DEBUG(dbgs() << '\n');
311 #endif
312 
313  if (!Changed)
314  return false;
315 
316  // Rewrite all MachineMemOperands.
317  for (unsigned SS = 0, SE = SSRefs.size(); SS != SE; ++SS) {
318  int NewFI = SlotMapping[SS];
319  if (NewFI == -1 || (NewFI == (int)SS))
320  continue;
321 
322  const PseudoSourceValue *NewSV = MF.getPSVManager().getFixedStack(NewFI);
323  SmallVectorImpl<MachineMemOperand *> &RefMMOs = SSRefs[SS];
324  for (unsigned i = 0, e = RefMMOs.size(); i != e; ++i)
325  RefMMOs[i]->setValue(NewSV);
326  }
327 
328  // Rewrite all MO_FrameIndex operands. Look for dead stores.
329  for (MachineBasicBlock &MBB : MF) {
330  for (MachineInstr &MI : MBB)
331  RewriteInstruction(MI, SlotMapping, MF);
332  RemoveDeadStores(&MBB);
333  }
334 
335  // Delete unused stack slots.
336  while (NextColor != -1) {
337  DEBUG(dbgs() << "Removing unused stack object fi#" << NextColor << "\n");
338  MFI->RemoveStackObject(NextColor);
339  NextColor = AllColors.find_next(NextColor);
340  }
341 
342  return true;
343 }
344 
345 /// RewriteInstruction - Rewrite specified instruction by replacing references
346 /// to old frame index with new one.
347 void StackSlotColoring::RewriteInstruction(MachineInstr &MI,
349  MachineFunction &MF) {
350  // Update the operands.
351  for (unsigned i = 0, ee = MI.getNumOperands(); i != ee; ++i) {
352  MachineOperand &MO = MI.getOperand(i);
353  if (!MO.isFI())
354  continue;
355  int OldFI = MO.getIndex();
356  if (OldFI < 0)
357  continue;
358  int NewFI = SlotMapping[OldFI];
359  if (NewFI == -1 || NewFI == OldFI)
360  continue;
361  MO.setIndex(NewFI);
362  }
363 
364  // The MachineMemOperands have already been updated.
365 }
366 
367 
368 /// RemoveDeadStores - Scan through a basic block and look for loads followed
369 /// by stores. If they're both using the same stack slot, then the store is
370 /// definitely dead. This could obviously be much more aggressive (consider
371 /// pairs with instructions between them), but such extensions might have a
372 /// considerable compile time impact.
373 bool StackSlotColoring::RemoveDeadStores(MachineBasicBlock* MBB) {
374  // FIXME: This could be much more aggressive, but we need to investigate
375  // the compile time impact of doing so.
376  bool changed = false;
377 
379 
380  for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
381  I != E; ++I) {
382  if (DCELimit != -1 && (int)NumDead >= DCELimit)
383  break;
384  int FirstSS, SecondSS;
385  if (TII->isStackSlotCopy(*I, FirstSS, SecondSS) && FirstSS == SecondSS &&
386  FirstSS != -1) {
387  ++NumDead;
388  changed = true;
389  toErase.push_back(&*I);
390  continue;
391  }
392 
393  MachineBasicBlock::iterator NextMI = std::next(I);
394  MachineBasicBlock::iterator ProbableLoadMI = I;
395 
396  unsigned LoadReg = 0;
397  unsigned StoreReg = 0;
398  if (!(LoadReg = TII->isLoadFromStackSlot(*I, FirstSS)))
399  continue;
400  // Skip the ...pseudo debugging... instructions between a load and store.
401  while ((NextMI != E) && NextMI->isDebugValue()) {
402  ++NextMI;
403  ++I;
404  }
405  if (NextMI == E) continue;
406  if (!(StoreReg = TII->isStoreToStackSlot(*NextMI, SecondSS)))
407  continue;
408  if (FirstSS != SecondSS || LoadReg != StoreReg || FirstSS == -1) continue;
409 
410  ++NumDead;
411  changed = true;
412 
413  if (NextMI->findRegisterUseOperandIdx(LoadReg, true, nullptr) != -1) {
414  ++NumDead;
415  toErase.push_back(&*ProbableLoadMI);
416  }
417 
418  toErase.push_back(&*NextMI);
419  ++I;
420  }
421 
423  E = toErase.end(); I != E; ++I)
424  (*I)->eraseFromParent();
425 
426  return changed;
427 }
428 
429 
430 bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) {
431  DEBUG({
432  dbgs() << "********** Stack Slot Coloring **********\n"
433  << "********** Function: " << MF.getName() << '\n';
434  });
435 
436  MFI = &MF.getFrameInfo();
437  TII = MF.getSubtarget().getInstrInfo();
438  LS = &getAnalysis<LiveStacks>();
439  MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
440 
441  bool Changed = false;
442 
443  unsigned NumSlots = LS->getNumIntervals();
444  if (NumSlots == 0)
445  // Nothing to do!
446  return false;
447 
448  // If there are calls to setjmp or sigsetjmp, don't perform stack slot
449  // coloring. The stack could be modified before the longjmp is executed,
450  // resulting in the wrong value being used afterwards. (See
451  // <rdar://problem/8007500>.)
452  if (MF.exposesReturnsTwice())
453  return false;
454 
455  // Gather spill slot references
456  ScanForSpillSlotRefs(MF);
457  InitializeSlots();
458  Changed = ColorSlots(MF);
459 
460  NextColor = -1;
461  SSIntervals.clear();
462  for (unsigned i = 0, e = SSRefs.size(); i != e; ++i)
463  SSRefs[i].clear();
464  SSRefs.clear();
465  OrigAlignments.clear();
466  OrigSizes.clear();
467  AllColors.clear();
468  UsedColors.clear();
469  for (unsigned i = 0, e = Assignments.size(); i != e; ++i)
470  Assignments[i].clear();
471  Assignments.clear();
472 
473  return Changed;
474 }
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
const unsigned reg
Definition: LiveInterval.h:656
STATISTIC(NumFunctions,"Total number of functions")
size_t i
char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
LiveInterval - This class represents the liveness of a register, or stack slot.
Definition: LiveInterval.h:625
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
void reserve(size_type N)
Definition: SmallVector.h:377
static int stackSlot2Index(unsigned Reg)
Compute the frame index from a register value representing a stack slot.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:53
A description of a memory reference used in the backend.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
void setIndex(int Idx)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
unsigned getNumOperands() const
Access to explicit operands of the instruction.
Definition: MachineInstr.h:277
SlotIndexes pass.
Definition: SlotIndexes.h:323
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
MachineBasicBlock * MBB
char & StackSlotColoringID
StackSlotColoring - This pass performs stack slot coloring.
AnalysisUsage & addPreservedID(const void *ID)
PseudoSourceValueManager & getPSVManager() const
const PseudoSourceValue * getFixedStack(int FI)
Return a pseudo source value referencing a fixed stack frame entry, e.g., a spill slot...
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
TargetInstrInfo - Interface to description of machine instruction set.
bool isDebugValue() const
Definition: MachineInstr.h:777
mmo_iterator memoperands_end() const
Definition: MachineInstr.h:359
void initializeStackSlotColoringPass(PassRegistry &)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:395
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:115
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:279
static cl::opt< int > DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden)
bool overlaps(const LiveRange &other) const
overlaps - Return true if the intersection of the two live ranges is not empty.
Definition: LiveInterval.h:423
Represent the analysis usage information of a pass.
void dump() const
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
const PseudoSourceValue * getPseudoValue() const
stack slot Stack Slot false
static cl::opt< bool > DisableSharing("no-stack-slot-sharing", cl::init(false), cl::Hidden, cl::desc("Suppress slot sharing during stack coloring"))
Iterator for intrusive lists based on ilist_node.
Color
A "color", which is either even or odd.
bool operator()(LiveInterval *LHS, LiveInterval *RHS) const
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
Module.h This file contains the declarations for the Module class.
SI Fix CF Live Intervals
unsigned isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
If the specified machine instruction is a direct store to a stack slot, return the virtual or physica...
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:276
static float getSpillWeight(bool isDef, bool isUse, const MachineBlockFrequencyInfo *MBFI, const MachineInstr &Instr)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
Special value supplied for machine level alias analysis.
unsigned isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
TargetInstrInfo overrides.
stack slot coloring
This struct contains the mappings from the slot numbers to unnamed metadata nodes, global values and types.
Definition: SlotMapping.h:33
static void clear(coro::Shape &Shape)
Definition: Coroutines.cpp:191
Representation of each machine instruction.
Definition: MachineInstr.h:52
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:119
stack slot Stack Slot Coloring
bool exposesReturnsTwice() const
exposesReturnsTwice - Returns true if the function calls setjmp or any other similar functions with a...
#define I(x, y, z)
Definition: MD5.cpp:54
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:135
INITIALIZE_PASS_BEGIN(StackSlotColoring,"stack-slot-coloring","Stack Slot Coloring", false, false) INITIALIZE_PASS_END(StackSlotColoring
safe stack
Definition: SafeStack.cpp:796
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
virtual const TargetInstrInfo * getInstrInfo() const
#define DEBUG(X)
Definition: Debug.h:100
IRTranslator LLVM IR MI
A specialized PseudoSourceValue for holding FixedStack values, which must include a frame index...
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:358