Factor out the predicate check code from DAGISelEmitter.cpp

and use it in FastISelEmitter.cpp, and make FastISel
subtarget aware. Among other things, this lets it work
properly on x86 targets that don't have SSE, where it
successfully selects x87 instructions.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55156 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman
2008-08-22 00:20:26 +00:00
parent a6211d9e83
commit 22bb31103d
8 changed files with 111 additions and 54 deletions

View File

@ -26,18 +26,21 @@ class MachineRegisterInfo;
class TargetData; class TargetData;
class TargetInstrInfo; class TargetInstrInfo;
class TargetLowering; class TargetLowering;
class TargetMachine;
class TargetRegisterClass; class TargetRegisterClass;
/// FastISel - This is a fast-path instruction selection class that /// FastISel - This is a fast-path instruction selection class that
/// generates poor code and doesn't support illegal types or non-trivial /// generates poor code and doesn't support illegal types or non-trivial
/// lowering, but runs quickly. /// lowering, but runs quickly.
class FastISel { class FastISel {
protected:
MachineBasicBlock *MBB; MachineBasicBlock *MBB;
MachineFunction &MF; MachineFunction &MF;
MachineRegisterInfo &MRI; MachineRegisterInfo &MRI;
const TargetMachine &TM;
const TargetData &TD; const TargetData &TD;
const TargetInstrInfo &TII; const TargetInstrInfo &TII;
TargetLowering &TLI; const TargetLowering &TLI;
public: public:
/// SelectInstructions - Do "fast" instruction selection over the /// SelectInstructions - Do "fast" instruction selection over the

View File

@ -220,10 +220,12 @@ FastISel::SelectInstructions(BasicBlock::iterator Begin,
} }
FastISel::FastISel(MachineFunction &mf) FastISel::FastISel(MachineFunction &mf)
: MF(mf), MRI(mf.getRegInfo()), : MF(mf),
TD(*mf.getTarget().getTargetData()), MRI(mf.getRegInfo()),
TII(*mf.getTarget().getInstrInfo()), TM(mf.getTarget()),
TLI(*mf.getTarget().getTargetLowering()) { TD(*TM.getTargetData()),
TII(*TM.getInstrInfo()),
TLI(*TM.getTargetLowering()) {
} }
FastISel::~FastISel() {} FastISel::~FastISel() {}

View File

@ -17,4 +17,5 @@
#include "X86RegisterInfo.h" #include "X86RegisterInfo.h"
#include "X86ISelLowering.h" #include "X86ISelLowering.h"
#include "X86FastISel.h" #include "X86FastISel.h"
#include "X86TargetMachine.h"
#include "X86GenFastISel.inc" #include "X86GenFastISel.inc"

View File

@ -1,4 +1,4 @@
; RUN: llvm-as < %s | llc -fast-isel -march=x86 -mattr=sse2 ; RUN: llvm-as < %s | llc -fast-isel -march=x86
; This tests very minimal fast-isel functionality. ; This tests very minimal fast-isel functionality.

View File

@ -140,6 +140,33 @@ void DumpDepVars(MultipleUseVarSet &DepVars) {
} }
} }
//===----------------------------------------------------------------------===//
// PatternToMatch implementation
//
/// getPredicateCheck - Return a single string containing all of this
/// pattern's predicates concatenated with "&&" operators.
///
std::string PatternToMatch::getPredicateCheck() const {
std::string PredicateCheck;
for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
Record *Def = Pred->getDef();
if (!Def->isSubClassOf("Predicate")) {
#ifndef NDEBUG
Def->dump();
#endif
assert(0 && "Unknown predicate type!");
}
if (!PredicateCheck.empty())
PredicateCheck += " && ";
PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
}
}
return PredicateCheck;
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// SDTypeConstraint implementation // SDTypeConstraint implementation
// //

View File

@ -444,6 +444,8 @@ struct PatternToMatch {
TreePatternNode *getDstPattern() const { return DstPattern; } TreePatternNode *getDstPattern() const { return DstPattern; }
const std::vector<Record*> &getDstRegs() const { return Dstregs; } const std::vector<Record*> &getDstRegs() const { return Dstregs; }
unsigned getAddedComplexity() const { return AddedComplexity; } unsigned getAddedComplexity() const { return AddedComplexity; }
std::string getPredicateCheck() const;
}; };

View File

@ -317,7 +317,7 @@ private:
CodeGenDAGPatterns &CGP; CodeGenDAGPatterns &CGP;
// Predicates. // Predicates.
ListInit *Predicates; std::string PredicateCheck;
// Pattern cost. // Pattern cost.
unsigned Cost; unsigned Cost;
// Instruction selector pattern. // Instruction selector pattern.
@ -395,7 +395,7 @@ private:
VTNo++; VTNo++;
} }
public: public:
PatternCodeEmitter(CodeGenDAGPatterns &cgp, ListInit *preds, PatternCodeEmitter(CodeGenDAGPatterns &cgp, std::string predcheck,
TreePatternNode *pattern, TreePatternNode *instr, TreePatternNode *pattern, TreePatternNode *instr,
std::vector<std::pair<unsigned, std::string> > &gc, std::vector<std::pair<unsigned, std::string> > &gc,
std::set<std::string> &gd, std::set<std::string> &gd,
@ -403,7 +403,7 @@ public:
std::vector<std::string> &tv, std::vector<std::string> &tv,
bool &oiv, bool &oiv,
unsigned &niro) unsigned &niro)
: CGP(cgp), Predicates(preds), Pattern(pattern), Instruction(instr), : CGP(cgp), PredicateCheck(predcheck), Pattern(pattern), Instruction(instr),
GeneratedCode(gc), GeneratedDecl(gd), GeneratedCode(gc), GeneratedDecl(gd),
TargetOpcodes(to), TargetVTs(tv), TargetOpcodes(to), TargetVTs(tv),
OutputIsVariadic(oiv), NumInputRootOps(niro), OutputIsVariadic(oiv), NumInputRootOps(niro),
@ -431,22 +431,6 @@ public:
if (DisablePatternForFastISel(N, CGP)) if (DisablePatternForFastISel(N, CGP))
emitCheck("!Fast"); emitCheck("!Fast");
std::string PredicateCheck;
for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
Record *Def = Pred->getDef();
if (!Def->isSubClassOf("Predicate")) {
#ifndef NDEBUG
Def->dump();
#endif
assert(0 && "Unknown predicate type!");
}
if (!PredicateCheck.empty())
PredicateCheck += " && ";
PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
}
}
emitCheck(PredicateCheck); emitCheck(PredicateCheck);
} }
@ -1412,7 +1396,7 @@ void DAGISelEmitter::GenerateCodeForPattern(const PatternToMatch &Pattern,
OutputIsVariadic = false; OutputIsVariadic = false;
NumInputRootOps = 0; NumInputRootOps = 0;
PatternCodeEmitter Emitter(CGP, Pattern.getPredicates(), PatternCodeEmitter Emitter(CGP, Pattern.getPredicateCheck(),
Pattern.getSrcPattern(), Pattern.getDstPattern(), Pattern.getSrcPattern(), Pattern.getDstPattern(),
GeneratedCode, GeneratedDecl, GeneratedCode, GeneratedDecl,
TargetOpcodes, TargetVTs, TargetOpcodes, TargetVTs,

View File

@ -175,10 +175,11 @@ void FastISelEmitter::run(std::ostream &OS) {
OS << "namespace " << InstNS.substr(0, InstNS.size() - 2) << " {\n"; OS << "namespace " << InstNS.substr(0, InstNS.size() - 2) << " {\n";
OS << "\n"; OS << "\n";
typedef std::map<MVT::SimpleValueType, InstructionMemo> TypeMap; typedef std::map<std::string, InstructionMemo> PredMap;
typedef std::map<std::string, TypeMap> OpcodeTypeMap; typedef std::map<MVT::SimpleValueType, PredMap> TypePredMap;
typedef std::map<OperandsSignature, OpcodeTypeMap> OperandsOpcodeTypeMap; typedef std::map<std::string, TypePredMap> OpcodeTypePredMap;
OperandsOpcodeTypeMap SimplePatterns; typedef std::map<OperandsSignature, OpcodeTypePredMap> OperandsOpcodeTypePredMap;
OperandsOpcodeTypePredMap SimplePatterns;
for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
E = CGP.ptm_end(); I != E; ++I) { E = CGP.ptm_end(); I != E; ++I) {
@ -230,27 +231,32 @@ void FastISelEmitter::run(std::ostream &OS) {
if (!Operands.initialize(InstPatNode, Target, VT, DstRC)) if (!Operands.initialize(InstPatNode, Target, VT, DstRC))
continue; continue;
// Get the predicate that guards this pattern.
std::string PredicateCheck = Pattern.getPredicateCheck();
// Ok, we found a pattern that we can handle. Remember it. // Ok, we found a pattern that we can handle. Remember it.
InstructionMemo Memo = { InstructionMemo Memo = {
Pattern.getDstPattern()->getOperator()->getName(), Pattern.getDstPattern()->getOperator()->getName(),
DstRC DstRC
}; };
SimplePatterns[Operands][OpcodeName][VT] = Memo; assert(!SimplePatterns[Operands][OpcodeName][VT].count(PredicateCheck) &&
"Duplicate pattern!");
SimplePatterns[Operands][OpcodeName][VT][PredicateCheck] = Memo;
} }
// Declare the target FastISel class. // Declare the target FastISel class.
OS << "class FastISel : public llvm::FastISel {\n"; OS << "class FastISel : public llvm::FastISel {\n";
for (OperandsOpcodeTypeMap::const_iterator OI = SimplePatterns.begin(), for (OperandsOpcodeTypePredMap::const_iterator OI = SimplePatterns.begin(),
OE = SimplePatterns.end(); OI != OE; ++OI) { OE = SimplePatterns.end(); OI != OE; ++OI) {
const OperandsSignature &Operands = OI->first; const OperandsSignature &Operands = OI->first;
const OpcodeTypeMap &OTM = OI->second; const OpcodeTypePredMap &OTM = OI->second;
for (OpcodeTypeMap::const_iterator I = OTM.begin(), E = OTM.end(); for (OpcodeTypePredMap::const_iterator I = OTM.begin(), E = OTM.end();
I != E; ++I) { I != E; ++I) {
const std::string &Opcode = I->first; const std::string &Opcode = I->first;
const TypeMap &TM = I->second; const TypePredMap &TM = I->second;
for (TypeMap::const_iterator TI = TM.begin(), TE = TM.end(); for (TypePredMap::const_iterator TI = TM.begin(), TE = TM.end();
TI != TE; ++TI) { TI != TE; ++TI) {
MVT::SimpleValueType VT = TI->first; MVT::SimpleValueType VT = TI->first;
@ -279,8 +285,19 @@ void FastISelEmitter::run(std::ostream &OS) {
Operands.PrintParameters(OS); Operands.PrintParameters(OS);
OS << ");\n"; OS << ");\n";
} }
OS << "\n";
// Declare the Subtarget member, which is used for predicate checks.
OS << " const " << InstNS.substr(0, InstNS.size() - 2)
<< "Subtarget *Subtarget;\n";
OS << "\n";
// Declare the constructor.
OS << "public:\n"; OS << "public:\n";
OS << " explicit FastISel(MachineFunction &mf) : llvm::FastISel(mf) {}\n"; OS << " explicit FastISel(MachineFunction &mf)\n";
OS << " : llvm::FastISel(mf),\n";
OS << " Subtarget(&TM.getSubtarget<" << InstNS.substr(0, InstNS.size() - 2)
<< "Subtarget>()) {}\n";
OS << "};\n"; OS << "};\n";
OS << "\n"; OS << "\n";
@ -291,25 +308,26 @@ void FastISelEmitter::run(std::ostream &OS) {
OS << "\n"; OS << "\n";
// Now emit code for all the patterns that we collected. // Now emit code for all the patterns that we collected.
for (OperandsOpcodeTypeMap::const_iterator OI = SimplePatterns.begin(), for (OperandsOpcodeTypePredMap::const_iterator OI = SimplePatterns.begin(),
OE = SimplePatterns.end(); OI != OE; ++OI) { OE = SimplePatterns.end(); OI != OE; ++OI) {
const OperandsSignature &Operands = OI->first; const OperandsSignature &Operands = OI->first;
const OpcodeTypeMap &OTM = OI->second; const OpcodeTypePredMap &OTM = OI->second;
for (OpcodeTypeMap::const_iterator I = OTM.begin(), E = OTM.end(); for (OpcodeTypePredMap::const_iterator I = OTM.begin(), E = OTM.end();
I != E; ++I) { I != E; ++I) {
const std::string &Opcode = I->first; const std::string &Opcode = I->first;
const TypeMap &TM = I->second; const TypePredMap &TM = I->second;
OS << "// FastEmit functions for " << Opcode << ".\n"; OS << "// FastEmit functions for " << Opcode << ".\n";
OS << "\n"; OS << "\n";
// Emit one function for each opcode,type pair. // Emit one function for each opcode,type pair.
for (TypeMap::const_iterator TI = TM.begin(), TE = TM.end(); for (TypePredMap::const_iterator TI = TM.begin(), TE = TM.end();
TI != TE; ++TI) { TI != TE; ++TI) {
MVT::SimpleValueType VT = TI->first; MVT::SimpleValueType VT = TI->first;
const InstructionMemo &Memo = TI->second; const PredMap &PM = TI->second;
bool HasPred = false;
OS << "unsigned FastISel::FastEmit_" OS << "unsigned FastISel::FastEmit_"
<< getLegalCName(Opcode) << getLegalCName(Opcode)
<< "_" << getLegalCName(getName(VT)) << "_"; << "_" << getLegalCName(getName(VT)) << "_";
@ -317,14 +335,34 @@ void FastISelEmitter::run(std::ostream &OS) {
OS << "("; OS << "(";
Operands.PrintParameters(OS); Operands.PrintParameters(OS);
OS << ") {\n"; OS << ") {\n";
OS << " return FastEmitInst_";
Operands.PrintManglingSuffix(OS); // Emit code for each possible instruction. There may be
OS << "(" << InstNS << Memo.Name << ", "; // multiple if there are subtarget concerns.
OS << InstNS << Memo.RC->getName() << "RegisterClass"; for (PredMap::const_iterator PI = PM.begin(), PE = PM.end();
if (!Operands.empty()) PI != PE; ++PI) {
OS << ", "; std::string PredicateCheck = PI->first;
Operands.PrintArguments(OS); const InstructionMemo &Memo = PI->second;
OS << ");\n";
if (PredicateCheck.empty()) {
assert(!HasPred && "Multiple instructions match, at least one has "
"a predicate and at least one doesn't!");
} else {
OS << " if (" + PredicateCheck + ")\n";
OS << " ";
HasPred = true;
}
OS << " return FastEmitInst_";
Operands.PrintManglingSuffix(OS);
OS << "(" << InstNS << Memo.Name << ", ";
OS << InstNS << Memo.RC->getName() << "RegisterClass";
if (!Operands.empty())
OS << ", ";
Operands.PrintArguments(OS);
OS << ");\n";
}
// Return 0 if none of the predicates were satisfied.
if (HasPred)
OS << " return 0;\n";
OS << "}\n"; OS << "}\n";
OS << "\n"; OS << "\n";
} }
@ -339,7 +377,7 @@ void FastISelEmitter::run(std::ostream &OS) {
Operands.PrintParameters(OS); Operands.PrintParameters(OS);
OS << ") {\n"; OS << ") {\n";
OS << " switch (VT) {\n"; OS << " switch (VT) {\n";
for (TypeMap::const_iterator TI = TM.begin(), TE = TM.end(); for (TypePredMap::const_iterator TI = TM.begin(), TE = TM.end();
TI != TE; ++TI) { TI != TE; ++TI) {
MVT::SimpleValueType VT = TI->first; MVT::SimpleValueType VT = TI->first;
std::string TypeName = getName(VT); std::string TypeName = getName(VT);
@ -366,7 +404,7 @@ void FastISelEmitter::run(std::ostream &OS) {
Operands.PrintParameters(OS); Operands.PrintParameters(OS);
OS << ") {\n"; OS << ") {\n";
OS << " switch (Opcode) {\n"; OS << " switch (Opcode) {\n";
for (OpcodeTypeMap::const_iterator I = OTM.begin(), E = OTM.end(); for (OpcodeTypePredMap::const_iterator I = OTM.begin(), E = OTM.end();
I != E; ++I) { I != E; ++I) {
const std::string &Opcode = I->first; const std::string &Opcode = I->first;