Remove trailing whitespace to reduce later commit patch noise.
[oota-llvm.git] / lib / CodeGen / StackSlotColoring.cpp
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 #define DEBUG_TYPE "stackcoloring"
15 #include "llvm/CodeGen/Passes.h"
16 #include "llvm/CodeGen/LiveStackAnalysis.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/PseudoSourceValue.h"
19 #include "llvm/Support/CommandLine.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/ADT/BitVector.h"
23 #include "llvm/ADT/SmallVector.h"
24 #include "llvm/ADT/Statistic.h"
25 #include <vector>
26 using namespace llvm;
27
28 static cl::opt<bool>
29 DisableSharing("no-stack-slot-sharing",
30              cl::init(false), cl::Hidden,
31              cl::desc("Surpress slot sharing during stack coloring"));
32
33 STATISTIC(NumEliminated,   "Number of stack slots eliminated due to coloring");
34
35 namespace {
36   class VISIBILITY_HIDDEN StackSlotColoring : public MachineFunctionPass {
37     LiveStacks* LS;
38     MachineFrameInfo *MFI;
39
40     // SSIntervals - Spill slot intervals.
41     std::vector<LiveInterval*> SSIntervals;
42
43     // OrigAlignments - Alignments of stack objects before coloring.
44     SmallVector<unsigned, 16> OrigAlignments;
45
46     // OrigSizes - Sizess of stack objects before coloring.
47     SmallVector<unsigned, 16> OrigSizes;
48
49     // AllColors - If index is set, it's a spill slot, i.e. color.
50     // FIXME: This assumes PEI locate spill slot with smaller indices
51     // closest to stack pointer / frame pointer. Therefore, smaller
52     // index == better color.
53     BitVector AllColors;
54
55     // NextColor - Next "color" that's not yet used.
56     int NextColor;
57
58     // UsedColors - "Colors" that have been assigned.
59     BitVector UsedColors;
60
61     // Assignments - Color to intervals mapping.
62     SmallVector<SmallVector<LiveInterval*,4>,16> Assignments;
63
64   public:
65     static char ID; // Pass identification
66     StackSlotColoring() : MachineFunctionPass(&ID), NextColor(-1) {}
67     
68     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
69       AU.addRequired<LiveStacks>();
70       AU.addPreservedID(MachineLoopInfoID);
71       AU.addPreservedID(MachineDominatorsID);
72       MachineFunctionPass::getAnalysisUsage(AU);
73     }
74
75     virtual bool runOnMachineFunction(MachineFunction &MF);
76     virtual const char* getPassName() const {
77       return "Stack Slot Coloring";
78     }
79
80   private:
81     bool InitializeSlots();
82     bool OverlapWithAssignments(LiveInterval *li, int Color) const;
83     int ColorSlot(LiveInterval *li);
84     bool ColorSlots(MachineFunction &MF);
85   };
86 } // end anonymous namespace
87
88 char StackSlotColoring::ID = 0;
89
90 static RegisterPass<StackSlotColoring>
91 X("stack-slot-coloring", "Stack Slot Coloring");
92
93 FunctionPass *llvm::createStackSlotColoringPass() {
94   return new StackSlotColoring();
95 }
96
97 namespace {
98   // IntervalSorter - Comparison predicate that sort live intervals by
99   // their weight.
100   struct IntervalSorter {
101     bool operator()(LiveInterval* LHS, LiveInterval* RHS) const {
102       return LHS->weight > RHS->weight;
103     }
104   };
105 }
106
107 /// InitializeSlots - Process all spill stack slot liveintervals and add them
108 /// to a sorted (by weight) list.
109 bool StackSlotColoring::InitializeSlots() {
110   if (LS->getNumIntervals() < 2)
111     return false;
112
113   int LastFI = MFI->getObjectIndexEnd();
114   OrigAlignments.resize(LastFI);
115   OrigSizes.resize(LastFI);
116   AllColors.resize(LastFI);
117   UsedColors.resize(LastFI);
118   Assignments.resize(LastFI);
119
120   // Gather all spill slots into a list.
121   for (LiveStacks::iterator i = LS->begin(), e = LS->end(); i != e; ++i) {
122     LiveInterval &li = i->second;
123     int FI = li.getStackSlotIndex();
124     if (MFI->isDeadObjectIndex(FI))
125       continue;
126     SSIntervals.push_back(&li);
127     OrigAlignments[FI] = MFI->getObjectAlignment(FI);
128     OrigSizes[FI]      = MFI->getObjectSize(FI);
129     AllColors.set(FI);
130   }
131
132   // Sort them by weight.
133   std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter());
134
135   // Get first "color".
136   NextColor = AllColors.find_first();
137   return true;
138 }
139
140 /// OverlapWithAssignments - Return true if LiveInterval overlaps with any
141 /// LiveIntervals that have already been assigned to the specified color.
142 bool
143 StackSlotColoring::OverlapWithAssignments(LiveInterval *li, int Color) const {
144   const SmallVector<LiveInterval*,4> &OtherLIs = Assignments[Color];
145   for (unsigned i = 0, e = OtherLIs.size(); i != e; ++i) {
146     LiveInterval *OtherLI = OtherLIs[i];
147     if (OtherLI->overlaps(*li))
148       return true;
149   }
150   return false;
151 }
152
153 /// ColorSlot - Assign a "color" (stack slot) to the specified stack slot.
154 ///
155 int StackSlotColoring::ColorSlot(LiveInterval *li) {
156   int Color = -1;
157   bool Share = false;
158   if (!DisableSharing) {
159     // Check if it's possible to reuse any of the used colors.
160     Color = UsedColors.find_first();
161     while (Color != -1) {
162       if (!OverlapWithAssignments(li, Color)) {
163         Share = true;
164         ++NumEliminated;
165         break;
166       }
167       Color = UsedColors.find_next(Color);
168     }
169   }
170
171   // Assign it to the first available color (assumed to be the best) if it's
172   // not possible to share a used color with other objects.
173   if (!Share) {
174     assert(NextColor != -1 && "No more spill slots?");
175     Color = NextColor;
176     UsedColors.set(Color);
177     NextColor = AllColors.find_next(NextColor);
178   }
179
180   // Record the assignment.
181   Assignments[Color].push_back(li);
182   int FI = li->getStackSlotIndex();
183   DOUT << "Assigning fi#" << FI << " to fi#" << Color << "\n";
184
185   // Change size and alignment of the allocated slot. If there are multiple
186   // objects sharing the same slot, then make sure the size and alignment
187   // are large enough for all.
188   unsigned Align = OrigAlignments[FI];
189   if (!Share || Align > MFI->getObjectAlignment(Color))
190     MFI->setObjectAlignment(Color, Align);
191   int64_t Size = OrigSizes[FI];
192   if (!Share || Size > MFI->getObjectSize(Color))
193     MFI->setObjectSize(Color, Size);
194   return Color;
195 }
196
197 /// Colorslots - Color all spill stack slots and rewrite all frameindex machine
198 /// operands in the function.
199 bool StackSlotColoring::ColorSlots(MachineFunction &MF) {
200   unsigned NumObjs = MFI->getObjectIndexEnd();
201   std::vector<int> SlotMapping(NumObjs, -1);
202
203   bool Changed = false;
204   for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) {
205     LiveInterval *li = SSIntervals[i];
206     int SS = li->getStackSlotIndex();
207     int NewSS = ColorSlot(li);
208     SlotMapping[SS] = NewSS;
209     Changed |= (SS != NewSS);
210   }
211
212   if (!Changed)
213     return false;
214
215   // Rewrite all MO_FrameIndex operands.
216   // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands.
217   for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
218        MBB != E; ++MBB) {
219     for (MachineBasicBlock::iterator MII = MBB->begin(), EE = MBB->end();
220          MII != EE; ++MII) {
221       MachineInstr &MI = *MII;
222       for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
223         MachineOperand &MO = MI.getOperand(i);
224         if (!MO.isFI())
225           continue;
226         int FI = MO.getIndex();
227         if (FI < 0)
228           continue;
229         int NewFI = SlotMapping[FI];
230         if (NewFI == -1)
231           continue;
232         MO.setIndex(NewFI);
233
234         // Update the MachineMemOperand for the new memory location.
235         // FIXME: We need a better method of managing these too.
236         SmallVector<MachineMemOperand, 2> MMOs(MI.memoperands_begin(),
237                                                MI.memoperands_end());
238         MI.clearMemOperands(MF);
239         const Value *OldSV = PseudoSourceValue::getFixedStack(FI);
240         for (unsigned i = 0, e = MMOs.size(); i != e; ++i) {
241           if (MMOs[i].getValue() == OldSV) {
242             MachineMemOperand MMO(PseudoSourceValue::getFixedStack(NewFI),
243                                   MMOs[i].getFlags(), MMOs[i].getOffset(),
244                                   MMOs[i].getSize(), MMOs[i].getAlignment());
245             MI.addMemOperand(MF, MMO);
246           } else
247             MI.addMemOperand(MF, MMOs[i]);
248         }
249       }
250     }
251   }
252
253   // Delete unused stack slots.
254   while (NextColor != -1) {
255     DOUT << "Removing unused stack object fi#" << NextColor << "\n";
256     MFI->RemoveStackObject(NextColor);
257     NextColor = AllColors.find_next(NextColor);
258   }
259
260   return true;
261 }
262
263 bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) {
264   DOUT << "********** Stack Slot Coloring **********\n";
265
266   MFI = MF.getFrameInfo();
267   LS = &getAnalysis<LiveStacks>();
268
269   bool Changed = false;
270   if (InitializeSlots())
271     Changed = ColorSlots(MF);
272
273   NextColor = -1;
274   SSIntervals.clear();
275   OrigAlignments.clear();
276   OrigSizes.clear();
277   AllColors.clear();
278   UsedColors.clear();
279   for (unsigned i = 0, e = Assignments.size(); i != e; ++i)
280     Assignments[i].clear();
281   Assignments.clear();
282
283   return Changed;
284 }