mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-23 04:01:16 +00:00
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:
parent
2062b1260f
commit
13745262a8
@ -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 = ?;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user