[llvm-commits] [llvm] r133320 - in /llvm/trunk: include/llvm/Target/Target.td utils/TableGen/CodeGenRegisters.cpp utils/TableGen/CodeGenRegisters.h utils/TableGen/RegisterInfoEmitter.cpp

Jakob Stoklund Olesen stoklund at 2pi.dk
Fri Jun 17 17:50:49 PDT 2011


Author: stoklund
Date: Fri Jun 17 19:50:49 2011
New Revision: 133320

URL: http://llvm.org/viewvc/llvm-project?rev=133320&view=rev
Log:
Provide AltOrders for specifying alternative allocation orders.

A register class can define AltOrders and AltOrderSelect instead of
defining method protos and bodies. The AltOrders lists can be defined
with set operations, and TableGen can verify that the alternative
allocation orders only contain valid registers.

This is currently an opt-in feature, and it is still possible to
override allocation_order_begin/end. That will not be true for long.

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

Modified: llvm/trunk/include/llvm/Target/Target.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=133320&r1=133319&r2=133320&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/Target.td (original)
+++ llvm/trunk/include/llvm/Target/Target.td Fri Jun 17 19:50:49 2011
@@ -138,6 +138,22 @@
   // overload virtual methods.
   code MethodProtos = [{}];
   code MethodBodies = [{}];
+
+  // AltOrders - List of alternative allocation orders. The default order is
+  // MemberList itself, and that is good enough for most targets since the
+  // register allocators automatically remove reserved registers and move
+  // callee-saved registers to the end.
+  list<dag> AltOrders = [];
+
+  // AltOrderSelect - The body of a function that selects the allocation order
+  // to use in a given machine function. The code will be inserted in a
+  // function like this:
+  //
+  //   static inline unsigned f(const MachineFunction &MF) { ... }
+  //
+  // The function should return 0 to select the default order defined by
+  // MemberList, 1 to select the first AltOrders entry and so on.
+  code AltOrderSelect = [{}];
 }
 
 // The memberList in a RegisterClass is a dag of set operations. TableGen

Modified: llvm/trunk/utils/TableGen/CodeGenRegisters.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.cpp?rev=133320&r1=133319&r2=133320&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenRegisters.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenRegisters.cpp Fri Jun 17 19:50:49 2011
@@ -172,10 +172,28 @@
   }
   assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");
 
+  // Default allocation order always contains all registers.
   Elements = RegBank.getSets().expand(R);
   for (unsigned i = 0, e = Elements->size(); i != e; ++i)
     Members.insert(RegBank.getReg((*Elements)[i]));
 
+  // Alternative allocation orders may be subsets.
+  ListInit *Alts = R->getValueAsListInit("AltOrders");
+  AltOrders.resize(Alts->size());
+  SetTheory::RecSet Order;
+  for (unsigned i = 0, e = Alts->size(); i != e; ++i) {
+    RegBank.getSets().evaluate(Alts->getElement(i), Order);
+    AltOrders[i].append(Order.begin(), Order.end());
+    // Verify that all altorder members are regclass members.
+    while (!Order.empty()) {
+      CodeGenRegister *Reg = RegBank.getReg(Order.back());
+      Order.pop_back();
+      if (!contains(Reg))
+        throw TGError(R->getLoc(), " AltOrder register " + Reg->getName() +
+                      " is not a class member");
+    }
+  }
+
   // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags.
   ListInit *SRC = R->getValueAsListInit("SubRegClasses");
   for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) {
@@ -209,6 +227,7 @@
   Allocatable = R->getValueAsBit("isAllocatable");
   MethodBodies = R->getValueAsCode("MethodBodies");
   MethodProtos = R->getValueAsCode("MethodProtos");
+  AltOrderSelect = R->getValueAsCode("AltOrderSelect");
 }
 
 bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {

Modified: llvm/trunk/utils/TableGen/CodeGenRegisters.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.h?rev=133320&r1=133319&r2=133320&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenRegisters.h (original)
+++ llvm/trunk/utils/TableGen/CodeGenRegisters.h Fri Jun 17 19:50:49 2011
@@ -86,6 +86,7 @@
   class CodeGenRegisterClass {
     CodeGenRegister::Set Members;
     const std::vector<Record*> *Elements;
+    std::vector<SmallVector<Record*, 16> > AltOrders;
   public:
     Record *TheDef;
     std::string Namespace;
@@ -96,7 +97,7 @@
     bool Allocatable;
     // Map SubRegIndex -> RegisterClass
     DenseMap<Record*,Record*> SubRegClasses;
-    std::string MethodProtos, MethodBodies;
+    std::string MethodProtos, MethodBodies, AltOrderSelect;
 
     const std::string &getName() const;
     const std::vector<MVT::SimpleValueType> &getValueTypes() const {return VTs;}
@@ -125,10 +126,17 @@
 
     // Returns an ordered list of class members.
     // The order of registers is the same as in the .td file.
-    ArrayRef<Record*> getOrder() const {
-      return *Elements;
+    // No = 0 is the default allocation order, No = 1 is the first alternative.
+    ArrayRef<Record*> getOrder(unsigned No = 0) const {
+      if (No == 0)
+        return *Elements;
+      else
+        return AltOrders[No - 1];
     }
 
+    // Return the total number of allocation orders available.
+    unsigned getNumOrders() const { return 1 + AltOrders.size(); }
+
     CodeGenRegisterClass(CodeGenRegBank&, Record *R);
   };
 

Modified: llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp?rev=133320&r1=133319&r2=133320&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp Fri Jun 17 19:50:49 2011
@@ -108,12 +108,16 @@
     OS << "\n  };\n\n";
 
     for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
-      const std::string &Name = RegisterClasses[i].getName();
+      const CodeGenRegisterClass &RC = RegisterClasses[i];
+      const std::string &Name = RC.getName();
 
       // Output the register class definition.
       OS << "  struct " << Name << "Class : public TargetRegisterClass {\n"
-         << "    " << Name << "Class();\n"
-         << RegisterClasses[i].MethodProtos << "  };\n";
+         << "    " << Name << "Class();\n";
+      if (!RC.AltOrderSelect.empty())
+        OS << "    ArrayRef<unsigned> "
+              "getRawAllocationOrder(const MachineFunction&) const;\n";
+      OS << RC.MethodProtos << "  };\n";
 
       // Output the extern for the instance.
       OS << "  extern " << Name << "Class\t" << Name << "RegClass;\n";
@@ -349,7 +353,7 @@
       OS << "\n  };\n\n";
     }
 
-
+    // Emit methods.
     for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
       const CodeGenRegisterClass &RC = RegisterClasses[i];
       OS << RC.MethodBodies << "\n";
@@ -371,6 +375,27 @@
          << RC.getName() << ", " << RC.getName() << " + "
          << RC.getOrder().size()
          << ") {}\n";
+      if (!RC.AltOrderSelect.empty()) {
+        OS << "\nstatic inline unsigned " << RC.getName()
+           << "AltOrderSelect(const MachineFunction &MF) {"
+           << RC.AltOrderSelect << "}\n\nArrayRef<unsigned> "
+           << RC.getName() << "Class::"
+           << "getRawAllocationOrder(const MachineFunction &MF) const {\n";
+        for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) {
+          ArrayRef<Record*> Elems = RC.getOrder(oi);
+          OS << "  static const unsigned AltOrder" << oi << "[] = {";
+          for (unsigned elem = 0; elem != Elems.size(); ++elem)
+            OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]);
+          OS << " };\n";
+        }
+        OS << "  static const ArrayRef<unsigned> Order[] = {\n"
+           << "    ArrayRef<unsigned>(" << RC.getName();
+        for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi)
+          OS << "),\n    ArrayRef<unsigned>(AltOrder" << oi;
+        OS << ")\n  };\n  const unsigned Select = " << RC.getName()
+           << "AltOrderSelect(MF);\n  assert(Select < " << RC.getNumOrders()
+           << ");\n  return Order[Select];\n}\n";
+        }
     }
 
     OS << "}\n";





More information about the llvm-commits mailing list