Skip to content

Commit ff53086

Browse files
authored
AMDGPU: Add new VA inline asm constraint for AV registers (#152665)
Add a new constraint corresponding to the AV_* register classes for operands which can allocate AGPRs or VGPRs. This applies to load and stores on gfx90a+, and srcA / srcB for MFMA instructions. The error emitted on unsupported targets isn't ideal, it is produced by the register allocator without a rationale, but it is consistent with the existing errors. I mostly want this for writing allocation tests.
1 parent a9c5d33 commit ff53086

File tree

4 files changed

+272
-8
lines changed

4 files changed

+272
-8
lines changed

llvm/docs/LangRef.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5582,9 +5582,13 @@ AArch64:
55825582
AMDGPU:
55835583

55845584
- ``r``: A 32 or 64-bit integer register.
5585-
- ``[0-9]v``: The 32-bit VGPR register, number 0-9.
5586-
- ``[0-9]s``: The 32-bit SGPR register, number 0-9.
5587-
- ``[0-9]a``: The 32-bit AGPR register, number 0-9.
5585+
- ``s``: SGPR register or tuple
5586+
- ``v``: VGPR register or tuple
5587+
- ``a``: AGPR register or tuple. Only valid on gfx908+.
5588+
- ``VA``: VGPR or AGPR register or tuple. Only valid on gfx90a+.
5589+
- ``v[0-9]``: The 32-bit VGPR register, number 0-9.
5590+
- ``s[0-9]``: The 32-bit SGPR register, number 0-9.
5591+
- ``a[0-9]``: The 32-bit AGPR register, number 0-9.
55885592
- ``I``: An integer inline constant in the range from -16 to 64.
55895593
- ``J``: A 16-bit signed integer constant.
55905594
- ``A``: An integer or a floating-point inline constant.

llvm/lib/Target/AMDGPU/SIISelLowering.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16906,13 +16906,26 @@ SITargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI_,
1690616906
}
1690716907
break;
1690816908
}
16909-
// We actually support i128, i16 and f16 as inline parameters
16910-
// even if they are not reported as legal
16911-
if (RC && (isTypeLegal(VT) || VT.SimpleTy == MVT::i128 ||
16912-
VT.SimpleTy == MVT::i16 || VT.SimpleTy == MVT::f16))
16913-
return std::pair(0U, RC);
16909+
} else if (Constraint == "VA" && Subtarget->hasGFX90AInsts()) {
16910+
const unsigned BitWidth = VT.getSizeInBits();
16911+
switch (BitWidth) {
16912+
case 16:
16913+
RC = &AMDGPU::AV_32RegClass;
16914+
break;
16915+
default:
16916+
RC = TRI->getVectorSuperClassForBitWidth(BitWidth);
16917+
if (!RC)
16918+
return std::pair(0U, nullptr);
16919+
break;
16920+
}
1691416921
}
1691516922

16923+
// We actually support i128, i16 and f16 as inline parameters
16924+
// even if they are not reported as legal
16925+
if (RC && (isTypeLegal(VT) || VT.SimpleTy == MVT::i128 ||
16926+
VT.SimpleTy == MVT::i16 || VT.SimpleTy == MVT::f16))
16927+
return std::pair(0U, RC);
16928+
1691616929
auto [Kind, Idx, NumRegs] = AMDGPU::parseAsmConstraintPhysReg(Constraint);
1691716930
if (Kind != '\0') {
1691816931
if (Kind == 'v') {
@@ -16997,6 +17010,9 @@ SITargetLowering::getConstraintType(StringRef Constraint) const {
1699717010
case 'a':
1699817011
return C_RegisterClass;
1699917012
}
17013+
} else if (Constraint.size() == 2) {
17014+
if (Constraint == "VA")
17015+
return C_RegisterClass;
1700017016
}
1700117017
if (isImmConstraint(Constraint)) {
1700217018
return C_Other;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; RUN: not llc -mtriple=amdgcn -mcpu=gfx90a -filetype=null %s 2>&1 | FileCheck %s
2+
3+
; Make sure illegal type uses are correctly diagnosed
4+
5+
; CHECK: error: couldn't allocate input reg for constraint 'VA'
6+
define void @use_A_i8(i8 %x) {
7+
call void asm sideeffect "; use $0", "^VA"(i8 %x)
8+
ret void
9+
}
10+
11+
; CHECK: error: couldn't allocate output register for constraint 'VA'
12+
define i8 @def_A_i8() {
13+
%ret = call i8 asm sideeffect "; def $0", "=^VA"()
14+
ret i8 %ret
15+
}
16+
17+
; CHECK: error: couldn't allocate input reg for constraint 'VA'
18+
define void @use_A_i1(i1 %x) {
19+
call void asm sideeffect "; use $0", "^VA"(i1 %x)
20+
ret void
21+
}
22+
23+
; CHECK: error: couldn't allocate output register for constraint 'VA'
24+
define i1 @def_A_i1() {
25+
%ret = call i1 asm sideeffect "; def $0", "=^VA"()
26+
ret i1 %ret
27+
}
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: not llc -mtriple=amdgcn -mcpu=gfx908 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
3+
; RUN: llc -mtriple=amdgcn -mcpu=gfx90a < %s | FileCheck %s
4+
5+
; FIXME: Shouldn't emit and
6+
; ERR: error: couldn't allocate input reg for constraint 'VA'
7+
define void @use_A_i16(i16 %x) {
8+
; CHECK-LABEL: use_A_i16:
9+
; CHECK: ; %bb.0:
10+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
11+
; CHECK-NEXT: v_and_b32_e32 v0, 0xffff, v0
12+
; CHECK-NEXT: ;;#ASMSTART
13+
; CHECK-NEXT: ; use v0
14+
; CHECK-NEXT: ;;#ASMEND
15+
; CHECK-NEXT: s_setpc_b64 s[30:31]
16+
call void asm sideeffect "; use $0", "^VA"(i16 %x)
17+
ret void
18+
}
19+
20+
; ERR: error: couldn't allocate input reg for constraint 'VA'
21+
define void @use_A_f16(half %x) {
22+
; CHECK-LABEL: use_A_f16:
23+
; CHECK: ; %bb.0:
24+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
25+
; CHECK-NEXT: ;;#ASMSTART
26+
; CHECK-NEXT: ; use v0
27+
; CHECK-NEXT: ;;#ASMEND
28+
; CHECK-NEXT: s_setpc_b64 s[30:31]
29+
call void asm sideeffect "; use $0", "^VA"(half %x)
30+
ret void
31+
}
32+
33+
; ERR: error: couldn't allocate input reg for constraint 'VA'
34+
define void @use_A_bf16(bfloat %x) {
35+
; CHECK-LABEL: use_A_bf16:
36+
; CHECK: ; %bb.0:
37+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
38+
; CHECK-NEXT: ;;#ASMSTART
39+
; CHECK-NEXT: ; use v0
40+
; CHECK-NEXT: ;;#ASMEND
41+
; CHECK-NEXT: s_setpc_b64 s[30:31]
42+
call void asm sideeffect "; use $0", "^VA"(bfloat %x)
43+
ret void
44+
}
45+
46+
; ERR: error: couldn't allocate input reg for constraint 'VA'
47+
define void @use_A_v2i16(<2 x i16> %x) {
48+
; CHECK-LABEL: use_A_v2i16:
49+
; CHECK: ; %bb.0:
50+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
51+
; CHECK-NEXT: ;;#ASMSTART
52+
; CHECK-NEXT: ; use v0
53+
; CHECK-NEXT: ;;#ASMEND
54+
; CHECK-NEXT: s_setpc_b64 s[30:31]
55+
call void asm sideeffect "; use $0", "^VA"(<2 x i16> %x)
56+
ret void
57+
}
58+
59+
; ERR: error: couldn't allocate input reg for constraint 'VA'
60+
define void @use_A_v2f16(<2 x half> %x) {
61+
; CHECK-LABEL: use_A_v2f16:
62+
; CHECK: ; %bb.0:
63+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
64+
; CHECK-NEXT: ;;#ASMSTART
65+
; CHECK-NEXT: ; use v0
66+
; CHECK-NEXT: ;;#ASMEND
67+
; CHECK-NEXT: s_setpc_b64 s[30:31]
68+
call void asm sideeffect "; use $0", "^VA"(<2 x half> %x)
69+
ret void
70+
}
71+
72+
; ERR: error: couldn't allocate input reg for constraint 'VA'
73+
define void @use_A_v2bf16(<2 x bfloat> %x) {
74+
; CHECK-LABEL: use_A_v2bf16:
75+
; CHECK: ; %bb.0:
76+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
77+
; CHECK-NEXT: ;;#ASMSTART
78+
; CHECK-NEXT: ; use v0
79+
; CHECK-NEXT: ;;#ASMEND
80+
; CHECK-NEXT: s_setpc_b64 s[30:31]
81+
call void asm sideeffect "; use $0", "^VA"(<2 x bfloat> %x)
82+
ret void
83+
}
84+
85+
; ERR: error: couldn't allocate input reg for constraint 'VA'
86+
define void @use_A_i32(i32 %x) {
87+
; CHECK-LABEL: use_A_i32:
88+
; CHECK: ; %bb.0:
89+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
90+
; CHECK-NEXT: ;;#ASMSTART
91+
; CHECK-NEXT: ; use v0
92+
; CHECK-NEXT: ;;#ASMEND
93+
; CHECK-NEXT: s_setpc_b64 s[30:31]
94+
call void asm sideeffect "; use $0", "^VA"(i32 %x)
95+
ret void
96+
}
97+
98+
; ERR: error: couldn't allocate input reg for constraint 'VA'
99+
define void @use_A_f32(float %x) {
100+
; CHECK-LABEL: use_A_f32:
101+
; CHECK: ; %bb.0:
102+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
103+
; CHECK-NEXT: ;;#ASMSTART
104+
; CHECK-NEXT: ; use v0
105+
; CHECK-NEXT: ;;#ASMEND
106+
; CHECK-NEXT: s_setpc_b64 s[30:31]
107+
call void asm sideeffect "; use $0", "^VA"(float %x)
108+
ret void
109+
}
110+
111+
; ERR: error: couldn't allocate input reg for constraint 'VA'
112+
define void @use_A_i64(i64 %x) {
113+
; CHECK-LABEL: use_A_i64:
114+
; CHECK: ; %bb.0:
115+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
116+
; CHECK-NEXT: ;;#ASMSTART
117+
; CHECK-NEXT: ; use v[0:1]
118+
; CHECK-NEXT: ;;#ASMEND
119+
; CHECK-NEXT: s_setpc_b64 s[30:31]
120+
call void asm sideeffect "; use $0", "^VA"(i64 %x)
121+
ret void
122+
}
123+
124+
; ERR: error: couldn't allocate input reg for constraint 'VA'
125+
define void @use_A_f64(double %x) {
126+
; CHECK-LABEL: use_A_f64:
127+
; CHECK: ; %bb.0:
128+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
129+
; CHECK-NEXT: ;;#ASMSTART
130+
; CHECK-NEXT: ; use v[0:1]
131+
; CHECK-NEXT: ;;#ASMEND
132+
; CHECK-NEXT: s_setpc_b64 s[30:31]
133+
call void asm sideeffect "; use $0", "^VA"(double %x)
134+
ret void
135+
}
136+
137+
; ERR: error: couldn't allocate input reg for constraint 'VA'
138+
define void @use_A_p1(ptr addrspace(1) %x) {
139+
; CHECK-LABEL: use_A_p1:
140+
; CHECK: ; %bb.0:
141+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
142+
; CHECK-NEXT: ;;#ASMSTART
143+
; CHECK-NEXT: ; use v[0:1]
144+
; CHECK-NEXT: ;;#ASMEND
145+
; CHECK-NEXT: s_setpc_b64 s[30:31]
146+
call void asm sideeffect "; use $0", "^VA"(ptr addrspace(1) %x)
147+
ret void
148+
}
149+
150+
; ERR: error: couldn't allocate input reg for constraint 'VA'
151+
define void @use_A_v32i32(<32 x i32> %x) {
152+
; CHECK-LABEL: use_A_v32i32:
153+
; CHECK: ; %bb.0:
154+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
155+
; CHECK-NEXT: buffer_load_dword v31, off, s[0:3], s32
156+
; CHECK-NEXT: s_waitcnt vmcnt(0)
157+
; CHECK-NEXT: ;;#ASMSTART
158+
; CHECK-NEXT: ; use v[0:31]
159+
; CHECK-NEXT: ;;#ASMEND
160+
; CHECK-NEXT: s_setpc_b64 s[30:31]
161+
call void asm sideeffect "; use $0", "^VA"(<32 x i32> %x)
162+
ret void
163+
}
164+
165+
; ERR: error: couldn't allocate input reg for constraint 'VA'
166+
define void @use_A_v32f32(<32 x float> %x) {
167+
; CHECK-LABEL: use_A_v32f32:
168+
; CHECK: ; %bb.0:
169+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
170+
; CHECK-NEXT: buffer_load_dword v31, off, s[0:3], s32
171+
; CHECK-NEXT: s_waitcnt vmcnt(0)
172+
; CHECK-NEXT: ;;#ASMSTART
173+
; CHECK-NEXT: ; use v[0:31]
174+
; CHECK-NEXT: ;;#ASMEND
175+
; CHECK-NEXT: s_setpc_b64 s[30:31]
176+
call void asm sideeffect "; use $0", "^VA"(<32 x float> %x)
177+
ret void
178+
}
179+
180+
; ERR: error: couldn't allocate output register for constraint 'VA'
181+
define i16 @def_A_i16() {
182+
; CHECK-LABEL: def_A_i16:
183+
; CHECK: ; %bb.0:
184+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
185+
; CHECK-NEXT: ;;#ASMSTART
186+
; CHECK-NEXT: ; def v0
187+
; CHECK-NEXT: ;;#ASMEND
188+
; CHECK-NEXT: s_setpc_b64 s[30:31]
189+
%ret = call i16 asm sideeffect "; def $0", "=^VA"()
190+
ret i16 %ret
191+
}
192+
193+
; ERR: error: couldn't allocate output register for constraint 'VA'
194+
define i32 @def_A_i32() {
195+
; CHECK-LABEL: def_A_i32:
196+
; CHECK: ; %bb.0:
197+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
198+
; CHECK-NEXT: ;;#ASMSTART
199+
; CHECK-NEXT: ; def v0
200+
; CHECK-NEXT: ;;#ASMEND
201+
; CHECK-NEXT: s_setpc_b64 s[30:31]
202+
%ret = call i32 asm sideeffect "; def $0", "=^VA"()
203+
ret i32 %ret
204+
}
205+
206+
; ERR: error: couldn't allocate output register for constraint 'VA'
207+
define ptr addrspace(1) @def_A_p1() {
208+
; CHECK-LABEL: def_A_p1:
209+
; CHECK: ; %bb.0:
210+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
211+
; CHECK-NEXT: ;;#ASMSTART
212+
; CHECK-NEXT: ; def v[0:1]
213+
; CHECK-NEXT: ;;#ASMEND
214+
; CHECK-NEXT: s_setpc_b64 s[30:31]
215+
%ret = call ptr addrspace(1) asm sideeffect "; def $0", "=^VA"()
216+
ret ptr addrspace(1) %ret
217+
}

0 commit comments

Comments
 (0)