diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index cd6a6d61996..c414956bb55 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 450596e50d0..388028334d5 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 0c0660c7832..f049a4d363d 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 3510024fe4f..601e38578c6 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 1e957834a88..1e595dd4744 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -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(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 4434cf0c1c1..4d7ea58b06b 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 &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 12667d5656f..cf4d20f9c67 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 > &gc, std::set &gd, @@ -403,7 +403,7 @@ public: std::vector &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(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 cbe77f6d5df..b343013b067 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 TypeMap; - typedef std::map OpcodeTypeMap; - typedef std::map OperandsOpcodeTypeMap; - OperandsOpcodeTypeMap SimplePatterns; + typedef std::map PredMap; + typedef std::map TypePredMap; + typedef std::map OpcodeTypePredMap; + typedef std::map 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;