aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen
diff options
context:
space:
mode:
authorjofrn <jofernau@amd.com>2024-05-20 06:18:49 -0800
committerGitHub <noreply@github.com>2024-05-20 06:18:49 -0800
commitd0dc29c2084a18c33b1b5b1cad9fd42215869746 (patch)
treecd009a9ebefa8a2f682aff82a103cdfb0add9120 /llvm/utils/TableGen
parent1553b21f6d3b620b8e32121b974793342820ab8c (diff)
downloadllvm-d0dc29c2084a18c33b1b5b1cad9fd42215869746.zip
llvm-d0dc29c2084a18c33b1b5b1cad9fd42215869746.tar.gz
llvm-d0dc29c2084a18c33b1b5b1cad9fd42215869746.tar.bz2
[TableGen] HasOneUse builtin predicate on PatFrags (#91578)
This predicate tells GlobalISelEmitter and DAGISelEmitter to check that the instruction to emit has only one use of its result. This can be used on a PatFrag instead of defining custom predicates for both emitters per record that requires it.
Diffstat (limited to 'llvm/utils/TableGen')
-rw-r--r--llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp7
-rw-r--r--llvm/utils/TableGen/Common/CodeGenDAGPatterns.h2
-rw-r--r--llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h23
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp6
4 files changed, 36 insertions, 2 deletions
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
index 88d353e..709aa00 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -903,7 +903,7 @@ TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) {
}
bool TreePredicateFn::hasPredCode() const {
- return isLoad() || isStore() || isAtomic() || hasNoUse() ||
+ return isLoad() || isStore() || isAtomic() || hasNoUse() || hasOneUse() ||
!PatFragRec->getRecord()->getValueAsString("PredicateCode").empty();
}
@@ -1140,6 +1140,8 @@ std::string TreePredicateFn::getPredCode() const {
if (hasNoUse())
Code += "if (!SDValue(N, 0).use_empty()) return false;\n";
+ if (hasOneUse())
+ Code += "if (!SDValue(N, 0).hasOneUse()) return false;\n";
std::string PredicateCode =
std::string(PatFragRec->getRecord()->getValueAsString("PredicateCode"));
@@ -1187,6 +1189,9 @@ bool TreePredicateFn::usesOperands() const {
bool TreePredicateFn::hasNoUse() const {
return isPredefinedPredicateEqualTo("HasNoUse", true);
}
+bool TreePredicateFn::hasOneUse() const {
+ return isPredefinedPredicateEqualTo("HasOneUse", true);
+}
bool TreePredicateFn::isLoad() const {
return isPredefinedPredicateEqualTo("IsLoad", true);
}
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h
index 7f94db0..1f4d45d8 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h
@@ -533,6 +533,8 @@ public:
// Check if the HasNoUse predicate is set.
bool hasNoUse() const;
+ // Check if the HasOneUse predicate is set.
+ bool hasOneUse() const;
// Is the desired predefined predicate for a load?
bool isLoad() const;
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h
index 5fe3f9a..edddc05 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h
@@ -806,6 +806,7 @@ public:
IPM_MemoryAlignment,
IPM_VectorSplatImm,
IPM_NoUse,
+ IPM_OneUse,
IPM_GenericPredicate,
IPM_MIFlags,
OPM_SameOperand,
@@ -1691,6 +1692,28 @@ public:
}
};
+/// Generates code to check that the first result has only one use.
+class OneUsePredicateMatcher : public InstructionPredicateMatcher {
+public:
+ OneUsePredicateMatcher(unsigned InsnVarID)
+ : InstructionPredicateMatcher(IPM_OneUse, InsnVarID) {}
+
+ static bool classof(const PredicateMatcher *P) {
+ return P->getKind() == IPM_OneUse;
+ }
+
+ bool isIdentical(const PredicateMatcher &B) const override {
+ return InstructionPredicateMatcher::isIdentical(B);
+ }
+
+ void emitPredicateOpcodes(MatchTable &Table,
+ RuleMatcher &Rule) const override {
+ Table << MatchTable::Opcode("GIM_CheckHasOneUse")
+ << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
+ << MatchTable::LineBreak;
+ }
+};
+
/// Generates code to check that a set of predicates and operands match for a
/// particular instruction.
///
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index 9b35614..ec41cd9 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -207,7 +207,7 @@ static Error isTrivialOperatorNode(const TreePatternNode &N) {
if (Predicate.isImmediatePattern())
continue;
- if (Predicate.hasNoUse())
+ if (Predicate.hasNoUse() || Predicate.hasOneUse())
continue;
if (Predicate.isNonExtLoad() || Predicate.isAnyExtLoad() ||
@@ -782,6 +782,10 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
InsnMatcher.addPredicate<NoUsePredicateMatcher>();
HasAddedBuiltinMatcher = true;
}
+ if (Predicate.hasOneUse()) {
+ InsnMatcher.addPredicate<OneUsePredicateMatcher>();
+ HasAddedBuiltinMatcher = true;
+ }
if (Predicate.hasGISelPredicateCode()) {
if (Predicate.usesOperands()) {