diff options
Diffstat (limited to 'llvm/utils')
| -rw-r--r-- | llvm/utils/TableGen/CodeGenDAGPatterns.cpp | 8 | ||||
| -rw-r--r-- | llvm/utils/TableGen/CodeGenDAGPatterns.h | 4 | ||||
| -rw-r--r-- | llvm/utils/TableGen/GlobalISelEmitter.cpp | 102 |
3 files changed, 95 insertions, 19 deletions
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index a9f1b0be816..ced3e979c04 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -881,6 +881,14 @@ std::string TreePredicateFn::getImmType() const { return "int64_t"; } +std::string TreePredicateFn::getImmTypeIdentifier() const { + if (immCodeUsesAPInt()) + return "APInt"; + else if (immCodeUsesAPFloat()) + return "APFloat"; + return "I64"; +} + /// isAlwaysTrue - Return true if this is a noop predicate. bool TreePredicateFn::isAlwaysTrue() const { return getPredCode().empty() && getImmCode().empty(); diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/CodeGenDAGPatterns.h index 3033986fdd4..5918e901a3d 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -478,6 +478,10 @@ public: /// Get the data type of the argument to getImmediatePredicateCode(). std::string getImmType() const; + /// Get a string that describes the type returned by getImmType() but is + /// usable as part of an identifier. + std::string getImmTypeIdentifier() const; + private: std::string getPredCode() const; std::string getImmCode() const; diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 18eb271d4ef..2e86b17d0b9 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -65,6 +65,18 @@ static cl::opt<bool> WarnOnSkippedPatterns( namespace { //===- Helper functions ---------------------------------------------------===// + +/// Get the name of the enum value used to number the predicate function. +std::string getEnumNameForPredicate(const TreePredicateFn &Predicate) { + return "GIPFP_" + Predicate.getImmTypeIdentifier() + "_" + + Predicate.getFnName(); +} + +/// Get the opcode used to check this predicate. +std::string getMatchOpcodeForPredicate(const TreePredicateFn &Predicate) { + return "GIM_Check" + Predicate.getImmTypeIdentifier() + "ImmPredicate"; +} + /// This class stands in for LLT wherever we want to tablegen-erate an /// equivalent at compiler run-time. class LLTCodeGen { @@ -1057,10 +1069,10 @@ public: void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule, unsigned InsnVarID) const override { - Table << MatchTable::Opcode("GIM_CheckImmPredicate") + Table << MatchTable::Opcode(getMatchOpcodeForPredicate(Predicate)) << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID) << MatchTable::Comment("Predicate") - << MatchTable::NamedValue("GIPFP_" + Predicate.getFnName()) + << MatchTable::NamedValue(getEnumNameForPredicate(Predicate)) << MatchTable::LineBreak; } }; @@ -1258,6 +1270,7 @@ public: OR_Copy, OR_CopySubReg, OR_CopyConstantAsImm, + OR_CopyFConstantAsFPImm, OR_Imm, OR_Register, OR_ComplexPattern @@ -1345,6 +1358,36 @@ public: } }; +/// A CopyFConstantAsFPImmRenderer emits code to render a G_FCONSTANT +/// instruction to an extended immediate operand. +class CopyFConstantAsFPImmRenderer : public OperandRenderer { +protected: + unsigned NewInsnID; + /// The name of the operand. + const std::string SymbolicName; + +public: + CopyFConstantAsFPImmRenderer(unsigned NewInsnID, StringRef SymbolicName) + : OperandRenderer(OR_CopyFConstantAsFPImm), NewInsnID(NewInsnID), + SymbolicName(SymbolicName) {} + + static bool classof(const OperandRenderer *R) { + return R->getKind() == OR_CopyFConstantAsFPImm; + } + + const StringRef getSymbolicName() const { return SymbolicName; } + + void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override { + const InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName); + unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher); + Table << MatchTable::Opcode("GIR_CopyFConstantAsFPImm") + << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID) + << MatchTable::Comment("OldInsnID") + << MatchTable::IntValue(OldInsnVarID) + << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; + } +}; + /// A CopySubRegRenderer emits code to copy a single register operand from an /// existing instruction to the one being built and indicate that only a /// subregister should be copied. @@ -1913,7 +1956,8 @@ private: importImplicitDefRenderers(BuildMIAction &DstMIBuilder, const std::vector<Record *> &ImplicitDefs) const; - void emitImmPredicates(raw_ostream &OS, + void emitImmPredicates(raw_ostream &OS, StringRef TypeIdentifier, + StringRef Type, std::function<bool(const Record *R)> Filter); /// Analyze pattern \p P, returning a matcher for it if possible. @@ -2029,8 +2073,9 @@ GlobalISelEmitter::createAndImportSelDAGMatcher(InstructionMatcher &InsnMatcher, } else { assert(SrcGIOrNull && "Expected to have already found an equivalent Instruction"); - if (SrcGIOrNull->TheDef->getName() == "G_CONSTANT") { - // imm still has an operand but we don't need to do anything with it + if (SrcGIOrNull->TheDef->getName() == "G_CONSTANT" || + SrcGIOrNull->TheDef->getName() == "G_FCONSTANT") { + // imm/fpimm still have operands but we don't need to do anything with it // here since we don't support ImmLeaf predicates yet. However, we still // need to note the hidden operand to get GIM_CheckNumOperands correct. InsnMatcher.addOperand(OpIdx++, "", TempOpIdx); @@ -2185,6 +2230,10 @@ Error GlobalISelEmitter::importExplicitUseRenderer( DstMIBuilder.addRenderer<CopyConstantAsImmRenderer>(0, DstChild->getName()); return Error::success(); + } else if (DstChild->getOperator()->getName() == "fpimm") { + DstMIBuilder.addRenderer<CopyFConstantAsFPImmRenderer>( + 0, DstChild->getName()); + return Error::success(); } return failedImport("Dst pattern child isn't a leaf node or an MBB" + llvm::to_string(*DstChild)); @@ -2566,7 +2615,8 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { // The 'Predicate_' part of the name is redundant but eliminating it is more // trouble than it's worth. void GlobalISelEmitter::emitImmPredicates( - raw_ostream &OS, std::function<bool(const Record *R)> Filter) { + raw_ostream &OS, StringRef TypeIdentifier, StringRef Type, + std::function<bool(const Record *R)> Filter) { std::vector<const Record *> MatchedRecords; const auto &Defs = RK.getAllDerivedDefinitions("PatFrag"); std::copy_if(Defs.begin(), Defs.end(), std::back_inserter(MatchedRecords), @@ -2575,19 +2625,25 @@ void GlobalISelEmitter::emitImmPredicates( Filter(Record); }); - OS << "// PatFrag predicates.\n" - << "enum {\n"; - StringRef EnumeratorSeparator = " = GIPFP_Invalid + 1,\n"; - for (const auto *Record : MatchedRecords) { - OS << " GIPFP_Predicate_" << Record->getName() << EnumeratorSeparator; - EnumeratorSeparator = ",\n"; + if (!MatchedRecords.empty()) { + OS << "// PatFrag predicates.\n" + << "enum {\n"; + StringRef EnumeratorSeparator = + (" = GIPFP_" + TypeIdentifier + "_Invalid + 1,\n").str(); + for (const auto *Record : MatchedRecords) { + OS << " GIPFP_" << TypeIdentifier << "_Predicate_" << Record->getName() + << EnumeratorSeparator; + EnumeratorSeparator = ",\n"; + } + OS << "};\n"; } - OS << "};\n"; + for (const auto *Record : MatchedRecords) - OS << " static bool Predicate_" << Record->getName() << "(int64_t Imm) {" - << Record->getValueAsString("ImmediateCode") << " }\n"; - OS << "static InstructionSelector::ImmediatePredicateFn ImmPredicateFns[] = " - "{\n" + OS << "static bool Predicate_" << Record->getName() << "(" << Type + << " Imm) {" << Record->getValueAsString("ImmediateCode") << "}\n"; + + OS << "static InstructionSelector::" << TypeIdentifier + << "ImmediatePredicateFn " << TypeIdentifier << "ImmPredicateFns[] = {\n" << " nullptr,\n"; for (const auto *Record : MatchedRecords) OS << " Predicate_" << Record->getName() << ",\n"; @@ -2664,7 +2720,8 @@ void GlobalISelEmitter::run(raw_ostream &OS) { OS << "#ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n" << ", State(" << MaxTemporaries << "),\n" - << "MatcherInfo({TypeObjects, FeatureBitsets, ImmPredicateFns, {\n" + << "MatcherInfo({TypeObjects, FeatureBitsets, I64ImmPredicateFns, " + "APIntImmPredicateFns, APFloatImmPredicateFns, {\n" << " nullptr, // GICP_Invalid\n"; for (const auto &Record : ComplexPredicates) OS << " &" << Target.getName() @@ -2777,11 +2834,18 @@ void GlobalISelEmitter::run(raw_ostream &OS) { OS << "};\n" << "// See constructor for table contents\n\n"; - emitImmPredicates(OS, [](const Record *R) { + emitImmPredicates(OS, "I64", "int64_t", [](const Record *R) { bool Unset; return !R->getValueAsBitOrUnset("IsAPFloat", Unset) && !R->getValueAsBit("IsAPInt"); }); + emitImmPredicates(OS, "APFloat", "const APFloat &", [](const Record *R) { + bool Unset; + return R->getValueAsBitOrUnset("IsAPFloat", Unset); + }); + emitImmPredicates(OS, "APInt", "const APInt &", [](const Record *R) { + return R->getValueAsBit("IsAPInt"); + }); OS << "bool " << Target.getName() << "InstructionSelector::selectImpl(MachineInstr &I) const {\n" |

