Skip to content

Commit 88d2185

Browse files
authored
[stinkytofu] Fix verifier false positive for SGPR source on VOP2/VOPC instructions (#7270)
## Summary - The IR verifier's register type check only consulted the base VOP2 encoding, which restricts src1 to VGPR. VALU instructions with an SGPR in src1 are valid because the assembler promotes to VOP3 encoding, where src1 accepts both VGPR and SGPR. - The verifier now falls back to `promotedFields` before reporting a register type mismatch. - Adds FileCheck test covering `v_mul_u32_u24`, `v_cmp_eq_u32`, `v_cmp_gt_u32`, and `v_cmp_ge_u32` with SGPR in src1. ## Test plan - [x] All 562 ctest pass (unit tests + FileCheck) - [x] New test `FileCheck.verifier_vop2_sgpr_src` passes 🤖 Generated with [Claude Code](https://claude.ai/claude-code)
1 parent e36e63d commit 88d2185

2 files changed

Lines changed: 63 additions & 5 deletions

File tree

shared/stinkytofu/src/analysis/asm/AsmVerifierPass.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,23 @@ static std::string checkRegisterWidths(const StinkyInstruction* inst,
173173
// receive a VGPR, not a SGPR (and vice versa).
174174
RegType expectedType = fieldTypeToRegType(field.fieldType);
175175
if (!isExpectedTypeMatch(field.fieldType, expectedType, reg.reg.type)) {
176-
errors << "Instruction '";
177-
inst->dump(errors);
178-
errors << "' operand " << (isDest ? "dest[" : "src[") << operandIndex << "] "
179-
<< "has register type '" << regTypeToString(reg.reg.type) << "', expected '"
180-
<< regTypeToString(expectedType) << "'\n";
176+
// Check promoted encoding: e.g. VOP2 src1 is vgpr-only, but VOP3
177+
// promotion widens it to src (accepts SGPR). The assembler will
178+
// promote automatically, so accept the promoted field type too.
179+
unsigned fieldIdx = static_cast<unsigned>(&field - hwDesc->operandFields.data());
180+
bool promotedOk = false;
181+
if (fieldIdx < hwDesc->promotedFields.size()) {
182+
auto promotedFT = hwDesc->promotedFields[fieldIdx].fieldType;
183+
auto promotedET = fieldTypeToRegType(promotedFT);
184+
promotedOk = isExpectedTypeMatch(promotedFT, promotedET, reg.reg.type);
185+
}
186+
if (!promotedOk) {
187+
errors << "Instruction '";
188+
inst->dump(errors);
189+
errors << "' operand " << (isDest ? "dest[" : "src[") << operandIndex << "] "
190+
<< "has register type '" << regTypeToString(reg.reg.type) << "', expected '"
191+
<< regTypeToString(expectedType) << "'\n";
192+
}
181193
}
182194
}
183195

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# RUN: %stinkytofu-opt --arch gfx1250 %s --StinkyIRVerifierPass --print-output 2>&1
2+
#
3+
# Verify that VOP2/VOPC instructions accept SGPR source operands without
4+
# triggering register-type errors. The base VOP2 encoding restricts src1
5+
# to vgpr, but VOP3 promotion widens it to accept SGPRs. The verifier
6+
# must check promotedFields before rejecting.
7+
8+
#--- v_mul_u32_u24 with SGPR src1
9+
# CHECK-LABEL: @vop2_sgpr_src1_mul
10+
# CHECK-NOT: [StinkyIRVerifier]
11+
# CHECK: v_mul_u32_u24
12+
13+
st.func @vop2_sgpr_src1_mul() {
14+
^entry:
15+
v1 = "st.v_mul_u32_u24"(v0, s16) { issueCycles = 1, latencyCycles = 5 }
16+
}
17+
18+
#--- v_cmp_eq_u32 with SGPR src1
19+
# CHECK-LABEL: @vopc_sgpr_src1_cmp_eq
20+
# CHECK-NOT: [StinkyIRVerifier]
21+
# CHECK: v_cmp_eq_u32
22+
23+
st.func @vopc_sgpr_src1_cmp_eq() {
24+
^entry:
25+
vcc_lo0 = "st.v_cmp_eq_u32"(v1, s16) { issueCycles = 1, latencyCycles = 5 }
26+
}
27+
28+
#--- v_cmp_gt_u32 with SGPR src1
29+
# CHECK-LABEL: @vopc_sgpr_src1_cmp_gt
30+
# CHECK-NOT: [StinkyIRVerifier]
31+
# CHECK: v_cmp_gt_u32
32+
33+
st.func @vopc_sgpr_src1_cmp_gt() {
34+
^entry:
35+
vcc_lo0 = "st.v_cmp_gt_u32"(v1, s15) { issueCycles = 1, latencyCycles = 5 }
36+
}
37+
38+
#--- v_cmp_ge_u32 with SGPR src1
39+
# CHECK-LABEL: @vopc_sgpr_src1_cmp_ge
40+
# CHECK-NOT: [StinkyIRVerifier]
41+
# CHECK: v_cmp_ge_u32
42+
43+
st.func @vopc_sgpr_src1_cmp_ge() {
44+
^entry:
45+
vcc_lo0 = "st.v_cmp_ge_u32"(v2, s18) { issueCycles = 1, latencyCycles = 5 }
46+
}

0 commit comments

Comments
 (0)