Skip to content

Commit 8e6b835

Browse files
committed
[SelectionDAG] Verify SDTCisVT and SDTCVecEltisVT constraints
1 parent 91e6dee commit 8e6b835

File tree

18 files changed

+290
-104
lines changed

18 files changed

+290
-104
lines changed

llvm/include/llvm/CodeGen/SDNodeInfo.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,21 @@ enum SDNF {
4848
SDNFIsStrictFP,
4949
};
5050

51+
struct VTByHwModePair {
52+
uint8_t Mode;
53+
MVT::SimpleValueType VT;
54+
};
55+
5156
struct SDTypeConstraint {
5257
SDTC Kind;
5358
uint8_t OpNo;
5459
uint8_t OtherOpNo;
55-
MVT::SimpleValueType VT;
60+
/// For Kind == SDTCisVT or SDTCVecEltisVT:
61+
/// - if not using HwMode, NumHwModes == 0 and VT is MVT::SimpleValueType;
62+
/// - otherwise, VT is offset into VTByHwModeTable and NumHwModes specifies
63+
/// the number of entries.
64+
uint8_t NumHwModes;
65+
uint16_t VT;
5666
};
5767

5868
using SDNodeTSFlags = uint32_t;
@@ -76,13 +86,15 @@ class SDNodeInfo final {
7686
unsigned NumOpcodes;
7787
const SDNodeDesc *Descs;
7888
StringTable Names;
89+
const VTByHwModePair *VTByHwModeTable;
7990
const SDTypeConstraint *Constraints;
8091

8192
public:
8293
constexpr SDNodeInfo(unsigned NumOpcodes, const SDNodeDesc *Descs,
83-
StringTable Names, const SDTypeConstraint *Constraints)
94+
StringTable Names, const VTByHwModePair *VTByHwModeTable,
95+
const SDTypeConstraint *Constraints)
8496
: NumOpcodes(NumOpcodes), Descs(Descs), Names(Names),
85-
Constraints(Constraints) {}
97+
VTByHwModeTable(VTByHwModeTable), Constraints(Constraints) {}
8698

8799
/// Returns true if there is a generated description for a node with the given
88100
/// target-specific opcode.

llvm/lib/CodeGen/SelectionDAG/SDNodeInfo.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/CodeGen/SDNodeInfo.h"
10+
#include "llvm/CodeGen/SelectionDAG.h"
1011
#include "llvm/CodeGen/SelectionDAGNodes.h"
12+
#include "llvm/CodeGen/TargetLowering.h"
13+
#include "llvm/CodeGen/TargetSubtargetInfo.h"
1114

1215
using namespace llvm;
1316

@@ -40,6 +43,26 @@ static void checkOperandType(const SelectionDAG &DAG, const SDNode *N,
4043
ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString());
4144
}
4245

46+
namespace {
47+
48+
struct ConstraintOp {
49+
const SDNode *N;
50+
unsigned Idx;
51+
bool IsRes;
52+
53+
SDValue getValue() const {
54+
return IsRes ? SDValue(const_cast<SDNode *>(N), Idx) : N->getOperand(Idx);
55+
}
56+
57+
EVT getValueType() const { return getValue().getValueType(); }
58+
};
59+
60+
raw_ostream &operator<<(raw_ostream &OS, const ConstraintOp &Info) {
61+
return OS << (Info.IsRes ? "result" : "operand") << " #" << Info.Idx;
62+
}
63+
64+
} // namespace
65+
4366
void SDNodeInfo::verifyNode(const SelectionDAG &DAG, const SDNode *N) const {
4467
const SDNodeDesc &Desc = getDesc(N->getOpcode());
4568
bool HasChain = Desc.hasProperty(SDNPHasChain);
@@ -125,4 +148,86 @@ void SDNodeInfo::verifyNode(const SelectionDAG &DAG, const SDNode *N) const {
125148
" must be Register or RegisterMask");
126149
}
127150
}
151+
152+
unsigned VTHwMode =
153+
DAG.getSubtarget().getHwMode(MCSubtargetInfo::HwMode_ValueType);
154+
155+
auto GetConstraintOp = [&](unsigned Idx) {
156+
if (Idx < Desc.NumResults)
157+
return ConstraintOp{N, Idx, /*IsRes=*/true};
158+
return ConstraintOp{N, HasChain + (Idx - Desc.NumResults), /*IsRes=*/false};
159+
};
160+
161+
auto GetConstraintVT = [&](const SDTypeConstraint &C) {
162+
if (!C.NumHwModes)
163+
return static_cast<MVT::SimpleValueType>(C.VT);
164+
for (auto [Mode, VT] : ArrayRef(&VTByHwModeTable[C.VT], C.NumHwModes))
165+
if (Mode == VTHwMode)
166+
return VT;
167+
llvm_unreachable("No value type for this HW mode");
168+
};
169+
170+
SmallString<128> ES;
171+
raw_svector_ostream SS(ES);
172+
173+
for (const SDTypeConstraint &C : getConstraints(N->getOpcode())) {
174+
ConstraintOp Op = GetConstraintOp(C.OpNo);
175+
EVT OpVT = Op.getValue().getValueType();
176+
177+
switch (C.Kind) {
178+
case SDTCisVT: {
179+
EVT ExpectedVT = GetConstraintVT(C);
180+
181+
bool IsPtr = ExpectedVT == MVT::iPTR;
182+
if (IsPtr)
183+
ExpectedVT =
184+
DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout());
185+
186+
if (OpVT != ExpectedVT) {
187+
SS << Op << " must have type " << ExpectedVT;
188+
if (IsPtr)
189+
SS << " (iPTR)";
190+
SS << ", but has type " << OpVT;
191+
reportNodeError(DAG, N, SS.str());
192+
}
193+
break;
194+
}
195+
case SDTCisPtrTy:
196+
break;
197+
case SDTCisInt:
198+
break;
199+
case SDTCisFP:
200+
break;
201+
case SDTCisVec:
202+
break;
203+
case SDTCisSameAs:
204+
break;
205+
case SDTCisVTSmallerThanOp:
206+
break;
207+
case SDTCisOpSmallerThanOp:
208+
break;
209+
case SDTCisEltOfVec:
210+
break;
211+
case SDTCisSubVecOfVec:
212+
break;
213+
case SDTCVecEltisVT: {
214+
EVT ExpectedVT = GetConstraintVT(C);
215+
216+
if (!OpVT.isVector()) {
217+
SS << Op << " must have vector type";
218+
reportNodeError(DAG, N, SS.str());
219+
}
220+
if (OpVT.getVectorElementType() != ExpectedVT) {
221+
SS << Op << " must have " << ExpectedVT << " element type, but has "
222+
<< OpVT.getVectorElementType() << " element type";
223+
reportNodeError(DAG, N, SS.str());
224+
}
225+
break;
226+
}
227+
case SDTCisSameNumEltsAs:
228+
break;
229+
case SDTCisSameSizeAs:
230+
break;
231+
}
232+
}
128233
}

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,7 @@ def AArch64msrr : SDNode<"AArch64ISD::MSRR",
11781178
SDTCisVT<2, i64>]>,
11791179
[SDNPHasChain]>;
11801180

1181-
def SD_AArch64rshrnb : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisInt<2>]>;
1181+
def SD_AArch64rshrnb : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisVT<2, i32>]>;
11821182
// Vector narrowing shift by immediate (bottom)
11831183
def AArch64rshrnb : SDNode<"AArch64ISD::RSHRNB_I", SD_AArch64rshrnb>;
11841184
def AArch64rshrnb_pf : PatFrags<(ops node:$rs, node:$i),

llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,35 +32,27 @@ AArch64SelectionDAGInfo::AArch64SelectionDAGInfo()
3232

3333
void AArch64SelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
3434
const SDNode *N) const {
35+
switch (N->getOpcode()) {
36+
case AArch64ISD::WrapperLarge:
37+
// operand #0 must have type i32, but has type i64
38+
return;
39+
case AArch64ISD::LDNP:
40+
// result #0 must have type v4i32, but has type v2f64
41+
return;
42+
case AArch64ISD::STNP:
43+
// operand #1 must have type v4i32, but has type v2i64
44+
return;
45+
}
46+
3547
SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N);
3648

3749
#ifndef NDEBUG
3850
// Some additional checks not yet implemented by verifyTargetNode.
39-
constexpr MVT FlagsVT = MVT::i32;
4051
switch (N->getOpcode()) {
41-
case AArch64ISD::SUBS:
42-
assert(N->getValueType(1) == FlagsVT);
43-
break;
44-
case AArch64ISD::ADC:
45-
case AArch64ISD::SBC:
46-
assert(N->getOperand(2).getValueType() == FlagsVT);
47-
break;
48-
case AArch64ISD::ADCS:
49-
case AArch64ISD::SBCS:
50-
assert(N->getValueType(1) == FlagsVT);
51-
assert(N->getOperand(2).getValueType() == FlagsVT);
52-
break;
53-
case AArch64ISD::CSEL:
54-
case AArch64ISD::CSINC:
55-
case AArch64ISD::BRCOND:
56-
assert(N->getOperand(3).getValueType() == FlagsVT);
57-
break;
5852
case AArch64ISD::SADDWT:
5953
case AArch64ISD::SADDWB:
6054
case AArch64ISD::UADDWT:
6155
case AArch64ISD::UADDWB: {
62-
assert(N->getNumValues() == 1 && "Expected one result!");
63-
assert(N->getNumOperands() == 2 && "Expected two operands!");
6456
EVT VT = N->getValueType(0);
6557
EVT Op0VT = N->getOperand(0).getValueType();
6658
EVT Op1VT = N->getOperand(1).getValueType();
@@ -80,8 +72,6 @@ void AArch64SelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
8072
case AArch64ISD::SUNPKHI:
8173
case AArch64ISD::UUNPKLO:
8274
case AArch64ISD::UUNPKHI: {
83-
assert(N->getNumValues() == 1 && "Expected one result!");
84-
assert(N->getNumOperands() == 1 && "Expected one operand!");
8575
EVT VT = N->getValueType(0);
8676
EVT OpVT = N->getOperand(0).getValueType();
8777
assert(OpVT.isVector() && VT.isVector() && OpVT.isInteger() &&
@@ -98,8 +88,6 @@ void AArch64SelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
9888
case AArch64ISD::UZP2:
9989
case AArch64ISD::ZIP1:
10090
case AArch64ISD::ZIP2: {
101-
assert(N->getNumValues() == 1 && "Expected one result!");
102-
assert(N->getNumOperands() == 2 && "Expected two operands!");
10391
EVT VT = N->getValueType(0);
10492
EVT Op0VT = N->getOperand(0).getValueType();
10593
EVT Op1VT = N->getOperand(1).getValueType();
@@ -109,11 +97,8 @@ void AArch64SelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
10997
break;
11098
}
11199
case AArch64ISD::RSHRNB_I: {
112-
assert(N->getNumValues() == 1 && "Expected one result!");
113-
assert(N->getNumOperands() == 2 && "Expected two operands!");
114100
EVT VT = N->getValueType(0);
115101
EVT Op0VT = N->getOperand(0).getValueType();
116-
EVT Op1VT = N->getOperand(1).getValueType();
117102
assert(VT.isVector() && VT.isInteger() &&
118103
"Expected integer vector result type!");
119104
assert(Op0VT.isVector() && Op0VT.isInteger() &&
@@ -122,8 +107,8 @@ void AArch64SelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
122107
"Expected vectors of equal size!");
123108
assert(VT.getVectorElementCount() == Op0VT.getVectorElementCount() * 2 &&
124109
"Expected input vector with half the lanes of its result!");
125-
assert(Op1VT == MVT::i32 && isa<ConstantSDNode>(N->getOperand(1)) &&
126-
"Expected second operand to be a constant i32!");
110+
assert(isa<ConstantSDNode>(N->getOperand(1)) &&
111+
"Expected second operand to be a constant!");
127112
break;
128113
}
129114
}

llvm/lib/Target/M68k/M68kSelectionDAGInfo.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,19 @@ using namespace llvm;
1616
M68kSelectionDAGInfo::M68kSelectionDAGInfo()
1717
: SelectionDAGGenTargetInfo(M68kGenSDNodeInfo) {}
1818

19+
void M68kSelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
20+
const SDNode *N) const {
21+
switch (N->getOpcode()) {
22+
case M68kISD::ADD:
23+
case M68kISD::SUBX:
24+
// result #1 must have type i8, but has type i32
25+
return;
26+
case M68kISD::SETCC:
27+
// operand #1 must have type i8, but has type i32
28+
return;
29+
}
30+
31+
SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N);
32+
}
33+
1934
M68kSelectionDAGInfo::~M68kSelectionDAGInfo() = default;

llvm/lib/Target/M68k/M68kSelectionDAGInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ class M68kSelectionDAGInfo : public SelectionDAGGenTargetInfo {
2121
M68kSelectionDAGInfo();
2222

2323
~M68kSelectionDAGInfo() override;
24+
25+
void verifyTargetNode(const SelectionDAG &DAG,
26+
const SDNode *N) const override;
2427
};
2528

2629
} // namespace llvm

llvm/lib/Target/RISCV/RISCVSelectionDAGInfo.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,22 @@ RISCVSelectionDAGInfo::~RISCVSelectionDAGInfo() = default;
2222

2323
void RISCVSelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
2424
const SDNode *N) const {
25+
SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N);
26+
2527
#ifndef NDEBUG
28+
// Some additional checks not yet implemented by verifyTargetNode.
2629
switch (N->getOpcode()) {
27-
default:
28-
return SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N);
2930
case RISCVISD::TUPLE_EXTRACT:
30-
assert(N->getNumOperands() == 2 && "Expected three operands!");
3131
assert(N->getOperand(1).getOpcode() == ISD::TargetConstant &&
32-
N->getOperand(1).getValueType() == MVT::i32 &&
33-
"Expected index to be an i32 target constant!");
32+
"Expected index to be a target constant!");
3433
break;
3534
case RISCVISD::TUPLE_INSERT:
36-
assert(N->getNumOperands() == 3 && "Expected three operands!");
3735
assert(N->getOperand(2).getOpcode() == ISD::TargetConstant &&
38-
N->getOperand(2).getValueType() == MVT::i32 &&
39-
"Expected index to be an i32 target constant!");
36+
"Expected index to be a target constant!");
4037
break;
4138
case RISCVISD::VQDOT_VL:
4239
case RISCVISD::VQDOTU_VL:
4340
case RISCVISD::VQDOTSU_VL: {
44-
assert(N->getNumValues() == 1 && "Expected one result!");
45-
assert(N->getNumOperands() == 5 && "Expected five operands!");
4641
EVT VT = N->getValueType(0);
4742
assert(VT.isScalableVector() && VT.getVectorElementType() == MVT::i32 &&
4843
"Expected result to be an i32 scalable vector");
@@ -52,13 +47,9 @@ void RISCVSelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
5247
"Expected result and first 3 operands to have the same type!");
5348
EVT MaskVT = N->getOperand(3).getValueType();
5449
assert(MaskVT.isScalableVector() &&
55-
MaskVT.getVectorElementType() == MVT::i1 &&
5650
MaskVT.getVectorElementCount() == VT.getVectorElementCount() &&
5751
"Expected mask VT to be an i1 scalable vector with same number of "
5852
"elements as the result");
59-
assert((N->getOperand(4).getValueType() == MVT::i32 ||
60-
N->getOperand(4).getValueType() == MVT::i64) &&
61-
"Expect VL operand to be i32 or i64");
6253
break;
6354
}
6455
}

llvm/lib/Target/Sparc/SparcInstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_SPCallSeqStart,
369369
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_SPCallSeqEnd,
370370
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
371371

372-
def SDT_SPCall : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>;
372+
def SDT_SPCall : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
373373
def call : SDNode<"SPISD::CALL", SDT_SPCall,
374374
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
375375
SDNPVariadic]>;

0 commit comments

Comments
 (0)