aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/FastISel.h5
-rw-r--r--lib/CodeGen/SelectionDAG/FastISel.cpp10
-rw-r--r--lib/Target/X86/X86FastISel.cpp1
-rw-r--r--test/CodeGen/X86/fast-isel.ll2
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp27
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h2
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp24
-rw-r--r--utils/TableGen/FastISelEmitter.cpp94
8 files changed, 111 insertions, 54 deletions
diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h
index cd6a6d6199..c414956bb5 100644
--- a/include/llvm/CodeGen/FastISel.h
+++ b/include/llvm/CodeGen/FastISel.h
@@ -26,18 +26,21 @@ class MachineRegisterInfo;
class TargetData;
class TargetInstrInfo;
class TargetLowering;
+class TargetMachine;
class TargetRegisterClass;
/// FastISel - This is a fast-path instruction selection class that
/// generates poor code and doesn't support illegal types or non-trivial
/// lowering, but runs quickly.
class FastISel {
+protected:
MachineBasicBlock *MBB;
MachineFunction &MF;
MachineRegisterInfo &MRI;
+ const TargetMachine &TM;
const TargetData &TD;
const TargetInstrInfo &TII;
- TargetLowering &TLI;
+ const TargetLowering &TLI;
public:
/// SelectInstructions - Do "fast" instruction selection over the
diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp
index 450596e50d..388028334d 100644
--- a/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -220,10 +220,12 @@ FastISel::SelectInstructions(BasicBlock::iterator Begin,
}
FastISel::FastISel(MachineFunction &mf)
- : MF(mf), MRI(mf.getRegInfo()),
- TD(*mf.getTarget().getTargetData()),
- TII(*mf.getTarget().getInstrInfo()),
- TLI(*mf.getTarget().getTargetLowering()) {
+ : MF(mf),
+ MRI(mf.getRegInfo()),
+ TM(mf.getTarget()),
+ TD(*TM.getTargetData()),
+ TII(*TM.getInstrInfo()),
+ TLI(*TM.getTargetLowering()) {
}
FastISel::~FastISel() {}
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index 0c0660c783..f049a4d363 100644
--- a/lib/Target/X86/X86FastISel.cpp
+++ b/lib/Target/X86/X86FastISel.cpp
@@ -17,4 +17,5 @@
#include "X86RegisterInfo.h"
#include "X86ISelLowering.h"
#include "X86FastISel.h"
+#include "X86TargetMachine.h"
#include "X86GenFastISel.inc"
diff --git a/test/CodeGen/X86/fast-isel.ll b/test/CodeGen/X86/fast-isel.ll
index 3510024fe4..601e38578c 100644
--- a/test/CodeGen/X86/fast-isel.ll
+++ b/test/CodeGen/X86/fast-isel.ll
@@ -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.
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 1e957834a8..1e595dd474 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -141,6 +141,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
//
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index 4434cf0c1c..4d7ea58b06 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -444,6 +444,8 @@ struct PatternToMatch {
TreePatternNode *getDstPattern() const { return DstPattern; }
const std::vector<Record*> &getDstRegs() const { return Dstregs; }
unsigned getAddedComplexity() const { return AddedComplexity; }
+
+ std::string getPredicateCheck() const;
};
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 12667d5656..cf4d20f9c6 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -317,7 +317,7 @@ private:
CodeGenDAGPatterns &CGP;
// Predicates.
- ListInit *Predicates;
+ std::string PredicateCheck;
// Pattern cost.
unsigned Cost;
// Instruction selector pattern.
@@ -395,7 +395,7 @@ private:
VTNo++;
}
public:
- PatternCodeEmitter(CodeGenDAGPatterns &cgp, ListInit *preds,
+ PatternCodeEmitter(CodeGenDAGPatterns &cgp, std::string predcheck,
TreePatternNode *pattern, TreePatternNode *instr,
std::vector<std::pair<unsigned, std::string> > &gc,
std::set<std::string> &gd,
@@ -403,7 +403,7 @@ public:
std::vector<std::string> &tv,
bool &oiv,
unsigned &niro)
- : CGP(cgp), Predicates(preds), Pattern(pattern), Instruction(instr),
+ : CGP(cgp), PredicateCheck(predcheck), Pattern(pattern), Instruction(instr),
GeneratedCode(gc), GeneratedDecl(gd),
TargetOpcodes(to), TargetVTs(tv),
OutputIsVariadic(oiv), NumInputRootOps(niro),
@@ -431,22 +431,6 @@ public:
if (DisablePatternForFastISel(N, CGP))
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);
}
@@ -1412,7 +1396,7 @@ void DAGISelEmitter::GenerateCodeForPattern(const PatternToMatch &Pattern,
OutputIsVariadic = false;
NumInputRootOps = 0;
- PatternCodeEmitter Emitter(CGP, Pattern.getPredicates(),
+ PatternCodeEmitter Emitter(CGP, Pattern.getPredicateCheck(),
Pattern.getSrcPattern(), Pattern.getDstPattern(),
GeneratedCode, GeneratedDecl,
TargetOpcodes, TargetVTs,
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index cbe77f6d5d..b343013b06 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -175,10 +175,11 @@ void FastISelEmitter::run(std::ostream &OS) {
OS << "namespace " << InstNS.substr(0, InstNS.size() - 2) << " {\n";
OS << "\n";
- typedef std::map<MVT::SimpleValueType, InstructionMemo> TypeMap;
- typedef std::map<std::string, TypeMap> OpcodeTypeMap;
- typedef std::map<OperandsSignature, OpcodeTypeMap> OperandsOpcodeTypeMap;
- OperandsOpcodeTypeMap SimplePatterns;
+ typedef std::map<std::string, InstructionMemo> PredMap;
+ typedef std::map<MVT::SimpleValueType, PredMap> TypePredMap;
+ typedef std::map<std::string, TypePredMap> OpcodeTypePredMap;
+ typedef std::map<OperandsSignature, OpcodeTypePredMap> OperandsOpcodeTypePredMap;
+ OperandsOpcodeTypePredMap SimplePatterns;
for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
E = CGP.ptm_end(); I != E; ++I) {
@@ -230,27 +231,32 @@ void FastISelEmitter::run(std::ostream &OS) {
if (!Operands.initialize(InstPatNode, Target, VT, DstRC))
continue;
+ // Get the predicate that guards this pattern.
+ std::string PredicateCheck = Pattern.getPredicateCheck();
+
// Ok, we found a pattern that we can handle. Remember it.
InstructionMemo Memo = {
Pattern.getDstPattern()->getOperator()->getName(),
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.
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) {
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) {
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) {
MVT::SimpleValueType VT = TI->first;
@@ -279,8 +285,19 @@ void FastISelEmitter::run(std::ostream &OS) {
Operands.PrintParameters(OS);
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 << " 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";
@@ -291,25 +308,26 @@ void FastISelEmitter::run(std::ostream &OS) {
OS << "\n";
// 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) {
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) {
const std::string &Opcode = I->first;
- const TypeMap &TM = I->second;
+ const TypePredMap &TM = I->second;
OS << "// FastEmit functions for " << Opcode << ".\n";
OS << "\n";
// 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) {
MVT::SimpleValueType VT = TI->first;
- const InstructionMemo &Memo = TI->second;
-
+ const PredMap &PM = TI->second;
+ bool HasPred = false;
+
OS << "unsigned FastISel::FastEmit_"
<< getLegalCName(Opcode)
<< "_" << getLegalCName(getName(VT)) << "_";
@@ -317,14 +335,34 @@ void FastISelEmitter::run(std::ostream &OS) {
OS << "(";
Operands.PrintParameters(OS);
OS << ") {\n";
- 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";
+
+ // Emit code for each possible instruction. There may be
+ // multiple if there are subtarget concerns.
+ for (PredMap::const_iterator PI = PM.begin(), PE = PM.end();
+ PI != PE; ++PI) {
+ std::string PredicateCheck = PI->first;
+ const InstructionMemo &Memo = PI->second;
+
+ 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";
}
@@ -339,7 +377,7 @@ void FastISelEmitter::run(std::ostream &OS) {
Operands.PrintParameters(OS);
OS << ") {\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) {
MVT::SimpleValueType VT = TI->first;
std::string TypeName = getName(VT);
@@ -366,7 +404,7 @@ void FastISelEmitter::run(std::ostream &OS) {
Operands.PrintParameters(OS);
OS << ") {\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) {
const std::string &Opcode = I->first;