Skip to content

Commit 1d7a0fa

Browse files
authored
AMDGPU: Move asm constraint physreg parsing to utils (#150903)
Also fixes an assertion on out of bound physical register indexes.
1 parent 283c47b commit 1d7a0fa

File tree

4 files changed

+175
-40
lines changed

4 files changed

+175
-40
lines changed

llvm/lib/Target/AMDGPU/SIISelLowering.cpp

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16825,56 +16825,51 @@ SITargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI_,
1682516825
return std::pair(0U, RC);
1682616826
}
1682716827

16828-
if (Constraint.starts_with("{") && Constraint.ends_with("}")) {
16829-
StringRef RegName(Constraint.data() + 1, Constraint.size() - 2);
16830-
if (RegName.consume_front("v")) {
16828+
auto [Kind, Idx, NumRegs] = AMDGPU::parseAsmConstraintPhysReg(Constraint);
16829+
if (Kind != '\0') {
16830+
if (Kind == 'v') {
1683116831
RC = &AMDGPU::VGPR_32RegClass;
16832-
} else if (RegName.consume_front("s")) {
16832+
} else if (Kind == 's') {
1683316833
RC = &AMDGPU::SGPR_32RegClass;
16834-
} else if (RegName.consume_front("a")) {
16834+
} else if (Kind == 'a') {
1683516835
RC = &AMDGPU::AGPR_32RegClass;
1683616836
}
1683716837

1683816838
if (RC) {
16839-
uint32_t Idx;
16840-
if (RegName.consume_front("[")) {
16841-
uint32_t End;
16842-
bool Failed = RegName.consumeInteger(10, Idx);
16843-
Failed |= !RegName.consume_front(":");
16844-
Failed |= RegName.consumeInteger(10, End);
16845-
Failed |= !RegName.consume_back("]");
16846-
if (!Failed) {
16847-
uint32_t Width = (End - Idx + 1) * 32;
16848-
// Prohibit constraints for register ranges with a width that does not
16849-
// match the required type.
16850-
if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
16839+
if (NumRegs > 1) {
16840+
if (Idx >= RC->getNumRegs() || Idx + NumRegs - 1 > RC->getNumRegs())
16841+
return std::pair(0U, nullptr);
16842+
16843+
uint32_t Width = NumRegs * 32;
16844+
// Prohibit constraints for register ranges with a width that does not
16845+
// match the required type.
16846+
if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
16847+
return std::pair(0U, nullptr);
16848+
16849+
MCRegister Reg = RC->getRegister(Idx);
16850+
if (SIRegisterInfo::isVGPRClass(RC))
16851+
RC = TRI->getVGPRClassForBitWidth(Width);
16852+
else if (SIRegisterInfo::isSGPRClass(RC))
16853+
RC = TRI->getSGPRClassForBitWidth(Width);
16854+
else if (SIRegisterInfo::isAGPRClass(RC))
16855+
RC = TRI->getAGPRClassForBitWidth(Width);
16856+
if (RC) {
16857+
Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
16858+
if (!Reg) {
16859+
// The register class does not contain the requested register,
16860+
// e.g., because it is an SGPR pair that would violate alignment
16861+
// requirements.
1685116862
return std::pair(0U, nullptr);
16852-
MCRegister Reg = RC->getRegister(Idx);
16853-
if (SIRegisterInfo::isVGPRClass(RC))
16854-
RC = TRI->getVGPRClassForBitWidth(Width);
16855-
else if (SIRegisterInfo::isSGPRClass(RC))
16856-
RC = TRI->getSGPRClassForBitWidth(Width);
16857-
else if (SIRegisterInfo::isAGPRClass(RC))
16858-
RC = TRI->getAGPRClassForBitWidth(Width);
16859-
if (RC) {
16860-
Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
16861-
if (!Reg) {
16862-
// The register class does not contain the requested register,
16863-
// e.g., because it is an SGPR pair that would violate alignment
16864-
// requirements.
16865-
return std::pair(0U, nullptr);
16866-
}
16867-
return std::pair(Reg, RC);
1686816863
}
16864+
return std::pair(Reg, RC);
1686916865
}
16870-
} else {
16871-
// Check for lossy scalar/vector conversions.
16872-
if (VT.isVector() && VT.getSizeInBits() != 32)
16873-
return std::pair(0U, nullptr);
16874-
bool Failed = RegName.getAsInteger(10, Idx);
16875-
if (!Failed && Idx < RC->getNumRegs())
16876-
return std::pair(RC->getRegister(Idx), RC);
1687716866
}
16867+
16868+
// Check for lossy scalar/vector conversions.
16869+
if (VT.isVector() && VT.getSizeInBits() != 32)
16870+
return std::pair(0U, nullptr);
16871+
if (Idx < RC->getNumRegs())
16872+
return std::pair(RC->getRegister(Idx), RC);
1687816873
}
1687916874
}
1688016875

llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,42 @@ bool shouldEmitConstantsToTextSection(const Triple &TT) {
15481548
return TT.getArch() == Triple::r600;
15491549
}
15501550

1551+
static bool isValidRegPrefix(char C) {
1552+
return C == 'v' || C == 's' || C == 'a';
1553+
}
1554+
1555+
std::tuple<char, unsigned, unsigned>
1556+
parseAsmConstraintPhysReg(StringRef Constraint) {
1557+
StringRef RegName = Constraint;
1558+
if (!RegName.consume_front("{") || !RegName.consume_back("}"))
1559+
return {};
1560+
1561+
char Kind = RegName.front();
1562+
if (!isValidRegPrefix(Kind))
1563+
return {};
1564+
1565+
RegName = RegName.drop_front();
1566+
if (RegName.consume_front("[")) {
1567+
unsigned Idx, End;
1568+
bool Failed = RegName.consumeInteger(10, Idx);
1569+
Failed |= !RegName.consume_front(":");
1570+
Failed |= RegName.consumeInteger(10, End);
1571+
Failed |= !RegName.consume_back("]");
1572+
if (!Failed) {
1573+
unsigned NumRegs = End - Idx + 1;
1574+
if (NumRegs > 1)
1575+
return {Kind, Idx, NumRegs};
1576+
}
1577+
} else {
1578+
unsigned Idx;
1579+
bool Failed = RegName.getAsInteger(10, Idx);
1580+
if (!Failed)
1581+
return {Kind, Idx, 1};
1582+
}
1583+
1584+
return {};
1585+
}
1586+
15511587
std::pair<unsigned, unsigned>
15521588
getIntegerPairAttribute(const Function &F, StringRef Name,
15531589
std::pair<unsigned, unsigned> Default,

llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,12 @@ bool isReadOnlySegment(const GlobalValue *GV);
10121012
/// target triple \p TT, false otherwise.
10131013
bool shouldEmitConstantsToTextSection(const Triple &TT);
10141014

1015+
/// Returns a valid charcode or 0 in the first entry if this is a valid physical
1016+
/// register constraint. Followed by the start register number, and the register
1017+
/// width. Does not validate the number of registers exists in the class.
1018+
std::tuple<char, unsigned, unsigned>
1019+
parseAsmConstraintPhysReg(StringRef Constraint);
1020+
10151021
/// \returns Integer value requested using \p F's \p Name attribute.
10161022
///
10171023
/// \returns \p Default if attribute is not present.
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=bonaire -filetype=null %s 2>&1 | FileCheck -implicit-check-not=error %s
2+
3+
; CHECK: error: couldn't allocate output register for constraint '{v256}'
4+
define void @out_of_bounds_vgpr32_def() {
5+
%v = tail call i32 asm sideeffect "v_mov_b32 $0, -1", "={v256}"()
6+
ret void
7+
}
8+
9+
; CHECK: error: couldn't allocate output register for constraint '{v[255:256]}'
10+
define void @out_of_bounds_vgpr64_def_high_tuple() {
11+
%v = tail call i32 asm sideeffect "v_mov_b32 $0, -1", "={v[255:256]}"()
12+
ret void
13+
}
14+
15+
; CHECK: error: couldn't allocate output register for constraint '{v[256:257]}'
16+
define void @out_of_bounds_vgpr64_def_low_tuple() {
17+
%v = tail call i32 asm sideeffect "v_mov_b32 $0, -1", "={v[256:257]}"()
18+
ret void
19+
}
20+
21+
; CHECK: error: couldn't allocate input reg for constraint '{v256}'
22+
define void @out_of_bounds_vgpr32_use() {
23+
%v = tail call i32 asm sideeffect "v_mov_b32 %0, %1", "=v,{v256}"(i32 123)
24+
ret void
25+
}
26+
27+
; CHECK: error: couldn't allocate input reg for constraint '{v[255:256]}'
28+
define void @out_of_bounds_vgpr64_high_tuple() {
29+
tail call void asm sideeffect "; use %0", "{v[255:256]}"(i64 123)
30+
ret void
31+
}
32+
33+
; CHECK: error: couldn't allocate input reg for constraint '{v[256:257]}'
34+
define void @out_of_bounds_vgpr64_low_tuple() {
35+
tail call void asm sideeffect "; use %0", "{v[256:257]}"(i64 123)
36+
ret void
37+
}
38+
39+
; CHECK: error: couldn't allocate input reg for constraint '{v[1:0]}'
40+
define void @vgpr_tuple_swapped() {
41+
tail call void asm sideeffect "; use %0", "{v[1:0]}"(i64 123)
42+
ret void
43+
}
44+
45+
; CHECK: error: couldn't allocate input reg for constraint '{v4294967295}'
46+
define void @vgpr_uintmax() {
47+
tail call void asm sideeffect "; use %0", "{v4294967295}"(i64 123)
48+
ret void
49+
}
50+
51+
; CHECK: error: couldn't allocate input reg for constraint '{v4294967296}'
52+
define void @vgpr_uintmax_p1() {
53+
tail call void asm sideeffect "; use %0", "{v4294967296}"(i64 123)
54+
ret void
55+
}
56+
57+
; CHECK: error: couldn't allocate input reg for constraint '{v[4294967295:4294967296]}'
58+
define void @vgpr_tuple_uintmax() {
59+
tail call void asm sideeffect "; use %0", "{v[4294967295:4294967296]}"(i64 123)
60+
ret void
61+
}
62+
63+
; CHECK: error: couldn't allocate input reg for constraint '{v[0:4294967295]}'
64+
define void @vgpr_tuple_0_uintmax() {
65+
tail call void asm sideeffect "; use %0", "{v[0:4294967295]}"(i64 123)
66+
ret void
67+
}
68+
69+
; CHECK: error: couldn't allocate input reg for constraint '{v[0:4294967296]}'
70+
define void @vgpr_tuple_0_uintmax_p1() {
71+
tail call void asm sideeffect "; use %0", "{v[0:4294967296]}"(i64 123)
72+
ret void
73+
}
74+
75+
; CHECK: error: couldn't allocate input reg for constraint '{v[4294967264:4294967295]}'
76+
define void @vgpr32_last_is_uintmax() {
77+
tail call void asm sideeffect "; use %0", "{v[4294967264:4294967295]}"(i64 123)
78+
ret void
79+
}
80+
81+
; CHECK: error: couldn't allocate input reg for constraint '{v[4294967265:4294967296]}'
82+
define void @vgpr32_last_is_uintmax_p1() {
83+
tail call void asm sideeffect "; use %0", "{v[4294967265:4294967296]}"(i64 123)
84+
ret void
85+
}
86+
87+
; CHECK: error: couldn't allocate input reg for constraint '{v[2:2147483651]}'
88+
define void @overflow_bitwidth_0() {
89+
tail call void asm sideeffect "; use %0", "{v[2:2147483651]}"(i64 123)
90+
ret void
91+
}
92+
93+
; CHECK: error: couldn't allocate input reg for constraint '{v[2147483635:2147483651]}'
94+
define void @overflow_bitwidth_1() {
95+
tail call void asm sideeffect "; use %0", "{v[2147483635:2147483651]}"(i64 123)
96+
ret void
97+
}
98+

0 commit comments

Comments
 (0)