Add TRI::getSubClassWithSubReg(RC, Idx) function.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Wed, 5 Oct 2011 00:35:49 +0000 (00:35 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Wed, 5 Oct 2011 00:35:49 +0000 (00:35 +0000)
This function is used to constrain a register class to a sub-class that
supports the given sub-register index.

For example, getSubClassWithSubReg(GR32, sub_8bit) -> GR32_ABCD.

The function will be used to compute register classes when emitting
INSERT_SUBREG and EXTRACT_SUBREG nodes and for register class inflation
of sub-register operations.

The version provided by TableGen is usually adequate, but targets can
override.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141142 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetRegisterInfo.h
utils/TableGen/CodeGenRegisters.cpp
utils/TableGen/CodeGenRegisters.h
utils/TableGen/RegisterInfoEmitter.cpp

index bf9174cbc670707d807570f4d2aea30924598313..f77aa546c12696b57de4e0525031fff6f2b75ab1 100644 (file)
@@ -429,6 +429,20 @@ public:
     return 0;
   }
 
+  /// getSubClassWithSubReg - Returns the largest legal sub-class of RC that
+  /// supports the sub-register index Idx.
+  /// If no such sub-class exists, return NULL.
+  /// If all registers in RC already have an Idx sub-register, return RC.
+  ///
+  /// TableGen generates a version of this function that is good enough in most
+  /// cases.  Targets can override if they have constraints that TableGen
+  /// doesn't understand.  For example, the x86 sub_8bit sub-register index is
+  /// supported by the full GR32 register class in 64-bit mode, but only by the
+  /// GR32_ABCD regiister class in 32-bit mode.
+  ///
+  virtual const TargetRegisterClass *
+  getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx) const =0;
+
   /// composeSubRegIndices - Return the subregister index you get from composing
   /// two subregister indices.
   ///
index b7315446163d1d193218f5372033e13cda5d5a11..8de461527955832e210a661adcf26a4662c42a45 100644 (file)
@@ -768,23 +768,31 @@ void CodeGenRegBank::computeInferredRegisterClasses() {
     // Find matching classes for all SRSets entries.  Iterate in SubRegIndex
     // numerical order to visit synthetic indices last.
     for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
-      SubReg2SetMap::const_iterator I = SRSets.find(SubRegIndices[sri]);
+      Record *SubIdx = SubRegIndices[sri];
+      SubReg2SetMap::const_iterator I = SRSets.find(SubIdx);
       // Unsupported SubRegIndex. Skip it.
       if (I == SRSets.end())
         continue;
-      // In most cases, all RC registers support the SubRegIndex. Skip those.
-      if (I->second.size() == RC.getMembers().size())
+      // In most cases, all RC registers support the SubRegIndex.
+      if (I->second.size() == RC.getMembers().size()) {
+        RC.setSubClassWithSubReg(SubIdx, &RC);
         continue;
+      }
 
       // This is a real subset.  See if we have a matching class.
       CodeGenRegisterClass::Key K(&I->second, RC.SpillSize, RC.SpillAlignment);
       RCKeyMap::const_iterator FoundI = Key2RC.find(K);
-      if (FoundI != Key2RC.end())
+      if (FoundI != Key2RC.end()) {
+        RC.setSubClassWithSubReg(SubIdx, FoundI->second);
         continue;
+      }
 
       // Class doesn't exist.
-      addToMaps(new CodeGenRegisterClass(RC.getName() + "_with_" +
-                                         I->first->getName(), K));
+      CodeGenRegisterClass *NewRC =
+        new CodeGenRegisterClass(RC.getName() + "_with_" +
+                                 I->first->getName(), K);
+      addToMaps(NewRC);
+      RC.setSubClassWithSubReg(SubIdx, NewRC);
     }
   }
 }
index 72c8ac0502511a872a497744120486cd9851592f..ab3e68efc2467d5050b6f9c1e7e9319ac42544cb 100644 (file)
@@ -101,6 +101,9 @@ namespace llvm {
     // super-class.
     void inheritProperties(CodeGenRegBank&);
 
+    // Map SubRegIndex -> sub-class
+    DenseMap<Record*, CodeGenRegisterClass*> SubClassWithSubReg;
+
   public:
     unsigned EnumValue;
     std::string Namespace;
@@ -145,6 +148,16 @@ namespace llvm {
       return SubClasses.test(RC->EnumValue);
     }
 
+    // getSubClassWithSubReg - Returns the largest sub-class where all
+    // registers have a SubIdx sub-register.
+    CodeGenRegisterClass *getSubClassWithSubReg(Record *SubIdx) const {
+      return SubClassWithSubReg.lookup(SubIdx);
+    }
+
+    void setSubClassWithSubReg(Record *SubIdx, CodeGenRegisterClass *SubRC) {
+      SubClassWithSubReg[SubIdx] = SubRC;
+    }
+
     // getSubClasses - Returns a constant BitVector of subclasses indexed by
     // EnumValue.
     // The SubClasses vector includs an entry for this class.
index f2cc36d371e50e05c10f34b90b224f3e8bb8e6c5..a66a78cf9188c3cb02facd1e0e4bc293d0719d1e 100644 (file)
@@ -426,6 +426,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
      << "  unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n"
      << "  unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n"
      << "  unsigned composeSubRegIndices(unsigned, unsigned) const;\n"
+     << "  const TargetRegisterClass *"
+        "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n"
      << "};\n\n";
 
   const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices();
@@ -802,6 +804,44 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
   }
   OS << "  }\n}\n\n";
 
+  // Emit getSubClassWithSubReg.
+  OS << "const TargetRegisterClass *" << ClassName
+     << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)"
+        " const {\n";
+  if (SubRegIndices.empty()) {
+    OS << "  assert(Idx == 0 && \"Target has no sub-registers\");\n"
+       << "  return RC;\n";
+  } else {
+    // Use the smallest type that can hold a regclass ID with room for a
+    // sentinel.
+    if (RegisterClasses.size() < UINT8_MAX)
+      OS << "  static const uint8_t Table[";
+    else if (RegisterClasses.size() < UINT16_MAX)
+      OS << "  static const uint16_t Table[";
+    else
+      throw "Too many register classes.";
+    OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n";
+    for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) {
+      const CodeGenRegisterClass &RC = *RegisterClasses[rci];
+      OS << "    {\t// " << RC.getName() << "\n";
+      for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
+        Record *Idx = SubRegIndices[sri];
+        if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx))
+          OS << "      " << SRC->EnumValue + 1 << ",\t// " << Idx->getName()
+             << " -> " << SRC->getName() << "\n";
+        else
+          OS << "      0,\t// " << Idx->getName() << "\n";
+      }
+      OS << "    },\n";
+    }
+    OS << "  };\n  assert(RC && \"Missing regclass\");\n"
+       << "  if (!Idx) return RC;\n  --Idx;\n"
+       << "  assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n"
+       << "  unsigned TV = Table[RC->getID()][Idx];\n"
+       << "  return TV ? getRegClass(TV - 1) : 0;\n";
+  }
+  OS << "}\n\n";
+
   // Emit the constructor of the class...
   OS << "extern MCRegisterDesc " << TargetName << "RegDesc[];\n";