Skip to content

Commit f3ae683

Browse files
committed
TableGen backend & support classes
1 parent ab6e9a9 commit f3ae683

File tree

19 files changed

+1081
-145
lines changed

19 files changed

+1081
-145
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
//==------------------------------------------------------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_INCLUDE_LLVM_CODEGEN_SDNODEINFO_H
10+
#define LLVM_INCLUDE_LLVM_CODEGEN_SDNODEINFO_H
11+
12+
#include "ISDOpcodes.h"
13+
#include "llvm/ADT/ArrayRef.h"
14+
#include "llvm/CodeGenTypes/MachineValueType.h"
15+
16+
namespace llvm {
17+
18+
class SDNode;
19+
class SelectionDAG;
20+
21+
// SDNode Properties
22+
enum SDNP {
23+
SDNPCommutative,
24+
SDNPAssociative,
25+
SDNPHasChain,
26+
SDNPOutGlue,
27+
SDNPInGlue,
28+
SDNPOptInGlue,
29+
SDNPMayLoad,
30+
SDNPMayStore,
31+
SDNPSideEffect,
32+
SDNPMemOperand,
33+
SDNPVariadic,
34+
};
35+
36+
// SDNode Type Constraint kinds
37+
enum SDTC {
38+
SDTCisVT,
39+
SDTCisPtrTy,
40+
SDTCisInt,
41+
SDTCisFP,
42+
SDTCisVec,
43+
SDTCisSameAs,
44+
SDTCisVTSmallerThanOp,
45+
SDTCisOpSmallerThanOp,
46+
SDTCisEltOfVec,
47+
SDTCisSubVecOfVec,
48+
SDTCVecEltisVT,
49+
SDTCisSameNumEltsAs,
50+
SDTCisSameSizeAs,
51+
};
52+
53+
// SDNode Flags
54+
enum SDNF {
55+
SDNFIsStrictFP,
56+
};
57+
58+
struct SDTypeConstraint {
59+
SDTC Kind;
60+
uint8_t OpNo;
61+
uint8_t OtherOpNo;
62+
MVT::SimpleValueType VT;
63+
};
64+
65+
struct SDNodeDesc {
66+
unsigned NumResults;
67+
int NumOperands;
68+
uint32_t Properties;
69+
uint32_t Flags;
70+
uint32_t TSFlags;
71+
unsigned NameOffset;
72+
unsigned ConstraintOffset;
73+
unsigned ConstraintCount;
74+
75+
bool hasProperty(SDNP Property) const { return Properties & (1 << Property); }
76+
77+
bool hasFlag(SDNF Flag) const { return Flags & (1 << Flag); }
78+
};
79+
80+
class SDNodeInfo final {
81+
unsigned NumOpcodes;
82+
const SDNodeDesc *Descs;
83+
const char *Names;
84+
const SDTypeConstraint *Constraints;
85+
86+
public:
87+
constexpr SDNodeInfo(unsigned NumOpcodes, const SDNodeDesc *Descs,
88+
const char *Names, const SDTypeConstraint *Constraints)
89+
: NumOpcodes(NumOpcodes), Descs(Descs), Names(Names),
90+
Constraints(Constraints) {}
91+
92+
/// Returns true if there is a generated description for the given
93+
/// target-specific opcode.
94+
bool hasDesc(unsigned Opcode) const {
95+
assert(Opcode >= ISD::BUILTIN_OP_END && "Expected target-specific opcode");
96+
return Opcode < ISD::BUILTIN_OP_END + NumOpcodes;
97+
}
98+
99+
/// Returns the description of a node with the given opcode.
100+
const SDNodeDesc &getDesc(unsigned Opcode) const {
101+
assert(hasDesc(Opcode));
102+
return Descs[Opcode - ISD::BUILTIN_OP_END];
103+
}
104+
105+
/// Returns operand constraints for a node with the given opcode.
106+
ArrayRef<SDTypeConstraint> getConstraints(unsigned Opcode) const {
107+
const SDNodeDesc &Desc = getDesc(Opcode);
108+
return ArrayRef(&Constraints[Desc.ConstraintOffset], Desc.ConstraintCount);
109+
}
110+
111+
/// Returns the name of the given target-specific opcode, suitable for
112+
/// debug printing.
113+
StringRef getName(unsigned Opcode) const {
114+
return &Names[getDesc(Opcode).NameOffset];
115+
}
116+
117+
void verifyNode(const SelectionDAG &DAG, const SDNode *N) const;
118+
};
119+
120+
} // namespace llvm
121+
122+
#endif // LLVM_INCLUDE_LLVM_CODEGEN_SDNODEINFO_H

llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H
1616
#define LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H
1717

18+
#include "SDNodeInfo.h"
1819
#include "llvm/CodeGen/MachineMemOperand.h"
1920
#include "llvm/CodeGen/SelectionDAGNodes.h"
2021
#include "llvm/Support/CodeGen.h"
@@ -35,6 +36,8 @@ class SelectionDAGTargetInfo {
3536
SelectionDAGTargetInfo &operator=(const SelectionDAGTargetInfo &) = delete;
3637
virtual ~SelectionDAGTargetInfo();
3738

39+
virtual const char *getTargetNodeName(unsigned Opcode) const;
40+
3841
/// Returns true if a node with the given target-specific opcode has
3942
/// a memory operand. Nodes with such opcodes can only be created with
4043
/// `SelectionDAG::getMemIntrinsicNode`.
@@ -48,6 +51,9 @@ class SelectionDAGTargetInfo {
4851
/// may raise a floating-point exception.
4952
virtual bool mayRaiseFPException(unsigned Opcode) const;
5053

54+
virtual void verifyTargetNode(const SelectionDAG &DAG,
55+
const SDNode *N) const {}
56+
5157
/// Emit target-specific code that performs a memcpy.
5258
/// This can be used by targets to provide code sequences for cases
5359
/// that don't fit the target's parameters for simple loads/stores and can be
@@ -100,8 +106,8 @@ class SelectionDAGTargetInfo {
100106
return SDValue();
101107
}
102108

103-
/// Emit target-specific code that performs a memcmp/bcmp, in cases where that is
104-
/// faster than a libcall. The first returned SDValue is the result of the
109+
/// Emit target-specific code that performs a memcmp/bcmp, in cases where that
110+
/// is faster than a libcall. The first returned SDValue is the result of the
105111
/// memcmp and the second is the chain. Both SDValues can be null if a normal
106112
/// libcall should be used.
107113
virtual std::pair<SDValue, SDValue>
@@ -176,6 +182,41 @@ class SelectionDAGTargetInfo {
176182
}
177183
};
178184

179-
} // end namespace llvm
185+
class SelectionDAGGenTargetInfo : public SelectionDAGTargetInfo {
186+
protected:
187+
const SDNodeInfo &GenNodeInfo;
188+
189+
explicit SelectionDAGGenTargetInfo(const SDNodeInfo &GenNodeInfo)
190+
: GenNodeInfo(GenNodeInfo) {}
191+
192+
public:
193+
~SelectionDAGGenTargetInfo() override;
194+
195+
const char *getTargetNodeName(unsigned Opcode) const override {
196+
assert(GenNodeInfo.hasDesc(Opcode) && "Should be handled by derived class");
197+
return GenNodeInfo.getName(Opcode).data();
198+
}
199+
200+
bool isTargetMemoryOpcode(unsigned Opcode) const override {
201+
if (GenNodeInfo.hasDesc(Opcode))
202+
return GenNodeInfo.getDesc(Opcode).hasProperty(SDNPMemOperand);
203+
return SelectionDAGTargetInfo::isTargetMemoryOpcode(Opcode);
204+
}
205+
206+
bool isTargetStrictFPOpcode(unsigned Opcode) const override {
207+
if (GenNodeInfo.hasDesc(Opcode))
208+
return GenNodeInfo.getDesc(Opcode).hasFlag(SDNFIsStrictFP);
209+
return SelectionDAGTargetInfo::isTargetStrictFPOpcode(Opcode);
210+
}
211+
212+
void verifyTargetNode(const SelectionDAG &DAG,
213+
const SDNode *N) const override {
214+
if (GenNodeInfo.hasDesc(N->getOpcode()))
215+
GenNodeInfo.verifyNode(DAG, N);
216+
SelectionDAGTargetInfo::verifyTargetNode(DAG, N);
217+
}
218+
};
219+
220+
} // namespace llvm
180221

181222
#endif // LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4930,11 +4930,6 @@ class TargetLowering : public TargetLoweringBase {
49304930
bool verifyReturnAddressArgumentIsConstant(SDValue Op,
49314931
SelectionDAG &DAG) const;
49324932

4933-
#ifndef NDEBUG
4934-
/// Check the given SDNode. Aborts if it is invalid.
4935-
virtual void verifyTargetSDNode(const SDNode *N) const {};
4936-
#endif
4937-
49384933
//===--------------------------------------------------------------------===//
49394934
// Inline Asm Support hooks
49404935
//

llvm/include/llvm/Target/TargetSelectionDAG.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ class SDNode<string opcode, SDTypeProfile typeprof,
353353
string SDClass = sdclass;
354354
let Properties = props;
355355
SDTypeProfile TypeProfile = typeprof;
356+
bit IsStrictFP = false;
357+
bits<64> TSFlags = 0;
356358
}
357359

358360
// Special TableGen-recognized dag nodes

llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_llvm_component_library(LLVMSelectionDAG
1111
LegalizeVectorOps.cpp
1212
LegalizeVectorTypes.cpp
1313
ResourcePriorityQueue.cpp
14+
SDNodeInfo.cpp
1415
ScheduleDAGFast.cpp
1516
ScheduleDAGRRList.cpp
1617
ScheduleDAGSDNodes.cpp
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
//==------------------------------------------------------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/CodeGen/SDNodeInfo.h"
10+
#include "llvm/CodeGen/SelectionDAGNodes.h"
11+
12+
using namespace llvm;
13+
14+
[[noreturn]]
15+
static void reportNodeError(const SelectionDAG &DAG, const SDNode *N,
16+
const Twine &Msg) {
17+
std::string S;
18+
raw_string_ostream SS(S);
19+
SS << "invalid node: " << Msg << '\n';
20+
N->printrWithDepth(SS, &DAG, 2);
21+
report_fatal_error(StringRef(S));
22+
}
23+
24+
static void checkResultValueType(const SelectionDAG &DAG, const SDNode *N,
25+
unsigned ResIdx, EVT ExpectedVT) {
26+
EVT ActualVT = N->getValueType(ResIdx);
27+
if (ActualVT != ExpectedVT)
28+
reportNodeError(
29+
DAG, N,
30+
"result #" + Twine(ResIdx) + " has invalid type; expected " +
31+
ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString());
32+
}
33+
34+
static void checkOperandValueType(const SelectionDAG &DAG, const SDNode *N,
35+
unsigned OpIdx, EVT ExpectedVT) {
36+
EVT ActualVT = N->getOperand(OpIdx).getValueType();
37+
if (ActualVT != ExpectedVT)
38+
reportNodeError(
39+
DAG, N,
40+
"operand #" + Twine(OpIdx) + " has invalid type; expected " +
41+
ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString());
42+
}
43+
44+
void SDNodeInfo::verifyNode(const SelectionDAG &DAG, const SDNode *N) const {
45+
const SDNodeDesc &Desc = getDesc(N->getOpcode());
46+
bool HasChain = Desc.hasProperty(SDNPHasChain);
47+
bool HasOutGlue = Desc.hasProperty(SDNPOutGlue);
48+
bool HasInGlue = Desc.hasProperty(SDNPInGlue);
49+
bool HasOptInGlue = Desc.hasProperty(SDNPOptInGlue);
50+
bool IsVariadic = Desc.hasProperty(SDNPVariadic);
51+
52+
unsigned ActualNumResults = N->getNumValues();
53+
unsigned ExpectedNumResults = Desc.NumResults + HasChain + HasOutGlue;
54+
55+
if (ActualNumResults != ExpectedNumResults)
56+
reportNodeError(DAG, N,
57+
"invalid number of results; expected " +
58+
Twine(ExpectedNumResults) + ", got " +
59+
Twine(ActualNumResults));
60+
61+
// Chain result comes after all normal results.
62+
if (HasChain) {
63+
unsigned ChainResIdx = Desc.NumResults;
64+
checkResultValueType(DAG, N, ChainResIdx, MVT::Other);
65+
}
66+
67+
// Glue result comes last.
68+
if (HasOutGlue) {
69+
unsigned GlueResIdx = Desc.NumResults + HasChain;
70+
checkResultValueType(DAG, N, GlueResIdx, MVT::Glue);
71+
}
72+
73+
// In the most general case, the operands of a node go in the following order:
74+
// chain, fix#0, ..., fix#M-1, var#0, ... var#N-1, glue
75+
// If the number of operands is < 0, M can be any;
76+
// If the node has SDNPVariadic property, N can be any.
77+
bool HasOptionalOperands = Desc.NumOperands < 0 || IsVariadic;
78+
79+
unsigned ActualNumOperands = N->getNumOperands();
80+
unsigned ExpectedMinNumOperands =
81+
(Desc.NumOperands >= 0 ? Desc.NumOperands : 0) + HasChain + HasInGlue;
82+
83+
// Check the lower bound.
84+
if (ActualNumOperands < ExpectedMinNumOperands) {
85+
StringRef How = HasOptionalOperands ? "at least " : "";
86+
reportNodeError(DAG, N,
87+
"invalid number of operands; expected " + How +
88+
Twine(ExpectedMinNumOperands) + ", got " +
89+
Twine(ActualNumOperands));
90+
}
91+
92+
// Check the upper bound. We can only do this if the number of fixed operands
93+
// is known and there are no variadic operands.
94+
if (Desc.NumOperands >= 0 && !IsVariadic) {
95+
// Account for optional input glue.
96+
unsigned ExpectedMaxNumOperands = ExpectedMinNumOperands + HasOptInGlue;
97+
if (ActualNumOperands > ExpectedMaxNumOperands) {
98+
StringRef How = HasOptInGlue ? "at most " : "";
99+
reportNodeError(DAG, N,
100+
"invalid number of operands; expected " + How +
101+
Twine(ExpectedMaxNumOperands) + ", got " +
102+
Twine(ActualNumOperands));
103+
}
104+
}
105+
106+
// Chain operand comes first.
107+
if (HasChain)
108+
checkOperandValueType(DAG, N, 0, MVT::Other);
109+
110+
// Glue operand comes last.
111+
if (HasInGlue)
112+
checkOperandValueType(DAG, N, ActualNumOperands - 1, MVT::Glue);
113+
if (HasOptInGlue && ActualNumOperands >= 1 &&
114+
N->getOperand(ActualNumOperands - 1).getValueType() == MVT::Glue)
115+
HasInGlue = true;
116+
117+
// Check variadic operands.
118+
if (IsVariadic && Desc.NumOperands >= 0) {
119+
unsigned VarOpStart = HasChain + Desc.NumOperands;
120+
unsigned VarOpEnd = ActualNumOperands - HasInGlue;
121+
for (unsigned OpIdx = VarOpStart; OpIdx != VarOpEnd; ++OpIdx) {
122+
unsigned OpOpcode = N->getOperand(OpIdx).getOpcode();
123+
if (OpOpcode != ISD::Register && OpOpcode != ISD::RegisterMask)
124+
reportNodeError(DAG, N,
125+
"variadic operand #" + Twine(OpIdx) +
126+
" must be Register or RegisterMask");
127+
}
128+
}
129+
}

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,11 +1149,11 @@ void SelectionDAG::DeallocateNode(SDNode *N) {
11491149

11501150
#ifndef NDEBUG
11511151
/// VerifySDNode - Check the given SDNode. Aborts if it is invalid.
1152-
static void VerifySDNode(SDNode *N, const TargetLowering *TLI) {
1152+
static void VerifySDNode(const SelectionDAG &DAG, SDNode *N) {
11531153
switch (N->getOpcode()) {
11541154
default:
1155-
if (N->getOpcode() > ISD::BUILTIN_OP_END)
1156-
TLI->verifyTargetSDNode(N);
1155+
if (N->isTargetOpcode())
1156+
DAG.getSelectionDAGInfo().verifyTargetNode(DAG, N);
11571157
break;
11581158
case ISD::BUILD_PAIR: {
11591159
EVT VT = N->getValueType(0);
@@ -1197,7 +1197,7 @@ void SelectionDAG::InsertNode(SDNode *N) {
11971197
AllNodes.push_back(N);
11981198
#ifndef NDEBUG
11991199
N->PersistentId = NextPersistentId++;
1200-
VerifySDNode(N, TLI);
1200+
VerifySDNode(*this, N);
12011201
#endif
12021202
for (DAGUpdateListener *DUL = UpdateListeners; DUL; DUL = DUL->Next)
12031203
DUL->NodeInserted(N);

0 commit comments

Comments
 (0)