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

Jakob Stoklund Olesen stoklund at 2pi.dk
Sun Jun 19 19:50:54 PDT 2011


Author: stoklund
Date: Sun Jun 19 21:50:54 2011
New Revision: 133407

URL: http://llvm.org/viewvc/llvm-project?rev=133407&view=rev
Log:
Add a RegisterTuples class to Target.td and TableGen.

A RegisterTuples instance is used to synthesize super-registers by
zipping together lists of sub-registers. This is useful for generating
pseudo-registers representing register sequence constraints like 'two
consecutive GPRs', or 'an even-odd pair of floating point registers'.

The RegisterTuples def can be used in register set operations when
building register classes. That is the only way of accessing the
synthesized super-registers.

For example, the ARM QQ register class of pseudo-registers could have
been formed like this:

  // Form pairs Q0_Q1, Q2_Q3, ...
  def QQPairs : RegisterTuples<[qsub_0, qsub_1],
                               [(decimate QPR, 2),
                                (decimate (shl QPR, 1), 2)]>;

  def QQ : RegisterClass<..., (add QQPairs)>;

Similarly, pseudo-registers representing '3 consecutive D-regs with
wraparound' look like:

  // Form D0_D1_D2, D1_D2_D3, ..., D30_D31_D0, D31_D0_D1.
  def DSeqTriples : RegisterTuples<[dsub_0, dsub_1, dsub_2],
                                   [(rotl DPR, 0),
                                    (rotl DPR, 1),
                                    (rotl DPR, 2)]>;

TableGen automatically computes aliasing information for the synthesized
registers.

Register tuples are still somewhat experimental. We still need to see
how they interact with MC.

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

Modified: llvm/trunk/include/llvm/Target/Target.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=133407&r1=133406&r2=133407&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/Target.td (original)
+++ llvm/trunk/include/llvm/Target/Target.td Sun Jun 19 21:50:54 2011
@@ -184,6 +184,43 @@
 def sequence;
 def decimate;
 
+// RegisterTuples - Automatically generate super-registers by forming tuples of
+// sub-registers. This is useful for modeling register sequence constraints
+// with pseudo-registers that are larger than the architectural registers.
+//
+// The sub-register lists are zipped together:
+//
+//   def EvenOdd : RegisterTuples<[sube, subo], [(add R0, R2), (add R1, R3)]>;
+//
+// Generates the same registers as:
+//
+//   let SubRegIndices = [sube, subo] in {
+//     def R0_R1 : RegisterWithSubRegs<"", [R0, R1]>;
+//     def R2_R3 : RegisterWithSubRegs<"", [R2, R3]>;
+//   }
+//
+// The generated pseudo-registers inherit super-classes and fields from their
+// first sub-register. Most fields from the Register class are inferred, and
+// the AsmName and Dwarf numbers are cleared.
+//
+// RegisterTuples instances can be used in other set operations to form
+// register classes and so on. This is the only way of using the generated
+// registers.
+class RegisterTuples<list<SubRegIndex> Indices, list<dag> Regs> {
+  // SubRegs - N lists of registers to be zipped up. Super-registers are
+  // synthesized from the first element of each SubRegs list, the second
+  // element and so on.
+  list<dag> SubRegs = Regs;
+
+  // SubRegIndices - N SubRegIndex instances. This provides the names of the
+  // sub-registers in the synthesized super-registers.
+  list<SubRegIndex> SubRegIndices = Indices;
+
+  // Compose sub-register indices like in a normal Register.
+  list<dag> CompositeIndices = [];
+}
+
+
 //===----------------------------------------------------------------------===//
 // DwarfRegNum - This class provides a mapping of the llvm register enumeration
 // to the register numbering used by gcc and gdb.  These values are used by a

Modified: llvm/trunk/utils/TableGen/CodeGenRegisters.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.cpp?rev=133407&r1=133406&r2=133407&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenRegisters.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenRegisters.cpp Sun Jun 19 21:50:54 2011
@@ -151,6 +151,104 @@
 }
 
 //===----------------------------------------------------------------------===//
+//                               RegisterTuples
+//===----------------------------------------------------------------------===//
+
+// A RegisterTuples def is used to generate pseudo-registers from lists of
+// sub-registers. We provide a SetTheory expander class that returns the new
+// registers.
+namespace {
+struct TupleExpander : SetTheory::Expander {
+  void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) {
+    std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices");
+    unsigned Dim = Indices.size();
+    ListInit *SubRegs = Def->getValueAsListInit("SubRegs");
+    if (Dim != SubRegs->getSize())
+      throw TGError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch");
+    if (Dim < 2)
+      throw TGError(Def->getLoc(), "Tuples must have at least 2 sub-registers");
+
+    // Evaluate the sub-register lists to be zipped.
+    unsigned Length = ~0u;
+    SmallVector<SetTheory::RecSet, 4> Lists(Dim);
+    for (unsigned i = 0; i != Dim; ++i) {
+      ST.evaluate(SubRegs->getElement(i), Lists[i]);
+      Length = std::min(Length, unsigned(Lists[i].size()));
+    }
+
+    if (Length == 0)
+      return;
+
+    // Precompute some types.
+    Record *RegisterCl = Def->getRecords().getClass("Register");
+    RecTy *RegisterRecTy = new RecordRecTy(RegisterCl);
+    StringInit *BlankName = new StringInit("");
+
+    // Zip them up.
+    for (unsigned n = 0; n != Length; ++n) {
+      std::string Name;
+      Record *Proto = Lists[0][n];
+      std::vector<Init*> Tuple;
+      unsigned CostPerUse = 0;
+      for (unsigned i = 0; i != Dim; ++i) {
+        Record *Reg = Lists[i][n];
+        if (i) Name += '_';
+        Name += Reg->getName();
+        Tuple.push_back(new DefInit(Reg));
+        CostPerUse = std::max(CostPerUse,
+                              unsigned(Reg->getValueAsInt("CostPerUse")));
+      }
+
+      // Create a new Record representing the synthesized register. This record
+      // is only for consumption by CodeGenRegister, it is not added to the
+      // RecordKeeper.
+      Record *NewReg = new Record(Name, Def->getLoc(), Def->getRecords());
+      Elts.insert(NewReg);
+
+      // Copy Proto super-classes.
+      for (unsigned i = 0, e = Proto->getSuperClasses().size(); i != e; ++i)
+        NewReg->addSuperClass(Proto->getSuperClasses()[i]);
+
+      // Copy Proto fields.
+      for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) {
+        RecordVal RV = Proto->getValues()[i];
+
+        // Replace the sub-register list with Tuple.
+        if (RV.getName() == "SubRegs")
+          RV.setValue(new ListInit(Tuple, RegisterRecTy));
+
+        // Provide a blank AsmName. MC hacks are required anyway.
+        if (RV.getName() == "AsmName")
+          RV.setValue(BlankName);
+
+        // CostPerUse is aggregated from all Tuple members.
+        if (RV.getName() == "CostPerUse")
+          RV.setValue(new IntInit(CostPerUse));
+
+        // Copy fields from the RegisterTuples def.
+        if (RV.getName() == "SubRegIndices" ||
+            RV.getName() == "CompositeIndices") {
+          NewReg->addValue(*Def->getValue(RV.getName()));
+          continue;
+        }
+
+        // Some fields get their default uninitialized value.
+        if (RV.getName() == "DwarfNumbers" ||
+            RV.getName() == "DwarfAlias" ||
+            RV.getName() == "Aliases") {
+          NewReg->addValue(*RegisterCl->getValue(RV.getName()));
+          continue;
+        }
+
+        // Everything else is copied from Proto.
+        NewReg->addValue(RV);
+      }
+    }
+  }
+};
+}
+
+//===----------------------------------------------------------------------===//
 //                            CodeGenRegisterClass
 //===----------------------------------------------------------------------===//
 
@@ -258,8 +356,9 @@
 //===----------------------------------------------------------------------===//
 
 CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) {
-  // Configure register Sets to understand register classes.
+  // Configure register Sets to understand register classes and tuples.
   Sets.addFieldExpander("RegisterClass", "MemberList");
+  Sets.addExpander("RegisterTuples", new TupleExpander());
 
   // Read in the user-defined (named) sub-register indices.
   // More indices will be synthesized later.
@@ -275,6 +374,15 @@
   for (unsigned i = 0, e = Regs.size(); i != e; ++i)
     getReg(Regs[i]);
 
+  // Expand tuples and number the new registers.
+  std::vector<Record*> Tups =
+    Records.getAllDerivedDefinitions("RegisterTuples");
+  for (unsigned i = 0, e = Tups.size(); i != e; ++i) {
+    const std::vector<Record*> *TupRegs = Sets.expand(Tups[i]);
+    for (unsigned j = 0, je = TupRegs->size(); j != je; ++j)
+      getReg((*TupRegs)[j]);
+  }
+
   // Read in register class definitions.
   std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass");
   if (RCs.empty())





More information about the llvm-commits mailing list