Add a stack slot coloring pass. Not yet enabled.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51934 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index e4ad872..73f2902 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/LLVMTargetMachine.cpp
@@ -38,12 +38,13 @@
 EnableSinking("enable-sinking", cl::init(false), cl::Hidden,
               cl::desc("Perform sinking on machine code"));
 static cl::opt<bool>
-AlignLoops("align-loops", cl::init(true), cl::Hidden,
-           cl::desc("Align loop headers"));
+EnableStackColoring("stack-coloring",
+            cl::init(true), cl::Hidden,
+            cl::desc("Perform stack slot coloring"));
 static cl::opt<bool>
-PerformLICM("machine-licm",
-            cl::init(false), cl::Hidden,
-            cl::desc("Perform loop-invariant code motion on machine code"));
+EnableLICM("machine-licm",
+           cl::init(false), cl::Hidden,
+           cl::desc("Perform loop-invariant code motion on machine code"));
 
 // When this works it will be on by default.
 static cl::opt<bool>
@@ -88,7 +89,7 @@
   if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(cerr));
 
-  if (PerformLICM)
+  if (EnableLICM)
     PM.add(createMachineLICMPass());
   
   if (EnableSinking)
@@ -101,21 +102,28 @@
   // Perform register allocation to convert to a concrete x86 representation
   PM.add(createRegisterAllocator());
   
-  if (PrintMachineCode)
+  // Perform stack slot coloring.
+  if (EnableStackColoring)
+    PM.add(createStackSlotColoringPass());
+
+  if (PrintMachineCode)  // Print the register-allocated code
     PM.add(createMachineFunctionPrinterPass(cerr));
-    
+  
+  // Run post-ra passes.
+  if (addPostRegAlloc(PM, Fast) && PrintMachineCode)
+    PM.add(createMachineFunctionPrinterPass(cerr));
+
   PM.add(createLowerSubregsPass());
   
   if (PrintMachineCode)  // Print the subreg lowered code
     PM.add(createMachineFunctionPrinterPass(cerr));
 
-  // Run post-ra passes.
-  if (addPostRegAlloc(PM, Fast) && PrintMachineCode)
-    PM.add(createMachineFunctionPrinterPass(cerr));
-
   // Insert prolog/epilog code.  Eliminate abstract frame index references...
   PM.add(createPrologEpilogCodeInserter());
   
+  if (PrintMachineCode)
+    PM.add(createMachineFunctionPrinterPass(cerr));
+  
   // Second pass scheduler.
   if (!Fast && !DisablePostRAScheduler)
     PM.add(createPostRAScheduler());
@@ -140,7 +148,7 @@
   if (addPreEmitPass(PM, Fast) && PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(cerr));
 
-  if (AlignLoops && !Fast && !OptimizeForSize)
+  if (!Fast && !OptimizeForSize)
     PM.add(createLoopAlignerPass());
 
   switch (FileType) {
@@ -218,7 +226,7 @@
   if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(cerr));
 
-  if (PerformLICM)
+  if (EnableLICM)
     PM.add(createMachineLICMPass());
   
   if (EnableSinking)
@@ -228,25 +236,32 @@
   if (addPreRegAlloc(PM, Fast) && PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(cerr));
 
-  // Perform register allocation to convert to a concrete x86 representation
+  // Perform register allocation.
   PM.add(createRegisterAllocator());
-  
+
+  // Perform stack slot coloring.
+  if (EnableStackColoring)
+    PM.add(createStackSlotColoringPass());
+
   if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(cerr));
     
+  // Run post-ra passes.
+  if (addPostRegAlloc(PM, Fast) && PrintMachineCode)
+    PM.add(createMachineFunctionPrinterPass(cerr));
+
+  if (PrintMachineCode)  // Print the register-allocated code
+    PM.add(createMachineFunctionPrinterPass(cerr));
+  
   PM.add(createLowerSubregsPass());
   
   if (PrintMachineCode)  // Print the subreg lowered code
     PM.add(createMachineFunctionPrinterPass(cerr));
 
-  // Run post-ra passes.
-  if (addPostRegAlloc(PM, Fast) && PrintMachineCode)
-    PM.add(createMachineFunctionPrinterPass(cerr));
-
   // Insert prolog/epilog code.  Eliminate abstract frame index references...
   PM.add(createPrologEpilogCodeInserter());
   
-  if (PrintMachineCode)  // Print the register-allocated code
+  if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(cerr));
   
   // Second pass scheduler.
@@ -258,6 +273,7 @@
     PM.add(createBranchFoldingPass(getEnableTailMergeDefault()));
 
   PM.add(createGCMachineCodeAnalysisPass());
+
   if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(cerr));
   
diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp
index 48c25a1..24081b9 100644
--- a/lib/CodeGen/LiveInterval.cpp
+++ b/lib/CodeGen/LiveInterval.cpp
@@ -358,6 +358,20 @@
   return end();
 }
 
+/// findDefinedVNInfo - Find the VNInfo that's defined at the specified index
+/// (register interval) or defined by the specified register (stack inteval).
+VNInfo *LiveInterval::findDefinedVNInfo(unsigned DefIdxOrReg) const {
+  VNInfo *VNI = NULL;
+  for (LiveInterval::const_vni_iterator i = vni_begin(), e = vni_end();
+       i != e; ++i)
+    if ((*i)->def == DefIdxOrReg) {
+      VNI = *i;
+      break;
+    }
+  return VNI;
+}
+
+
 /// join - Join two live intervals (this, and other) together.  This applies
 /// mappings to the value numbers in the LHS/RHS intervals as specified.  If
 /// the intervals are not joinable, this aborts.
@@ -664,7 +678,9 @@
 
 void LiveInterval::print(std::ostream &OS,
                          const TargetRegisterInfo *TRI) const {
-  if (TRI && TargetRegisterInfo::isPhysicalRegister(reg))
+  if (isSS)
+    OS << "SS#" << reg;
+  else if (TRI && TargetRegisterInfo::isPhysicalRegister(reg))
     OS << TRI->getName(reg);
   else
     OS << "%reg" << reg;
@@ -672,7 +688,7 @@
   OS << ',' << weight;
 
   if (empty())
-    OS << "EMPTY";
+    OS << " EMPTY";
   else {
     OS << " = ";
     for (LiveInterval::Ranges::const_iterator I = ranges.begin(),
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index 5473853..f184191 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -65,6 +65,7 @@
 }
 
 void LiveIntervals::releaseMemory() {
+  MBB2IdxMap.clear();
   Idx2MBBMap.clear();
   mi2iMap_.clear();
   i2miMap_.clear();
@@ -229,8 +230,8 @@
 void LiveIntervals::print(std::ostream &O, const Module* ) const {
   O << "********** INTERVALS **********\n";
   for (const_iterator I = begin(), E = end(); I != E; ++I) {
-    I->second.print(DOUT, tri_);
-    DOUT << "\n";
+    I->second.print(O, tri_);
+    O << "\n";
   }
 
   O << "********** MACHINEINSTRS **********\n";
@@ -1160,17 +1161,6 @@
   return false;
 }
 
-static const VNInfo *findDefinedVNInfo(const LiveInterval &li, unsigned DefIdx) {
-  const VNInfo *VNI = NULL;
-  for (LiveInterval::const_vni_iterator i = li.vni_begin(),
-         e = li.vni_end(); i != e; ++i)
-    if ((*i)->def == DefIdx) {
-      VNI = *i;
-      break;
-    }
-  return VNI;
-}
-
 /// RewriteInfo - Keep track of machine instrs that will be rewritten
 /// during spilling.
 namespace {
@@ -1318,7 +1308,7 @@
           HasKill = anyKillInMBBAfterIdx(li, I->valno, MBB, getDefIndex(index));
         else {
           // If this is a two-address code, then this index starts a new VNInfo.
-          const VNInfo *VNI = findDefinedVNInfo(li, getDefIndex(index));
+          const VNInfo *VNI = li.findDefinedVNInfo(getDefIndex(index));
           if (VNI)
             HasKill = anyKillInMBBAfterIdx(li, VNI, MBB, getDefIndex(index));
         }
diff --git a/lib/CodeGen/LiveStackAnalysis.cpp b/lib/CodeGen/LiveStackAnalysis.cpp
new file mode 100644
index 0000000..9358c10
--- /dev/null
+++ b/lib/CodeGen/LiveStackAnalysis.cpp
@@ -0,0 +1,50 @@
+//===-- LiveStackAnalysis.cpp - Live Stack Slot Analysis ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the live stack slot analysis pass. It is analogous to
+// live interval analysis except it's analyzing liveness of stack slots rather
+// than registers.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "livestacks"
+#include "llvm/CodeGen/LiveStackAnalysis.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/ADT/Statistic.h"
+using namespace llvm;
+
+char LiveStacks::ID = 0;
+static RegisterPass<LiveStacks> X("livestacks", "Live Stack Slot Analysis");
+
+void LiveStacks::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.setPreservesAll();
+}
+
+void LiveStacks::releaseMemory() {
+  // Release VNInfo memroy regions after all VNInfo objects are dtor'd.
+  VNInfoAllocator.Reset();
+  s2iMap.clear();
+}
+
+bool LiveStacks::runOnMachineFunction(MachineFunction &) {
+  // FIXME: No analysis is being done right now. We are relying on the
+  // register allocators to provide the information.
+  return false;
+}
+
+/// print - Implement the dump method.
+void LiveStacks::print(std::ostream &O, const Module* ) const {
+  O << "********** INTERVALS **********\n";
+  for (const_iterator I = begin(), E = end(); I != E; ++I) {
+    I->second.print(O);
+    O << "\n";
+  }
+}
diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp
index 456ee63..8bfa868 100644
--- a/lib/CodeGen/RegAllocLinearScan.cpp
+++ b/lib/CodeGen/RegAllocLinearScan.cpp
@@ -12,10 +12,11 @@
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "regalloc"
-#include "llvm/CodeGen/LiveIntervalAnalysis.h"
 #include "PhysRegTracker.h"
 #include "VirtRegMap.h"
 #include "llvm/Function.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/CodeGen/LiveStackAnalysis.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineLoopInfo.h"
@@ -67,6 +68,7 @@
     MachineRegisterInfo *reginfo_;
     BitVector allocatableRegs_;
     LiveIntervals* li_;
+    LiveStacks* ls_;
     const MachineLoopInfo *loopInfo;
 
     /// handled_ - Intervals are added to the handled_ set in the order of their
@@ -103,6 +105,8 @@
       // Make sure PassManager knows which analyses to make available
       // to coalescing and which analyses coalescing invalidates.
       AU.addRequiredTransitive<RegisterCoalescer>();
+      AU.addRequired<LiveStacks>();
+      AU.addPreserved<LiveStacks>();
       AU.addRequired<MachineLoopInfo>();
       AU.addPreserved<MachineLoopInfo>();
       AU.addPreservedID(MachineDominatorsID);
@@ -171,6 +175,9 @@
   char RALinScan::ID = 0;
 }
 
+static RegisterPass<RALinScan>
+X("linearscan-regalloc", "Linear Scan Register Allocator");
+
 void RALinScan::ComputeRelatedRegClasses() {
   const TargetRegisterInfo &TRI = *tri_;
   
@@ -258,6 +265,7 @@
   reginfo_ = &mf_->getRegInfo();
   allocatableRegs_ = tri_->getAllocatableSet(fn);
   li_ = &getAnalysis<LiveIntervals>();
+  ls_ = &getAnalysis<LiveStacks>();
   loopInfo = &getAnalysis<MachineLoopInfo>();
 
   // We don't run the coalescer here because we have no reason to
@@ -504,6 +512,26 @@
   }
 }
 
+/// addStackInterval - Create a LiveInterval for stack if the specified live
+/// interval has been spilled.
+static void addStackInterval(LiveInterval *cur, LiveStacks *ls_,
+                             LiveIntervals *li_, VirtRegMap &vrm_) {
+  int SS = vrm_.getStackSlot(cur->reg);
+  if (SS == VirtRegMap::NO_STACK_SLOT)
+    return;
+  LiveInterval &SI = ls_->getOrCreateInterval(SS);
+  VNInfo *VNI;
+  if (SI.getNumValNums())
+    VNI = SI.getValNumInfo(0);
+  else
+    VNI = SI.getNextValue(~0U, 0, ls_->getVNInfoAllocator());
+
+  LiveInterval &RI = li_->getInterval(cur->reg);
+  // FIXME: This may be overly conservative.
+  SI.MergeRangesInAsValue(RI, VNI);
+  SI.weight += RI.weight;
+}
+
 /// assignRegOrStackSlotAtInterval - assign a register if one is available, or
 /// spill.
 void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
@@ -717,6 +745,7 @@
     DOUT << "\t\t\tspilling(c): " << *cur << '\n';
     std::vector<LiveInterval*> added =
       li_->addIntervalsForSpills(*cur, loopInfo, *vrm_);
+    addStackInterval(cur, ls_, li_, *vrm_);
     if (added.empty())
       return;  // Early exit if all spills were folded.
 
@@ -769,6 +798,7 @@
       earliestStart = std::min(earliestStart, i->first->beginNumber());
       std::vector<LiveInterval*> newIs =
         li_->addIntervalsForSpills(*i->first, loopInfo, *vrm_);
+      addStackInterval(i->first, ls_, li_, *vrm_);
       std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
       spilled.insert(reg);
     }
@@ -782,6 +812,7 @@
       earliestStart = std::min(earliestStart, i->first->beginNumber());
       std::vector<LiveInterval*> newIs =
         li_->addIntervalsForSpills(*i->first, loopInfo, *vrm_);
+      addStackInterval(i->first, ls_, li_, *vrm_);
       std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
       spilled.insert(reg);
     }
diff --git a/lib/CodeGen/StackSlotColoring.cpp b/lib/CodeGen/StackSlotColoring.cpp
new file mode 100644
index 0000000..24bd028
--- /dev/null
+++ b/lib/CodeGen/StackSlotColoring.cpp
@@ -0,0 +1,271 @@
+//===-- StackSlotColoring.cpp - Sinking for machine instructions ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the stack slot coloring pass.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "stackcoloring"
+#include "llvm/CodeGen/LiveStackAnalysis.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include <vector>
+using namespace llvm;
+
+static cl::opt<bool>
+DisableSharing("no-stack-slot-sharing",
+             cl::init(false), cl::Hidden,
+             cl::desc("Surpress slot sharing during stack coloring"));
+
+static cl::opt<int>
+DeleteLimit("slot-delete-limit", cl::init(-1), cl::Hidden,
+             cl::desc("Stack coloring slot deletion limit"));
+
+STATISTIC(NumEliminated,   "Number of stack slots eliminated due to coloring");
+
+namespace {
+  class VISIBILITY_HIDDEN StackSlotColoring : public MachineFunctionPass {
+    LiveStacks* LS;
+    MachineFrameInfo *MFI;
+
+    // SSIntervals - Spill slot intervals.
+    std::vector<LiveInterval*> SSIntervals;
+
+    // OrigAlignments - Alignments of stack objects before coloring.
+    SmallVector<unsigned, 16> OrigAlignments;
+
+    // OrigSizes - Sizess of stack objects before coloring.
+    SmallVector<unsigned, 16> OrigSizes;
+
+    // AllColors - If index is set, it's a spill slot, i.e. color.
+    // FIXME: This assumes PEI locate spill slot with smaller indices
+    // closest to stack pointer / frame pointer. Therefore, smaller
+    // index == better color.
+    BitVector AllColors;
+
+    // NextColor - Next "color" that's not yet used.
+    int NextColor;
+
+    // UsedColors - "Colors" that have been assigned.
+    BitVector UsedColors;
+
+    // Assignments - Color to intervals mapping.
+    SmallVector<SmallVector<LiveInterval*,4>,16> Assignments;
+
+  public:
+    static char ID; // Pass identification
+    StackSlotColoring() : MachineFunctionPass((intptr_t)&ID), NextColor(-1) {}
+    
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.addRequired<LiveStacks>();
+      MachineFunctionPass::getAnalysisUsage(AU);
+    }
+
+    virtual bool runOnMachineFunction(MachineFunction &MF);
+    virtual const char* getPassName() const {
+      return "Stack Slot Coloring";
+    }
+
+  private:
+    bool InitializeSlots();
+    bool OverlapWithAssignments(LiveInterval *li, int Color) const;
+    int ColorSlot(LiveInterval *li);
+    bool ColorSlots(MachineFunction &MF);
+  };
+} // end anonymous namespace
+
+char StackSlotColoring::ID = 0;
+
+static RegisterPass<StackSlotColoring>
+X("stack-slot-coloring", "Stack Slot Coloring");
+
+FunctionPass *llvm::createStackSlotColoringPass() {
+  return new StackSlotColoring();
+}
+
+namespace {
+  // IntervalSorter - Comparison predicate that sort live intervals by
+  // their weight.
+  struct IntervalSorter {
+    bool operator()(LiveInterval* LHS, LiveInterval* RHS) const {
+      return LHS->weight > RHS->weight;
+    }
+  };
+}
+
+/// InitializeSlots - Process all spill stack slot liveintervals and add them
+/// to a sorted (by weight) list.
+bool StackSlotColoring::InitializeSlots() {
+  if (LS->getNumIntervals() < 2)
+    return false;
+
+  int LastFI = MFI->getObjectIndexEnd();
+  OrigAlignments.resize(LastFI);
+  OrigSizes.resize(LastFI);
+  AllColors.resize(LastFI);
+  UsedColors.resize(LastFI);
+  Assignments.resize(LastFI);
+
+  // Gather all spill slots into a list.
+  for (LiveStacks::iterator i = LS->begin(), e = LS->end(); i != e; ++i) {
+    LiveInterval &li = i->second;
+    int FI = li.getStackSlotIndex();
+    if (MFI->isDeadObjectIndex(FI))
+      continue;
+    SSIntervals.push_back(&li);
+    OrigAlignments[FI] = MFI->getObjectAlignment(FI);
+    OrigSizes[FI]      = MFI->getObjectSize(FI);
+    AllColors.set(FI);
+  }
+
+  // Sort them by weight.
+  std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter());
+
+  // Get first "color".
+  NextColor = AllColors.find_first();
+  return true;
+}
+
+/// OverlapWithAssignments - Return true if LiveInterval overlaps with any
+/// LiveIntervals that have already been assigned to the specified color.
+bool
+StackSlotColoring::OverlapWithAssignments(LiveInterval *li, int Color) const {
+  const SmallVector<LiveInterval*,4> &OtherLIs = Assignments[Color];
+  for (unsigned i = 0, e = OtherLIs.size(); i != e; ++i) {
+    LiveInterval *OtherLI = OtherLIs[i];
+    if (OtherLI->overlaps(*li))
+      return true;
+  }
+  return false;
+}
+
+/// ColorSlot - Assign a "color" (stack slot) to the specified stack slot.
+///
+int StackSlotColoring::ColorSlot(LiveInterval *li) {
+  int Color = -1;
+  bool Share = false;
+  if (!DisableSharing &&
+      (DeleteLimit == -1 || (int)NumEliminated < DeleteLimit)) {
+    // Check if it's possible to reuse any of the used colors.
+    Color = UsedColors.find_first();
+    while (Color != -1) {
+      if (!OverlapWithAssignments(li, Color)) {
+        Share = true;
+        ++NumEliminated;
+        break;
+      }
+      Color = UsedColors.find_next(Color);
+    }
+  }
+
+  // Assign it to the first available color (assumed to be the best) if it's
+  // not possible to share a used color with other objects.
+  if (!Share) {
+    assert(NextColor != -1 && "No more spill slots?");
+    Color = NextColor;
+    UsedColors.set(Color);
+    NextColor = AllColors.find_next(NextColor);
+  }
+
+  // Record the assignment.
+  Assignments[Color].push_back(li);
+  int FI = li->getStackSlotIndex();
+  DOUT << "Assigning fi #" << FI << " to fi #" << Color << "\n";
+
+  // Change size and alignment of the allocated slot. If there are multiple
+  // objects sharing the same slot, then make sure the size and alignment
+  // are large enough for all.
+  unsigned Align = OrigAlignments[FI];
+  if (!Share || Align > MFI->getObjectAlignment(Color))
+    MFI->setObjectAlignment(Color, Align);
+  int64_t Size = OrigSizes[FI];
+  if (!Share || Size > MFI->getObjectSize(Color))
+    MFI->setObjectSize(Color, Size);
+  return Color;
+}
+
+/// Colorslots - Color all spill stack slots and rewrite all frameindex machine
+/// operands in the function.
+bool StackSlotColoring::ColorSlots(MachineFunction &MF) {
+  unsigned NumObjs = MFI->getObjectIndexEnd();
+  std::vector<int> SlotMapping(NumObjs, -1);
+  SlotMapping.resize(NumObjs, -1);
+
+  bool Changed = false;
+  for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) {
+    LiveInterval *li = SSIntervals[i];
+    int SS = li->getStackSlotIndex();
+    int NewSS = ColorSlot(li);
+    SlotMapping[SS] = NewSS;
+    Changed |= (SS != NewSS);
+  }
+
+  if (!Changed)
+    return false;
+
+  // Rewrite all MO_FrameIndex operands.
+  // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands.
+  for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
+       MBB != E; ++MBB) {
+    for (MachineBasicBlock::iterator MII = MBB->begin(), EE = MBB->end();
+         MII != EE; ++MII) {
+      MachineInstr &MI = *MII;
+      for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
+        MachineOperand &MO = MI.getOperand(i);
+        if (!MO.isFrameIndex())
+          continue;
+        int FI = MO.getIndex();
+        if (FI < 0)
+          continue;
+        FI = SlotMapping[FI];
+        if (FI == -1)
+          continue;
+        MO.setIndex(FI);
+      }
+    }
+  }
+
+  // Delete unused stack slots.
+  while (NextColor != -1) {
+    DOUT << "Removing unused stack object fi #" << NextColor << "\n";
+    MFI->RemoveStackObject(NextColor);
+    NextColor = AllColors.find_next(NextColor);
+  }
+
+  return true;
+}
+
+bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) {
+  DOUT << "******** Stack Slot Coloring ********\n";
+
+  MFI = MF.getFrameInfo();
+  LS = &getAnalysis<LiveStacks>();
+
+  bool Changed = false;
+  if (InitializeSlots())
+    Changed = ColorSlots(MF);
+
+  NextColor = -1;
+  SSIntervals.clear();
+  OrigAlignments.clear();
+  OrigSizes.clear();
+  AllColors.clear();
+  UsedColors.clear();
+  for (unsigned i = 0, e = Assignments.size(); i != e; ++i)
+    Assignments[i].clear();
+  Assignments.clear();
+
+  return Changed;
+}