1 //===-- StackSlotColoring.cpp - Stack slot coloring pass. -----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the stack slot coloring pass.
12 //===----------------------------------------------------------------------===//
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/Target/TargetInstrInfo.h"
23 #include "llvm/Target/TargetMachine.h"
24 #include "llvm/ADT/BitVector.h"
25 #include "llvm/ADT/SmallVector.h"
26 #include "llvm/ADT/Statistic.h"
31 DisableSharing("no-stack-slot-sharing",
32 cl::init(false), cl::Hidden
,
33 cl::desc("Suppress slot sharing during stack coloring"));
35 static cl::opt
<int> DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden
);
37 STATISTIC(NumEliminated
, "Number of stack slots eliminated due to coloring");
38 STATISTIC(NumDeadAccesses
,
39 "Number of trivially dead stack accesses eliminated");
42 class VISIBILITY_HIDDEN StackSlotColoring
: public MachineFunctionPass
{
44 MachineFrameInfo
*MFI
;
45 const TargetInstrInfo
*TII
;
47 // SSIntervals - Spill slot intervals.
48 std::vector
<LiveInterval
*> SSIntervals
;
50 // OrigAlignments - Alignments of stack objects before coloring.
51 SmallVector
<unsigned, 16> OrigAlignments
;
53 // OrigSizes - Sizess of stack objects before coloring.
54 SmallVector
<unsigned, 16> OrigSizes
;
56 // AllColors - If index is set, it's a spill slot, i.e. color.
57 // FIXME: This assumes PEI locate spill slot with smaller indices
58 // closest to stack pointer / frame pointer. Therefore, smaller
59 // index == better color.
62 // NextColor - Next "color" that's not yet used.
65 // UsedColors - "Colors" that have been assigned.
68 // Assignments - Color to intervals mapping.
69 SmallVector
<SmallVector
<LiveInterval
*,4>,16> Assignments
;
72 static char ID
; // Pass identification
73 StackSlotColoring() : MachineFunctionPass(&ID
), NextColor(-1) {}
75 virtual void getAnalysisUsage(AnalysisUsage
&AU
) const {
76 AU
.addRequired
<LiveStacks
>();
78 AU
.addPreservedID(MachineLoopInfoID
);
79 AU
.addPreservedID(MachineDominatorsID
);
80 MachineFunctionPass::getAnalysisUsage(AU
);
83 virtual bool runOnMachineFunction(MachineFunction
&MF
);
84 virtual const char* getPassName() const {
85 return "Stack Slot Coloring";
89 bool InitializeSlots();
90 bool OverlapWithAssignments(LiveInterval
*li
, int Color
) const;
91 int ColorSlot(LiveInterval
*li
);
92 bool ColorSlots(MachineFunction
&MF
);
93 bool removeDeadStores(MachineBasicBlock
* MBB
);
95 } // end anonymous namespace
97 char StackSlotColoring::ID
= 0;
99 static RegisterPass
<StackSlotColoring
>
100 X("stack-slot-coloring", "Stack Slot Coloring");
102 FunctionPass
*llvm::createStackSlotColoringPass() {
103 return new StackSlotColoring();
107 // IntervalSorter - Comparison predicate that sort live intervals by
109 struct IntervalSorter
{
110 bool operator()(LiveInterval
* LHS
, LiveInterval
* RHS
) const {
111 return LHS
->weight
> RHS
->weight
;
116 /// InitializeSlots - Process all spill stack slot liveintervals and add them
117 /// to a sorted (by weight) list.
118 bool StackSlotColoring::InitializeSlots() {
119 if (LS
->getNumIntervals() < 2)
122 int LastFI
= MFI
->getObjectIndexEnd();
123 OrigAlignments
.resize(LastFI
);
124 OrigSizes
.resize(LastFI
);
125 AllColors
.resize(LastFI
);
126 UsedColors
.resize(LastFI
);
127 Assignments
.resize(LastFI
);
129 // Gather all spill slots into a list.
130 for (LiveStacks::iterator i
= LS
->begin(), e
= LS
->end(); i
!= e
; ++i
) {
131 LiveInterval
&li
= i
->second
;
132 int FI
= li
.getStackSlotIndex();
133 if (MFI
->isDeadObjectIndex(FI
))
135 SSIntervals
.push_back(&li
);
136 OrigAlignments
[FI
] = MFI
->getObjectAlignment(FI
);
137 OrigSizes
[FI
] = MFI
->getObjectSize(FI
);
141 // Sort them by weight.
142 std::stable_sort(SSIntervals
.begin(), SSIntervals
.end(), IntervalSorter());
144 // Get first "color".
145 NextColor
= AllColors
.find_first();
149 /// OverlapWithAssignments - Return true if LiveInterval overlaps with any
150 /// LiveIntervals that have already been assigned to the specified color.
152 StackSlotColoring::OverlapWithAssignments(LiveInterval
*li
, int Color
) const {
153 const SmallVector
<LiveInterval
*,4> &OtherLIs
= Assignments
[Color
];
154 for (unsigned i
= 0, e
= OtherLIs
.size(); i
!= e
; ++i
) {
155 LiveInterval
*OtherLI
= OtherLIs
[i
];
156 if (OtherLI
->overlaps(*li
))
162 /// ColorSlot - Assign a "color" (stack slot) to the specified stack slot.
164 int StackSlotColoring::ColorSlot(LiveInterval
*li
) {
167 if (!DisableSharing
) {
168 // Check if it's possible to reuse any of the used colors.
169 Color
= UsedColors
.find_first();
170 while (Color
!= -1) {
171 if (!OverlapWithAssignments(li
, Color
)) {
176 Color
= UsedColors
.find_next(Color
);
180 // Assign it to the first available color (assumed to be the best) if it's
181 // not possible to share a used color with other objects.
183 assert(NextColor
!= -1 && "No more spill slots?");
185 UsedColors
.set(Color
);
186 NextColor
= AllColors
.find_next(NextColor
);
189 // Record the assignment.
190 Assignments
[Color
].push_back(li
);
191 int FI
= li
->getStackSlotIndex();
192 DOUT
<< "Assigning fi#" << FI
<< " to fi#" << Color
<< "\n";
194 // Change size and alignment of the allocated slot. If there are multiple
195 // objects sharing the same slot, then make sure the size and alignment
196 // are large enough for all.
197 unsigned Align
= OrigAlignments
[FI
];
198 if (!Share
|| Align
> MFI
->getObjectAlignment(Color
))
199 MFI
->setObjectAlignment(Color
, Align
);
200 int64_t Size
= OrigSizes
[FI
];
201 if (!Share
|| Size
> MFI
->getObjectSize(Color
))
202 MFI
->setObjectSize(Color
, Size
);
206 /// Colorslots - Color all spill stack slots and rewrite all frameindex machine
207 /// operands in the function.
208 bool StackSlotColoring::ColorSlots(MachineFunction
&MF
) {
209 unsigned NumObjs
= MFI
->getObjectIndexEnd();
210 std::vector
<int> SlotMapping(NumObjs
, -1);
212 bool Changed
= false;
213 for (unsigned i
= 0, e
= SSIntervals
.size(); i
!= e
; ++i
) {
214 LiveInterval
*li
= SSIntervals
[i
];
215 int SS
= li
->getStackSlotIndex();
216 int NewSS
= ColorSlot(li
);
217 SlotMapping
[SS
] = NewSS
;
218 Changed
|= (SS
!= NewSS
);
224 // Rewrite all MO_FrameIndex operands.
225 // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands.
226 for (MachineFunction::iterator MBB
= MF
.begin(), E
= MF
.end();
228 for (MachineBasicBlock::iterator MII
= MBB
->begin(), EE
= MBB
->end();
230 MachineInstr
&MI
= *MII
;
231 for (unsigned i
= 0, e
= MI
.getNumOperands(); i
!= e
; ++i
) {
232 MachineOperand
&MO
= MI
.getOperand(i
);
235 int FI
= MO
.getIndex();
238 int NewFI
= SlotMapping
[FI
];
243 // Update the MachineMemOperand for the new memory location.
244 // FIXME: We need a better method of managing these too.
245 SmallVector
<MachineMemOperand
, 2> MMOs(MI
.memoperands_begin(),
246 MI
.memoperands_end());
247 MI
.clearMemOperands(MF
);
248 const Value
*OldSV
= PseudoSourceValue::getFixedStack(FI
);
249 for (unsigned i
= 0, e
= MMOs
.size(); i
!= e
; ++i
) {
250 if (MMOs
[i
].getValue() == OldSV
) {
251 MachineMemOperand
MMO(PseudoSourceValue::getFixedStack(NewFI
),
252 MMOs
[i
].getFlags(), MMOs
[i
].getOffset(),
253 MMOs
[i
].getSize(), MMOs
[i
].getAlignment());
254 MI
.addMemOperand(MF
, MMO
);
256 MI
.addMemOperand(MF
, MMOs
[i
]);
262 // Delete unused stack slots.
263 while (NextColor
!= -1) {
264 DOUT
<< "Removing unused stack object fi#" << NextColor
<< "\n";
265 MFI
->RemoveStackObject(NextColor
);
266 NextColor
= AllColors
.find_next(NextColor
);
272 /// removeDeadStores - Scan through a basic block and look for loads followed
273 /// by stores. If they're both using the same stack slot, then the store is
274 /// definitely dead. This could obviously be much more aggressive (consider
275 /// pairs with instructions between them), but such extensions might have a
276 /// considerable compile time impact.
277 bool StackSlotColoring::removeDeadStores(MachineBasicBlock
* MBB
) {
278 // FIXME: This could be much more aggressive, but we need to investigate
279 // the compile time impact of doing so.
280 bool changed
= false;
282 SmallVector
<MachineInstr
*, 4> toErase
;
284 for (MachineBasicBlock::iterator I
= MBB
->begin(), E
= MBB
->end();
286 if (DCELimit
!= -1 && (int)NumDeadAccesses
>= DCELimit
)
289 MachineBasicBlock::iterator NextMI
= next(I
);
290 if (NextMI
== MBB
->end()) continue;
292 int FirstSS
, SecondSS
;
293 unsigned LoadReg
= 0;
294 unsigned StoreReg
= 0;
295 if (!(LoadReg
= TII
->isLoadFromStackSlot(I
, FirstSS
))) continue;
296 if (!(StoreReg
= TII
->isStoreToStackSlot(NextMI
, SecondSS
))) continue;
297 if (FirstSS
!= SecondSS
|| LoadReg
!= StoreReg
|| FirstSS
== -1) continue;
302 if (NextMI
->findRegisterUseOperandIdx(LoadReg
, true, 0) != -1) {
304 toErase
.push_back(I
);
307 toErase
.push_back(NextMI
);
311 for (SmallVector
<MachineInstr
*, 4>::iterator I
= toErase
.begin(),
312 E
= toErase
.end(); I
!= E
; ++I
)
313 (*I
)->eraseFromParent();
319 bool StackSlotColoring::runOnMachineFunction(MachineFunction
&MF
) {
320 DOUT
<< "********** Stack Slot Coloring **********\n";
322 MFI
= MF
.getFrameInfo();
323 TII
= MF
.getTarget().getInstrInfo();
324 LS
= &getAnalysis
<LiveStacks
>();
326 bool Changed
= false;
327 if (InitializeSlots())
328 Changed
= ColorSlots(MF
);
332 OrigAlignments
.clear();
336 for (unsigned i
= 0, e
= Assignments
.size(); i
!= e
; ++i
)
337 Assignments
[i
].clear();
341 for (MachineFunction::iterator I
= MF
.begin(), E
= MF
.end(); I
!= E
; ++I
)
342 Changed
|= removeDeadStores(I
);