1 ; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=GCN -check-prefix=GCN-NOAA %s
2 ; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=GCN -check-prefix=GCN-NOAA %s
4 ; RUN: llc -march=amdgcn -verify-machineinstrs -combiner-alias-analysis < %s | FileCheck -check-prefix=SI -check-prefix=GCN -check-prefix=GCN-AA %s
5 ; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs -combiner-alias-analysis < %s | FileCheck -check-prefix=SI -check-prefix=GCN -check-prefix=GCN-AA %s
7 ; Run with devices with different unaligned load restrictions.
9 ; TODO: Vector element tests
10 ; TODO: Non-zero base offset for load and store combinations
11 ; TODO: Same base addrspacecasted
14 ; GCN-LABEL: {{^}}merge_global_store_2_constants_i8:
15 ; GCN: buffer_store_byte
16 ; GCN: buffer_store_byte
18 define void @merge_global_store_2_constants_i8(i8 addrspace(1)* %out) #0 {
19 %out.gep.1 = getelementptr i8, i8 addrspace(1)* %out, i32 1
21 store i8 123, i8 addrspace(1)* %out.gep.1
22 store i8 456, i8 addrspace(1)* %out, align 2
26 ; GCN-LABEL: {{^}}merge_global_store_2_constants_i8_natural_align:
27 ; GCN: buffer_store_byte
28 ; GCN: buffer_store_byte
30 define void @merge_global_store_2_constants_i8_natural_align(i8 addrspace(1)* %out) #0 {
31 %out.gep.1 = getelementptr i8, i8 addrspace(1)* %out, i32 1
33 store i8 123, i8 addrspace(1)* %out.gep.1
34 store i8 456, i8 addrspace(1)* %out
38 ; GCN-LABEL: {{^}}merge_global_store_2_constants_i16:
39 ; GCN: buffer_store_dword v
40 define void @merge_global_store_2_constants_i16(i16 addrspace(1)* %out) #0 {
41 %out.gep.1 = getelementptr i16, i16 addrspace(1)* %out, i32 1
43 store i16 123, i16 addrspace(1)* %out.gep.1
44 store i16 456, i16 addrspace(1)* %out, align 4
48 ; GCN-LABEL: {{^}}merge_global_store_2_constants_0_i16:
49 ; GCN: buffer_store_dword v
50 define void @merge_global_store_2_constants_0_i16(i16 addrspace(1)* %out) #0 {
51 %out.gep.1 = getelementptr i16, i16 addrspace(1)* %out, i32 1
53 store i16 0, i16 addrspace(1)* %out.gep.1
54 store i16 0, i16 addrspace(1)* %out, align 4
58 ; GCN-LABEL: {{^}}merge_global_store_2_constants_i16_natural_align:
59 ; GCN: buffer_store_short
60 ; GCN: buffer_store_short
62 define void @merge_global_store_2_constants_i16_natural_align(i16 addrspace(1)* %out) #0 {
63 %out.gep.1 = getelementptr i16, i16 addrspace(1)* %out, i32 1
65 store i16 123, i16 addrspace(1)* %out.gep.1
66 store i16 456, i16 addrspace(1)* %out
70 ; GCN-LABEL: {{^}}merge_global_store_2_constants_i32:
71 ; SI-DAG: v_mov_b32_e32 v[[LO:[0-9]+]], 0x1c8
72 ; SI-DAG: v_mov_b32_e32 v[[HI:[0-9]+]], 0x7b
73 ; GCN: buffer_store_dwordx2 v{{\[}}[[LO]]:[[HI]]{{\]}}
74 define void @merge_global_store_2_constants_i32(i32 addrspace(1)* %out) #0 {
75 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
77 store i32 123, i32 addrspace(1)* %out.gep.1
78 store i32 456, i32 addrspace(1)* %out
82 ; GCN-LABEL: {{^}}merge_global_store_2_constants_i32_f32:
83 ; GCN: buffer_store_dwordx2
84 define void @merge_global_store_2_constants_i32_f32(i32 addrspace(1)* %out) #0 {
85 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
86 %out.gep.1.bc = bitcast i32 addrspace(1)* %out.gep.1 to float addrspace(1)*
87 store float 1.0, float addrspace(1)* %out.gep.1.bc
88 store i32 456, i32 addrspace(1)* %out
92 ; GCN-LABEL: {{^}}merge_global_store_2_constants_f32_i32:
93 ; SI-DAG: v_mov_b32_e32 v[[VLO:[0-9]+]], 4.0
94 ; SI-DAG: v_mov_b32_e32 v[[VHI:[0-9]+]], 0x7b
95 ; GCN: buffer_store_dwordx2 v{{\[}}[[VLO]]:[[VHI]]{{\]}}
96 define void @merge_global_store_2_constants_f32_i32(float addrspace(1)* %out) #0 {
97 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1
98 %out.gep.1.bc = bitcast float addrspace(1)* %out.gep.1 to i32 addrspace(1)*
99 store i32 123, i32 addrspace(1)* %out.gep.1.bc
100 store float 4.0, float addrspace(1)* %out
104 ; GCN-LABEL: {{^}}merge_global_store_4_constants_i32:
105 ; GCN-DAG: v_mov_b32_e32 v[[HI:[0-9]+]], 0x14d{{$}}
106 ; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, 0x1c8{{$}}
107 ; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, 0x7b{{$}}
108 ; GCN-DAG: v_mov_b32_e32 v[[LO:[0-9]+]], 0x4d2{{$}}
109 ; GCN: buffer_store_dwordx4 v{{\[}}[[LO]]:[[HI]]{{\]}}
110 define void @merge_global_store_4_constants_i32(i32 addrspace(1)* %out) #0 {
111 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
112 %out.gep.2 = getelementptr i32, i32 addrspace(1)* %out, i32 2
113 %out.gep.3 = getelementptr i32, i32 addrspace(1)* %out, i32 3
115 store i32 123, i32 addrspace(1)* %out.gep.1
116 store i32 456, i32 addrspace(1)* %out.gep.2
117 store i32 333, i32 addrspace(1)* %out.gep.3
118 store i32 1234, i32 addrspace(1)* %out
122 ; GCN-LABEL: {{^}}merge_global_store_4_constants_f32_order:
123 ; GCN: buffer_store_dwordx4
124 define void @merge_global_store_4_constants_f32_order(float addrspace(1)* %out) #0 {
125 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1
126 %out.gep.2 = getelementptr float, float addrspace(1)* %out, i32 2
127 %out.gep.3 = getelementptr float, float addrspace(1)* %out, i32 3
129 store float 8.0, float addrspace(1)* %out
130 store float 1.0, float addrspace(1)* %out.gep.1
131 store float 2.0, float addrspace(1)* %out.gep.2
132 store float 4.0, float addrspace(1)* %out.gep.3
136 ; First store is out of order.
137 ; GCN-LABEL: {{^}}merge_global_store_4_constants_f32:
138 ; GCN: buffer_store_dwordx4
139 define void @merge_global_store_4_constants_f32(float addrspace(1)* %out) #0 {
140 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1
141 %out.gep.2 = getelementptr float, float addrspace(1)* %out, i32 2
142 %out.gep.3 = getelementptr float, float addrspace(1)* %out, i32 3
144 store float 1.0, float addrspace(1)* %out.gep.1
145 store float 2.0, float addrspace(1)* %out.gep.2
146 store float 4.0, float addrspace(1)* %out.gep.3
147 store float 8.0, float addrspace(1)* %out
151 ; FIXME: Should be able to merge this
152 ; GCN-LABEL: {{^}}merge_global_store_4_constants_mixed_i32_f32:
153 ; GCN-NOAA: buffer_store_dword v
154 ; GCN-NOAA: buffer_store_dword v
155 ; GCN-NOAA: buffer_store_dword v
156 ; GCN-NOAA: buffer_store_dword v
158 ; GCN-AA: buffer_store_dwordx2
159 ; GCN-AA: buffer_store_dword v
160 ; GCN-AA: buffer_store_dword v
163 define void @merge_global_store_4_constants_mixed_i32_f32(float addrspace(1)* %out) #0 {
164 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1
165 %out.gep.2 = getelementptr float, float addrspace(1)* %out, i32 2
166 %out.gep.3 = getelementptr float, float addrspace(1)* %out, i32 3
168 %out.gep.1.bc = bitcast float addrspace(1)* %out.gep.1 to i32 addrspace(1)*
169 %out.gep.3.bc = bitcast float addrspace(1)* %out.gep.3 to i32 addrspace(1)*
171 store i32 11, i32 addrspace(1)* %out.gep.1.bc
172 store float 2.0, float addrspace(1)* %out.gep.2
173 store i32 17, i32 addrspace(1)* %out.gep.3.bc
174 store float 8.0, float addrspace(1)* %out
178 ; GCN-LABEL: {{^}}merge_global_store_3_constants_i32:
179 ; SI-DAG: buffer_store_dwordx2
180 ; SI-DAG: buffer_store_dword
181 ; SI-NOT: buffer_store_dword
183 define void @merge_global_store_3_constants_i32(i32 addrspace(1)* %out) #0 {
184 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
185 %out.gep.2 = getelementptr i32, i32 addrspace(1)* %out, i32 2
187 store i32 123, i32 addrspace(1)* %out.gep.1
188 store i32 456, i32 addrspace(1)* %out.gep.2
189 store i32 1234, i32 addrspace(1)* %out
193 ; GCN-LABEL: {{^}}merge_global_store_2_constants_i64:
194 ; GCN: buffer_store_dwordx4
195 define void @merge_global_store_2_constants_i64(i64 addrspace(1)* %out) #0 {
196 %out.gep.1 = getelementptr i64, i64 addrspace(1)* %out, i64 1
198 store i64 123, i64 addrspace(1)* %out.gep.1
199 store i64 456, i64 addrspace(1)* %out
203 ; GCN-LABEL: {{^}}merge_global_store_4_constants_i64:
204 ; GCN: buffer_store_dwordx4
205 ; GCN: buffer_store_dwordx4
206 define void @merge_global_store_4_constants_i64(i64 addrspace(1)* %out) #0 {
207 %out.gep.1 = getelementptr i64, i64 addrspace(1)* %out, i64 1
208 %out.gep.2 = getelementptr i64, i64 addrspace(1)* %out, i64 2
209 %out.gep.3 = getelementptr i64, i64 addrspace(1)* %out, i64 3
211 store i64 123, i64 addrspace(1)* %out.gep.1
212 store i64 456, i64 addrspace(1)* %out.gep.2
213 store i64 333, i64 addrspace(1)* %out.gep.3
214 store i64 1234, i64 addrspace(1)* %out
218 ; GCN-LABEL: {{^}}merge_global_store_2_adjacent_loads_i32:
219 ; GCN: buffer_load_dwordx2 [[LOAD:v\[[0-9]+:[0-9]+\]]]
220 ; GCN: buffer_store_dwordx2 [[LOAD]]
221 define void @merge_global_store_2_adjacent_loads_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
222 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
223 %in.gep.1 = getelementptr i32, i32 addrspace(1)* %in, i32 1
225 %lo = load i32, i32 addrspace(1)* %in
226 %hi = load i32, i32 addrspace(1)* %in.gep.1
228 store i32 %lo, i32 addrspace(1)* %out
229 store i32 %hi, i32 addrspace(1)* %out.gep.1
233 ; GCN-LABEL: {{^}}merge_global_store_2_adjacent_loads_i32_nonzero_base:
234 ; GCN: buffer_load_dwordx2 [[LOAD:v\[[0-9]+:[0-9]+\]]], s{{\[[0-9]+:[0-9]+\]}}, 0 offset:8
235 ; GCN: buffer_store_dwordx2 [[LOAD]], s{{\[[0-9]+:[0-9]+\]}}, 0 offset:8
236 define void @merge_global_store_2_adjacent_loads_i32_nonzero_base(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
237 %in.gep.0 = getelementptr i32, i32 addrspace(1)* %in, i32 2
238 %in.gep.1 = getelementptr i32, i32 addrspace(1)* %in, i32 3
240 %out.gep.0 = getelementptr i32, i32 addrspace(1)* %out, i32 2
241 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 3
242 %lo = load i32, i32 addrspace(1)* %in.gep.0
243 %hi = load i32, i32 addrspace(1)* %in.gep.1
245 store i32 %lo, i32 addrspace(1)* %out.gep.0
246 store i32 %hi, i32 addrspace(1)* %out.gep.1
250 ; GCN-LABEL: {{^}}merge_global_store_2_adjacent_loads_shuffle_i32:
251 ; GCN: buffer_load_dword v
252 ; GCN: buffer_load_dword v
253 ; GCN: buffer_store_dword v
254 ; GCN: buffer_store_dword v
255 define void @merge_global_store_2_adjacent_loads_shuffle_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
256 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
257 %in.gep.1 = getelementptr i32, i32 addrspace(1)* %in, i32 1
259 %lo = load i32, i32 addrspace(1)* %in
260 %hi = load i32, i32 addrspace(1)* %in.gep.1
262 store i32 %hi, i32 addrspace(1)* %out
263 store i32 %lo, i32 addrspace(1)* %out.gep.1
267 ; GCN-LABEL: {{^}}merge_global_store_4_adjacent_loads_i32:
268 ; GCN: buffer_load_dwordx4 [[LOAD:v\[[0-9]+:[0-9]+\]]]
269 ; GCN: buffer_store_dwordx4 [[LOAD]]
270 define void @merge_global_store_4_adjacent_loads_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
271 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
272 %out.gep.2 = getelementptr i32, i32 addrspace(1)* %out, i32 2
273 %out.gep.3 = getelementptr i32, i32 addrspace(1)* %out, i32 3
274 %in.gep.1 = getelementptr i32, i32 addrspace(1)* %in, i32 1
275 %in.gep.2 = getelementptr i32, i32 addrspace(1)* %in, i32 2
276 %in.gep.3 = getelementptr i32, i32 addrspace(1)* %in, i32 3
278 %x = load i32, i32 addrspace(1)* %in
279 %y = load i32, i32 addrspace(1)* %in.gep.1
280 %z = load i32, i32 addrspace(1)* %in.gep.2
281 %w = load i32, i32 addrspace(1)* %in.gep.3
283 store i32 %x, i32 addrspace(1)* %out
284 store i32 %y, i32 addrspace(1)* %out.gep.1
285 store i32 %z, i32 addrspace(1)* %out.gep.2
286 store i32 %w, i32 addrspace(1)* %out.gep.3
290 ; GCN-LABEL: {{^}}merge_global_store_3_adjacent_loads_i32:
291 ; SI-DAG: buffer_load_dwordx2
292 ; SI-DAG: buffer_load_dword v
294 ; SI-DAG: buffer_store_dword v
295 ; SI-DAG: buffer_store_dwordx2 v
297 define void @merge_global_store_3_adjacent_loads_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
298 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
299 %out.gep.2 = getelementptr i32, i32 addrspace(1)* %out, i32 2
300 %in.gep.1 = getelementptr i32, i32 addrspace(1)* %in, i32 1
301 %in.gep.2 = getelementptr i32, i32 addrspace(1)* %in, i32 2
303 %x = load i32, i32 addrspace(1)* %in
304 %y = load i32, i32 addrspace(1)* %in.gep.1
305 %z = load i32, i32 addrspace(1)* %in.gep.2
307 store i32 %x, i32 addrspace(1)* %out
308 store i32 %y, i32 addrspace(1)* %out.gep.1
309 store i32 %z, i32 addrspace(1)* %out.gep.2
313 ; GCN-LABEL: {{^}}merge_global_store_4_adjacent_loads_f32:
314 ; GCN: buffer_load_dwordx4 [[LOAD:v\[[0-9]+:[0-9]+\]]]
315 ; GCN: buffer_store_dwordx4 [[LOAD]]
316 define void @merge_global_store_4_adjacent_loads_f32(float addrspace(1)* %out, float addrspace(1)* %in) #0 {
317 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1
318 %out.gep.2 = getelementptr float, float addrspace(1)* %out, i32 2
319 %out.gep.3 = getelementptr float, float addrspace(1)* %out, i32 3
320 %in.gep.1 = getelementptr float, float addrspace(1)* %in, i32 1
321 %in.gep.2 = getelementptr float, float addrspace(1)* %in, i32 2
322 %in.gep.3 = getelementptr float, float addrspace(1)* %in, i32 3
324 %x = load float, float addrspace(1)* %in
325 %y = load float, float addrspace(1)* %in.gep.1
326 %z = load float, float addrspace(1)* %in.gep.2
327 %w = load float, float addrspace(1)* %in.gep.3
329 store float %x, float addrspace(1)* %out
330 store float %y, float addrspace(1)* %out.gep.1
331 store float %z, float addrspace(1)* %out.gep.2
332 store float %w, float addrspace(1)* %out.gep.3
336 ; GCN-LABEL: {{^}}merge_global_store_4_adjacent_loads_i32_nonzero_base:
337 ; GCN: buffer_load_dwordx4 [[LOAD:v\[[0-9]+:[0-9]+\]]], s{{\[[0-9]+:[0-9]+\]}}, 0 offset:44
338 ; GCN: buffer_store_dwordx4 [[LOAD]], s{{\[[0-9]+:[0-9]+\]}}, 0 offset:28
339 define void @merge_global_store_4_adjacent_loads_i32_nonzero_base(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
340 %in.gep.0 = getelementptr i32, i32 addrspace(1)* %in, i32 11
341 %in.gep.1 = getelementptr i32, i32 addrspace(1)* %in, i32 12
342 %in.gep.2 = getelementptr i32, i32 addrspace(1)* %in, i32 13
343 %in.gep.3 = getelementptr i32, i32 addrspace(1)* %in, i32 14
344 %out.gep.0 = getelementptr i32, i32 addrspace(1)* %out, i32 7
345 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 8
346 %out.gep.2 = getelementptr i32, i32 addrspace(1)* %out, i32 9
347 %out.gep.3 = getelementptr i32, i32 addrspace(1)* %out, i32 10
349 %x = load i32, i32 addrspace(1)* %in.gep.0
350 %y = load i32, i32 addrspace(1)* %in.gep.1
351 %z = load i32, i32 addrspace(1)* %in.gep.2
352 %w = load i32, i32 addrspace(1)* %in.gep.3
354 store i32 %x, i32 addrspace(1)* %out.gep.0
355 store i32 %y, i32 addrspace(1)* %out.gep.1
356 store i32 %z, i32 addrspace(1)* %out.gep.2
357 store i32 %w, i32 addrspace(1)* %out.gep.3
361 ; GCN-LABEL: {{^}}merge_global_store_4_adjacent_loads_inverse_i32:
362 ; GCN: buffer_load_dwordx4 [[LOAD:v\[[0-9]+:[0-9]+\]]]
364 ; GCN: buffer_store_dwordx4 [[LOAD]]
365 define void @merge_global_store_4_adjacent_loads_inverse_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
366 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
367 %out.gep.2 = getelementptr i32, i32 addrspace(1)* %out, i32 2
368 %out.gep.3 = getelementptr i32, i32 addrspace(1)* %out, i32 3
369 %in.gep.1 = getelementptr i32, i32 addrspace(1)* %in, i32 1
370 %in.gep.2 = getelementptr i32, i32 addrspace(1)* %in, i32 2
371 %in.gep.3 = getelementptr i32, i32 addrspace(1)* %in, i32 3
373 %x = load i32, i32 addrspace(1)* %in
374 %y = load i32, i32 addrspace(1)* %in.gep.1
375 %z = load i32, i32 addrspace(1)* %in.gep.2
376 %w = load i32, i32 addrspace(1)* %in.gep.3
378 ; Make sure the barrier doesn't stop this
379 tail call void @llvm.AMDGPU.barrier.local() #1
381 store i32 %w, i32 addrspace(1)* %out.gep.3
382 store i32 %z, i32 addrspace(1)* %out.gep.2
383 store i32 %y, i32 addrspace(1)* %out.gep.1
384 store i32 %x, i32 addrspace(1)* %out
389 ; TODO: Re-packing of loaded register required. Maybe an IR pass
392 ; GCN-LABEL: {{^}}merge_global_store_4_adjacent_loads_shuffle_i32:
393 ; GCN: buffer_load_dword v
394 ; GCN: buffer_load_dword v
395 ; GCN: buffer_load_dword v
396 ; GCN: buffer_load_dword v
398 ; GCN: buffer_store_dword v
399 ; GCN: buffer_store_dword v
400 ; GCN: buffer_store_dword v
401 ; GCN: buffer_store_dword v
402 define void @merge_global_store_4_adjacent_loads_shuffle_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
403 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
404 %out.gep.2 = getelementptr i32, i32 addrspace(1)* %out, i32 2
405 %out.gep.3 = getelementptr i32, i32 addrspace(1)* %out, i32 3
406 %in.gep.1 = getelementptr i32, i32 addrspace(1)* %in, i32 1
407 %in.gep.2 = getelementptr i32, i32 addrspace(1)* %in, i32 2
408 %in.gep.3 = getelementptr i32, i32 addrspace(1)* %in, i32 3
410 %x = load i32, i32 addrspace(1)* %in
411 %y = load i32, i32 addrspace(1)* %in.gep.1
412 %z = load i32, i32 addrspace(1)* %in.gep.2
413 %w = load i32, i32 addrspace(1)* %in.gep.3
415 ; Make sure the barrier doesn't stop this
416 tail call void @llvm.AMDGPU.barrier.local() #1
418 store i32 %w, i32 addrspace(1)* %out
419 store i32 %z, i32 addrspace(1)* %out.gep.1
420 store i32 %y, i32 addrspace(1)* %out.gep.2
421 store i32 %x, i32 addrspace(1)* %out.gep.3
426 ; GCN-LABEL: {{^}}merge_global_store_4_adjacent_loads_i8:
427 ; GCN: buffer_load_dword [[LOAD:v[0-9]+]]
428 ; GCN: buffer_store_dword [[LOAD]]
430 define void @merge_global_store_4_adjacent_loads_i8(i8 addrspace(1)* %out, i8 addrspace(1)* %in) #0 {
431 %out.gep.1 = getelementptr i8, i8 addrspace(1)* %out, i8 1
432 %out.gep.2 = getelementptr i8, i8 addrspace(1)* %out, i8 2
433 %out.gep.3 = getelementptr i8, i8 addrspace(1)* %out, i8 3
434 %in.gep.1 = getelementptr i8, i8 addrspace(1)* %in, i8 1
435 %in.gep.2 = getelementptr i8, i8 addrspace(1)* %in, i8 2
436 %in.gep.3 = getelementptr i8, i8 addrspace(1)* %in, i8 3
438 %x = load i8, i8 addrspace(1)* %in, align 4
439 %y = load i8, i8 addrspace(1)* %in.gep.1
440 %z = load i8, i8 addrspace(1)* %in.gep.2
441 %w = load i8, i8 addrspace(1)* %in.gep.3
443 store i8 %x, i8 addrspace(1)* %out, align 4
444 store i8 %y, i8 addrspace(1)* %out.gep.1
445 store i8 %z, i8 addrspace(1)* %out.gep.2
446 store i8 %w, i8 addrspace(1)* %out.gep.3
450 ; GCN-LABEL: {{^}}merge_global_store_4_adjacent_loads_i8_natural_align:
451 ; GCN: buffer_load_ubyte
452 ; GCN: buffer_load_ubyte
453 ; GCN: buffer_load_ubyte
454 ; GCN: buffer_load_ubyte
455 ; GCN: buffer_store_byte
456 ; GCN: buffer_store_byte
457 ; GCN: buffer_store_byte
458 ; GCN: buffer_store_byte
460 define void @merge_global_store_4_adjacent_loads_i8_natural_align(i8 addrspace(1)* %out, i8 addrspace(1)* %in) #0 {
461 %out.gep.1 = getelementptr i8, i8 addrspace(1)* %out, i8 1
462 %out.gep.2 = getelementptr i8, i8 addrspace(1)* %out, i8 2
463 %out.gep.3 = getelementptr i8, i8 addrspace(1)* %out, i8 3
464 %in.gep.1 = getelementptr i8, i8 addrspace(1)* %in, i8 1
465 %in.gep.2 = getelementptr i8, i8 addrspace(1)* %in, i8 2
466 %in.gep.3 = getelementptr i8, i8 addrspace(1)* %in, i8 3
468 %x = load i8, i8 addrspace(1)* %in
469 %y = load i8, i8 addrspace(1)* %in.gep.1
470 %z = load i8, i8 addrspace(1)* %in.gep.2
471 %w = load i8, i8 addrspace(1)* %in.gep.3
473 store i8 %x, i8 addrspace(1)* %out
474 store i8 %y, i8 addrspace(1)* %out.gep.1
475 store i8 %z, i8 addrspace(1)* %out.gep.2
476 store i8 %w, i8 addrspace(1)* %out.gep.3
480 ; This works once AA is enabled on the subtarget
481 ; GCN-LABEL: {{^}}merge_global_store_4_vector_elts_loads_v4i32:
482 ; GCN: buffer_load_dwordx4 [[LOAD:v\[[0-9]+:[0-9]+\]]]
484 ; GCN-NOAA: buffer_store_dword v
485 ; GCN-NOAA: buffer_store_dword v
486 ; GCN-NOAA: buffer_store_dword v
487 ; GCN-NOAA: buffer_store_dword v
489 ; GCN-AA: buffer_store_dwordx4 [[LOAD]]
492 define void @merge_global_store_4_vector_elts_loads_v4i32(i32 addrspace(1)* %out, <4 x i32> addrspace(1)* %in) #0 {
493 %out.gep.1 = getelementptr i32, i32 addrspace(1)* %out, i32 1
494 %out.gep.2 = getelementptr i32, i32 addrspace(1)* %out, i32 2
495 %out.gep.3 = getelementptr i32, i32 addrspace(1)* %out, i32 3
496 %vec = load <4 x i32>, <4 x i32> addrspace(1)* %in
498 %x = extractelement <4 x i32> %vec, i32 0
499 %y = extractelement <4 x i32> %vec, i32 1
500 %z = extractelement <4 x i32> %vec, i32 2
501 %w = extractelement <4 x i32> %vec, i32 3
503 store i32 %x, i32 addrspace(1)* %out
504 store i32 %y, i32 addrspace(1)* %out.gep.1
505 store i32 %z, i32 addrspace(1)* %out.gep.2
506 store i32 %w, i32 addrspace(1)* %out.gep.3
510 ; GCN-LABEL: {{^}}merge_local_store_2_constants_i8:
514 define void @merge_local_store_2_constants_i8(i8 addrspace(3)* %out) #0 {
515 %out.gep.1 = getelementptr i8, i8 addrspace(3)* %out, i32 1
517 store i8 123, i8 addrspace(3)* %out.gep.1
518 store i8 456, i8 addrspace(3)* %out, align 2
522 ; GCN-LABEL: {{^}}merge_local_store_2_constants_i32:
523 ; GCN-DAG: v_mov_b32_e32 v[[LO:[0-9]+]], 0x1c8
524 ; GCN-DAG: v_mov_b32_e32 v[[HI:[0-9]+]], 0x7b
525 ; GCN: ds_write2_b32 v{{[0-9]+}}, v[[LO]], v[[HI]] offset1:1{{$}}
526 define void @merge_local_store_2_constants_i32(i32 addrspace(3)* %out) #0 {
527 %out.gep.1 = getelementptr i32, i32 addrspace(3)* %out, i32 1
529 store i32 123, i32 addrspace(3)* %out.gep.1
530 store i32 456, i32 addrspace(3)* %out
534 ; GCN-LABEL: {{^}}merge_local_store_4_constants_i32:
535 ; GCN-DAG: v_mov_b32_e32 [[K2:v[0-9]+]], 0x1c8
536 ; GCN-DAG: v_mov_b32_e32 [[K3:v[0-9]+]], 0x14d
537 ; GCN-DAG: ds_write2_b32 v{{[0-9]+}}, [[K2]], [[K3]] offset0:2 offset1:3
539 ; GCN-DAG: v_mov_b32_e32 [[K0:v[0-9]+]], 0x4d2
540 ; GCN-DAG: v_mov_b32_e32 [[K1:v[0-9]+]], 0x7b
541 ; GCN-DAG: ds_write2_b32 v{{[0-9]+}}, [[K0]], [[K1]] offset1:1
544 define void @merge_local_store_4_constants_i32(i32 addrspace(3)* %out) #0 {
545 %out.gep.1 = getelementptr i32, i32 addrspace(3)* %out, i32 1
546 %out.gep.2 = getelementptr i32, i32 addrspace(3)* %out, i32 2
547 %out.gep.3 = getelementptr i32, i32 addrspace(3)* %out, i32 3
549 store i32 123, i32 addrspace(3)* %out.gep.1
550 store i32 456, i32 addrspace(3)* %out.gep.2
551 store i32 333, i32 addrspace(3)* %out.gep.3
552 store i32 1234, i32 addrspace(3)* %out
556 ; GCN-LABEL: {{^}}merge_global_store_5_constants_i32:
557 ; GCN-DAG: v_mov_b32_e32 v[[LO:[0-9]+]], 9{{$}}
558 ; GCN-DAG: v_mov_b32_e32 v[[HI4:[0-9]+]], -12{{$}}
559 ; GCN: buffer_store_dwordx4 v{{\[}}[[LO]]:[[HI4]]{{\]}}
560 ; GCN: v_mov_b32_e32 v[[HI:[0-9]+]], 11{{$}}
561 ; GCN: buffer_store_dword v[[HI]]
562 define void @merge_global_store_5_constants_i32(i32 addrspace(1)* %out) {
563 store i32 9, i32 addrspace(1)* %out, align 4
564 %idx1 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 1
565 store i32 12, i32 addrspace(1)* %idx1, align 4
566 %idx2 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 2
567 store i32 16, i32 addrspace(1)* %idx2, align 4
568 %idx3 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 3
569 store i32 -12, i32 addrspace(1)* %idx3, align 4
570 %idx4 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 4
571 store i32 11, i32 addrspace(1)* %idx4, align 4
575 ; GCN-LABEL: {{^}}merge_global_store_6_constants_i32:
576 ; GCN: buffer_store_dwordx4
577 ; GCN: buffer_store_dwordx2
578 define void @merge_global_store_6_constants_i32(i32 addrspace(1)* %out) {
579 store i32 13, i32 addrspace(1)* %out, align 4
580 %idx1 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 1
581 store i32 15, i32 addrspace(1)* %idx1, align 4
582 %idx2 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 2
583 store i32 62, i32 addrspace(1)* %idx2, align 4
584 %idx3 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 3
585 store i32 63, i32 addrspace(1)* %idx3, align 4
586 %idx4 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 4
587 store i32 11, i32 addrspace(1)* %idx4, align 4
588 %idx5 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 5
589 store i32 123, i32 addrspace(1)* %idx5, align 4
593 ; GCN-LABEL: {{^}}merge_global_store_7_constants_i32:
594 ; GCN: buffer_store_dwordx4
595 ; GCN: buffer_store_dwordx2
596 ; GCN: buffer_store_dword v
597 define void @merge_global_store_7_constants_i32(i32 addrspace(1)* %out) {
598 store i32 34, i32 addrspace(1)* %out, align 4
599 %idx1 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 1
600 store i32 999, i32 addrspace(1)* %idx1, align 4
601 %idx2 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 2
602 store i32 65, i32 addrspace(1)* %idx2, align 4
603 %idx3 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 3
604 store i32 33, i32 addrspace(1)* %idx3, align 4
605 %idx4 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 4
606 store i32 98, i32 addrspace(1)* %idx4, align 4
607 %idx5 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 5
608 store i32 91, i32 addrspace(1)* %idx5, align 4
609 %idx6 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 6
610 store i32 212, i32 addrspace(1)* %idx6, align 4
614 ; GCN-LABEL: {{^}}merge_global_store_8_constants_i32:
615 ; GCN: buffer_store_dwordx4
616 ; GCN: buffer_store_dwordx4
618 define void @merge_global_store_8_constants_i32(i32 addrspace(1)* %out) {
619 store i32 34, i32 addrspace(1)* %out, align 4
620 %idx1 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 1
621 store i32 999, i32 addrspace(1)* %idx1, align 4
622 %idx2 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 2
623 store i32 65, i32 addrspace(1)* %idx2, align 4
624 %idx3 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 3
625 store i32 33, i32 addrspace(1)* %idx3, align 4
626 %idx4 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 4
627 store i32 98, i32 addrspace(1)* %idx4, align 4
628 %idx5 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 5
629 store i32 91, i32 addrspace(1)* %idx5, align 4
630 %idx6 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 6
631 store i32 212, i32 addrspace(1)* %idx6, align 4
632 %idx7 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 7
633 store i32 999, i32 addrspace(1)* %idx7, align 4
637 declare void @llvm.AMDGPU.barrier.local() #1
639 attributes #0 = { nounwind }
640 attributes #1 = { noduplicate nounwind }