[llvm] [LLVM][TableGen] Support type casts of nodes with multiple results (PR #109728)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 23 16:11:56 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-selectiondag
Author: Stephen Chou (stephenchouca)
<details>
<summary>Changes</summary>
Currently, type casts can only be used to pattern match for intrinsics with a single overloaded return value. For example:
```
def int_foo : Intrinsic<[llvm_anyint_ty], []>;
def : Pat<(i32 (int_foo)), ...>;
```
This patch extends type casts to support matching intrinsics with multiple overloaded return values. This is enabled with a new `ValueTypeList` class that can be used to define the target of a type cast. As an example, the following defines a pattern that matches only if the results of the overloaded intrinsic call are both `i32`:
```
def int_bar : Intrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>;
def i32_i32 : ValueTypeList<[i32, i32]>;
def : Pat<(i32_i32 (int_bar)), ...>;
```
---
Full diff: https://github.com/llvm/llvm-project/pull/109728.diff
3 Files Affected:
- (modified) llvm/include/llvm/Target/TargetSelectionDAG.td (+15)
- (added) llvm/test/TableGen/dag-isel-valuetypelist.td (+38)
- (modified) llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp (+31-8)
``````````diff
diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index adf8a75f620225..df50cc07d5cb22 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -2070,3 +2070,18 @@ class ComplexPattern<ValueType ty, int numops, string fn,
list<SDNodeProperty> Properties = props;
int Complexity = complexity;
}
+
+//===----------------------------------------------------------------------===//
+// Value type list.
+//
+// This can be used to pattern match for intrinsics with multiple overloaded
+// return values. For example:
+//
+// def int_foo : Irtrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>;
+// def i32_i32 : ValueTypeList<[i32, i32]>;
+// def : Pat<(i32_i32 (int_foo)), ...>;
+//
+
+class ValueTypeList<list<ValueType> vts> {
+ list<ValueType> VTs = vts ;
+}
diff --git a/llvm/test/TableGen/dag-isel-valuetypelist.td b/llvm/test/TableGen/dag-isel-valuetypelist.td
new file mode 100644
index 00000000000000..db0b30695522d9
--- /dev/null
+++ b/llvm/test/TableGen/dag-isel-valuetypelist.td
@@ -0,0 +1,38 @@
+// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include %s | FileCheck %s
+
+include "llvm/Target/Target.td"
+
+def TestTargetInstrInfo : InstrInfo;
+
+def TestTarget : Target {
+ let InstructionSet = TestTargetInstrInfo;
+}
+
+def REG : Register<"REG">;
+def GPR : RegisterClass<"TestTarget", [i16, i32], 32, (add REG)>;
+
+def int_foo : Intrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>;
+
+def INSTR_FOO_I16_I32 : Instruction {
+ let OutOperandList = (outs GPR:$a, GPR:$b);
+ let InOperandList = (ins);
+}
+
+def INSTR_FOO_I32_I16 : Instruction {
+ let OutOperandList = (outs GPR:$a, GPR:$b);
+ let InOperandList = (ins);
+}
+
+def i16_i32 : ValueTypeList<[i16, i32]>;
+def i32_i16 : ValueTypeList<[i32, i16]>;
+
+// CHECK: OPC_CheckOpcode, TARGET_VAL(ISD::INTRINSIC_W_CHAIN)
+// CHECK: 7*/ OPC_SwitchType {{.*}}, 10, /*MVT::i16*/6
+// CHECK: OPC_CheckTypeRes, 1, /*MVT::i32*/7
+// CHECK: OPC_MorphNodeTo2Chain, TARGET_VAL(::INSTR_FOO_I16_I32)
+def : Pat<(i16_i32 (int_foo)), (i16_i32 (INSTR_FOO_I16_I32))>;
+
+// CHECK: 20*/ /*SwitchType*/ {{.*}} /*MVT::i32*/7
+// CHECK: OPC_CheckTypeRes, 1, /*MVT::i16*/6
+// CHECK: OPC_MorphNodeTo2Chain, TARGET_VAL(::INSTR_FOO_I32_I16)
+def : Pat<(i32_i16 (int_foo)), (i32_i16 (INSTR_FOO_I32_I16))>;
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
index fd80bc681c70d9..578275c36b69cd 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -2903,23 +2903,46 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
}
Record *Operator = OpDef->getDef();
+ auto ParseCastOperand = [this](DagInit *Dag, StringRef OpName) {
+ if (Dag->getNumArgs() != 1)
+ error("Type cast only takes one operand!");
+
+ if (!OpName.empty())
+ error("Type cast should not have a name!");
+
+ return ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
+ };
+
if (Operator->isSubClassOf("ValueType")) {
// If the operator is a ValueType, then this must be "type cast" of a leaf
// node.
- if (Dag->getNumArgs() != 1)
- error("Type cast only takes one operand!");
+ TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
- TreePatternNodePtr New =
- ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
+ if (New->getNumTypes() != 1)
+ error("ValueType cast can only have one type!");
// Apply the type cast.
- if (New->getNumTypes() != 1)
- error("Type cast can only have one type!");
const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this);
- if (!OpName.empty())
- error("ValueType cast should not have a name!");
+ return New;
+ }
+
+ if (Operator->isSubClassOf("ValueTypeList")) {
+ // If the operator is a ValueTypeList, then this must be "type cast" of a
+ // leaf node with multiple results.
+ TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
+
+ ListInit *LI = Operator->getValueAsListInit("VTs");
+ if (New->getNumTypes() != LI->size())
+ error("Invalid number of type casts!");
+
+ // Apply the type casts.
+ const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
+ for (unsigned i = 0, e = New->getNumTypes(); i != e; ++i)
+ New->UpdateNodeType(
+ i, getValueTypeByHwMode(LI->getElementAsRecord(i), CGH), *this);
+
return New;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/109728
More information about the llvm-commits
mailing list