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
This commit is contained in:
Andrew Trick 2012-10-03 23:06:32 +00:00
parent 2062b1260f
commit 13745262a8
4 changed files with 95 additions and 12 deletions

View 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 = ?;
}

View 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;

View 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;

View 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);
}