diff options
author | jyli0116 <yu.li@arm.com> | 2025-06-09 09:02:56 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-09 09:02:56 +0100 |
commit | f3ffee601c1746eafa9a6684541e90d182c9126e (patch) | |
tree | e964933542e6bef4f5d383f05185f8846e14f3be /llvm/utils | |
parent | 2f15637e04f51e3ef435c0c0d39aab0e8b933023 (diff) | |
download | llvm-f3ffee601c1746eafa9a6684541e90d182c9126e.zip llvm-f3ffee601c1746eafa9a6684541e90d182c9126e.tar.gz llvm-f3ffee601c1746eafa9a6684541e90d182c9126e.tar.bz2 |
[GISel][AArch64] Allow PatLeafs to be imported in GISel which were previously causing warnings (#140935)
Previously PatLeafs could not be imported, causing the following
warnings to be emitted when running tblgen with
`-warn-on-skipped-patterns:`
```
/work/clean/llvm/lib/Target/AArch64/AArch64InstrInfo.td:2631:1: warning: Skipped pattern: Src pattern child has unsupported predicate
def : Pat<(i64 (mul top32Zero:$Rn, top32Zero:$Rm)),
^
```
These changes allow the patterns to now be imported successfully.
Diffstat (limited to 'llvm/utils')
8 files changed, 132 insertions, 10 deletions
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp index a87aa8b..d33c0db 100644 --- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp @@ -899,6 +899,11 @@ TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) { assert( (!hasPredCode() || !hasImmCode()) && ".td file corrupt: can't have a node predicate *and* an imm predicate"); + + if (hasGISelPredicateCode() && hasGISelLeafPredicateCode()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + ".td file corrupt: can't have GISelPredicateCode *and* " + "GISelLeafPredicateCode"); } bool TreePredicateFn::hasPredCode() const { @@ -1293,8 +1298,20 @@ bool TreePredicateFn::hasGISelPredicateCode() const { } std::string TreePredicateFn::getGISelPredicateCode() const { - return std::string( - PatFragRec->getRecord()->getValueAsString("GISelPredicateCode")); + return PatFragRec->getRecord()->getValueAsString("GISelPredicateCode").str(); +} + +bool TreePredicateFn::hasGISelLeafPredicateCode() const { + return PatFragRec->getRecord() + ->getValueAsOptionalString("GISelLeafPredicateCode") + .has_value(); +} + +std::string TreePredicateFn::getGISelLeafPredicateCode() const { + return PatFragRec->getRecord() + ->getValueAsOptionalString("GISelLeafPredicateCode") + .value_or(StringRef()) + .str(); } StringRef TreePredicateFn::getImmType() const { diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h index 725414f..a5aadf2 100644 --- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h @@ -590,6 +590,11 @@ public: bool hasGISelPredicateCode() const; std::string getGISelPredicateCode() const; + // If true, indicates that GlobalISel-based C++ code was supplied for checking + // register operands. + bool hasGISelLeafPredicateCode() const; + std::string getGISelLeafPredicateCode() const; + private: bool hasPredCode() const; bool hasImmCode() const; diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp index 2cb3579..327ac5f 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp @@ -33,6 +33,8 @@ Error failUnsupported(const Twine &Reason) { std::string getEnumNameForPredicate(const TreePredicateFn &Predicate) { if (Predicate.hasGISelPredicateCode()) return "GICXXPred_MI_" + Predicate.getFnName(); + if (Predicate.hasGISelLeafPredicateCode()) + return "GICXXPred_MO_" + Predicate.getFnName(); return "GICXXPred_" + Predicate.getImmTypeIdentifier().str() + "_" + Predicate.getFnName(); } @@ -1326,6 +1328,19 @@ void OperandImmPredicateMatcher::emitPredicateOpcodes(MatchTable &Table, << MatchTable::LineBreak; } +//===- OperandLeafPredicateMatcher +//-----------------------------------------===// + +void OperandLeafPredicateMatcher::emitPredicateOpcodes( + MatchTable &Table, RuleMatcher &Rule) const { + Table << MatchTable::Opcode("GIM_CheckLeafOperandPredicate") + << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) + << MatchTable::Comment("MO") << MatchTable::ULEB128Value(OpIdx) + << MatchTable::Comment("Predicate") + << MatchTable::NamedValue(2, getEnumNameForPredicate(Predicate)) + << MatchTable::LineBreak; +} + //===- OperandMatcher -----------------------------------------------------===// std::string OperandMatcher::getOperandExpr(unsigned InsnVarID) const { diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h index fd24459..6647257 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h @@ -824,6 +824,7 @@ public: IPM_OneUse, IPM_GenericPredicate, IPM_MIFlags, + OPM_LeafPredicate, OPM_SameOperand, OPM_ComplexPattern, OPM_IntrinsicID, @@ -1255,6 +1256,26 @@ public: RuleMatcher &Rule) const override; }; +/// Generates code to check that this operand is a register whose value meets +/// the predicate. +class OperandLeafPredicateMatcher : public OperandPredicateMatcher { +protected: + TreePredicateFn Predicate; + +public: + OperandLeafPredicateMatcher(unsigned InsnVarID, unsigned OpIdx, + const TreePredicateFn &Predicate) + : OperandPredicateMatcher(OPM_LeafPredicate, InsnVarID, OpIdx), + Predicate(Predicate) {} + + static bool classof(const PredicateMatcher *P) { + return P->getKind() == OPM_LeafPredicate; + } + + void emitPredicateOpcodes(MatchTable &Table, + RuleMatcher &Rule) const override; +}; + /// Generates code to check that a set of predicates match for a particular /// operand. class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> { diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp index ffab2fd..333d956 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp @@ -182,6 +182,7 @@ void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl( emitSubtargetFeatureBitsetImpl(OS, Rules); emitComplexPredicates(OS, ComplexOperandMatchers); emitMIPredicateFns(OS); + emitLeafPredicateFns(OS); emitI64ImmPredicateFns(OS); emitAPFloatImmPredicateFns(OS); emitAPIntImmPredicateFns(OS); @@ -234,6 +235,9 @@ void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl( << " bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI" ", const MatcherState &State) " "const override;\n" + << " bool testMOPredicate_MO(unsigned PredicateID, const MachineOperand " + "&MO, const MatcherState &State) " + "const override;\n" << " bool testSimplePredicate(unsigned PredicateID) const override;\n" << " bool runCustomAction(unsigned FnID, const MatcherState &State, " "NewMIVector &OutMIs) " diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h index 862f1e8..1f66d73 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h @@ -79,8 +79,8 @@ class GlobalISelMatchTableExecutorEmitter { raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType, StringRef ArgName, StringRef AdditionalArgs, StringRef AdditionalDeclarations, ArrayRef<PredicateObject> Predicates, - std::function<StringRef(PredicateObject)> GetPredEnumName, - std::function<StringRef(PredicateObject)> GetPredCode, + llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName, + llvm::function_ref<StringRef(PredicateObject)> GetPredCode, StringRef Comment) { if (!Comment.empty()) OS << "// " << Comment << "\n"; @@ -135,14 +135,34 @@ protected: void emitMIPredicateFnsImpl( raw_ostream &OS, StringRef AdditionalDecls, ArrayRef<PredicateObject> Predicates, - std::function<StringRef(PredicateObject)> GetPredEnumName, - std::function<StringRef(PredicateObject)> GetPredCode, + llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName, + llvm::function_ref<StringRef(PredicateObject)> GetPredCode, StringRef Comment = "") { return emitCxxPredicateFns( OS, "MI", "const MachineInstr &", "MI", ", const MatcherState &State", AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment); } + /// Emits `testMOPredicate_MO`. + /// \tparam PredicateObject An object representing a predicate to emit. + /// \param OS Output stream. + /// \param AdditionalDecls Additional C++ variable declarations. + /// \param Predicates Predicates to emit. + /// \param GetPredEnumName Returns an enum name for a given predicate. + /// \param GetPredCode Returns the C++ code of a given predicate. + /// \param Comment Optional comment for the enum declaration. + template <typename PredicateObject> + void emitLeafPredicateFnsImpl( + raw_ostream &OS, StringRef AdditionalDecls, + ArrayRef<PredicateObject> Predicates, + llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName, + llvm::function_ref<StringRef(PredicateObject)> GetPredCode, + StringRef Comment = "") { + return emitCxxPredicateFns( + OS, "MO", "const MachineOperand &", "MO", ", const MatcherState &State", + AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment); + } + /// Helper function to emit the following executor functions: /// * testImmPredicate_I64 (TypeIdentifier=I64) /// * testImmPredicate_APInt (TypeIdentifier=APInt) @@ -160,8 +180,8 @@ protected: void emitImmPredicateFnsImpl( raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType, ArrayRef<PredicateObject> Predicates, - std::function<StringRef(PredicateObject)> GetPredEnumName, - std::function<StringRef(PredicateObject)> GetPredCode, + llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName, + llvm::function_ref<StringRef(PredicateObject)> GetPredCode, StringRef Comment = "") { return emitCxxPredicateFns(OS, TypeIdentifier, ArgType, "Imm", "", "", Predicates, GetPredEnumName, GetPredCode, @@ -189,6 +209,10 @@ public: /// Note: `emitMIPredicateFnsImpl` can be used to do most of the work. virtual void emitMIPredicateFns(raw_ostream &OS) = 0; + /// Emit the `testLeafPredicate` function + /// Note `emitLeafPredicateFnsImpl` can be used to do most of the work. + virtual void emitLeafPredicateFns(raw_ostream &OS) = 0; + /// Emit the `testImmPredicate_I64` function. /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work. virtual void emitI64ImmPredicateFns(raw_ostream &OS) = 0; diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp index afaf050..f62b265 100644 --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -2414,6 +2414,7 @@ class GICombinerEmitter final : public GlobalISelMatchTableExecutorEmitter { void emitAdditionalImpl(raw_ostream &OS) override; void emitMIPredicateFns(raw_ostream &OS) override; + void emitLeafPredicateFns(raw_ostream &OS) override; void emitI64ImmPredicateFns(raw_ostream &OS) override; void emitAPFloatImmPredicateFns(raw_ostream &OS) override; void emitAPIntImmPredicateFns(raw_ostream &OS) override; @@ -2581,6 +2582,12 @@ void GICombinerEmitter::emitMIPredicateFns(raw_ostream &OS) { [](const CXXPredicateCode *C) -> StringRef { return C->Code; }); } +void GICombinerEmitter::emitLeafPredicateFns(raw_ostream &OS) { + // Unused, but still needs to be called. + emitLeafPredicateFnsImpl<unsigned>( + OS, "", {}, [](unsigned) { return ""; }, [](unsigned) { return ""; }); +} + void GICombinerEmitter::emitI64ImmPredicateFns(raw_ostream &OS) { // Unused, but still needs to be called. emitImmPredicateFnsImpl<unsigned>( diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 55f60db..5b61d6e 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -321,6 +321,7 @@ public: void emitAdditionalImpl(raw_ostream &OS) override; void emitMIPredicateFns(raw_ostream &OS) override; + void emitLeafPredicateFns(raw_ostream &OS) override; void emitI64ImmPredicateFns(raw_ostream &OS) override; void emitAPFloatImmPredicateFns(raw_ostream &OS) override; void emitAPIntImmPredicateFns(raw_ostream &OS) override; @@ -1110,8 +1111,16 @@ Error GlobalISelEmitter::importChildMatcher( return Error::success(); } - if (SrcChild.hasAnyPredicate()) - return failedImport("Src pattern child has unsupported predicate"); + if (SrcChild.hasAnyPredicate()) { + for (const TreePredicateCall &Call : SrcChild.getPredicateCalls()) { + const TreePredicateFn &Predicate = Call.Fn; + + if (!Predicate.hasGISelLeafPredicateCode()) + return failedImport("Src pattern child has unsupported predicate"); + OM.addPredicate<OperandLeafPredicateMatcher>(Predicate); + } + return Error::success(); + } // Check for constant immediates. if (auto *ChildInt = dyn_cast<IntInit>(SrcChild.getLeafValue())) { @@ -2293,6 +2302,26 @@ void GlobalISelEmitter::emitMIPredicateFns(raw_ostream &OS) { "PatFrag predicates."); } +void GlobalISelEmitter::emitLeafPredicateFns(raw_ostream &OS) { + std::vector<const Record *> MatchedRecords; + llvm::copy_if(AllPatFrags, std::back_inserter(MatchedRecords), + [](const Record *R) { + return (!R->getValueAsOptionalString("GISelLeafPredicateCode") + .value_or(std::string()) + .empty()); + }); + emitLeafPredicateFnsImpl<const Record *>( + OS, + " const auto &Operands = State.RecordedOperands;\n" + " Register Reg = MO.getReg();\n" + " (void)Operands;", + ArrayRef<const Record *>(MatchedRecords), &getPatFragPredicateEnumName, + [](const Record *R) { + return R->getValueAsString("GISelLeafPredicateCode"); + }, + "PatFrag predicates."); +} + void GlobalISelEmitter::emitI64ImmPredicateFns(raw_ostream &OS) { std::vector<const Record *> MatchedRecords; llvm::copy_if(AllPatFrags, std::back_inserter(MatchedRecords), |