[llvm-commits] [llvm] r151348 - in /llvm/trunk/lib/CodeGen: ScheduleDAGInstrs.cpp ScheduleDAGInstrs.h

Andrew Trick atrick at apple.com
Thu Feb 23 23:04:55 PST 2012


Author: atrick
Date: Fri Feb 24 01:04:55 2012
New Revision: 151348

URL: http://llvm.org/viewvc/llvm-project?rev=151348&view=rev
Log:
PostRA sched: speed up physreg tracking by not abusing SparseSet.

Modified:
    llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
    llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.h

Modified: llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp?rev=151348&r1=151347&r2=151348&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp (original)
+++ llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp Fri Feb 24 01:04:55 2012
@@ -148,6 +148,20 @@
       LoopRegs.VisitLoop(ML);
 }
 
+/// Initialize the map with the number of registers.
+void ScheduleDAGInstrs::Reg2SUnitsMap::setRegLimit(unsigned Limit) {
+  PhysRegSet.setUniverse(Limit);
+  SUnits.resize(Limit);
+}
+
+/// Clear the map without deallocating storage.
+void ScheduleDAGInstrs::Reg2SUnitsMap::clear() {
+  for (const_iterator I = reg_begin(), E = reg_end(); I != E; ++I) {
+    SUnits[*I].clear();
+  }
+  PhysRegSet.clear();
+}
+
 /// AddSchedBarrierDeps - Add dependencies from instructions in the current
 /// list of instructions being scheduled to scheduling barrier by adding
 /// the exit SU to the register defs and use list. This is because we want to
@@ -171,7 +185,7 @@
       if (Reg == 0) continue;
 
       if (TRI->isPhysicalRegister(Reg))
-        Uses[Reg].SUnits.push_back(&ExitSU);
+        Uses[Reg].push_back(&ExitSU);
       else
         assert(!IsPostRA && "Virtual register encountered after regalloc.");
     }
@@ -185,7 +199,7 @@
              E = (*SI)->livein_end(); I != E; ++I) {
         unsigned Reg = *I;
         if (Seen.insert(Reg))
-          Uses[Reg].SUnits.push_back(&ExitSU);
+          Uses[Reg].push_back(&ExitSU);
       }
   }
 }
@@ -202,10 +216,9 @@
   unsigned DataLatency = SU->Latency;
 
   for (const unsigned *Alias = TRI->getOverlaps(MO.getReg()); *Alias; ++Alias) {
-    Reg2SUnitsMap::iterator UsesI = Uses.find(*Alias);
-    if (UsesI == Uses.end())
+    if (!Uses.contains(*Alias))
       continue;
-    std::vector<SUnit*> &UseList = UsesI->SUnits;
+    std::vector<SUnit*> &UseList = Uses[*Alias];
     for (unsigned i = 0, e = UseList.size(); i != e; ++i) {
       SUnit *UseSU = UseList[i];
       if (UseSU == SU)
@@ -256,10 +269,9 @@
   //       there's no cost for reusing registers.
   SDep::Kind Kind = MO.isUse() ? SDep::Anti : SDep::Output;
   for (const unsigned *Alias = TRI->getOverlaps(MO.getReg()); *Alias; ++Alias) {
-    Reg2SUnitsMap::iterator DefI = Defs.find(*Alias);
-    if (DefI == Defs.end())
+    if (!Defs.contains(*Alias))
       continue;
-    std::vector<SUnit *> &DefList = DefI->SUnits;
+    std::vector<SUnit *> &DefList = Defs[*Alias];
     for (unsigned i = 0, e = DefList.size(); i != e; ++i) {
       SUnit *DefSU = DefList[i];
       if (DefSU == &ExitSU)
@@ -282,14 +294,14 @@
     // Either insert a new Reg2SUnits entry with an empty SUnits list, or
     // retrieve the existing SUnits list for this register's uses.
     // Push this SUnit on the use list.
-    Uses[MO.getReg()].SUnits.push_back(SU);
+    Uses[MO.getReg()].push_back(SU);
   }
   else {
     addPhysRegDataDeps(SU, MO);
 
     // Either insert a new Reg2SUnits entry with an empty SUnits list, or
     // retrieve the existing SUnits list for this register's defs.
-    std::vector<SUnit *> &DefList = Defs[MO.getReg()].SUnits;
+    std::vector<SUnit *> &DefList = Defs[MO.getReg()];
 
     // If a def is going to wrap back around to the top of the loop,
     // backschedule it.
@@ -339,9 +351,8 @@
     }
 
     // clear this register's use list
-    Reg2SUnitsMap::iterator UsesI = Uses.find(MO.getReg());
-    if (UsesI != Uses.end())
-      UsesI->SUnits.clear();
+    if (Uses.contains(MO.getReg()))
+      Uses[MO.getReg()].clear();
 
     if (!MO.isDead())
       DefList.clear();
@@ -495,8 +506,8 @@
 
   assert(Defs.empty() && Uses.empty() &&
          "Only BuildGraph should update Defs/Uses");
-  Defs.setUniverse(TRI->getNumRegs());
-  Uses.setUniverse(TRI->getNumRegs());
+  Defs.setRegLimit(TRI->getNumRegs());
+  Uses.setRegLimit(TRI->getNumRegs());
 
   assert(VRegDefs.empty() && "Only BuildSchedGraph may access VRegDefs");
   // FIXME: Allow SparseSet to reserve space for the creation of virtual

Modified: llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.h?rev=151348&r1=151347&r2=151348&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.h (original)
+++ llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.h Fri Feb 24 01:04:55 2012
@@ -118,15 +118,57 @@
     /// the def-side latency only.
     bool UnitLatencies;
 
-    /// An individual mapping from physical register number to an SUnit vector.
-    struct Reg2SUnits {
-      unsigned PhysReg;
-      std::vector<SUnit*> SUnits;
-
-      explicit Reg2SUnits(unsigned reg): PhysReg(reg) {}
+    /// Combine a SparseSet with a 1x1 vector to track physical registers.
+    /// The SparseSet allows iterating over the (few) live registers for quickly
+    /// comparing against a regmask or clearing the set.
+    ///
+    /// Storage for the map is allocated once for the pass. The map can be
+    /// cleared between scheduling regions without freeing unused entries.
+    class Reg2SUnitsMap {
+      SparseSet<unsigned> PhysRegSet;
+      std::vector<std::vector<SUnit*> > SUnits;
+    public:
+      typedef SparseSet<unsigned>::const_iterator const_iterator;
+
+      // Allow iteration over register numbers (keys) in the map. If needed, we
+      // can provide an iterator over SUnits (values) as well.
+      const_iterator reg_begin() const { return PhysRegSet.begin(); }
+      const_iterator reg_end() const { return PhysRegSet.end(); }
+
+      /// Initialize the map with the number of registers.
+      /// If the map is already large enough, no allocation occurs.
+      /// For simplicity we expect the map to be empty().
+      void setRegLimit(unsigned Limit);
+
+      /// Returns true if the map is empty.
+      bool empty() const { return PhysRegSet.empty(); }
+
+      /// Clear the map without deallocating storage.
+      void clear();
+
+      bool contains(unsigned Reg) const { return PhysRegSet.count(Reg); }
+
+      /// If this register is mapped, return its existing SUnits vector.
+      /// Otherwise map the register and return an empty SUnits vector.
+      std::vector<SUnit *> &operator[](unsigned Reg) {
+        bool New = PhysRegSet.insert(Reg).second;
+        assert(!New || SUnits[Reg].empty() && "stale SUnits vector");
+        (void)New;
+        return SUnits[Reg];
+      }
 
-      unsigned getSparseSetKey() const { return PhysReg; }
+      /// Erase an existing element without freeing memory.
+      void erase(unsigned Reg) {
+        PhysRegSet.erase(Reg);
+        SUnits[Reg].clear();
+      }
     };
+    /// Defs, Uses - Remember where defs and uses of each register are as we
+    /// iterate upward through the instructions. This is allocated here instead
+    /// of inside BuildSchedGraph to avoid the need for it to be initialized and
+    /// destructed for each block.
+    Reg2SUnitsMap Defs;
+    Reg2SUnitsMap Uses;
 
     /// An individual mapping from virtual register number to SUnit.
     struct VReg2SUnit {
@@ -139,20 +181,12 @@
         return TargetRegisterInfo::virtReg2Index(VirtReg);
       }
     };
-    // Use SparseSet as a SparseMap by relying on the fact that it never
-    // compares ValueT's, only unsigned keys. This allows the set to be cleared
-    // between scheduling regions in constant time.
-    typedef SparseSet<Reg2SUnits> Reg2SUnitsMap;
+    /// Use SparseSet as a SparseMap by relying on the fact that it never
+    /// compares ValueT's, only unsigned keys. This allows the set to be cleared
+    /// between scheduling regions in constant time as long as ValueT does not
+    /// require a destructor.
     typedef SparseSet<VReg2SUnit> VReg2SUnitMap;
-
-    /// Defs, Uses - Remember where defs and uses of each register are as we
-    /// iterate upward through the instructions. This is allocated here instead
-    /// of inside BuildSchedGraph to avoid the need for it to be initialized and
-    /// destructed for each block.
-    Reg2SUnitsMap Defs;
-    Reg2SUnitsMap Uses;
-
-    // Track the last instructon in this region defining each virtual register.
+    /// Track the last instructon in this region defining each virtual register.
     VReg2SUnitMap VRegDefs;
 
     /// PendingLoads - Remember where unknown loads are after the most recent





More information about the llvm-commits mailing list