1; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -enable-misched=0 -post-RA-scheduler=0 -stress-regalloc=8 < %s | FileCheck %s 2 3; Test that the VGPR spiller correctly switches to SGPR offsets when the 4; instruction offset field would overflow, and that it accounts for memory 5; swizzling. 6 7; CHECK-LABEL: test_inst_offset_kernel 8define amdgpu_kernel void @test_inst_offset_kernel() { 9entry: 10 ; Occupy 4092 bytes of scratch, so the offset of the spill of %a just fits in 11 ; the instruction offset field. 12 %alloca = alloca i8, i32 4088, align 4, addrspace(5) 13 %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)* 14 15 %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1 16 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4092 ; 4-byte Folded Spill 17 %a = load volatile i32, i32 addrspace(5)* %aptr 18 19 ; Force %a to spill. 20 call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" () 21 22 %outptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1 23 store volatile i32 %a, i32 addrspace(5)* %outptr 24 25 ret void 26} 27 28; CHECK-LABEL: test_sgpr_offset_kernel 29define amdgpu_kernel void @test_sgpr_offset_kernel() { 30entry: 31 ; Occupy 4096 bytes of scratch, so the offset of the spill of %a does not 32 ; fit in the instruction, and has to live in the SGPR offset. 33 %alloca = alloca i8, i32 4092, align 4, addrspace(5) 34 %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)* 35 36 %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1 37 ; 0x40000 / 64 = 4096 (for wave64) 38 ; CHECK: s_add_u32 s6, s7, 0x40000 39 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 ; 4-byte Folded Spill 40 %a = load volatile i32, i32 addrspace(5)* %aptr 41 42 ; Force %a to spill 43 call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" () 44 45 %outptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1 46 store volatile i32 %a, i32 addrspace(5)* %outptr 47 48 ret void 49} 50 51; CHECK-LABEL: test_sgpr_offset_kernel_scavenge_fail 52define amdgpu_kernel void @test_sgpr_offset_kernel_scavenge_fail() #1 { 53entry: 54 ; Occupy 4096 bytes of scratch, so the offset of the spill of %a does not 55 ; fit in the instruction, and has to live in the SGPR offset. 56 %alloca = alloca i8, i32 4092, align 4, addrspace(5) 57 %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)* 58 59 %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1 60 61 ; 0x40000 / 64 = 4096 (for wave64) 62 %a = load volatile i32, i32 addrspace(5)* %aptr 63 64 %asm = call { i32, i32, i32, i32, i32, i32, i32, i32 } asm sideeffect "", "=s,=s,=s,=s,=s,=s,=s,=s"() 65 %asm0 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 0 66 %asm1 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 1 67 %asm2 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 2 68 %asm3 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 3 69 %asm4 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 4 70 %asm5 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 5 71 %asm6 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 6 72 %asm7 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 7 73 74 call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}"() #0 75 76 ; CHECK: s_add_u32 s7, s7, 0x40000 77 ; CHECK: buffer_load_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s7 ; 4-byte Folded Reload 78 ; CHECK: s_sub_u32 s7, s7, 0x40000 79 80 ; Force %a to spill with no free SGPRs 81 call void asm sideeffect "", "s,s,s,s,s,s,s,s,v"(i32 %asm0, i32 %asm1, i32 %asm2, i32 %asm3, i32 %asm4, i32 %asm5, i32 %asm6, i32 %asm7, i32 %a) 82 ret void 83} 84 85; CHECK-LABEL: test_sgpr_offset_subregs_kernel 86define amdgpu_kernel void @test_sgpr_offset_subregs_kernel() { 87entry: 88 ; Occupy 4088 bytes of scratch, so that the spill of the last subreg of %a 89 ; still fits below offset 4096 (4088 + 8 - 4 = 4092), and can be placed in 90 ; the instruction offset field. 91 %alloca = alloca i8, i32 4084, align 4, addrspace(5) 92 %bufv1 = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)* 93 %bufv2 = bitcast i8 addrspace(5)* %alloca to <2 x i32> addrspace(5)* 94 95 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4088 ; 4-byte Folded Spill 96 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4092 ; 4-byte Folded Spill 97 %aptr = getelementptr <2 x i32>, <2 x i32> addrspace(5)* %bufv2, i32 1 98 %a = load volatile <2 x i32>, <2 x i32> addrspace(5)* %aptr 99 100 ; Force %a to spill. 101 call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" () 102 103 ; Ensure the alloca sticks around. 104 %bptr = getelementptr i32, i32 addrspace(5)* %bufv1, i32 1 105 %b = load volatile i32, i32 addrspace(5)* %bptr 106 107 ; Ensure the spill is of the full super-reg. 108 call void asm sideeffect "; $0", "r"(<2 x i32> %a) 109 110 ret void 111} 112 113; CHECK-LABEL: test_inst_offset_subregs_kernel 114define amdgpu_kernel void @test_inst_offset_subregs_kernel() { 115entry: 116 ; Occupy 4092 bytes of scratch, so that the spill of the last subreg of %a 117 ; does not fit below offset 4096 (4092 + 8 - 4 = 4096), and has to live 118 ; in the SGPR offset. 119 %alloca = alloca i8, i32 4088, align 4, addrspace(5) 120 %bufv1 = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)* 121 %bufv2 = bitcast i8 addrspace(5)* %alloca to <2 x i32> addrspace(5)* 122 123 ; 0x3ff00 / 64 = 4092 (for wave64) 124 ; CHECK: s_add_u32 s6, s7, 0x3ff00 125 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 ; 4-byte Folded Spill 126 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 offset:4 ; 4-byte Folded Spill 127 %aptr = getelementptr <2 x i32>, <2 x i32> addrspace(5)* %bufv2, i32 1 128 %a = load volatile <2 x i32>, <2 x i32> addrspace(5)* %aptr 129 130 ; Force %a to spill. 131 call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" () 132 133 ; Ensure the alloca sticks around. 134 %bptr = getelementptr i32, i32 addrspace(5)* %bufv1, i32 1 135 %b = load volatile i32, i32 addrspace(5)* %bptr 136 137 ; Ensure the spill is of the full super-reg. 138 call void asm sideeffect "; $0", "r"(<2 x i32> %a) 139 140 ret void 141} 142 143; CHECK-LABEL: test_inst_offset_function 144define void @test_inst_offset_function() { 145entry: 146 ; Occupy 4092 bytes of scratch, so the offset of the spill of %a just fits in 147 ; the instruction offset field. 148 %alloca = alloca i8, i32 4088, align 4, addrspace(5) 149 %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)* 150 151 %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1 152 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4092 ; 4-byte Folded Spill 153 %a = load volatile i32, i32 addrspace(5)* %aptr 154 155 ; Force %a to spill. 156 call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" () 157 158 %outptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1 159 store volatile i32 %a, i32 addrspace(5)* %outptr 160 161 ret void 162} 163 164; CHECK-LABEL: test_sgpr_offset_function 165define void @test_sgpr_offset_function() { 166entry: 167 ; Occupy 4096 bytes of scratch, so the offset of the spill of %a does not 168 ; fit in the instruction, and has to live in the SGPR offset. 169 %alloca = alloca i8, i32 4092, align 4, addrspace(5) 170 %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)* 171 172 %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1 173 ; 0x40000 / 64 = 4096 (for wave64) 174 ; CHECK: s_add_u32 s6, s5, 0x40000 175 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 ; 4-byte Folded Spill 176 %a = load volatile i32, i32 addrspace(5)* %aptr 177 178 ; Force %a to spill 179 call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" () 180 181 %outptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1 182 store volatile i32 %a, i32 addrspace(5)* %outptr 183 184 ret void 185} 186 187; CHECK-LABEL: test_sgpr_offset_subregs_function 188define void @test_sgpr_offset_subregs_function() { 189entry: 190 ; Occupy 4088 bytes of scratch, so that the spill of the last subreg of %a 191 ; still fits below offset 4096 (4088 + 8 - 4 = 4092), and can be placed in 192 ; the instruction offset field. 193 %alloca = alloca i8, i32 4084, align 4, addrspace(5) 194 %bufv1 = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)* 195 %bufv2 = bitcast i8 addrspace(5)* %alloca to <2 x i32> addrspace(5)* 196 197 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4088 ; 4-byte Folded Spill 198 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4092 ; 4-byte Folded Spill 199 %aptr = getelementptr <2 x i32>, <2 x i32> addrspace(5)* %bufv2, i32 1 200 %a = load volatile <2 x i32>, <2 x i32> addrspace(5)* %aptr 201 202 ; Force %a to spill. 203 call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" () 204 205 ; Ensure the alloca sticks around. 206 %bptr = getelementptr i32, i32 addrspace(5)* %bufv1, i32 1 207 %b = load volatile i32, i32 addrspace(5)* %bptr 208 209 ; Ensure the spill is of the full super-reg. 210 call void asm sideeffect "; $0", "r"(<2 x i32> %a) 211 212 ret void 213} 214 215; CHECK-LABEL: test_inst_offset_subregs_function 216define void @test_inst_offset_subregs_function() { 217entry: 218 ; Occupy 4092 bytes of scratch, so that the spill of the last subreg of %a 219 ; does not fit below offset 4096 (4092 + 8 - 4 = 4096), and has to live 220 ; in the SGPR offset. 221 %alloca = alloca i8, i32 4088, align 4, addrspace(5) 222 %bufv1 = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)* 223 %bufv2 = bitcast i8 addrspace(5)* %alloca to <2 x i32> addrspace(5)* 224 225 ; 0x3ff00 / 64 = 4092 (for wave64) 226 ; CHECK: s_add_u32 s6, s5, 0x3ff00 227 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 ; 4-byte Folded Spill 228 ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 offset:4 ; 4-byte Folded Spill 229 %aptr = getelementptr <2 x i32>, <2 x i32> addrspace(5)* %bufv2, i32 1 230 %a = load volatile <2 x i32>, <2 x i32> addrspace(5)* %aptr 231 232 ; Force %a to spill. 233 call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" () 234 235 ; Ensure the alloca sticks around. 236 %bptr = getelementptr i32, i32 addrspace(5)* %bufv1, i32 1 237 %b = load volatile i32, i32 addrspace(5)* %bptr 238 239 ; Ensure the spill is of the full super-reg. 240 call void asm sideeffect "; $0", "r"(<2 x i32> %a) 241 242 ret void 243} 244 245attributes #0 = { nounwind } 246attributes #1 = { nounwind "amdgpu-num-sgpr"="18" "amdgpu-num-vgpr"="8" } 247