Skip to content

[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

Merged
merged 8 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/include/llvm/Target/TargetSelectionDAG.td
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@ class SDNode<string opcode, SDTypeProfile typeprof,
string SDClass = sdclass;
let Properties = props;
SDTypeProfile TypeProfile = typeprof;
bit IsStrictFP = false;
bits<32> TSFlags = 0;
}

// Special TableGen-recognized dag nodes
Expand Down
73 changes: 73 additions & 0 deletions llvm/test/TableGen/SDNodeInfoEmitter/ambiguous-constraints.td
Original file line number Diff line number Diff line change
@@ -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);
183 changes: 183 additions & 0 deletions llvm/test/TableGen/SDNodeInfoEmitter/basic.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// 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
// CHECK-EMPTY:
// CHECK-NEXT: #endif // GET_SDNODE_DESC


//--- 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);

//--- advanced.td
// RUN: llvm-tblgen -gen-sd-node-info -I %p/../../../include %t/advanced.td \
// RUN: | FileCheck %t/advanced.td

include "llvm/Target/Target.td"

def MyTarget : Target;

def my_node_1 : SDNode<
"MyTargetISD::NODE_1",
SDTypeProfile<1, 1, [SDTCisVT<0, i1>, SDTCisVT<1, i2>]>,
[SDNPHasChain]
>;

let TSFlags = 42 in
def my_node_2 : SDNode<
"MyTargetISD::NODE_2",
SDTypeProfile<3, 1, [
// Prefix of my_node_3 constraints.
SDTCisVT<0, i1>,
SDTCisPtrTy<1>,
SDTCisInt<2>,
SDTCisFP<3>,
]>,
[SDNPMayStore, SDNPMayLoad, SDNPSideEffect,
SDNPMemOperand, SDNPVariadic]
>;

let IsStrictFP = true, TSFlags = 24 in
def my_node_3 : SDNode<
"MyTargetISD::NODE_3",
SDTypeProfile<2, -1, [
SDTCisVT<0, i1>,
SDTCisPtrTy<1>,
SDTCisInt<2>,
SDTCisFP<3>,
SDTCisVec<4>,
SDTCisSameAs<6, 5>,
SDTCisVTSmallerThanOp<8, 7>,
SDTCisOpSmallerThanOp<10, 9>,
SDTCisEltOfVec<12, 11>,
SDTCisSubVecOfVec<14, 13>,
SDTCVecEltisVT<15, i32>,
SDTCisSameNumEltsAs<17, 16>,
SDTCisSameSizeAs<19, 18>,
]>,
[SDNPCommutative, SDNPAssociative, SDNPHasChain,
SDNPOutGlue, SDNPInGlue, SDNPOptInGlue]
>;

// 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: NODE_3,
// CHECK-NEXT: };
// CHECK-EMPTY:
// CHECK-NEXT: static constexpr unsigned GENERATED_OPCODE_END = NODE_3 + 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: "MyTargetISD::NODE_3\0"
// CHECK-NEXT: "\0";

// CHECK: static const SDTypeConstraint MyTargetSDTypeConstraints[] = {
// CHECK-NEXT: /* 0 */ {SDTCisVT, 1, 0, MVT::i2},
// CHECK-SAME: {SDTCisVT, 0, 0, MVT::i1},
// CHECK-NEXT: /* 2 */ {SDTCisSameSizeAs, 19, 18, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisSameNumEltsAs, 17, 16, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCVecEltisVT, 15, 0, MVT::i32},
// CHECK-SAME: {SDTCisSubVecOfVec, 14, 13, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisEltOfVec, 12, 11, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisOpSmallerThanOp, 10, 9, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisVTSmallerThanOp, 8, 7, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisSameAs, 6, 5, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisVec, 4, 0, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisFP, 3, 0, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisInt, 2, 0, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisPtrTy, 1, 0, MVT::INVALID_SIMPLE_VALUE_TYPE},
// CHECK-SAME: {SDTCisVT, 0, 0, MVT::i1},
// CHECK-NEXT: };
// CHECK-EMPTY:
// CHECK-NEXT: static const SDNodeDesc MyTargetSDNodeDescs[] = {
// CHECK-NEXT: {1, 1, 0|1<<SDNPHasChain, 0, 0, 0, 0, 2}, // NODE_1
// CHECK-NEXT: {3, 1, 0|1<<SDNPVariadic|1<<SDNPMemOperand, 0, 42, 20, 11, 4}, // NODE_2
// CHECK-NEXT: {2, -1, 0|1<<SDNPHasChain|1<<SDNPOutGlue|1<<SDNPInGlue|1<<SDNPOptInGlue, 0|1<<SDNFIsStrictFP, 24, 40, 2, 13}, // NODE_3
// CHECK-NEXT: };
// CHECK-EMPTY:
// CHECK-NEXT: static const SDNodeInfo MyTargetGenSDNodeInfo(
// CHECK-NEXT: /*NumOpcodes=*/3, MyTargetSDNodeDescs,
// CHECK-NEXT: MyTargetSDNodeNames, MyTargetSDTypeConstraints);
62 changes: 62 additions & 0 deletions llvm/test/TableGen/SDNodeInfoEmitter/namespace.td
Original file line number Diff line number Diff line change
@@ -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);
Loading
Loading