Added instregex support to TableGen subtarget emitter.
authorAndrew Trick <atrick@apple.com>
Wed, 3 Oct 2012 23:06:32 +0000 (23:06 +0000)
committerAndrew Trick <atrick@apple.com>
Wed, 3 Oct 2012 23:06:32 +0000 (23:06 +0000)
This allows the processor-specific machine model to override selected
base opcodes without any fanciness.
e.g. InstRW<[CoreXWriteVANDP], (instregex "VANDP")>.

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

include/llvm/Target/TargetSchedule.td
utils/TableGen/CodeGenSchedule.cpp
utils/TableGen/CodeGenSchedule.h
utils/TableGen/SetTheory.cpp

index cf3d2505906cc5408f2706268b60f4a7a73b96cc..0da82fdd8971849fa172824ea9618a3ab382edf7 100644 (file)
@@ -55,6 +55,15 @@ include "llvm/Target/TargetItinerary.td"
 
 class Instruction; // Forward def
 
+// DAG operator that interprets the DAG args as Instruction defs.
+def instrs;
+
+// DAG operator that interprets each DAG arg as a regex pattern for
+// matching Instruction opcode names.
+// The regex must match the beginning of the opcode (as in Python re.match).
+// To avoid matching prefixes, append '$' to the pattern.
+def instregex;
+
 // Define the SchedMachineModel and provide basic properties for
 // coarse grained instruction cost model. Default values for the
 // properties are defined in MCSchedModel. A value of "-1" in the
@@ -325,9 +334,9 @@ class SchedReadVariant<list<SchedVar> variants> : SchedRead,
 // the subtarget to easily override specific operations.
 //
 // SchedModel ties this opcode mapping to a processor.
-class InstRW<list<SchedReadWrite> rw, list<Instruction> instrs> {
+class InstRW<list<SchedReadWrite> rw, dag instrlist> {
   list<SchedReadWrite> OperandReadWrites = rw;
-  list<Instruction> Instrs = instrs;
+  dag Instrs = instrlist;
   SchedMachineModel SchedModel = ?;
 }
 
index 90bc5b4e15639349b06bafea2e0d1ff3abaec34f..b9b1c293f04b98051c7119f2da532f596bae6a93 100644 (file)
@@ -18,6 +18,8 @@
 #include "CodeGenTarget.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/ADT/STLExtras.h"
 
 using namespace llvm;
 
@@ -34,11 +36,64 @@ static void dumpIdxVec(const SmallVectorImpl<unsigned> &V) {
 }
 #endif
 
+// (instrs a, b, ...) Evaluate and union all arguments. Identical to AddOp.
+struct InstrsOp : public SetTheory::Operator {
+  void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts) {
+    ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts);
+  }
+};
+
+// (instregex "OpcPat",...) Find all instructions matching an opcode pattern.
+//
+// TODO: Since this is a prefix match, perform a binary search over the
+// instruction names using lower_bound. Note that the predefined instrs must be
+// scanned linearly first. However, this is only safe if the regex pattern has
+// no top-level bars. The DAG already has a list of patterns, so there's no
+// reason to use top-level bars, but we need a way to verify they don't exist
+// before implementing the optimization.
+struct InstRegexOp : public SetTheory::Operator {
+  const CodeGenTarget &Target;
+  InstRegexOp(const CodeGenTarget &t): Target(t) {}
+
+  void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts) {
+    SmallVector<Regex*, 4> RegexList;
+    for (DagInit::const_arg_iterator
+           AI = Expr->arg_begin(), AE = Expr->arg_end(); AI != AE; ++AI) {
+      StringInit *SI = dynamic_cast<StringInit*>(*AI);
+      if (!SI)
+        throw "instregex requires pattern string: " + Expr->getAsString();
+      std::string pat = SI->getValue();
+      // Implement a python-style prefix match.
+      if (pat[0] != '^') {
+        pat.insert(0, "^(");
+        pat.insert(pat.end(), ')');
+      }
+      RegexList.push_back(new Regex(pat));
+    }
+    for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
+           E = Target.inst_end(); I != E; ++I) {
+      for (SmallVectorImpl<Regex*>::iterator
+             RI = RegexList.begin(), RE = RegexList.end(); RI != RE; ++RI) {
+        if ((*RI)->match((*I)->TheDef->getName()))
+          Elts.insert((*I)->TheDef);
+      }
+    }
+    DeleteContainerPointers(RegexList);
+  }
+};
+
 /// CodeGenModels ctor interprets machine model records and populates maps.
 CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
                                        const CodeGenTarget &TGT):
   Records(RK), Target(TGT), NumItineraryClasses(0) {
 
+  Sets.addFieldExpander("InstRW", "Instrs");
+
+  // Allow Set evaluation to recognize the dags used in InstRW records:
+  // (instrs Op1, Op1...)
+  Sets.addOperator("instrs", new InstrsOp);
+  Sets.addOperator("instregex", new InstRegexOp(Target));
+
   // Instantiate a CodeGenProcModel for each SchedMachineModel with the values
   // that are explicitly referenced in tablegen records. Resources associated
   // with each processor will be derived later. Populate ProcModelMap with the
@@ -646,9 +701,11 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
   // determined from ItinDef or SchedRW.
   SmallVector<std::pair<unsigned, SmallVector<Record *, 8> >, 4> ClassInstrs;
   // Sort Instrs into sets.
-  RecVec InstDefs = InstRWDef->getValueAsListOfDefs("Instrs");
-  std::sort(InstDefs.begin(), InstDefs.end(), LessRecord());
-  for (RecIter I = InstDefs.begin(), E = InstDefs.end(); I != E; ++I) {
+  const RecVec *InstDefs = Sets.expand(InstRWDef);
+  if (InstDefs->empty())
+    throw TGError(InstRWDef->getLoc(), "No matching instruction opcodes");
+
+  for (RecIter I = InstDefs->begin(), E = InstDefs->end(); I != E; ++I) {
     unsigned SCIdx = 0;
     InstClassMapTy::const_iterator Pos = InstrClassMap.find(*I);
     if (Pos != InstrClassMap.end())
@@ -697,13 +754,22 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
     SC.ProcIndices.push_back(0);
     // Map each Instr to this new class.
     // Note that InstDefs may be a smaller list than InstRWDef's "Instrs".
+    Record *RWModelDef = InstRWDef->getValueAsDef("SchedModel");
+    SmallSet<unsigned, 4> RemappedClassIDs;
     for (ArrayRef<Record*>::const_iterator
            II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) {
       unsigned OldSCIdx = InstrClassMap[*II];
-      if (OldSCIdx) {
-        SC.InstRWs.insert(SC.InstRWs.end(),
-                          SchedClasses[OldSCIdx].InstRWs.begin(),
-                          SchedClasses[OldSCIdx].InstRWs.end());
+      if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx)) {
+        for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(),
+               RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) {
+          if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) {
+            throw TGError(InstRWDef->getLoc(), "Overlapping InstRW def " +
+                          (*II)->getName() + " also matches " +
+                          (*RI)->getValue("Instrs")->getValue()->getAsString());
+          }
+          assert(*RI != InstRWDef && "SchedClass has duplicate InstRW def");
+          SC.InstRWs.push_back(*RI);
+        }
       }
       InstrClassMap[*II] = SCIdx;
     }
@@ -814,8 +880,8 @@ void CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef,
 void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
   const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs;
   for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); RWI != RWE; ++RWI) {
-    RecVec Instrs = (*RWI)->getValueAsListOfDefs("Instrs");
-    RecIter II = Instrs.begin(), IE = Instrs.end();
+    const RecVec *InstDefs = Sets.expand(*RWI);
+    RecIter II = InstDefs->begin(), IE = InstDefs->end();
     for (; II != IE; ++II) {
       if (InstrClassMap[*II] == SCIdx)
         break;
index 211c05c8c64d8ef94e13591bc7f964f36fc4a07e..cc3a10223b3b47f7d2c8cb3346abc66b2c276304 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef CODEGEN_SCHEDULE_H
 #define CODEGEN_SCHEDULE_H
 
+#include "SetTheory.h"
 #include "llvm/TableGen/Record.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/ADT/DenseMap.h"
@@ -208,6 +209,9 @@ class CodeGenSchedModels {
   RecordKeeper &Records;
   const CodeGenTarget &Target;
 
+  // Map dag expressions to Instruction lists.
+  SetTheory Sets;
+
   // List of unique processor models.
   std::vector<CodeGenProcModel> ProcModels;
 
index 46e6db173ea947cc0a454b46771701d0f45f4fee..bdca9a63bd28489560bd8e5bfbb385a1dfa2b90e 100644 (file)
@@ -294,7 +294,10 @@ const RecVec *SetTheory::expand(Record *Set) {
   // This is the first time we see Set. Find a suitable expander.
   try {
     const std::vector<Record*> &SC = Set->getSuperClasses();
-    for (unsigned i = 0, e = SC.size(); i != e; ++i)
+    for (unsigned i = 0, e = SC.size(); i != e; ++i) {
+      // Skip unnamed superclasses.
+      if (!dynamic_cast<const StringInit *>(SC[i]->getNameInit()))
+        continue;
       if (Expander *Exp = Expanders.lookup(SC[i]->getName())) {
         // This breaks recursive definitions.
         RecVec &EltVec = Expansions[Set];
@@ -303,6 +306,7 @@ const RecVec *SetTheory::expand(Record *Set) {
         EltVec.assign(Elts.begin(), Elts.end());
         return &EltVec;
       }
+    }
   } catch (const std::string &Error) {
     throw TGError(Set->getLoc(), Error);
   }