mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-19 03:24:09 +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:
@ -55,6 +55,15 @@ include "llvm/Target/TargetItinerary.td"
|
|||||||
|
|
||||||
class Instruction; // Forward def
|
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
|
// Define the SchedMachineModel and provide basic properties for
|
||||||
// coarse grained instruction cost model. Default values for the
|
// coarse grained instruction cost model. Default values for the
|
||||||
// properties are defined in MCSchedModel. A value of "-1" in 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.
|
// the subtarget to easily override specific operations.
|
||||||
//
|
//
|
||||||
// SchedModel ties this opcode mapping to a processor.
|
// 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<SchedReadWrite> OperandReadWrites = rw;
|
||||||
list<Instruction> Instrs = instrs;
|
dag Instrs = instrlist;
|
||||||
SchedMachineModel SchedModel = ?;
|
SchedMachineModel SchedModel = ?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
#include "CodeGenTarget.h"
|
#include "CodeGenTarget.h"
|
||||||
#include "llvm/TableGen/Error.h"
|
#include "llvm/TableGen/Error.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
|
#include "llvm/Support/Regex.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@ -34,11 +36,64 @@ static void dumpIdxVec(const SmallVectorImpl<unsigned> &V) {
|
|||||||
}
|
}
|
||||||
#endif
|
#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.
|
/// CodeGenModels ctor interprets machine model records and populates maps.
|
||||||
CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
|
CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
|
||||||
const CodeGenTarget &TGT):
|
const CodeGenTarget &TGT):
|
||||||
Records(RK), Target(TGT), NumItineraryClasses(0) {
|
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
|
// Instantiate a CodeGenProcModel for each SchedMachineModel with the values
|
||||||
// that are explicitly referenced in tablegen records. Resources associated
|
// that are explicitly referenced in tablegen records. Resources associated
|
||||||
// with each processor will be derived later. Populate ProcModelMap with the
|
// 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.
|
// determined from ItinDef or SchedRW.
|
||||||
SmallVector<std::pair<unsigned, SmallVector<Record *, 8> >, 4> ClassInstrs;
|
SmallVector<std::pair<unsigned, SmallVector<Record *, 8> >, 4> ClassInstrs;
|
||||||
// Sort Instrs into sets.
|
// Sort Instrs into sets.
|
||||||
RecVec InstDefs = InstRWDef->getValueAsListOfDefs("Instrs");
|
const RecVec *InstDefs = Sets.expand(InstRWDef);
|
||||||
std::sort(InstDefs.begin(), InstDefs.end(), LessRecord());
|
if (InstDefs->empty())
|
||||||
for (RecIter I = InstDefs.begin(), E = InstDefs.end(); I != E; ++I) {
|
throw TGError(InstRWDef->getLoc(), "No matching instruction opcodes");
|
||||||
|
|
||||||
|
for (RecIter I = InstDefs->begin(), E = InstDefs->end(); I != E; ++I) {
|
||||||
unsigned SCIdx = 0;
|
unsigned SCIdx = 0;
|
||||||
InstClassMapTy::const_iterator Pos = InstrClassMap.find(*I);
|
InstClassMapTy::const_iterator Pos = InstrClassMap.find(*I);
|
||||||
if (Pos != InstrClassMap.end())
|
if (Pos != InstrClassMap.end())
|
||||||
@ -697,13 +754,22 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
|
|||||||
SC.ProcIndices.push_back(0);
|
SC.ProcIndices.push_back(0);
|
||||||
// Map each Instr to this new class.
|
// Map each Instr to this new class.
|
||||||
// Note that InstDefs may be a smaller list than InstRWDef's "Instrs".
|
// 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
|
for (ArrayRef<Record*>::const_iterator
|
||||||
II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) {
|
II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) {
|
||||||
unsigned OldSCIdx = InstrClassMap[*II];
|
unsigned OldSCIdx = InstrClassMap[*II];
|
||||||
if (OldSCIdx) {
|
if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx)) {
|
||||||
SC.InstRWs.insert(SC.InstRWs.end(),
|
for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(),
|
||||||
SchedClasses[OldSCIdx].InstRWs.begin(),
|
RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) {
|
||||||
SchedClasses[OldSCIdx].InstRWs.end());
|
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;
|
InstrClassMap[*II] = SCIdx;
|
||||||
}
|
}
|
||||||
@ -814,8 +880,8 @@ void CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef,
|
|||||||
void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
|
void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
|
||||||
const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs;
|
const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs;
|
||||||
for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); RWI != RWE; ++RWI) {
|
for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); RWI != RWE; ++RWI) {
|
||||||
RecVec Instrs = (*RWI)->getValueAsListOfDefs("Instrs");
|
const RecVec *InstDefs = Sets.expand(*RWI);
|
||||||
RecIter II = Instrs.begin(), IE = Instrs.end();
|
RecIter II = InstDefs->begin(), IE = InstDefs->end();
|
||||||
for (; II != IE; ++II) {
|
for (; II != IE; ++II) {
|
||||||
if (InstrClassMap[*II] == SCIdx)
|
if (InstrClassMap[*II] == SCIdx)
|
||||||
break;
|
break;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#ifndef CODEGEN_SCHEDULE_H
|
#ifndef CODEGEN_SCHEDULE_H
|
||||||
#define CODEGEN_SCHEDULE_H
|
#define CODEGEN_SCHEDULE_H
|
||||||
|
|
||||||
|
#include "SetTheory.h"
|
||||||
#include "llvm/TableGen/Record.h"
|
#include "llvm/TableGen/Record.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
@ -208,6 +209,9 @@ class CodeGenSchedModels {
|
|||||||
RecordKeeper &Records;
|
RecordKeeper &Records;
|
||||||
const CodeGenTarget &Target;
|
const CodeGenTarget &Target;
|
||||||
|
|
||||||
|
// Map dag expressions to Instruction lists.
|
||||||
|
SetTheory Sets;
|
||||||
|
|
||||||
// List of unique processor models.
|
// List of unique processor models.
|
||||||
std::vector<CodeGenProcModel> ProcModels;
|
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.
|
// This is the first time we see Set. Find a suitable expander.
|
||||||
try {
|
try {
|
||||||
const std::vector<Record*> &SC = Set->getSuperClasses();
|
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())) {
|
if (Expander *Exp = Expanders.lookup(SC[i]->getName())) {
|
||||||
// This breaks recursive definitions.
|
// This breaks recursive definitions.
|
||||||
RecVec &EltVec = Expansions[Set];
|
RecVec &EltVec = Expansions[Set];
|
||||||
@ -303,6 +306,7 @@ const RecVec *SetTheory::expand(Record *Set) {
|
|||||||
EltVec.assign(Elts.begin(), Elts.end());
|
EltVec.assign(Elts.begin(), Elts.end());
|
||||||
return &EltVec;
|
return &EltVec;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (const std::string &Error) {
|
} catch (const std::string &Error) {
|
||||||
throw TGError(Set->getLoc(), Error);
|
throw TGError(Set->getLoc(), Error);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user