1; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX9 %s
2; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX10 %s
3
4declare void @extern_func()
5
6define <4 x float> @non_preserved_vgpr_tuple8(<8 x i32> %rsrc, <4 x i32> %samp, float %bias, float %zcompare, float %s, float %t, float %clamp) {
7; The vgpr tuple8 operand in image_gather4_c_b_cl instruction needs not be
8; preserved across the call and should get 8 scratch registers.
9
10; GFX9-LABEL: non_preserved_vgpr_tuple8:
11; GFX9: buffer_store_dword v44, off, s[0:3], s32 offset:16 ; 4-byte Folded Spill
12; GFX9: buffer_store_dword v40, off, s[0:3], s33 offset:12 ; 4-byte Folded Spill
13; GFX9-NEXT: buffer_store_dword v41, off, s[0:3], s33 offset:8 ; 4-byte Folded Spill
14; GFX9-NEXT: buffer_store_dword v42, off, s[0:3], s33 offset:4 ; 4-byte Folded Spill
15; GFX9-NEXT: buffer_store_dword v43, off, s[0:3], s33 ; 4-byte Folded Spill
16
17; GFX9: v_mov_b32_e32 v37, v11
18; GFX9-NEXT: v_mov_b32_e32 v38, v10
19; GFX9-NEXT: v_mov_b32_e32 v49, v9
20; GFX9-NEXT: v_writelane_b32 v44, s30, 0
21; GFX9-NEXT: v_mov_b32_e32 v36, v16
22; GFX9-NEXT: v_mov_b32_e32 v35, v15
23; GFX9-NEXT: v_mov_b32_e32 v34, v14
24; GFX9-NEXT: v_mov_b32_e32 v33, v13
25; GFX9-NEXT: v_mov_b32_e32 v32, v12
26
27; GFX9: ;;#ASMSTART
28; GFX9-NEXT: ;;#ASMEND
29
30; GFX9: image_gather4_c_b_cl v[40:43], v[32:39], s[4:11], s[12:15] dmask:0x1
31; GFX9-NEXT: s_getpc_b64 s[4:5]
32; GFX9-NEXT: s_add_u32 s4, s4, extern_func@gotpcrel32@lo+4
33; GFX9-NEXT: s_addc_u32 s5, s5, extern_func@gotpcrel32@hi+4
34; GFX9-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x0
35; GFX9-NEXT: s_waitcnt lgkmcnt(0)
36; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5]
37
38; GFX9: buffer_load_dword v43, off, s[0:3], s33 ; 4-byte Folded Reload
39; GFX9-NEXT: buffer_load_dword v42, off, s[0:3], s33 offset:4 ; 4-byte Folded Reload
40; GFX9-NEXT: buffer_load_dword v41, off, s[0:3], s33 offset:8 ; 4-byte Folded Reload
41; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 offset:12 ; 4-byte Folded Reload
42; GFX9: buffer_load_dword v44, off, s[0:3], s32 offset:16 ; 4-byte Folded Reload
43; GFX9: s_setpc_b64 s[4:5]
44;
45; GFX10-LABEL: non_preserved_vgpr_tuple8:
46; GFX10: buffer_store_dword v44, off, s[0:3], s32 offset:16 ; 4-byte Folded Spill
47; GFX10: buffer_store_dword v40, off, s[0:3], s33 offset:12 ; 4-byte Folded Spill
48; GFX10-NEXT: buffer_store_dword v41, off, s[0:3], s33 offset:8 ; 4-byte Folded Spill
49; GFX10-NEXT: buffer_store_dword v42, off, s[0:3], s33 offset:4 ; 4-byte Folded Spill
50; GFX10-NEXT: buffer_store_dword v43, off, s[0:3], s33 ; 4-byte Folded Spill
51
52; GFX10: v_mov_b32_e32 v36, v16
53; GFX10-NEXT: v_mov_b32_e32 v35, v15
54; GFX10-NEXT: v_mov_b32_e32 v34, v14
55; GFX10-NEXT: v_mov_b32_e32 v33, v13
56; GFX10-NEXT: v_mov_b32_e32 v32, v12
57
58; GFX10: ;;#ASMSTART
59; GFX10-NEXT: ;;#ASMEND
60
61; GFX10: image_gather4_c_b_cl v[40:43], v[32:39], s[4:11], s[12:15] dmask:0x1
62; GFX10-NEXT: v_nop
63; GFX10-NEXT: s_getpc_b64 s[4:5]
64; GFX10-NEXT: s_add_u32 s4, s4, extern_func@gotpcrel32@lo+4
65; GFX10-NEXT: s_addc_u32 s5, s5, extern_func@gotpcrel32@hi+4
66; GFX10-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x0
67; GFX10-NEXT: s_waitcnt lgkmcnt(0)
68; GFX10-NEXT: s_swappc_b64 s[30:31], s[4:5]
69
70; GFX10: buffer_load_dword v43, off, s[0:3], s33
71; GFX10-NEXT: buffer_load_dword v42, off, s[0:3], s33 offset:4
72; GFX10-NEXT: buffer_load_dword v41, off, s[0:3], s33 offset:8
73; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 offset:12
74
75; GFX10: buffer_load_dword v44, off, s[0:3], s32 offset:16 ; 4-byte Folded Reload
76; GFX10: s_setpc_b64 s[4:5]
77main_body:
78  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}"() #0
79  call void asm sideeffect "", "~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15}"() #0
80  call void asm sideeffect "", "~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23}"() #0
81  call void asm sideeffect "", "~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() #0
82  %v = call <4 x float> @llvm.amdgcn.image.gather4.c.b.cl.2d.v4f32.f32.f32(i32 1, float %bias, float %zcompare, float %s, float %t, float %clamp, <8 x i32> %rsrc, <4 x i32> %samp, i1 false, i32 0, i32 0)
83  call void @extern_func()
84  ret <4 x float> %v
85}
86
87define <4 x float> @call_preserved_vgpr_tuple8(<8 x i32> %rsrc, <4 x i32> %samp, float %bias, float %zcompare, float %s, float %t, float %clamp) {
88; The vgpr tuple8 operand in image_gather4_c_b_cl instruction needs to be preserved
89; across the call and should get allcoated to 8 CSRs.
90; Only the lower 5 sub-registers of the tuple are preserved.
91; The upper 3 sub-registers are unused.
92
93; GFX9-LABEL: call_preserved_vgpr_tuple8:
94; GFX9: buffer_store_dword v56, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill
95; GFX9: buffer_store_dword v40, off, s[0:3], s33 offset:16 ; 4-byte Folded Spill
96; GFX9-NEXT: buffer_store_dword v41, off, s[0:3], s33 offset:12 ; 4-byte Folded Spill
97; GFX9-NEXT: buffer_store_dword v42, off, s[0:3], s33 offset:8 ; 4-byte Folded Spill
98; GFX9-NEXT: buffer_store_dword v43, off, s[0:3], s33 offset:4 ; 4-byte Folded Spill
99; GFX9-NEXT: buffer_store_dword v44, off, s[0:3], s33 ; 4-byte Folded Spill
100
101; GFX9: v_mov_b32_e32 v44, v16
102; GFX9-NEXT: v_mov_b32_e32 v43, v15
103; GFX9-NEXT: v_mov_b32_e32 v42, v14
104; GFX9-NEXT: v_mov_b32_e32 v41, v13
105; GFX9-NEXT: v_mov_b32_e32 v40, v12
106
107; GFX9: s_getpc_b64 s[4:5]
108; GFX9-NEXT: s_add_u32 s4, s4, extern_func@gotpcrel32@lo+4
109; GFX9-NEXT: s_addc_u32 s5, s5, extern_func@gotpcrel32@hi+4
110; GFX9-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x0
111; GFX9-NEXT: image_gather4_c_b_cl v[0:3], v[40:47], s[36:43], s[44:47] dmask:0x1
112; GFX9-NEXT: s_waitcnt vmcnt(0)
113; GFX9-NEXT: global_store_dwordx4 v[0:1], v[0:3], off
114; GFX9-NEXT: s_waitcnt lgkmcnt(0)
115; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5]
116; GFX9-NEXT: image_gather4_c_b_cl v[0:3], v[40:47], s[36:43], s[44:47] dmask:0x1
117
118; GFX9: buffer_load_dword v44, off, s[0:3], s33 ; 4-byte Folded Reload
119; GFX9-NEXT: buffer_load_dword v43, off, s[0:3], s33 offset:4 ; 4-byte Folded Reload
120; GFX9-NEXT: buffer_load_dword v42, off, s[0:3], s33 offset:8 ; 4-byte Folded Reload
121; GFX9-NEXT: buffer_load_dword v41, off, s[0:3], s33 offset:12 ; 4-byte Folded Reload
122; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 offset:16 ; 4-byte Folded Reload
123
124; GFX9: buffer_load_dword v56, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload
125; GFX9: s_setpc_b64 s[4:5]
126;
127; GFX10-LABEL: call_preserved_vgpr_tuple8:
128; GFX10: buffer_store_dword v45, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill
129; GFX10: buffer_store_dword v40, off, s[0:3], s33 offset:16 ; 4-byte Folded Spill
130; GFX10-NEXT: buffer_store_dword v41, off, s[0:3], s33 offset:12 ; 4-byte Folded Spill
131; GFX10-NEXT: buffer_store_dword v42, off, s[0:3], s33 offset:8 ; 4-byte Folded Spill
132; GFX10-NEXT: buffer_store_dword v43, off, s[0:3], s33 offset:4 ; 4-byte Folded Spill
133; GFX10-NEXT: buffer_store_dword v44, off, s[0:3], s33 ; 4-byte Folded Spill
134
135; GFX10: s_getpc_b64 s[4:5]
136; GFX10-NEXT: s_add_u32 s4, s4, extern_func@gotpcrel32@lo+4
137; GFX10-NEXT: s_addc_u32 s5, s5, extern_func@gotpcrel32@hi+4
138; GFX10-NEXT: v_mov_b32_e32 v40, v16
139; GFX10-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x0
140; GFX10-NEXT: image_gather4_c_b_cl v[0:3], v[12:19], s[36:43], s[44:47] dmask:0x1
141; GFX10-NEXT: v_mov_b32_e32 v41, v15
142; GFX10-NEXT: v_mov_b32_e32 v42, v14
143; GFX10-NEXT: v_mov_b32_e32 v43, v13
144; GFX10-NEXT: v_mov_b32_e32 v44, v12
145; GFX10-NEXT: ; implicit-def: $vcc_hi
146; GFX10-NEXT: s_waitcnt vmcnt(0)
147; GFX10-NEXT: global_store_dwordx4 v[0:1], v[0:3], off
148; GFX10-NEXT: s_waitcnt lgkmcnt(0)
149; GFX10-NEXT: s_swappc_b64 s[30:31], s[4:5]
150; GFX10-NEXT: image_gather4_c_b_cl v[0:3], [v44, v43, v42, v41, v40], s[36:43], s[44:47] dmask:0x1
151
152; GFX10: buffer_load_dword v44, off, s[0:3], s33
153; GFX10-NEXT: buffer_load_dword v43, off, s[0:3], s33 offset:4
154; GFX10-NEXT: buffer_load_dword v42, off, s[0:3], s33 offset:8
155; GFX10-NEXT: buffer_load_dword v41, off, s[0:3], s33 offset:12
156; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 offset:16
157; GFX10: buffer_load_dword v45, off, s[0:3], s32 offset:20
158; GFX10: s_setpc_b64 s[4:5]
159main_body:
160  %v = call <4 x float> @llvm.amdgcn.image.gather4.c.b.cl.2d.v4f32.f32.f32(i32 1, float %bias, float %zcompare, float %s, float %t, float %clamp, <8 x i32> %rsrc, <4 x i32> %samp, i1 false, i32 0, i32 0)
161  store <4 x float> %v, <4 x float> addrspace(1)* undef
162  call void @extern_func()
163  %v1 = call <4 x float> @llvm.amdgcn.image.gather4.c.b.cl.2d.v4f32.f32.f32(i32 1, float %bias, float %zcompare, float %s, float %t, float %clamp, <8 x i32> %rsrc, <4 x i32> %samp, i1 false, i32 0, i32 0)
164  ret <4 x float> %v1
165}
166
167declare <4 x float> @llvm.amdgcn.image.gather4.c.b.cl.2d.v4f32.f32.f32(i32 immarg, float, float, float, float, float, <8 x i32>, <4 x i32>, i1 immarg, i32 immarg, i32 immarg) #1
168
169attributes #0 = { nounwind writeonly }
170attributes #1 = { nounwind readonly }
171