LLVM API Documentation

StackSlotColoring.cpp

Go to the documentation of this file.
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.