[llvm] r227682 - Replace another std::set in the core of CodeGenRegister, this time with sorted arrays.

Owen Anderson resistor at mac.com
Sat Jan 31 01:13:36 PST 2015


Author: resistor
Date: Sat Jan 31 03:13:36 2015
New Revision: 227682

URL: http://llvm.org/viewvc/llvm-project?rev=227682&view=rev
Log:
Replace another std::set in the core of CodeGenRegister, this time with sorted arrays.

The hot path through this region of code does lots of batch inserts into sets. By storing them as sorted arrays, we can defer the sorting to the end of the batch, which is dramatically more efficient. This reduces tblgen runtime by 25% on my worst-case target.

Modified:
    llvm/trunk/utils/TableGen/CodeGenRegisters.cpp
    llvm/trunk/utils/TableGen/CodeGenRegisters.h
    llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp

Modified: llvm/trunk/utils/TableGen/CodeGenRegisters.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.cpp?rev=227682&r1=227681&r2=227682&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenRegisters.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenRegisters.cpp Sat Jan 31 03:13:36 2015
@@ -152,11 +152,11 @@ const std::string &CodeGenRegister::getN
 namespace {
 // Iterate over all register units in a set of registers.
 class RegUnitIterator {
-  CodeGenRegister::Set::const_iterator RegI, RegE;
+  CodeGenRegister::Vec::const_iterator RegI, RegE;
   CodeGenRegister::RegUnitList::iterator UnitI, UnitE;
 
 public:
-  RegUnitIterator(const CodeGenRegister::Set &Regs):
+  RegUnitIterator(const CodeGenRegister::Vec &Regs):
     RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() {
 
     if (RegI != RegE) {
@@ -642,6 +642,11 @@ struct TupleExpander : SetTheory::Expand
 //                            CodeGenRegisterClass
 //===----------------------------------------------------------------------===//
 
+static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) {
+  std::sort(M.begin(), M.end(), CodeGenRegister::Less());
+  M.erase(std::unique(M.begin(), M.end(), CodeGenRegister::Equal()), M.end());
+}
+
 CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
   : TheDef(R),
     Name(R->getName()),
@@ -675,9 +680,10 @@ CodeGenRegisterClass::CodeGenRegisterCla
   for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
     Orders[0].push_back((*Elements)[i]);
     const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]);
-    Members.insert(Reg);
+    Members.push_back(Reg);
     TopoSigs.set(Reg->getTopoSig());
   }
+  sortAndUniqueRegisters(Members);
 
   // Alternative allocation orders may be subsets.
   SetTheory::RecSet Order;
@@ -719,9 +725,8 @@ CodeGenRegisterClass::CodeGenRegisterCla
     SpillAlignment(Props.SpillAlignment),
     CopyCost(0),
     Allocatable(true) {
-  for (CodeGenRegister::Set::iterator I = Members.begin(), E = Members.end();
-       I != E; ++I)
-    TopoSigs.set((*I)->getTopoSig());
+  for (const auto R : Members)
+    TopoSigs.set(R->getTopoSig());
 }
 
 // Compute inherited propertied for a synthesized register class.
@@ -750,15 +755,15 @@ void CodeGenRegisterClass::inheritProper
 }
 
 bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
-  return Members.count(Reg);
+  return std::binary_search(Members.begin(), Members.end(), Reg,
+                            CodeGenRegister::Less());
 }
 
 namespace llvm {
   raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
     OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
-    for (CodeGenRegister::Set::const_iterator I = K.Members->begin(),
-         E = K.Members->end(); I != E; ++I)
-      OS << ", " << (*I)->getName();
+    for (const auto R : *K.Members)
+      OS << ", " << R->getName();
     return OS << " }";
   }
 }
@@ -1034,7 +1039,7 @@ void CodeGenRegBank::addToMaps(CodeGenRe
 // Create a synthetic sub-class if it is missing.
 CodeGenRegisterClass*
 CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
-                                    const CodeGenRegister::Set *Members,
+                                    const CodeGenRegister::Vec *Members,
                                     StringRef Name) {
   // Synthetic sub-class has the same size and alignment as RC.
   CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment);
@@ -1283,7 +1288,7 @@ namespace {
 // for which the unit weight equals the set weight. These units should not have
 // their weight increased.
 struct UberRegSet {
-  CodeGenRegister::Set Regs;
+  CodeGenRegister::Vec Regs;
   unsigned Weight;
   CodeGenRegister::RegUnitList SingularDeterminants;
 
@@ -1312,7 +1317,7 @@ static void computeUberSets(std::vector<
     if (!RegClass.Allocatable)
       continue;
 
-    const CodeGenRegister::Set &Regs = RegClass.getMembers();
+    const CodeGenRegister::Vec &Regs = RegClass.getMembers();
     if (Regs.empty())
       continue;
 
@@ -1320,8 +1325,7 @@ static void computeUberSets(std::vector<
     assert(USetID && "register number 0 is invalid");
 
     AllocatableRegs.insert((*Regs.begin())->EnumValue);
-    for (CodeGenRegister::Set::const_iterator I = std::next(Regs.begin()),
-           E = Regs.end(); I != E; ++I) {
+    for (auto I = std::next(Regs.begin()), E = Regs.end(); I != E; ++I) {
       AllocatableRegs.insert((*I)->EnumValue);
       UberSetIDs.join(USetID, (*I)->EnumValue);
     }
@@ -1351,7 +1355,8 @@ static void computeUberSets(std::vector<
       USetID = 0;
 
     UberRegSet *USet = &UberSets[USetID];
-    USet->Regs.insert(&Reg);
+    USet->Regs.push_back(&Reg);
+    sortAndUniqueRegisters(USet->Regs);
     RegSets[i++] = USet;
   }
 }
@@ -1393,11 +1398,9 @@ static void computeUberWeights(std::vect
     }
 
     // Find singular determinants.
-    for (CodeGenRegister::Set::iterator RegI = I->Regs.begin(),
-           RegE = I->Regs.end(); RegI != RegE; ++RegI) {
-      if ((*RegI)->getRegUnits().count() == 1
-          && (*RegI)->getWeight(RegBank) == I->Weight) {
-        I->SingularDeterminants |= (*RegI)->getRegUnits();
+    for (const auto R : I->Regs) {
+      if (R->getRegUnits().count() == 1 && R->getWeight(RegBank) == I->Weight) {
+        I->SingularDeterminants |= R->getRegUnits();
       }
     }
   }
@@ -1838,9 +1841,9 @@ void CodeGenRegBank::inferCommonSubClass
       continue;
 
     // Compute the set intersection of RC1 and RC2.
-    const CodeGenRegister::Set &Memb1 = RC1->getMembers();
-    const CodeGenRegister::Set &Memb2 = RC2->getMembers();
-    CodeGenRegister::Set Intersection;
+    const CodeGenRegister::Vec &Memb1 = RC1->getMembers();
+    const CodeGenRegister::Vec &Memb2 = RC2->getMembers();
+    CodeGenRegister::Vec Intersection;
     std::set_intersection(Memb1.begin(), Memb1.end(),
                           Memb2.begin(), Memb2.end(),
                           std::inserter(Intersection, Intersection.begin()),
@@ -1870,19 +1873,21 @@ void CodeGenRegBank::inferCommonSubClass
 //
 void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
   // Map SubRegIndex to set of registers in RC supporting that SubRegIndex.
-  typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Set,
+  typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Vec,
                    CodeGenSubRegIndex::Less> SubReg2SetMap;
 
   // Compute the set of registers supporting each SubRegIndex.
   SubReg2SetMap SRSets;
-  for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
-       RE = RC->getMembers().end(); RI != RE; ++RI) {
-    const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs();
+  for (const auto R : RC->getMembers()) {
+    const CodeGenRegister::SubRegMap &SRM = R->getSubRegs();
     for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
          E = SRM.end(); I != E; ++I)
-      SRSets[I->first].insert(*RI);
+      SRSets[I->first].push_back(R);
   }
 
+  for (auto I : SRSets)
+    sortAndUniqueRegisters(I.second);
+
   // Find matching classes for all SRSets entries.  Iterate in SubRegIndex
   // numerical order to visit synthetic indices last.
   for (const auto &SubIdx : SubRegIndices) {
@@ -1927,9 +1932,7 @@ void CodeGenRegBank::inferMatchingSuperR
     // Build list of (Super, Sub) pairs for this SubIdx.
     SSPairs.clear();
     TopoSigs.reset();
-    for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
-         RE = RC->getMembers().end(); RI != RE; ++RI) {
-      const CodeGenRegister *Super = *RI;
+    for (const auto Super : RC->getMembers()) {
       const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second;
       assert(Sub && "Missing sub-register");
       SSPairs.push_back(std::make_pair(Super, Sub));
@@ -1948,22 +1951,26 @@ void CodeGenRegBank::inferMatchingSuperR
       if (!TopoSigs.anyCommon(SubRC.getTopoSigs()))
         continue;
       // Compute the subset of RC that maps into SubRC.
-      CodeGenRegister::Set SubSet;
+      CodeGenRegister::Vec SubSetVec;
       for (unsigned i = 0, e = SSPairs.size(); i != e; ++i)
         if (SubRC.contains(SSPairs[i].second))
-          SubSet.insert(SSPairs[i].first);
-      if (SubSet.empty())
+          SubSetVec.push_back(SSPairs[i].first);
+
+      if (SubSetVec.empty())
         continue;
+
       // RC injects completely into SubRC.
-      if (SubSet.size() == SSPairs.size()) {
+      sortAndUniqueRegisters(SubSetVec);
+      if (SubSetVec.size() == SSPairs.size()) {
         SubRC.addSuperRegClass(&SubIdx, RC);
         continue;
       }
+
       // Only a subset of RC maps into SubRC. Make sure it is represented by a
       // class.
-      getOrCreateSubClass(RC, &SubSet, RC->getName() + "_with_" +
-                                           SubIdx.getName() + "_in_" +
-                                           SubRC.getName());
+      getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" +
+                                          SubIdx.getName() + "_in_" +
+                                          SubRC.getName());
     }
   }
 }

Modified: llvm/trunk/utils/TableGen/CodeGenRegisters.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.h?rev=227682&r1=227681&r2=227682&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenRegisters.h (original)
+++ llvm/trunk/utils/TableGen/CodeGenRegisters.h Sat Jan 31 03:13:36 2015
@@ -241,8 +241,16 @@ namespace llvm {
       }
     };
 
+    struct Equal {
+      bool operator()(const CodeGenRegister *A,
+                      const CodeGenRegister *B) const {
+        assert(A && B);
+        return A->EnumValue == B->EnumValue;
+      }
+    };
+
     // Canonically ordered set.
-    typedef std::set<const CodeGenRegister*, Less> Set;
+    typedef std::vector<const CodeGenRegister*> Vec;
 
   private:
     bool SubRegsComplete;
@@ -268,7 +276,7 @@ namespace llvm {
 
 
   class CodeGenRegisterClass {
-    CodeGenRegister::Set Members;
+    CodeGenRegister::Vec Members;
     // Allocation orders. Order[0] always contains all registers in Members.
     std::vector<SmallVector<Record*, 16> > Orders;
     // Bit mask of sub-classes including this, indexed by their EnumValue.
@@ -389,7 +397,7 @@ namespace llvm {
 
     // Get the set of registers.  This set contains the same registers as
     // getOrder(0).
-    const CodeGenRegister::Set &getMembers() const { return Members; }
+    const CodeGenRegister::Vec &getMembers() const { return Members; }
 
     // Get a bit vector of TopoSigs present in this register class.
     const BitVector &getTopoSigs() const { return TopoSigs; }
@@ -403,11 +411,11 @@ namespace llvm {
     // sub-classes.  Note the ordering provided by this key is not the same as
     // the topological order used for the EnumValues.
     struct Key {
-      const CodeGenRegister::Set *Members;
+      const CodeGenRegister::Vec *Members;
       unsigned SpillSize;
       unsigned SpillAlignment;
 
-      Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0)
+      Key(const CodeGenRegister::Vec *M, unsigned S = 0, unsigned A = 0)
         : Members(M), SpillSize(S), SpillAlignment(A) {}
 
       Key(const CodeGenRegisterClass &RC)
@@ -525,7 +533,7 @@ namespace llvm {
 
     // Create a synthetic sub-class if it is missing.
     CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC,
-                                              const CodeGenRegister::Set *Membs,
+                                              const CodeGenRegister::Vec *Membs,
                                               StringRef Name);
 
     // Infer missing register classes.

Modified: llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp?rev=227682&r1=227681&r2=227682&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp Sat Jan 31 03:13:36 2015
@@ -180,7 +180,7 @@ EmitRegUnitPressure(raw_ostream &OS, con
      << "getRegClassWeight(const TargetRegisterClass *RC) const {\n"
      << "  static const RegClassWeight RCWeightTable[] = {\n";
   for (const auto &RC : RegBank.getRegClasses()) {
-    const CodeGenRegister::Set &Regs = RC.getMembers();
+    const CodeGenRegister::Vec &Regs = RC.getMembers();
     if (Regs.empty())
       OS << "    {0, 0";
     else {





More information about the llvm-commits mailing list