1; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=fiji -enable-ipra=0 -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s 2; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=hawaii -enable-ipra=0 -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s 3; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -enable-ipra=0 -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s 4 5declare void @external_void_func_void() #0 6 7; GCN-LABEL: {{^}}test_kernel_call_external_void_func_void_clobber_s30_s31_call_external_void_func_void: 8; GCN: s_mov_b32 s33, s7 9; GCN: s_getpc_b64 s[34:35] 10; GCN-NEXT: s_add_u32 s34, s34, 11; GCN-NEXT: s_addc_u32 s35, s35, 12; GCN-NEXT: s_mov_b32 s4, s33 13; GCN-NEXT: s_mov_b32 s32, s33 14; GCN: s_swappc_b64 s[30:31], s[34:35] 15 16; GCN-NEXT: s_mov_b32 s4, s33 17; GCN-NEXT: #ASMSTART 18; GCN-NEXT: #ASMEND 19; GCN-NEXT: s_swappc_b64 s[30:31], s[34:35] 20define amdgpu_kernel void @test_kernel_call_external_void_func_void_clobber_s30_s31_call_external_void_func_void() #0 { 21 call void @external_void_func_void() 22 call void asm sideeffect "", ""() #0 23 call void @external_void_func_void() 24 ret void 25} 26 27; GCN-LABEL: {{^}}test_func_call_external_void_func_void_clobber_s30_s31_call_external_void_func_void: 28; GCN: v_writelane_b32 v32, s33, 0 29; GCN: v_writelane_b32 v32, s34, 1 30; GCN: v_writelane_b32 v32, s35, 2 31; GCN: v_writelane_b32 v32, s36, 3 32; GCN: v_writelane_b32 v32, s37, 4 33 34; GCN: s_mov_b32 s33, s5 35; GCN-NEXT: s_swappc_b64 36; GCN-NEXT: s_mov_b32 s5, s33 37; GCN-NEXT: s_mov_b32 s33, s5 38; GCN-NEXT: ;;#ASMSTART 39; GCN-NEXT: ;;#ASMEND 40; GCN-NEXT: s_swappc_b64 41; GCN-NEXT: s_mov_b32 s5, s33 42; GCN: v_readlane_b32 s37, v32, 4 43; GCN: v_readlane_b32 s36, v32, 3 44; GCN: v_readlane_b32 s35, v32, 2 45; GCN: v_readlane_b32 s34, v32, 1 46; GCN: v_readlane_b32 s33, v32, 0 47; GCN: s_setpc_b64 48define void @test_func_call_external_void_func_void_clobber_s30_s31_call_external_void_func_void() #0 { 49 call void @external_void_func_void() 50 call void asm sideeffect "", ""() #0 51 call void @external_void_func_void() 52 ret void 53} 54 55; FIXME: Avoid extra restore of FP in between calls. 56; GCN-LABEL: {{^}}test_func_call_external_void_funcx2: 57; GCN: s_mov_b32 s33, s5 58; GCN-NEXT: s_swappc_b64 59; GCN-NEXT: s_mov_b32 s5, s33 60; GCN-NEXT: s_mov_b32 s33, s5 61; GCN-NEXT: s_swappc_b64 62; GCN-NEXT: s_mov_b32 s5, s33 63define void @test_func_call_external_void_funcx2() #0 { 64 call void @external_void_func_void() 65 call void @external_void_func_void() 66 ret void 67} 68 69; GCN-LABEL: {{^}}void_func_void_clobber_s30_s31: 70; GCN: s_waitcnt 71; GCN-NEXT: s_mov_b64 [[SAVEPC:s\[[0-9]+:[0-9]+\]]], s[30:31] 72; GCN-NEXT: #ASMSTART 73; GCN: ; clobber 74; GCN-NEXT: #ASMEND 75; GCN-NEXT: s_mov_b64 s[30:31], [[SAVEPC]] 76; GCN-NEXT: s_setpc_b64 s[30:31] 77define void @void_func_void_clobber_s30_s31() #2 { 78 call void asm sideeffect "; clobber", "~{s[30:31]}"() #0 79 ret void 80} 81 82; GCN-LABEL: {{^}}void_func_void_clobber_vcc: 83; GCN: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 84; GCN-NEXT: ;;#ASMSTART 85; GCN-NEXT: ;;#ASMEND 86; GCN-NEXT: s_setpc_b64 s[30:31] 87define void @void_func_void_clobber_vcc() #2 { 88 call void asm sideeffect "", "~{VCC}"() #0 89 ret void 90} 91 92; GCN-LABEL: {{^}}test_call_void_func_void_clobber_vcc: 93; GCN: s_getpc_b64 94; GCN-NEXT: s_add_u32 95; GCN-NEXT: s_addc_u32 96; GCN: s_mov_b64 s[34:35], vcc 97; GCN-NEXT: s_swappc_b64 98; GCN: s_mov_b64 vcc, s[34:35] 99define amdgpu_kernel void @test_call_void_func_void_clobber_vcc(i32 addrspace(1)* %out) #0 { 100 %vcc = call i64 asm sideeffect "; def $0", "={vcc}"() 101 call void @void_func_void_clobber_vcc() 102 %val0 = load volatile i32, i32 addrspace(1)* undef 103 %val1 = load volatile i32, i32 addrspace(1)* undef 104 call void asm sideeffect "; use $0", "{vcc}"(i64 %vcc) 105 ret void 106} 107 108; GCN-LABEL: {{^}}test_call_void_func_void_mayclobber_s31: 109; GCN: s_mov_b32 s33, s31 110; GCN-NEXT: s_swappc_b64 111; GCN-NEXT: s_mov_b32 s31, s33 112define amdgpu_kernel void @test_call_void_func_void_mayclobber_s31(i32 addrspace(1)* %out) #0 { 113 %s31 = call i32 asm sideeffect "; def $0", "={s31}"() 114 call void @external_void_func_void() 115 call void asm sideeffect "; use $0", "{s31}"(i32 %s31) 116 ret void 117} 118 119; GCN-LABEL: {{^}}test_call_void_func_void_mayclobber_v31: 120; GCN: v_mov_b32_e32 v32, v31 121; GCN-NEXT: s_swappc_b64 122; GCN-NEXT: v_mov_b32_e32 v31, v32 123define amdgpu_kernel void @test_call_void_func_void_mayclobber_v31(i32 addrspace(1)* %out) #0 { 124 %v31 = call i32 asm sideeffect "; def $0", "={v31}"() 125 call void @external_void_func_void() 126 call void asm sideeffect "; use $0", "{v31}"(i32 %v31) 127 ret void 128} 129 130; GCN-LABEL: {{^}}test_call_void_func_void_preserves_s33: 131; GCN: s_mov_b32 s34, s9 132; GCN: ; def s33 133; GCN-NEXT: #ASMEND 134; GCN: s_getpc_b64 s[6:7] 135; GCN-NEXT: s_add_u32 s6, s6, external_void_func_void@rel32@lo+4 136; GCN-NEXT: s_addc_u32 s7, s7, external_void_func_void@rel32@hi+4 137; GCN-NEXT: s_mov_b32 s4, s34 138; GCN-NEXT: s_mov_b32 s32, s34 139; GCN-NEXT: s_swappc_b64 s[30:31], s[6:7] 140; GCN-NEXT: ;;#ASMSTART 141; GCN-NEXT: ; use s33 142; GCN-NEXT: ;;#ASMEND 143; GCN-NEXT: s_endpgm 144define amdgpu_kernel void @test_call_void_func_void_preserves_s33(i32 addrspace(1)* %out) #0 { 145 %s33 = call i32 asm sideeffect "; def $0", "={s33}"() 146 call void @external_void_func_void() 147 call void asm sideeffect "; use $0", "{s33}"(i32 %s33) 148 ret void 149} 150 151; GCN-LABEL: {{^}}test_call_void_func_void_preserves_v32: 152; GCN: s_mov_b32 s33, s9 153; GCN: ; def v32 154; GCN-NEXT: #ASMEND 155; GCN: s_getpc_b64 s[6:7] 156; GCN-NEXT: s_add_u32 s6, s6, external_void_func_void@rel32@lo+4 157; GCN-NEXT: s_addc_u32 s7, s7, external_void_func_void@rel32@hi+4 158; GCN-NEXT: s_mov_b32 s4, s33 159; GCN-NEXT: s_mov_b32 s32, s33 160; GCN-NEXT: s_swappc_b64 s[30:31], s[6:7] 161; GCN-NEXT: ;;#ASMSTART 162; GCN-NEXT: ; use v32 163; GCN-NEXT: ;;#ASMEND 164; GCN-NEXT: s_endpgm 165define amdgpu_kernel void @test_call_void_func_void_preserves_v32(i32 addrspace(1)* %out) #0 { 166 %v32 = call i32 asm sideeffect "; def $0", "={v32}"() 167 call void @external_void_func_void() 168 call void asm sideeffect "; use $0", "{v32}"(i32 %v32) 169 ret void 170} 171 172; GCN-LABEL: {{^}}void_func_void_clobber_s33: 173; GCN: v_writelane_b32 v0, s33, 0 174; GCN-NEXT: #ASMSTART 175; GCN-NEXT: ; clobber 176; GCN-NEXT: #ASMEND 177; GCN-NEXT: v_readlane_b32 s33, v0, 0 178; GCN-NEXT: s_setpc_b64 179define void @void_func_void_clobber_s33() #2 { 180 call void asm sideeffect "; clobber", "~{s33}"() #0 181 ret void 182} 183 184; GCN-LABEL: {{^}}test_call_void_func_void_clobber_s33: 185; GCN: s_mov_b32 s33, s7 186; GCN: s_getpc_b64 187; GCN-NEXT: s_add_u32 188; GCN-NEXT: s_addc_u32 189; GCN-NEXT: s_mov_b32 s4, s33 190; GCN-NEXT: s_mov_b32 s32, s33 191; GCN: s_swappc_b64 192; GCN-NEXT: s_endpgm 193define amdgpu_kernel void @test_call_void_func_void_clobber_s33() #0 { 194 call void @void_func_void_clobber_s33() 195 ret void 196} 197 198; GCN-LABEL: {{^}}callee_saved_sgpr_func: 199; GCN-NOT: s40 200; GCN: v_writelane_b32 v32, s40 201; GCN: s_swappc_b64 202; GCN-NOT: s40 203; GCN: ; use s40 204; GCN-NOT: s40 205; GCN: v_readlane_b32 s40, v32 206; GCN-NOT: s40 207define void @callee_saved_sgpr_func() #2 { 208 %s40 = call i32 asm sideeffect "; def s40", "={s40}"() #0 209 call void @external_void_func_void() 210 call void asm sideeffect "; use $0", "s"(i32 %s40) #0 211 ret void 212} 213 214; GCN-LABEL: {{^}}callee_saved_sgpr_kernel: 215; GCN-NOT: s40 216; GCN: ; def s40 217; GCN-NOT: s40 218; GCN: s_swappc_b64 219; GCN-NOT: s40 220; GCN: ; use s40 221; GCN-NOT: s40 222define amdgpu_kernel void @callee_saved_sgpr_kernel() #2 { 223 %s40 = call i32 asm sideeffect "; def s40", "={s40}"() #0 224 call void @external_void_func_void() 225 call void asm sideeffect "; use $0", "s"(i32 %s40) #0 226 ret void 227} 228 229; First call preserved VGPR is used so it can't be used for SGPR spills. 230; GCN-LABEL: {{^}}callee_saved_sgpr_vgpr_func: 231; GCN-NOT: s40 232; GCN: v_writelane_b32 v33, s40 233; GCN: s_swappc_b64 234; GCN-NOT: s40 235; GCN: ; use s40 236; GCN-NOT: s40 237; GCN: v_readlane_b32 s40, v33 238; GCN-NOT: s40 239define void @callee_saved_sgpr_vgpr_func() #2 { 240 %s40 = call i32 asm sideeffect "; def s40", "={s40}"() #0 241 %v32 = call i32 asm sideeffect "; def v32", "={v32}"() #0 242 call void @external_void_func_void() 243 call void asm sideeffect "; use $0", "s"(i32 %s40) #0 244 call void asm sideeffect "; use $0", "v"(i32 %v32) #0 245 ret void 246} 247 248; GCN-LABEL: {{^}}callee_saved_sgpr_vgpr_kernel: 249; GCN-NOT: s40 250; GCN: ; def s40 251; GCN-NOT: s40 252; GCN: s_swappc_b64 253; GCN-NOT: s40 254; GCN: ; use s40 255; GCN-NOT: s40 256define amdgpu_kernel void @callee_saved_sgpr_vgpr_kernel() #2 { 257 %s40 = call i32 asm sideeffect "; def s40", "={s40}"() #0 258 %v32 = call i32 asm sideeffect "; def v32", "={v32}"() #0 259 call void @external_void_func_void() 260 call void asm sideeffect "; use $0", "s"(i32 %s40) #0 261 call void asm sideeffect "; use $0", "v"(i32 %v32) #0 262 ret void 263} 264 265attributes #0 = { nounwind } 266attributes #1 = { nounwind readnone } 267attributes #2 = { nounwind noinline } 268