-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[LLVM][TableGen] Support type casts of nodes with multiple results #109728
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-tablegen Author: Stephen Chou (stephenchouca) ChangesCurrently, type casts can only be used to pattern match for intrinsics with a single overloaded return value. For example:
This patch extends type casts to support matching intrinsics with multiple overloaded return values. This is enabled with a new
Full diff: https://github.com/llvm/llvm-project/pull/109728.diff 3 Files Affected:
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;
}
|
@llvm/pr-subscribers-llvm-selectiondag Author: Stephen Chou (stephenchouca) ChangesCurrently, type casts can only be used to pattern match for intrinsics with a single overloaded return value. For example:
This patch extends type casts to support matching intrinsics with multiple overloaded return values. This is enabled with a new
Full diff: https://github.com/llvm/llvm-project/pull/109728.diff 3 Files Affected:
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;
}
|
65f0c3a
to
5a307be
Compare
5a307be
to
8a9513e
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
3b8aa40
to
cbf6f65
Compare
cbf6f65
to
ee9c4ce
Compare
4747f1f
to
8bc8eff
Compare
a1fae64
to
d35fb1f
Compare
d35fb1f
to
d6cc3d9
Compare
Currently, type casts can only be used to pattern match for intrinsics with a single overloaded return value. For instance: ``` 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. As an example, the following defines a pattern that matches only if the overloaded intrinsic call returns an `i16` for the first result and an `i32` for the second result: ``` def int_bar : Intrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>; def : Pat<([i16, i32] (int_bar)), ...>; ```
d6cc3d9
to
ed2b750
Compare
It'd be great if someone can merge this pull request for me; I don't have write access. Thanks! |
…lvm#109728) Currently, type casts can only be used to pattern match for intrinsics with a single overloaded return value. For instance: ``` 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. As an example, the following defines a pattern that matches only if the overloaded intrinsic call returns an `i16` for the first result and an `i32` for the second result: ``` def int_bar : Intrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>; def : Pat<([i16, i32] (int_bar)), ...>; ```
Currently, type casts can only be used to pattern match for intrinsics with a single overloaded return value. For instance:
This patch extends type casts to support matching intrinsics with multiple overloaded return values. As an example, the following defines a pattern that matches only if the overloaded intrinsic call returns an
i16
for the first result and ani32
for the second result: