LLVM API Documentation
00001 //===-- StackSlotColoring.cpp - Stack slot coloring pass. -----------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the stack slot coloring pass. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #define DEBUG_TYPE "stackcoloring" 00015 #include "llvm/CodeGen/Passes.h" 00016 #include "llvm/CodeGen/LiveStackAnalysis.h" 00017 #include "llvm/CodeGen/MachineFrameInfo.h" 00018 #include "llvm/CodeGen/PseudoSourceValue.h" 00019 #include "llvm/Support/CommandLine.h" 00020 #include "llvm/Support/Compiler.h" 00021 #include "llvm/Support/Debug.h" 00022 #include "llvm/ADT/BitVector.h" 00023 #include "llvm/ADT/SmallVector.h" 00024 #include "llvm/ADT/Statistic.h" 00025 #include <vector> 00026 using namespace llvm; 00027 00028 static cl::opt<bool> 00029 DisableSharing("no-stack-slot-sharing", 00030 cl::init(false), cl::Hidden, 00031 cl::desc("Surpress slot sharing during stack coloring")); 00032 00033 STATISTIC(NumEliminated, "Number of stack slots eliminated due to coloring"); 00034 00035 namespace { 00036 class VISIBILITY_HIDDEN StackSlotColoring : public MachineFunctionPass { 00037 LiveStacks* LS; 00038 MachineFrameInfo *MFI; 00039 00040 // SSIntervals - Spill slot intervals. 00041 std::vector<LiveInterval*> SSIntervals; 00042 00043 // OrigAlignments - Alignments of stack objects before coloring. 00044 SmallVector<unsigned, 16> OrigAlignments; 00045 00046 // OrigSizes - Sizess of stack objects before coloring. 00047 SmallVector<unsigned, 16> OrigSizes; 00048 00049 // AllColors - If index is set, it's a spill slot, i.e. color. 00050 // FIXME: This assumes PEI locate spill slot with smaller indices 00051 // closest to stack pointer / frame pointer. Therefore, smaller 00052 // index == better color. 00053 BitVector AllColors; 00054 00055 // NextColor - Next "color" that's not yet used. 00056 int NextColor; 00057 00058 // UsedColors - "Colors" that have been assigned. 00059 BitVector UsedColors; 00060 00061 // Assignments - Color to intervals mapping. 00062 SmallVector<SmallVector<LiveInterval*,4>,16> Assignments; 00063 00064 public: 00065 static char ID; // Pass identification 00066 StackSlotColoring() : MachineFunctionPass(&ID), NextColor(-1) {} 00067 00068 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00069 AU.addRequired<LiveStacks>(); 00070 AU.addPreservedID(MachineLoopInfoID); 00071 AU.addPreservedID(MachineDominatorsID); 00072 MachineFunctionPass::getAnalysisUsage(AU); 00073 } 00074 00075 virtual bool runOnMachineFunction(MachineFunction &MF); 00076 virtual const char* getPassName() const { 00077 return "Stack Slot Coloring"; 00078 } 00079 00080 private: 00081 bool InitializeSlots(); 00082 bool OverlapWithAssignments(LiveInterval *li, int Color) const; 00083 int ColorSlot(LiveInterval *li); 00084 bool ColorSlots(MachineFunction &MF); 00085 }; 00086 } // end anonymous namespace 00087 00088 char StackSlotColoring::ID = 0; 00089 00090 static RegisterPass<StackSlotColoring> 00091 X("stack-slot-coloring", "Stack Slot Coloring"); 00092 00093 FunctionPass *llvm::createStackSlotColoringPass() { 00094 return new StackSlotColoring(); 00095 } 00096 00097 namespace { 00098 // IntervalSorter - Comparison predicate that sort live intervals by 00099 // their weight. 00100 struct IntervalSorter { 00101 bool operator()(LiveInterval* LHS, LiveInterval* RHS) const { 00102 return LHS->weight > RHS->weight; 00103 } 00104 }; 00105 } 00106 00107 /// InitializeSlots - Process all spill stack slot liveintervals and add them 00108 /// to a sorted (by weight) list. 00109 bool StackSlotColoring::InitializeSlots() { 00110 if (LS->getNumIntervals() < 2) 00111 return false; 00112 00113 int LastFI = MFI->getObjectIndexEnd(); 00114 OrigAlignments.resize(LastFI); 00115 OrigSizes.resize(LastFI); 00116 AllColors.resize(LastFI); 00117 UsedColors.resize(LastFI); 00118 Assignments.resize(LastFI); 00119 00120 // Gather all spill slots into a list. 00121 for (LiveStacks::iterator i = LS->begin(), e = LS->end(); i != e; ++i) { 00122 LiveInterval &li = i->second; 00123 int FI = li.getStackSlotIndex(); 00124 if (MFI->isDeadObjectIndex(FI)) 00125 continue; 00126 SSIntervals.push_back(&li); 00127 OrigAlignments[FI] = MFI->getObjectAlignment(FI); 00128 OrigSizes[FI] = MFI->getObjectSize(FI); 00129 AllColors.set(FI); 00130 } 00131 00132 // Sort them by weight. 00133 std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter()); 00134 00135 // Get first "color". 00136 NextColor = AllColors.find_first(); 00137 return true; 00138 } 00139 00140 /// OverlapWithAssignments - Return true if LiveInterval overlaps with any 00141 /// LiveIntervals that have already been assigned to the specified color. 00142 bool 00143 StackSlotColoring::OverlapWithAssignments(LiveInterval *li, int Color) const { 00144 const SmallVector<LiveInterval*,4> &OtherLIs = Assignments[Color]; 00145 for (unsigned i = 0, e = OtherLIs.size(); i != e; ++i) { 00146 LiveInterval *OtherLI = OtherLIs[i]; 00147 if (OtherLI->overlaps(*li)) 00148 return true; 00149 } 00150 return false; 00151 } 00152 00153 /// ColorSlot - Assign a "color" (stack slot) to the specified stack slot. 00154 /// 00155 int StackSlotColoring::ColorSlot(LiveInterval *li) { 00156 int Color = -1; 00157 bool Share = false; 00158 if (!DisableSharing) { 00159 // Check if it's possible to reuse any of the used colors. 00160 Color = UsedColors.find_first(); 00161 while (Color != -1) { 00162 if (!OverlapWithAssignments(li, Color)) { 00163 Share = true; 00164 ++NumEliminated; 00165 break; 00166 } 00167 Color = UsedColors.find_next(Color); 00168 } 00169 } 00170 00171 // Assign it to the first available color (assumed to be the best) if it's 00172 // not possible to share a used color with other objects. 00173 if (!Share) { 00174 assert(NextColor != -1 && "No more spill slots?"); 00175 Color = NextColor; 00176 UsedColors.set(Color); 00177 NextColor = AllColors.find_next(NextColor); 00178 } 00179 00180 // Record the assignment. 00181 Assignments[Color].push_back(li); 00182 int FI = li->getStackSlotIndex(); 00183 DOUT << "Assigning fi#" << FI << " to fi#" << Color << "\n"; 00184 00185 // Change size and alignment of the allocated slot. If there are multiple 00186 // objects sharing the same slot, then make sure the size and alignment 00187 // are large enough for all. 00188 unsigned Align = OrigAlignments[FI]; 00189 if (!Share || Align > MFI->getObjectAlignment(Color)) 00190 MFI->setObjectAlignment(Color, Align); 00191 int64_t Size = OrigSizes[FI]; 00192 if (!Share || Size > MFI->getObjectSize(Color)) 00193 MFI->setObjectSize(Color, Size); 00194 return Color; 00195 } 00196 00197 /// Colorslots - Color all spill stack slots and rewrite all frameindex machine 00198 /// operands in the function. 00199 bool StackSlotColoring::ColorSlots(MachineFunction &MF) { 00200 unsigned NumObjs = MFI->getObjectIndexEnd(); 00201 std::vector<int> SlotMapping(NumObjs, -1); 00202 00203 bool Changed = false; 00204 for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) { 00205 LiveInterval *li = SSIntervals[i]; 00206 int SS = li->getStackSlotIndex(); 00207 int NewSS = ColorSlot(li); 00208 SlotMapping[SS] = NewSS; 00209 Changed |= (SS != NewSS); 00210 } 00211 00212 if (!Changed) 00213 return false; 00214 00215 // Rewrite all MO_FrameIndex operands. 00216 // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands. 00217 for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 00218 MBB != E; ++MBB) { 00219 for (MachineBasicBlock::iterator MII = MBB->begin(), EE = MBB->end(); 00220 MII != EE; ++MII) { 00221 MachineInstr &MI = *MII; 00222 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { 00223 MachineOperand &MO = MI.getOperand(i); 00224 if (!MO.isFI()) 00225 continue; 00226 int FI = MO.getIndex(); 00227 if (FI < 0) 00228 continue; 00229 int NewFI = SlotMapping[FI]; 00230 if (NewFI == -1) 00231 continue; 00232 MO.setIndex(NewFI); 00233 00234 // Update the MachineMemOperand for the new memory location. 00235 // FIXME: We need a better method of managing these too. 00236 SmallVector<MachineMemOperand, 2> MMOs(MI.memoperands_begin(), 00237 MI.memoperands_end()); 00238 MI.clearMemOperands(MF); 00239 const Value *OldSV = PseudoSourceValue::getFixedStack(FI); 00240 for (unsigned i = 0, e = MMOs.size(); i != e; ++i) { 00241 if (MMOs[i].getValue() == OldSV) { 00242 MachineMemOperand MMO(PseudoSourceValue::getFixedStack(NewFI), 00243 MMOs[i].getFlags(), MMOs[i].getOffset(), 00244 MMOs[i].getSize(), MMOs[i].getAlignment()); 00245 MI.addMemOperand(MF, MMO); 00246 } else 00247 MI.addMemOperand(MF, MMOs[i]); 00248 } 00249 } 00250 } 00251 } 00252 00253 // Delete unused stack slots. 00254 while (NextColor != -1) { 00255 DOUT << "Removing unused stack object fi#" << NextColor << "\n"; 00256 MFI->RemoveStackObject(NextColor); 00257 NextColor = AllColors.find_next(NextColor); 00258 } 00259 00260 return true; 00261 } 00262 00263 bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) { 00264 DOUT << "********** Stack Slot Coloring **********\n"; 00265 00266 MFI = MF.getFrameInfo(); 00267 LS = &getAnalysis<LiveStacks>(); 00268 00269 bool Changed = false; 00270 if (InitializeSlots()) 00271 Changed = ColorSlots(MF); 00272 00273 NextColor = -1; 00274 SSIntervals.clear(); 00275 OrigAlignments.clear(); 00276 OrigSizes.clear(); 00277 AllColors.clear(); 00278 UsedColors.clear(); 00279 for (unsigned i = 0, e = Assignments.size(); i != e; ++i) 00280 Assignments[i].clear(); 00281 Assignments.clear(); 00282 00283 return Changed; 00284 }
This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.