Simplify by using isFullCopy().
[oota-llvm.git] / lib / CodeGen / RenderMachineFunction.cpp
index 6520449a79a613ab8d87b1e9f5efd953c9697154..8b02ec44273a99aa680ef345349b54619f9d31ef 100644 (file)
@@ -11,6 +11,8 @@
 
 #include "RenderMachineFunction.h"
 
+#include "VirtRegMap.h"
+
 #include "llvm/Function.h"
 #include "llvm/Module.h"
 #include "llvm/ADT/SmallVector.h"
 using namespace llvm;
 
 char RenderMachineFunction::ID = 0;
-static RegisterPass<RenderMachineFunction>
-X("rendermf", "Render machine functions (and related info) to HTML pages");
+INITIALIZE_PASS_BEGIN(RenderMachineFunction, "rendermf",
+                "Render machine functions (and related info) to HTML pages",
+                false, false)
+INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
+INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
+INITIALIZE_PASS_END(RenderMachineFunction, "rendermf",
+                "Render machine functions (and related info) to HTML pages",
+                false, false)
 
 static cl::opt<std::string>
 outputFileSuffix("rmf-file-suffix",
@@ -39,7 +47,7 @@ outputFileSuffix("rmf-file-suffix",
 
 static cl::opt<std::string>
 machineFuncsToRender("rmf-funcs",
-                     cl::desc("Coma seperated list of functions to render"
+                     cl::desc("Comma separated list of functions to render"
                               ", or \"*\"."),
                      cl::init(""), cl::Hidden);
 
@@ -53,6 +61,11 @@ showIntervals("rmf-intervals",
               cl::desc("Live intervals to show alongside code."),
               cl::init(""), cl::Hidden);
 
+static cl::opt<bool>
+filterEmpty("rmf-filter-empty-intervals",
+            cl::desc("Don't display empty intervals."),
+            cl::init(true), cl::Hidden);
+
 static cl::opt<bool>
 showEmptyIndexes("rmf-empty-indexes",
                  cl::desc("Render indexes not associated with instructions or "
@@ -64,6 +77,12 @@ useFancyVerticals("rmf-fancy-verts",
                   cl::desc("Use SVG for vertical text."),
                   cl::init(true), cl::Hidden);
 
+static cl::opt<bool>
+prettyHTML("rmf-pretty-html",
+           cl::desc("Pretty print HTML. For debugging the renderer only.."),
+           cl::init(false), cl::Hidden);
+
+
 namespace llvm {
 
   bool MFRenderingOptions::renderingOptionsProcessed;
@@ -141,10 +160,14 @@ namespace llvm {
                                           const std::string &intervalRangeStr) {
     if (intervalRangeStr == "*") {
       intervalTypesToRender |= All;
+    } else if (intervalRangeStr == "virt-nospills*") {
+      intervalTypesToRender |= VirtNoSpills;
+    } else if (intervalRangeStr == "spills*") {
+      intervalTypesToRender |= VirtSpills;
     } else if (intervalRangeStr == "virt*") {
-      intervalTypesToRender |= VirtPlusExplicit;
+      intervalTypesToRender |= AllVirt;
     } else if (intervalRangeStr == "phys*") {
-      intervalTypesToRender |= PhysPlusExplicit;
+      intervalTypesToRender |= AllPhys;
     } else {
       std::istringstream iss(intervalRangeStr);
       unsigned reg1, reg2;
@@ -170,10 +193,12 @@ namespace llvm {
 
   void MFRenderingOptions::setup(MachineFunction *mf,
                                  const TargetRegisterInfo *tri,
-                                 LiveIntervals *lis) {
+                                 LiveIntervals *lis,
+                                 const RenderMachineFunction *rmf) {
     this->mf = mf;
     this->tri = tri;
     this->lis = lis;
+    this->rmf = rmf;
 
     clear();
   }
@@ -243,12 +268,19 @@ namespace llvm {
       if (intervalTypesToRender != ExplicitOnly) {
         for (LiveIntervals::iterator liItr = lis->begin(), liEnd = lis->end();
              liItr != liEnd; ++liItr) {
-
-          if ((TargetRegisterInfo::isPhysicalRegister(liItr->first) &&
-               (intervalTypesToRender & PhysPlusExplicit)) ||
-              (TargetRegisterInfo::isVirtualRegister(liItr->first) &&
-               (intervalTypesToRender & VirtPlusExplicit))) {
-            intervalSet.insert(liItr->second);
+          LiveInterval *li = liItr->second;
+
+          if (filterEmpty && li->empty())
+            continue;
+
+          if ((TargetRegisterInfo::isPhysicalRegister(li->reg) &&
+               (intervalTypesToRender & AllPhys))) {
+            intervalSet.insert(li);
+          } else if (TargetRegisterInfo::isVirtualRegister(li->reg)) {
+            if (((intervalTypesToRender & VirtNoSpills) && !rmf->isSpill(li)) || 
+                ((intervalTypesToRender & VirtSpills) && rmf->isSpill(li))) {
+              intervalSet.insert(li);
+            }
           }
         }
       }
@@ -402,8 +434,7 @@ namespace llvm {
            rcEnd = tri->regclass_end();
          rcItr != rcEnd; ++rcItr) {
       const TargetRegisterClass *trc = *rcItr;
-      unsigned capacity = std::distance(trc->allocation_order_begin(*mf),
-                                        trc->allocation_order_end(*mf));
+      unsigned capacity = trc->getRawAllocationOrder(*mf).size();
 
       if (capacity != 0)
         capacityMap[trc] = capacity;
@@ -431,14 +462,9 @@ namespace llvm {
          liItr != liEnd; ++liItr) {
       LiveInterval *li = liItr->second;
 
-      const TargetRegisterClass *liTRC;
-
       if (TargetRegisterInfo::isPhysicalRegister(li->reg))
         continue;
       
-      liTRC = mri->getRegClass(li->reg);
-     
-
       // For all ranges in the current interal.
       for (LiveInterval::iterator lrItr = li->begin(),
              lrEnd = li->end();
@@ -455,8 +481,7 @@ namespace llvm {
                rcItr != rcEnd; ++rcItr) {
             const TargetRegisterClass *trc = *rcItr;
 
-            if (trc->allocation_order_begin(*mf) ==
-                trc->allocation_order_end(*mf))
+            if (trc->getRawAllocationOrder(*mf).empty())
               continue;
 
             unsigned worstAtI = getWorst(li->reg, trc);
@@ -491,6 +516,23 @@ namespace llvm {
 
   // ---------- MachineFunctionRenderer implementation ----------
 
+  void RenderMachineFunction::Spacer::print(raw_ostream &os) const {
+    if (!prettyHTML)
+      return;
+    for (unsigned i = 0; i < ns; ++i) {
+      os << " ";
+    }
+  }
+
+  RenderMachineFunction::Spacer RenderMachineFunction::s(unsigned ns) const {
+    return Spacer(ns);
+  }
+
+  raw_ostream& operator<<(raw_ostream &os, const RenderMachineFunction::Spacer &s) {
+    s.print(os);
+    return os;
+  }
+
   template <typename Iterator>
   std::string RenderMachineFunction::escapeChars(Iterator sBegin, Iterator sEnd) const {
     std::string r;
@@ -511,23 +553,95 @@ namespace llvm {
     return r;
   }
 
-  template <typename OStream, typename T>
-  void RenderMachineFunction::renderVertical(const std::string &indent,
-                                             OStream &os,
+  RenderMachineFunction::LiveState
+  RenderMachineFunction::getLiveStateAt(const LiveInterval *li,
+                                        SlotIndex i) const {
+    const MachineInstr *mi = sis->getInstructionFromIndex(i);
+
+    // For uses/defs recorded use/def indexes override current liveness and
+    // instruction operands (Only for the interval which records the indexes).
+    if (i.isUse() || i.isDef()) {
+      UseDefs::const_iterator udItr = useDefs.find(li);
+      if (udItr != useDefs.end()) {
+        const SlotSet &slotSet = udItr->second;
+        if (slotSet.count(i)) {
+          if (i.isUse()) {
+            return Used;
+          }
+          // else
+          return Defined;
+        }
+      }
+    }
+
+    // If the slot is a load/store, or there's no info in the use/def set then
+    // use liveness and instruction operand info.
+    if (li->liveAt(i)) {
+
+      if (mi == 0) {
+        if (vrm == 0 || 
+            (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
+          return AliveReg;
+        } else {
+          return AliveStack;
+        }
+      } else {
+        if (i.isDef() && mi->definesRegister(li->reg, tri)) {
+          return Defined;
+        } else if (i.isUse() && mi->readsRegister(li->reg)) {
+          return Used;
+        } else {
+          if (vrm == 0 || 
+              (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
+            return AliveReg;
+          } else {
+            return AliveStack;
+          }
+        }
+      }
+    }
+    return Dead;
+  }
+
+  RenderMachineFunction::PressureState
+  RenderMachineFunction::getPressureStateAt(const TargetRegisterClass *trc,
+                                              SlotIndex i) const {
+    if (trei.getPressureAtSlot(trc, i) == 0) {
+      return Zero;
+    } else if (trei.classOverCapacityAtSlot(trc, i)){
+      return High;
+    }
+    return Low;
+  }
+
+  /// \brief Render a machine instruction.
+  void RenderMachineFunction::renderMachineInstr(raw_ostream &os,
+                                                 const MachineInstr *mi) const {
+    std::string s;
+    raw_string_ostream oss(s);
+    oss << *mi;
+
+    os << escapeChars(oss.str());
+  }
+
+  template <typename T>
+  void RenderMachineFunction::renderVertical(const Spacer &indent,
+                                             raw_ostream &os,
                                              const T &t) const {
     if (ro.fancyVerticals()) {
       os << indent << "<object\n"
-         << indent << "  class=\"obj\"\n"
-         << indent << "  type=\"image/svg+xml\"\n"
-         << indent << "  width=\"14px\"\n"
-         << indent << "  height=\"55px\"\n"
-         << indent << "  data=\"data:image/svg+xml,\n"
-         << indent << "    <svg xmlns='http://www.w3.org/2000/svg'>\n"
-         << indent << "      <text x='-55' y='10' "
-                      "font-family='Courier' font-size='12' "
-                      "transform='rotate(-90)' text-rendering='optimizeSpeed' "
-                      "fill='#000'>" << t << "</text>\n"
-         << indent << "    </svg>\">\n"
+         << indent + s(2) << "class=\"obj\"\n"
+         << indent + s(2) << "type=\"image/svg+xml\"\n"
+         << indent + s(2) << "width=\"14px\"\n"
+         << indent + s(2) << "height=\"55px\"\n"
+         << indent + s(2) << "data=\"data:image/svg+xml,\n"
+         << indent + s(4) << "<svg xmlns='http://www.w3.org/2000/svg'>\n"
+         << indent + s(6) << "<text x='-55' y='10' "
+                             "font-family='Courier' font-size='12' "
+                             "transform='rotate(-90)' "
+                             "text-rendering='optimizeSpeed' "
+                             "fill='#000'>" << t << "</text>\n"
+         << indent + s(4) << "</svg>\">\n"
          << indent << "</object>\n";
     } else {
       std::ostringstream oss;
@@ -537,35 +651,34 @@ namespace llvm {
       os << indent;
       for (std::string::iterator tStrItr = tStr.begin(), tStrEnd = tStr.end();
            tStrItr != tStrEnd; ++tStrItr) {
-        os << *tStrItr << "<br/> ";
+        os << *tStrItr << "<br/>";
       }
       os << "\n";
     }
   }
 
-  template <typename OStream>
-  void RenderMachineFunction::insertCSS(const std::string &indent,
-                                        OStream &os) const {
+  void RenderMachineFunction::insertCSS(const Spacer &indent,
+                                        raw_ostream &os) const {
     os << indent << "<style type=\"text/css\">\n"
-       << indent << "  body { font-color: black; }\n"
-       << indent << "  table.code td { font-family: monospace; "
+       << indent + s(2) << "body { font-color: black; }\n"
+       << indent + s(2) << "table.code td { font-family: monospace; "
                     "border-width: 0px; border-style: solid; "
                     "border-bottom: 1px solid #dddddd; white-space: nowrap; }\n"
-       << indent << "  table.code td.s-zp { background-color: #000000; }\n"
-       << indent << "  table.code td.s-up { background-color: #00ff00; }\n"
-       << indent << "  table.code td.s-op { background-color: #ff0000; }\n"
-       << indent << "  table.code td.l-na { background-color: #ffffff; }\n"
-       << indent << "  table.code td.l-def { background-color: #ff0000; }\n"
-       << indent << "  table.code td.l-use { background-color: #ffff00; }\n"
-       << indent << "  table.code td.l-sa { background-color: #000000; }\n"
-       << indent << "  table.code th { border-width: 0px; "
+       << indent + s(2) << "table.code td.p-z { background-color: #000000; }\n"
+       << indent + s(2) << "table.code td.p-l { background-color: #00ff00; }\n"
+       << indent + s(2) << "table.code td.p-h { background-color: #ff0000; }\n"
+       << indent + s(2) << "table.code td.l-n { background-color: #ffffff; }\n"
+       << indent + s(2) << "table.code td.l-d { background-color: #ff0000; }\n"
+       << indent + s(2) << "table.code td.l-u { background-color: #ffff00; }\n"
+       << indent + s(2) << "table.code td.l-r { background-color: #000000; }\n"
+       << indent + s(2) << "table.code td.l-s { background-color: #770000; }\n"
+       << indent + s(2) << "table.code th { border-width: 0px; "
                     "border-style: solid; }\n"
        << indent << "</style>\n";
   }
 
-  template <typename OStream>
   void RenderMachineFunction::renderFunctionSummary(
-                                    const std::string &indent, OStream &os,
+                                    const Spacer &indent, raw_ostream &os,
                                     const char * const renderContextStr) const {
     os << indent << "<h1>Function: " << mf->getFunction()->getName()
                  << "</h1>\n"
@@ -573,61 +686,97 @@ namespace llvm {
   }
 
 
-  template <typename OStream>
   void RenderMachineFunction::renderPressureTableLegend(
-                                                      const std::string &indent,
-                                                      OStream &os) const {
+                                                      const Spacer &indent,
+                                                      raw_ostream &os) const {
     os << indent << "<h2>Rendering Pressure Legend:</h2>\n"
        << indent << "<table class=\"code\">\n"
-       << indent << "  <tr>\n"
-       << indent << "    <th>Pressure</th><th>Description</th>"
+       << indent + s(2) << "<tr>\n"
+       << indent + s(4) << "<th>Pressure</th><th>Description</th>"
                     "<th>Appearance</th>\n"
-       << indent << "  </tr>\n"
-       << indent << "  <tr>\n"
-       << indent << "    <td>No Pressure</td>"
-                    "    <td>No physical registers of this class requested.</td>"
-                    "    <td class=\"s-zp\">&nbsp;&nbsp;</td>\n"
-       << indent << "  </tr>\n"
-       << indent << "  <tr>\n"
-       << indent << "    <td>Low Pressure</td>"
-                    "    <td>Sufficient physical registers to meet demand.</td>"
-                    "    <td class=\"s-up\">&nbsp;&nbsp;</td>\n"
-       << indent << "  </tr>\n"
-       << indent << "  <tr>\n"
-       << indent << "    <td>High Pressure</td>"
-                    "    <td>Potentially insufficient physical registers to meet demand.</td>"
-                    "    <td class=\"s-op\">&nbsp;&nbsp;</td>\n"
-       << indent << "  </tr>\n"
+       << indent + s(2) << "</tr>\n"
+       << indent + s(2) << "<tr>\n"
+       << indent + s(4) << "<td>No Pressure</td>"
+                    "<td>No physical registers of this class requested.</td>"
+                    "<td class=\"p-z\">&nbsp;&nbsp;</td>\n"
+       << indent + s(2) << "</tr>\n"
+       << indent + s(2) << "<tr>\n"
+       << indent + s(4) << "<td>Low Pressure</td>"
+                    "<td>Sufficient physical registers to meet demand.</td>"
+                    "<td class=\"p-l\">&nbsp;&nbsp;</td>\n"
+       << indent + s(2) << "</tr>\n"
+       << indent + s(2) << "<tr>\n"
+       << indent + s(4) << "<td>High Pressure</td>"
+                    "<td>Potentially insufficient physical registers to meet demand.</td>"
+                    "<td class=\"p-h\">&nbsp;&nbsp;</td>\n"
+       << indent + s(2) << "</tr>\n"
        << indent << "</table>\n";
   }
 
-  template <typename OStream>
-  void RenderMachineFunction::renderCodeTablePlusPI(const std::string & indent,
-                                                    OStream &os) const {
+  template <typename CellType>
+  void RenderMachineFunction::renderCellsWithRLE(
+                   const Spacer &indent, raw_ostream &os,
+                   const std::pair<CellType, unsigned> &rleAccumulator,
+                   const std::map<CellType, std::string> &cellTypeStrs) const {
+
+    if (rleAccumulator.second == 0)
+      return; 
+
+    typename std::map<CellType, std::string>::const_iterator ctsItr =
+      cellTypeStrs.find(rleAccumulator.first);
+
+    assert(ctsItr != cellTypeStrs.end() && "No string for given cell type.");
+
+    os << indent + s(4) << "<td class=\"" << ctsItr->second << "\"";
+    if (rleAccumulator.second > 1)
+      os << " colspan=" << rleAccumulator.second;
+    os << "></td>\n";
+  }
+
+
+  void RenderMachineFunction::renderCodeTablePlusPI(const Spacer &indent,
+                                                    raw_ostream &os) const {
+
+    std::map<LiveState, std::string> lsStrs;
+    lsStrs[Dead] = "l-n";
+    lsStrs[Defined] = "l-d";
+    lsStrs[Used] = "l-u";
+    lsStrs[AliveReg] = "l-r";
+    lsStrs[AliveStack] = "l-s";
+
+    std::map<PressureState, std::string> psStrs;
+    psStrs[Zero] = "p-z";
+    psStrs[Low] = "p-l";
+    psStrs[High] = "p-h";
+
+    // Open the table... 
 
     os << indent << "<table cellpadding=0 cellspacing=0 class=\"code\">\n"
-       << indent << "  <tr>\n"
-       << indent << "    <th>index</th>\n"
-       << indent << "    <th>instr</th>\n";
+       << indent + s(2) << "<tr>\n";
+
+    // Render the header row...
 
-    // Header row:
-       
+    os << indent + s(4) << "<th>index</th>\n"
+       << indent + s(4) << "<th>instr</th>\n";
+
+    // Render class names if necessary...
     if (!ro.regClasses().empty()) {
       for (MFRenderingOptions::RegClassSet::const_iterator
              rcItr = ro.regClasses().begin(),
              rcEnd = ro.regClasses().end();
            rcItr != rcEnd; ++rcItr) {
         const TargetRegisterClass *trc = *rcItr;
-        os << indent << "    <th>\n";
-        renderVertical(indent + "      ", os, trc->getName());
-        os << indent << "    </th>\n";
+        os << indent + s(4) << "<th>\n";
+        renderVertical(indent + s(6), os, trc->getName());
+        os << indent + s(4) << "</th>\n";
       }
     }
 
     // FIXME: Is there a nicer way to insert space between columns in HTML?
     if (!ro.regClasses().empty() && !ro.intervals().empty())
-      os << indent << "    <th>&nbsp;&nbsp;</th>\n";
+      os << indent + s(4) << "<th>&nbsp;&nbsp;</th>\n";
 
+    // Render interval numbers if necessary...
     if (!ro.intervals().empty()) {
       for (MFRenderingOptions::IntervalSet::const_iterator
              liItr = ro.intervals().begin(),
@@ -635,98 +784,95 @@ namespace llvm {
            liItr != liEnd; ++liItr) {
 
         const LiveInterval *li = *liItr;
-        os << indent << "    <th>\n";
-        renderVertical(indent + "      ", os, li->reg);
-        os << indent << "    </th>\n";
+        os << indent + s(4) << "<th>\n";
+        renderVertical(indent + s(6), os, li->reg);
+        os << indent + s(4) << "</th>\n";
       }
     }
 
-    os << indent << "  </tr>\n";
+    os << indent + s(2) << "</tr>\n";
+
+    // End header row, start with the data rows...
 
     MachineInstr *mi = 0;
 
     // Data rows:
     for (SlotIndex i = sis->getZeroIndex(); i != sis->getLastIndex();
          i = i.getNextSlot()) {
+     
+      // Render the slot column. 
+      os << indent + s(2) << "<tr height=6ex>\n";
       
-      os << indent << "  <tr height=6ex>\n";
-      
-      if (i.getSlot() == SlotIndex::LOAD) {
+      // Render the code column.
+      if (i.isLoad()) {
         MachineBasicBlock *mbb = sis->getMBBFromIndex(i);
         mi = sis->getInstructionFromIndex(i);
 
         if (i == sis->getMBBStartIdx(mbb) || mi != 0 ||
             ro.renderEmptyIndexes()) {
-          os << indent << "    <td rowspan=4>" << i << "&nbsp;</td>\n"
-             << indent << "    <td rowspan=4>\n";
+          os << indent + s(4) << "<td rowspan=4>" << i << "&nbsp;</td>\n"
+             << indent + s(4) << "<td rowspan=4>\n";
 
           if (i == sis->getMBBStartIdx(mbb)) {
-            os << indent << "      BB#" << mbb->getNumber() << ":&nbsp;\n";
+            os << indent + s(6) << "BB#" << mbb->getNumber() << ":&nbsp;\n";
           } else if (mi != 0) {
-            os << indent << "      &nbsp;&nbsp;" << escapeChars(mi) << "\n";
+            os << indent + s(6) << "&nbsp;&nbsp;";
+            renderMachineInstr(os, mi);
           } else {
-            os << indent << "      &nbsp;\n";
+            // Empty interval - leave blank.
           }
-          os << indent << "    </td>\n";
+          os << indent + s(4) << "</td>\n";
         } else {
           i = i.getStoreIndex(); // <- Will be incremented to the next index.
           continue;
         }
       }
 
+      // Render the class columns.
       if (!ro.regClasses().empty()) {
+        std::pair<PressureState, unsigned> psRLEAccumulator(Zero, 0);
         for (MFRenderingOptions::RegClassSet::const_iterator
                rcItr = ro.regClasses().begin(),
                rcEnd = ro.regClasses().end();
              rcItr != rcEnd; ++rcItr) {
           const TargetRegisterClass *trc = *rcItr;
+          PressureState newPressure = getPressureStateAt(trc, i);
 
-          os << indent << "    <td class=\"";
-
-          if (trei.getPressureAtSlot(trc, i) == 0) {
-            os << "s-zp";
-          } else if (trei.classOverCapacityAtSlot(trc, i)){
-            os << "s-op";
+          if (newPressure == psRLEAccumulator.first) {
+            ++psRLEAccumulator.second;
           } else {
-            os << "s-up";
+            renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
+            psRLEAccumulator.first = newPressure;
+            psRLEAccumulator.second = 1;
           }
-
-          os << "\"></td>\n";
         }
+        renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
       }
   
       // FIXME: Is there a nicer way to insert space between columns in HTML?
       if (!ro.regClasses().empty() && !ro.intervals().empty())
-        os << indent << "    <td width=2em></td>\n";
+        os << indent + s(4) << "<td width=2em></td>\n";
 
       if (!ro.intervals().empty()) {
+        std::pair<LiveState, unsigned> lsRLEAccumulator(Dead, 0);
         for (MFRenderingOptions::IntervalSet::const_iterator
                liItr = ro.intervals().begin(),
                liEnd = ro.intervals().end();
              liItr != liEnd; ++liItr) {
           const LiveInterval *li = *liItr;
-          os << indent << "    <td class=\"";
-          if (li->liveAt(i)) {
-            if (mi == 0) {
-              os << "l-sa";
-            } else {
-              if (i.getSlot() == SlotIndex::DEF &&
-                  mi->definesRegister(li->reg, tri)) {
-                os << "l-def";
-              } else if (i.getSlot() == SlotIndex::USE &&
-                         mi->readsRegister(li->reg)) {
-                os << "l-use";
-              } else {
-                os << "l-sa";
-              }
-            }
+          LiveState newLiveness = getLiveStateAt(li, i);
+
+          if (newLiveness == lsRLEAccumulator.first) {
+            ++lsRLEAccumulator.second;
           } else {
-            os << "l-na";
+            renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
+            lsRLEAccumulator.first = newLiveness;
+            lsRLEAccumulator.second = 1;
           }
-          os << "\"></td>\n";
         }
+        renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
       }
-      os << indent << "  </tr>\n";
+      os << indent + s(2) << "</tr>\n";
     }
 
     os << indent << "</table>\n";
@@ -735,35 +881,29 @@ namespace llvm {
       renderPressureTableLegend(indent, os);
   }
 
-  template <typename OStream>
-  void RenderMachineFunction::renderWarnings(const std::string &indent,
-                                             OStream &os) const {
-  }
-
-  template <typename OStream>
   void RenderMachineFunction::renderFunctionPage(
-                                    OStream &os,
+                                    raw_ostream &os,
                                     const char * const renderContextStr) const {
     os << "<html>\n"
-       << "  <head>\n"
-       << "    <title>" << fqn << "</title>\n";
+       << s(2) << "<head>\n"
+       << s(4) << "<title>" << fqn << "</title>\n";
 
-    insertCSS("    ", os);
+    insertCSS(s(4), os);
 
-    os << "  <head>\n"
-       << "  <body >\n";
+    os << s(2) << "<head>\n"
+       << s(2) << "<body >\n";
 
-    renderFunctionSummary("    ", os, renderContextStr);
+    renderFunctionSummary(s(4), os, renderContextStr);
 
-    os << "    <br/><br/><br/>\n";
+    os << s(4) << "<br/><br/><br/>\n";
 
     //renderLiveIntervalInfoTable("    ", os);
 
-    os << "    <br/><br/><br/>\n";
+    os << s(4) << "<br/><br/><br/>\n";
 
-    renderCodeTablePlusPI("    ", os);
+    renderCodeTablePlusPI(s(4), os);
 
-    os << "  </body>\n"
+    os << s(2) << "</body>\n"
        << "</html>\n";
   }
 
@@ -775,6 +915,7 @@ namespace llvm {
   }
 
   bool RenderMachineFunction::runOnMachineFunction(MachineFunction &fn) {
+
     mf = &fn;
     mri = &mf->getRegInfo();
     tri = mf->getTarget().getRegisterInfo();
@@ -782,7 +923,10 @@ namespace llvm {
     sis = &getAnalysis<SlotIndexes>();
 
     trei.setup(mf, mri, tri, lis);
-    ro.setup(mf, tri, lis);
+    ro.setup(mf, tri, lis, this);
+    spillIntervals.clear();
+    spillFor.clear();
+    useDefs.clear();
 
     fqn = mf->getFunction()->getParent()->getModuleIdentifier() + "." +
           mf->getFunction()->getName().str();
@@ -793,14 +937,60 @@ namespace llvm {
   void RenderMachineFunction::releaseMemory() {
     trei.clear();
     ro.clear();
+    spillIntervals.clear();
+    spillFor.clear();
+    useDefs.clear();
+  }
+
+  void RenderMachineFunction::rememberUseDefs(const LiveInterval *li) {
+
+    if (!ro.shouldRenderCurrentMachineFunction())
+      return; 
+
+    for (MachineRegisterInfo::reg_iterator rItr = mri->reg_begin(li->reg),
+                                           rEnd = mri->reg_end();
+         rItr != rEnd; ++rItr) {
+      const MachineInstr *mi = &*rItr;
+      if (mi->readsRegister(li->reg)) {
+        useDefs[li].insert(lis->getInstructionIndex(mi).getUseIndex());
+      }
+      if (mi->definesRegister(li->reg)) {
+        useDefs[li].insert(lis->getInstructionIndex(mi).getDefIndex());
+      }
+    }
+  }
+
+  void RenderMachineFunction::rememberSpills(
+                                     const LiveInterval *li,
+                                     const std::vector<LiveInterval*> &spills) {
+
+    if (!ro.shouldRenderCurrentMachineFunction())
+      return; 
+
+    for (std::vector<LiveInterval*>::const_iterator siItr = spills.begin(),
+                                                    siEnd = spills.end();
+         siItr != siEnd; ++siItr) {
+      const LiveInterval *spill = *siItr;
+      spillIntervals[li].insert(spill);
+      spillFor[spill] = li;
+    }
+  }
+
+  bool RenderMachineFunction::isSpill(const LiveInterval *li) const {
+    SpillForMap::const_iterator sfItr = spillFor.find(li);
+    if (sfItr == spillFor.end())
+      return false;
+    return true;
   }
 
   void RenderMachineFunction::renderMachineFunction(
                                                    const char *renderContextStr,
+                                                   const VirtRegMap *vrm,
                                                    const char *renderSuffix) {
     if (!ro.shouldRenderCurrentMachineFunction())
       return; 
 
+    this->vrm = vrm;
     trei.reset();
 
     std::string rpFileName(mf->getFunction()->getName().str() +
@@ -815,20 +1005,8 @@ namespace llvm {
     ro.resetRenderSpecificOptions();
   }
 
-  void RenderMachineFunction::setupRenderingOptions() {
-
-  }
-
   std::string RenderMachineFunction::escapeChars(const std::string &s) const {
     return escapeChars(s.begin(), s.end());
   }
 
-  std::string RenderMachineFunction::escapeChars(const MachineInstr *mi) const {
-    std::string s;
-    raw_string_ostream os(s);
-    os << *mi;
-    std::string s2 = os.str();
-    return escapeChars(s2);
-  }
-
 }