diff options
author | Andrew Trick <atrick@apple.com> | 2012-10-03 23:06:32 +0000 |
---|---|---|
committer | Andrew Trick <atrick@apple.com> | 2012-10-03 23:06:32 +0000 |
commit | 13745262a8db98d6c4513ff9934db4be75a8b26c (patch) | |
tree | 94a2e5f6ae75723c8ef8895bbd96fc264d52821d /utils | |
parent | 2062b1260fa9df3e69e7b4d24a657a0ebb7f8710 (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
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/CodeGenSchedule.cpp | 84 | ||||
-rw-r--r-- | utils/TableGen/CodeGenSchedule.h | 4 | ||||
-rw-r--r-- | utils/TableGen/SetTheory.cpp | 6 |
3 files changed, 84 insertions, 10 deletions
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); } |