-
Notifications
You must be signed in to change notification settings - Fork 13.9k
[TableGen] Add a backend generating SDNode descriptions #123002
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 @llvm/pr-subscribers-llvm-selectiondag Author: Sergei Barannikov (s-barannikov) ChangesThis patch adds a simplistic backend that gathers all target-specific SelectionDAG nodes and emits descriptions for most of them. This includes generating node enumeration, node names, and information about node "prototype" that can be used to verify that a node is valid. The patch also extends SDNode by adding target-specific flags, which are also included in the generated tables. Part of #119709, RFC. Patch is 38.59 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/123002.diff 9 Files Affected:
diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index bee0a4298c786f..cd2ca3a08bd691 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -353,6 +353,8 @@ class SDNode<string opcode, SDTypeProfile typeprof,
string SDClass = sdclass;
let Properties = props;
SDTypeProfile TypeProfile = typeprof;
+ bit IsStrictFP = false;
+ bits<64> TSFlags = 0;
}
// Special TableGen-recognized dag nodes
diff --git a/llvm/test/TableGen/SDNodeInfoEmitter/ambiguous-constraints.td b/llvm/test/TableGen/SDNodeInfoEmitter/ambiguous-constraints.td
new file mode 100644
index 00000000000000..668464190e6d89
--- /dev/null
+++ b/llvm/test/TableGen/SDNodeInfoEmitter/ambiguous-constraints.td
@@ -0,0 +1,73 @@
+// RUN: split-file %s %t
+
+//--- test1.td
+// RUN: llvm-tblgen -gen-sd-node-info -I %p/../../../include %t/test1.td | FileCheck %t/test1.td
+
+include "llvm/Target/Target.td"
+
+def MyTarget : Target;
+
+def my_node_a : SDNode<"MyTargetISD::NODE", SDTypeProfile<1, 0, [SDTCisVT<0, i32>]>>;
+def my_node_b : SDNode<"MyTargetISD::NODE", SDTypeProfile<1, 0, [SDTCisVT<0, f32>]>>;
+
+// CHECK: enum GenNodeType : unsigned {
+// CHECK-NEXT: NODE = ISD::BUILTIN_OP_END,
+// CHECK-NEXT: };
+
+// CHECK: static const char MyTargetSDNodeNames[] =
+// CHECK-NEXT: "MyTargetISD::NODE\0"
+// CHECK-NEXT: "\0";
+
+// CHECK: static const SDTypeConstraint MyTargetSDTypeConstraints[] = {
+// CHECK-NEXT: /* dummy */ {SDTCisVT, 0, 0, MVT::INVALID_SIMPLE_VALUE_TYPE}
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeDesc MyTargetSDNodeDescs[] = {
+// CHECK-NEXT: {1, 0, 0, 0, 0, 0, 0, 0}, // NODE
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeInfo MyTargetGenSDNodeInfo(
+// CHECK-NEXT: /*NumOpcodes=*/1, MyTargetSDNodeDescs,
+// CHECK-NEXT: MyTargetSDNodeNames, MyTargetSDTypeConstraints);
+
+
+//--- test2.td
+// RUN: llvm-tblgen -gen-sd-node-info -I %p/../../../include %t/test2.td | FileCheck %t/test2.td
+
+include "llvm/Target/Target.td"
+
+def MyTarget : Target;
+
+def my_node_1a : SDNode<"MyTargetISD::NODE_1", SDTypeProfile<1, 0, [SDTCisVT<0, i32>]>>;
+def my_node_1b : SDNode<"MyTargetISD::NODE_1", SDTypeProfile<1, 0, [SDTCisVT<0, i32>]>>;
+def my_node_2a : SDNode<"MyTargetISD::NODE_2", SDTypeProfile<1, 0, [SDTCisVT<0, i32>]>>;
+def my_node_2b : SDNode<"MyTargetISD::NODE_2", SDTypeProfile<1, 0, [SDTCisVT<0, untyped>]>>;
+
+// CHECK: namespace llvm::MyTargetISD {
+// CHECK-EMPTY:
+// CHECK-NEXT: enum GenNodeType : unsigned {
+// CHECK-NEXT: NODE_1 = ISD::BUILTIN_OP_END,
+// CHECK-NEXT: NODE_2,
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static constexpr unsigned GENERATED_OPCODE_END = NODE_2 + 1;
+// CHECK-EMPTY:
+// CHECK-NEXT: } // namespace llvm::MyTargetISD
+
+// CHECK: static const char MyTargetSDNodeNames[] =
+// CHECK-NEXT: "MyTargetISD::NODE_1\0"
+// CHECK-NEXT: "MyTargetISD::NODE_2\0"
+// CHECK-NEXT: "\0";
+
+// CHECK: static const SDTypeConstraint MyTargetSDTypeConstraints[] = {
+// CHECK-NEXT: /* 0 */ {SDTCisVT, 0, 0, MVT::i32},
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeDesc MyTargetSDNodeDescs[] = {
+// CHECK-NEXT: {1, 0, 0, 0, 0, 0, 0, 1}, // NODE_1
+// CHECK-NEXT: {1, 0, 0, 0, 0, 20, 0, 0}, // NODE_2
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeInfo MyTargetGenSDNodeInfo(
+// CHECK-NEXT: /*NumOpcodes=*/2, MyTargetSDNodeDescs,
+// CHECK-NEXT: MyTargetSDNodeNames, MyTargetSDTypeConstraints);
diff --git a/llvm/test/TableGen/SDNodeInfoEmitter/basic.td b/llvm/test/TableGen/SDNodeInfoEmitter/basic.td
new file mode 100644
index 00000000000000..7f5085e31e02c4
--- /dev/null
+++ b/llvm/test/TableGen/SDNodeInfoEmitter/basic.td
@@ -0,0 +1,85 @@
+// RUN: split-file %s %t
+
+//--- no-nodes.td
+// RUN: llvm-tblgen -gen-sd-node-info -I %p/../../../include %t/no-nodes.td \
+// RUN: | FileCheck %t/no-nodes.td
+
+include "llvm/Target/Target.td"
+
+def MyTarget : Target;
+
+// CHECK: #ifdef GET_SDNODE_ENUM
+// CHECK-NEXT: #undef GET_SDNODE_ENUM
+// CHECK-EMPTY:
+// CHECK-NEXT: namespace llvm::MyTargetISD {
+// CHECK-EMPTY:
+// CHECK-NEXT: static constexpr unsigned GENERATED_OPCODE_END = ISD::BUILTIN_OP_END;
+// CHECK-EMPTY:
+// CHECK-NEXT: } // namespace llvm::MyTargetISD
+// CHECK-EMPTY:
+// CHECK-NEXT: #endif // GET_SDNODE_ENUM
+// CHECK-EMPTY:
+// CHECK-NEXT: #ifdef GET_SDNODE_DESC
+// CHECK-NEXT: #undef GET_SDNODE_DESC
+// CHECK-EMPTY:
+// CHECK-NEXT: namespace llvm {
+// CHECK-EMPTY:
+// CHECK-NEXT: #ifdef __GNUC__
+// CHECK-NEXT: #pragma GCC diagnostic push
+// CHECK-NEXT: #pragma GCC diagnostic ignored "-Woverlength-strings"
+// CHECK-NEXT: #endif
+// CHECK-NEXT: static const char MyTargetSDNodeNames[] =
+// CHECK-NEXT: "\0";
+// CHECK-NEXT: #ifdef __GNUC__
+// CHECK-NEXT: #pragma GCC diagnostic pop
+// CHECK-NEXT: #endif
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDTypeConstraint MyTargetSDTypeConstraints[] = {
+// CHECK-NEXT: /* dummy */ {SDTCisVT, 0, 0, MVT::INVALID_SIMPLE_VALUE_TYPE}
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeDesc MyTargetSDNodeDescs[] = {
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeInfo MyTargetGenSDNodeInfo(
+// CHECK-NEXT: /*NumOpcodes=*/0, MyTargetSDNodeDescs,
+// CHECK-NEXT: MyTargetSDNodeNames, MyTargetSDTypeConstraints);
+// CHECK-EMPTY:
+// CHECK-NEXT: } // namespace llvm
+
+
+//--- trivial-node.td
+// RUN: llvm-tblgen -gen-sd-node-info -I %p/../../../include %t/trivial-node.td \
+// RUN: | FileCheck %t/trivial-node.td
+
+include "llvm/Target/Target.td"
+
+def MyTarget : Target;
+
+def my_noop : SDNode<"MyTargetISD::NOOP", SDTypeProfile<0, 0, []>>;
+
+// CHECK: namespace llvm::MyTargetISD {
+// CHECK-EMPTY:
+// CHECK-NEXT: enum GenNodeType : unsigned {
+// CHECK-NEXT: NOOP = ISD::BUILTIN_OP_END,
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static constexpr unsigned GENERATED_OPCODE_END = NOOP + 1;
+// CHECK-EMPTY:
+// CHECK-NEXT: } // namespace llvm::MyTargetISD
+
+// CHECK: static const char MyTargetSDNodeNames[] =
+// CHECK-NEXT: "MyTargetISD::NOOP\0"
+// CHECK-NEXT: "\0";
+
+// CHECK: static const SDTypeConstraint MyTargetSDTypeConstraints[] = {
+// CHECK-NEXT: /* dummy */ {SDTCisVT, 0, 0, MVT::INVALID_SIMPLE_VALUE_TYPE}
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeDesc MyTargetSDNodeDescs[] = {
+// CHECK-NEXT: {0, 0, 0, 0, 0, 0, 0, 0}, // NOOP
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeInfo MyTargetGenSDNodeInfo(
+// CHECK-NEXT: /*NumOpcodes=*/1, MyTargetSDNodeDescs,
+// CHECK-NEXT: MyTargetSDNodeNames, MyTargetSDTypeConstraints);
diff --git a/llvm/test/TableGen/SDNodeInfoEmitter/namespace.td b/llvm/test/TableGen/SDNodeInfoEmitter/namespace.td
new file mode 100644
index 00000000000000..844c12bd182fc6
--- /dev/null
+++ b/llvm/test/TableGen/SDNodeInfoEmitter/namespace.td
@@ -0,0 +1,62 @@
+// RUN: llvm-tblgen -gen-sd-node-info -I %p/../../../include %s -sdnode-namespace=EmptyISD \
+// RUN: | FileCheck %s -check-prefix=EMPTY
+
+// RUN: llvm-tblgen -gen-sd-node-info -I %p/../../../include %s \
+// RUN: | FileCheck %s --check-prefixes=COMMON,TARGET -DNS=MyTargetISD
+// RUN: llvm-tblgen -gen-sd-node-info -I %p/../../../include %s -sdnode-namespace=MyCustomISD \
+// RUN: | FileCheck %s -check-prefixes=COMMON,CUSTOM -DNS=MyCustomISD
+
+include "llvm/Target/Target.td"
+
+def MyTarget : Target;
+
+def node_1 : SDNode<"MyTargetISD::NODE", SDTypeProfile<1, 0, [SDTCisVT<0, i1>]>>;
+def node_2 : SDNode<"MyCustomISD::NODE", SDTypeProfile<0, 1, [SDTCisVT<0, i2>]>>;
+
+// EMPTY: namespace llvm::EmptyISD {
+// EMPTY-EMPTY:
+// EMPTY-NEXT: static constexpr unsigned GENERATED_OPCODE_END = ISD::BUILTIN_OP_END;
+// EMPTY-EMPTY:
+// EMPTY-NEXT: } // namespace llvm::EmptyISD
+
+// EMPTY: static const char MyTargetSDNodeNames[] =
+// EMPTY-NEXT: "\0";
+
+// EMPTY: static const SDTypeConstraint MyTargetSDTypeConstraints[] = {
+// EMPTY-NEXT: /* dummy */ {SDTCisVT, 0, 0, MVT::INVALID_SIMPLE_VALUE_TYPE}
+// EMPTY-NEXT: };
+// EMPTY-EMPTY:
+// EMPTY-NEXT: static const SDNodeDesc MyTargetSDNodeDescs[] = {
+// EMPTY-NEXT: };
+// EMPTY-EMPTY:
+// EMPTY-NEXT: static const SDNodeInfo MyTargetGenSDNodeInfo(
+// EMPTY-NEXT: /*NumOpcodes=*/0, MyTargetSDNodeDescs,
+// EMPTY-NEXT: MyTargetSDNodeNames, MyTargetSDTypeConstraints);
+
+// COMMON: namespace llvm::[[NS]] {
+// COMMON-EMPTY:
+// COMMON-NEXT: enum GenNodeType : unsigned {
+// COMMON-NEXT: NODE = ISD::BUILTIN_OP_END,
+// COMMON-NEXT: };
+// COMMON-EMPTY:
+// COMMON-NEXT: static constexpr unsigned GENERATED_OPCODE_END = NODE + 1;
+// COMMON-EMPTY:
+// COMMON-NEXT: } // namespace llvm::[[NS]]
+
+// COMMON: static const char MyTargetSDNodeNames[] =
+// COMMON-NEXT: "[[NS]]::NODE\0"
+// COMMON-NEXT: "\0";
+
+// COMMON: static const SDTypeConstraint MyTargetSDTypeConstraints[] = {
+// TARGET-NEXT: /* 0 */ {SDTCisVT, 0, 0, MVT::i1},
+// CUSTOM-NEXT: /* 0 */ {SDTCisVT, 0, 0, MVT::i2},
+// COMMON-NEXT: };
+// COMMON-EMPTY:
+// COMMON-NEXT: static const SDNodeDesc MyTargetSDNodeDescs[] = {
+// TARGET-NEXT: {1, 0, 0, 0, 0, 0, 0, 1}, // NODE
+// CUSTOM-NEXT: {0, 1, 0, 0, 0, 0, 0, 1}, // NODE
+// COMMON-NEXT: };
+// COMMON-EMPTY:
+// COMMON-NEXT: static const SDNodeInfo MyTargetGenSDNodeInfo(
+// COMMON-NEXT: /*NumOpcodes=*/1, MyTargetSDNodeDescs,
+// COMMON-NEXT: MyTargetSDNodeNames, MyTargetSDTypeConstraints);
diff --git a/llvm/test/TableGen/SDNodeInfoEmitter/skipped-nodes.td b/llvm/test/TableGen/SDNodeInfoEmitter/skipped-nodes.td
new file mode 100644
index 00000000000000..ed278f262ca8f7
--- /dev/null
+++ b/llvm/test/TableGen/SDNodeInfoEmitter/skipped-nodes.td
@@ -0,0 +1,91 @@
+// RUN: llvm-tblgen -gen-sd-node-info -I %p/../../../include %s 2> %t.warn | FileCheck %s
+// RUN: FileCheck --check-prefix=WARN --implicit-check-not=warning %s < %t.warn
+
+// RUN: llvm-tblgen -gen-sd-node-info -warn-on-skipped-nodes=false \
+// RUN: -I %p/../../../include %s 2> %t.nowarn | FileCheck %s
+// RUN: not test -s %t.nowarn
+
+include "llvm/Target/Target.td"
+
+def MyTarget : Target;
+
+// WARN: [[#@LINE+1]]:5: warning: skipped node: invalid enum name
+def bad_name_1 : SDNode<"", SDTypeProfile<0, 0, []>>;
+
+// WARN: [[#@LINE+1]]:5: warning: skipped node: invalid enum name
+def bad_name_2 : SDNode<"NODE", SDTypeProfile<0, 0, []>>;
+
+// WARN: [[#@LINE+1]]:5: warning: skipped node: invalid enum name
+def bad_name_3 : SDNode<"MyTargetISD::", SDTypeProfile<0, 0, []>>;
+
+// WARN: [[#@LINE+1]]:5: warning: skipped node: invalid enum name
+def bad_name_4 : SDNode<"MyISD::", SDTypeProfile<0, 0, []>>;
+
+// WARN: [[#@LINE+1]]:5: warning: skipped node: invalid enum name
+def bad_name_5 : SDNode<"::NODE", SDTypeProfile<0, 0, []>>;
+
+
+// Standard namespace.
+def silent_1 : SDNode<"ISD::SILENT", SDTypeProfile<0, 0, []>>;
+
+// Different namespace.
+def silent_2 : SDNode<"MyISD::SILENT", SDTypeProfile<0, 0, []>>;
+
+
+// Different number of results.
+// WARN: [[#@LINE+2]]:5: warning: skipped node: incompatible description
+// WARN: [[#@LINE+2]]:5: warning: skipped node: incompatible description
+def node_1a : SDNode<"MyTargetISD::NODE_1", SDTypeProfile<0, 0, []>>;
+def node_1b : SDNode<"MyTargetISD::NODE_1", SDTypeProfile<1, 0, []>>;
+
+// Different number of operands.
+// WARN: [[#@LINE+2]]:5: warning: skipped node: incompatible description
+// WARN: [[#@LINE+2]]:5: warning: skipped node: incompatible description
+def node_2a : SDNode<"MyTargetISD::NODE_2", SDTypeProfile<0, 0, []>>;
+def node_2b : SDNode<"MyTargetISD::NODE_2", SDTypeProfile<0, 1, []>>;
+
+// Different value of IsStrictFP.
+// WARN: [[#@LINE+3]]:5: warning: skipped node: incompatible description
+// WARN: [[#@LINE+3]]:5: warning: skipped node: incompatible description
+let IsStrictFP = true in
+def node_3a : SDNode<"MyTargetISD::NODE_3", SDTypeProfile<0, 0, []>>;
+def node_3b : SDNode<"MyTargetISD::NODE_3", SDTypeProfile<0, 0, []>>;
+
+// Different value of TSFlags.
+// WARN: [[#@LINE+3]]:5: warning: skipped node: incompatible description
+// WARN: [[#@LINE+3]]:5: warning: skipped node: incompatible description
+let TSFlags = 1 in
+def node_4a : SDNode<"MyTargetISD::NODE_4", SDTypeProfile<0, 0, []>>;
+def node_4b : SDNode<"MyTargetISD::NODE_4", SDTypeProfile<0, 0, []>>;
+
+// Different properties.
+// WARN: [[#@LINE+2]]:5: warning: skipped node: incompatible description
+// WARN: [[#@LINE+2]]:5: warning: skipped node: incompatible description
+def node_5a : SDNode<"MyTargetISD::NODE_5", SDTypeProfile<0, 0, []>>;
+def node_5b : SDNode<"MyTargetISD::NODE_5", SDTypeProfile<0, 0, []>, [SDNPHasChain]>;
+
+
+// CHECK: enum GenNodeType : unsigned {
+// CHECK-NEXT: COMPAT = ISD::BUILTIN_OP_END,
+// CHECK-NEXT: };
+
+// CHECK: static const char MyTargetSDNodeNames[] =
+// CHECK-NEXT: "MyTargetISD::COMPAT\0"
+// CHECK-NEXT: "\0";
+
+// CHECK: static const SDTypeConstraint MyTargetSDTypeConstraints[] = {
+// CHECK-NEXT: /* dummy */ {SDTCisVT, 0, 0, MVT::INVALID_SIMPLE_VALUE_TYPE}
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeDesc MyTargetSDNodeDescs[] = {
+// CHECK-NEXT: {1, -1, 0, 0, 0, 0, 0, 0}, // COMPAT
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: static const SDNodeInfo MyTargetGenSDNodeInfo(
+// CHECK-NEXT: /*NumOpcodes=*/1, MyTargetSDNodeDescs,
+// CHECK-NEXT: MyTargetSDNodeNames, MyTargetSDTypeConstraints);
+
+def compat_a : SDNode<"MyTargetISD::COMPAT", SDTypeProfile<1, -1, []>>;
+def compat_b : SDNode<"MyTargetISD::COMPAT", SDTypeProfile<1, -1, [SDTCisVT<0, untyped>]>>;
+def compat_c : SDNode<"MyTargetISD::COMPAT", SDTypeProfile<1, -1, [SDTCisVT<0, untyped>]>,
+ [SDNPCommutative, SDNPAssociative, SDNPMayStore, SDNPMayLoad, SDNPSideEffect]>;
diff --git a/llvm/utils/TableGen/CMakeLists.txt b/llvm/utils/TableGen/CMakeLists.txt
index 96a74c6fd89f73..67291214c14e60 100644
--- a/llvm/utils/TableGen/CMakeLists.txt
+++ b/llvm/utils/TableGen/CMakeLists.txt
@@ -60,6 +60,7 @@ add_tablegen(llvm-tblgen LLVM
PseudoLoweringEmitter.cpp
RegisterBankEmitter.cpp
RegisterInfoEmitter.cpp
+ SDNodeInfoEmitter.cpp
SearchableTableEmitter.cpp
SubtargetEmitter.cpp
WebAssemblyDisassemblerEmitter.cpp
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
index 1a61d32b4869a4..6629baa6e071ea 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -1537,21 +1537,19 @@ SDTypeConstraint::SDTypeConstraint(const Record *R, const CodeGenHwModes &CGH) {
ConstraintType = SDTCisVec;
} else if (R->isSubClassOf("SDTCisSameAs")) {
ConstraintType = SDTCisSameAs;
- x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum");
+ OtherOperandNo = R->getValueAsInt("OtherOperandNum");
} else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) {
ConstraintType = SDTCisVTSmallerThanOp;
- x.SDTCisVTSmallerThanOp_Info.OtherOperandNum =
- R->getValueAsInt("OtherOperandNum");
+ OtherOperandNo = R->getValueAsInt("OtherOperandNum");
} else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) {
ConstraintType = SDTCisOpSmallerThanOp;
- x.SDTCisOpSmallerThanOp_Info.BigOperandNum =
- R->getValueAsInt("BigOperandNum");
+ OtherOperandNo = R->getValueAsInt("BigOperandNum");
} else if (R->isSubClassOf("SDTCisEltOfVec")) {
ConstraintType = SDTCisEltOfVec;
- x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum");
+ OtherOperandNo = R->getValueAsInt("OtherOpNum");
} else if (R->isSubClassOf("SDTCisSubVecOfVec")) {
ConstraintType = SDTCisSubVecOfVec;
- x.SDTCisSubVecOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum");
+ OtherOperandNo = R->getValueAsInt("OtherOpNum");
} else if (R->isSubClassOf("SDTCVecEltisVT")) {
ConstraintType = SDTCVecEltisVT;
VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH);
@@ -1566,12 +1564,10 @@ SDTypeConstraint::SDTypeConstraint(const Record *R, const CodeGenHwModes &CGH) {
}
} else if (R->isSubClassOf("SDTCisSameNumEltsAs")) {
ConstraintType = SDTCisSameNumEltsAs;
- x.SDTCisSameNumEltsAs_Info.OtherOperandNum =
- R->getValueAsInt("OtherOperandNum");
+ OtherOperandNo = R->getValueAsInt("OtherOperandNum");
} else if (R->isSubClassOf("SDTCisSameSizeAs")) {
ConstraintType = SDTCisSameSizeAs;
- x.SDTCisSameSizeAs_Info.OtherOperandNum =
- R->getValueAsInt("OtherOperandNum");
+ OtherOperandNo = R->getValueAsInt("OtherOperandNum");
} else {
PrintFatalError(R->getLoc(),
"Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
@@ -1632,7 +1628,7 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode &N,
case SDTCisSameAs: {
unsigned OResNo = 0;
TreePatternNode &OtherNode =
- getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo);
+ getOperandNum(OtherOperandNo, N, NodeInfo, OResNo);
return (int)NodeToApply.UpdateNodeType(ResNo, OtherNode.getExtType(OResNo),
TP) |
(int)OtherNode.UpdateNodeType(OResNo, NodeToApply.getExtType(ResNo),
@@ -1654,23 +1650,23 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode &N,
TypeSetByHwMode TypeListTmp(VVT);
unsigned OResNo = 0;
- TreePatternNode &OtherNode = getOperandNum(
- x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo, OResNo);
+ TreePatternNode &OtherNode =
+ getOperandNum(OtherOperandNo, N, NodeInfo, OResNo);
return TI.EnforceSmallerThan(TypeListTmp, OtherNode.getExtType(OResNo),
/*SmallIsVT*/ true);
}
case SDTCisOpSmallerThanOp: {
unsigned BResNo = 0;
- TreePatternNode &BigOperand = getOperandNum(
- x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo, BResNo);
+ TreePatternNode &BigOperand =
+ getOperandNum(OtherOperandNo, N, NodeInfo, BResNo);
return TI.EnforceSmallerThan(NodeToApply.getExtType(ResNo),
BigOperand.getExtType(BResNo));
}
case SDTCisEltOfVec: {
unsigned VResNo = 0;
- TreePatternNode &VecOperand = getOperandNum(
- x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo, VResNo);
+ TreePatternNode &VecOperand =
+ getOperandNum(OtherOperandNo, N, NodeInfo, VResNo);
// Filter vector types out of VecOperand that don't have the right element
// type.
return TI.EnforceVectorEltTypeIs(VecOperand.getExtType(VResNo),
@@ -1678,8 +1674,8 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode &N,
}
case SDTCisSubVecOfVec: {
unsigned VResNo = 0;
- TreePatternNode &BigVecOperand = getOperandNum(
- x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo, VResNo);
+ TreePatternNode &BigVecOperand =
+ getOperandNum(OtherOperandNo, N, NodeInfo, VResNo);
// Filter vector types out of BigVecOperand that don't have the
// right subvector type.
@@ -1691,15 +1687,15 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode &N,
}
case SDTCisSameNumEltsAs: {
unsigned OResNo = 0;
- TreePatternNode &OtherNode = getOperandNum(
- x.SDTCisSameNumEltsAs_Info.OtherOperandNum, N, NodeInfo, OResNo);
+ TreePatternNode &OtherNode =
+ getOperandNum(OtherOperandNo, N, NodeInfo, OResNo);
return TI.EnforceSameNumElts(OtherNode.getExtType(OResNo),
NodeToApply.getExtType(ResNo));
}
case SDTCisSameSizeAs: {
unsigned OResNo = 0;
- TreePatternNode &OtherNode = getOperandNum(
- x.SDTCisSameSizeAs_Info.OtherOperandNum, N, NodeInfo, OResNo);
+ TreePatternNode &OtherNode =
+ getOperandNum(OtherOperandNo, N, NodeInfo, OResNo);
return TI.EnforceSameSize(OtherNode.getExtType(OResNo),
NodeToApply.getExtType(ResNo));
}
@@ -1707,6 +1703,58 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode &N,
llvm_unreachable("Invalid ConstraintType!");
}
+bool llvm::operator==(cons...
[truncated]
|
This patch adds a simplistic backend that gathers all target-specific SelectionDAG nodes and emits descriptions for most of them. This includes generating node enumeration, node names, and information about node "prototype" that can be used to verify that a node is valid. The patch also extends SDNode by adding target-specific flags, which are also included in the generated tables. Part of llvm#119709, [RFC](https://discourse.llvm.org/t/rfc-tablegen-erating-sdnode-descriptions/83627).
06d6890
to
9ec5e48
Compare
|
||
SmallVector<StringRef> SkippedNodes; | ||
for (const auto &[EnumName, Nodes] : TargetNodesByName) { | ||
ArrayRef Constraints = Nodes.front()->getTypeConstraints(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing template parameter on the ArrayRef. I feel like I've seen something like this were it didn't work with all compilers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've seen it used in other places, but it's uncommon. I'll add the parameter.
@@ -353,6 +353,8 @@ class SDNode<string opcode, SDTypeProfile typeprof, | |||
string SDClass = sdclass; | |||
let Properties = props; | |||
SDTypeProfile TypeProfile = typeprof; | |||
bit IsStrictFP = false; | |||
bits<64> TSFlags = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TSFlags in SDNodeDesc in #119709 is declared as uint32_t. Are you going to enlarge that or should this be 32?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for spotting this. I think 32 bits should be more than enough, at least for now.
* Add missing template parameter to ArrayRef * Shrink TSFlags to 32 bits
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm with nits
constexpr unsigned PropMask = (1 << SDNPHasChain) | (1 << SDNPOutGlue) | | ||
(1 << SDNPInGlue) | (1 << SDNPOptInGlue) | | ||
(1 << SDNPMemOperand) | (1 << SDNPVariadic); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At some point we should probably upgrade the enum to a bitmask enum
|
||
for (StringRef EnumName : make_first_range(TargetNodesByName)) { | ||
SmallString<64> DebugName; | ||
(TargetSDNodeNamespace + "::" + EnumName).toVector(DebugName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use raw_svector_ostream?
NameTable.EmitStringLiteralDef( | ||
OS, "static const char " + Target.getName() + "SDNodeNames[]", | ||
/*Indent=*/""); | ||
OS << "\n"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OS << "\n"; | |
OS << '\n'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…123002) This patch adds a simplistic backend that gathers all target-specific SelectionDAG nodes and emits descriptions for most of them. This includes generating node enumeration, node names, and information about node "prototype" that can be used to verify that a node is valid. The patch also extends SDNode by adding target-specific flags, which are also included in the generated tables. Part of #119709, [RFC](https://discourse.llvm.org/t/rfc-tablegen-erating-sdnode-descriptions/83627). Pull Request: llvm/llvm-project#123002
This patch adds a simplistic backend that gathers all target-specific SelectionDAG nodes and emits descriptions for most of them.
This includes generating node enumeration, node names, and information about node "prototype" that can be used to verify that a node is valid.
The patch also extends SDNode by adding target-specific flags, which are also included in the generated tables.
Part of #119709, RFC.