From 22bb31103de3337f0bb74c7bee16d1817d4dca14 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 22 Aug 2008 00:20:26 +0000 Subject: [PATCH] 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 --- include/llvm/CodeGen/FastISel.h | 5 +- lib/CodeGen/SelectionDAG/FastISel.cpp | 10 +-- lib/Target/X86/X86FastISel.cpp | 1 + test/CodeGen/X86/fast-isel.ll | 2 +- utils/TableGen/CodeGenDAGPatterns.cpp | 27 ++++++++ utils/TableGen/CodeGenDAGPatterns.h | 2 + utils/TableGen/DAGISelEmitter.cpp | 24 ++----- utils/TableGen/FastISelEmitter.cpp | 94 +++++++++++++++++++-------- 8 files changed, 111 insertions(+), 54 deletions(-) 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; -- 2.34.1