aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2012-10-03 23:06:32 +0000
committerAndrew Trick <atrick@apple.com>2012-10-03 23:06:32 +0000
commit13745262a8db98d6c4513ff9934db4be75a8b26c (patch)
tree94a2e5f6ae75723c8ef8895bbd96fc264d52821d
parent2062b1260fa9df3e69e7b4d24a657a0ebb7f8710 (diff)
Added instregex support to TableGen subtarget emitter.
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
-rw-r--r--include/llvm/Target/TargetSchedule.td13
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp84
-rw-r--r--utils/TableGen/CodeGenSchedule.h4
-rw-r--r--utils/TableGen/SetTheory.cpp6
4 files changed, 95 insertions, 12 deletions
diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td
index cf3d250590..0da82fdd89 100644
--- a/include/llvm/Target/TargetSchedule.td
+++ b/include/llvm/Target/TargetSchedule.td
@@ -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 = ?;
}
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
index 90bc5b4e15..b9b1c293f0 100644
--- a/utils/TableGen/CodeGenSchedule.cpp
+++ b/utils/TableGen/CodeGenSchedule.cpp
@@ -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;
diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h
index 211c05c8c6..cc3a10223b 100644
--- a/utils/TableGen/CodeGenSchedule.h
+++ b/utils/TableGen/CodeGenSchedule.h
@@ -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;
diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp
index 46e6db173e..bdca9a63bd 100644
--- a/utils/TableGen/SetTheory.cpp
+++ b/utils/TableGen/SetTheory.cpp
@@ -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);
}