Skip to content

Commit b917c11

Browse files
committed
AMDGPU: Move asm constraint physreg parsing to utils
Also fixes an assertion on out of bound physical register indexes.
1 parent 6a45697 commit b917c11

File tree

4 files changed

+161
-40
lines changed

4 files changed

+161
-40
lines changed

llvm/lib/Target/AMDGPU/SIISelLowering.cpp

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16700,56 +16700,50 @@ SITargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI_,
1670016700
return std::pair(0U, RC);
1670116701
}
1670216702

16703-
if (Constraint.starts_with("{") && Constraint.ends_with("}")) {
16704-
StringRef RegName(Constraint.data() + 1, Constraint.size() - 2);
16705-
if (RegName.consume_front("v")) {
16703+
auto [Kind, Idx, NumRegs] = AMDGPU::parseAsmConstraintPhysReg(Constraint);
16704+
if (Kind != '\0') {
16705+
if (Kind == 'v') {
1670616706
RC = &AMDGPU::VGPR_32RegClass;
16707-
} else if (RegName.consume_front("s")) {
16707+
} else if (Kind == 's') {
1670816708
RC = &AMDGPU::SGPR_32RegClass;
16709-
} else if (RegName.consume_front("a")) {
16709+
} else if (Kind == 'a') {
1671016710
RC = &AMDGPU::AGPR_32RegClass;
1671116711
}
1671216712

1671316713
if (RC) {
16714-
uint32_t Idx;
16715-
if (RegName.consume_front("[")) {
16716-
uint32_t End;
16717-
bool Failed = RegName.consumeInteger(10, Idx);
16718-
Failed |= !RegName.consume_front(":");
16719-
Failed |= RegName.consumeInteger(10, End);
16720-
Failed |= !RegName.consume_back("]");
16721-
if (!Failed) {
16722-
uint32_t Width = (End - Idx + 1) * 32;
16723-
// Prohibit constraints for register ranges with a width that does not
16724-
// match the required type.
16725-
if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
16714+
if (NumRegs > 1) {
16715+
uint32_t Width = NumRegs * 32;
16716+
// Prohibit constraints for register ranges with a width that does not
16717+
// match the required type.
16718+
if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
16719+
return std::pair(0U, nullptr);
16720+
if (Idx >= RC->getNumRegs())
16721+
return std::pair(0U, nullptr);
16722+
16723+
MCRegister Reg = RC->getRegister(Idx);
16724+
if (SIRegisterInfo::isVGPRClass(RC))
16725+
RC = TRI->getVGPRClassForBitWidth(Width);
16726+
else if (SIRegisterInfo::isSGPRClass(RC))
16727+
RC = TRI->getSGPRClassForBitWidth(Width);
16728+
else if (SIRegisterInfo::isAGPRClass(RC))
16729+
RC = TRI->getAGPRClassForBitWidth(Width);
16730+
if (RC) {
16731+
Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
16732+
if (!Reg) {
16733+
// The register class does not contain the requested register,
16734+
// e.g., because it is an SGPR pair that would violate alignment
16735+
// requirements.
1672616736
return std::pair(0U, nullptr);
16727-
MCRegister Reg = RC->getRegister(Idx);
16728-
if (SIRegisterInfo::isVGPRClass(RC))
16729-
RC = TRI->getVGPRClassForBitWidth(Width);
16730-
else if (SIRegisterInfo::isSGPRClass(RC))
16731-
RC = TRI->getSGPRClassForBitWidth(Width);
16732-
else if (SIRegisterInfo::isAGPRClass(RC))
16733-
RC = TRI->getAGPRClassForBitWidth(Width);
16734-
if (RC) {
16735-
Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
16736-
if (!Reg) {
16737-
// The register class does not contain the requested register,
16738-
// e.g., because it is an SGPR pair that would violate alignment
16739-
// requirements.
16740-
return std::pair(0U, nullptr);
16741-
}
16742-
return std::pair(Reg, RC);
1674316737
}
16738+
return std::pair(Reg, RC);
1674416739
}
16745-
} else {
16746-
// Check for lossy scalar/vector conversions.
16747-
if (VT.isVector() && VT.getSizeInBits() != 32)
16748-
return std::pair(0U, nullptr);
16749-
bool Failed = RegName.getAsInteger(10, Idx);
16750-
if (!Failed && Idx < RC->getNumRegs())
16751-
return std::pair(RC->getRegister(Idx), RC);
1675216740
}
16741+
16742+
// Check for lossy scalar/vector conversions.
16743+
if (VT.isVector() && VT.getSizeInBits() != 32)
16744+
return std::pair(0U, nullptr);
16745+
if (Idx < RC->getNumRegs())
16746+
return std::pair(RC->getRegister(Idx), RC);
1675316747
}
1675416748
}
1675516749

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

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

1544+
static bool isValidRegPrefix(char C) {
1545+
return C == 'v' || C == 's' || C == 'a';
1546+
}
1547+
1548+
std::tuple<char, unsigned, unsigned>
1549+
parseAsmConstraintPhysReg(StringRef Constraint) {
1550+
StringRef RegName = Constraint;
1551+
if (!RegName.consume_front("{") || !RegName.consume_back("}"))
1552+
return {};
1553+
1554+
char Kind = RegName.front();
1555+
if (!isValidRegPrefix(Kind))
1556+
return {};
1557+
1558+
RegName = RegName.drop_front();
1559+
if (RegName.consume_front("[")) {
1560+
unsigned Idx, End;
1561+
bool Failed = RegName.consumeInteger(10, Idx);
1562+
Failed |= !RegName.consume_front(":");
1563+
Failed |= RegName.consumeInteger(10, End);
1564+
Failed |= !RegName.consume_back("]");
1565+
if (!Failed) {
1566+
unsigned NumRegs = End - Idx + 1;
1567+
if (NumRegs > 1)
1568+
return {Kind, Idx, NumRegs};
1569+
}
1570+
} else {
1571+
unsigned Idx;
1572+
bool Failed = RegName.getAsInteger(10, Idx);
1573+
if (!Failed)
1574+
return {Kind, Idx, 1};
1575+
}
1576+
1577+
return {};
1578+
}
1579+
15441580
std::pair<unsigned, unsigned>
15451581
getIntegerPairAttribute(const Function &F, StringRef Name,
15461582
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: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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+
}

0 commit comments

Comments
 (0)