R600/SI: Add an extra check line to make test more strict
[oota-llvm.git] / test / CodeGen / R600 / shl_add_ptr.ll
1 ; RUN: llc -march=r600 -mcpu=bonaire -verify-machineinstrs -mattr=+load-store-opt -enable-misched < %s | FileCheck -check-prefix=SI %s
2
3 ; Test that doing a shift of a pointer with a constant add will be
4 ; folded into the constant offset addressing mode even if the add has
5 ; multiple uses. This is relevant to accessing 2 separate, adjacent
6 ; LDS globals.
7
8
9 declare i32 @llvm.r600.read.tidig.x() #1
10
11 @lds0 = addrspace(3) global [512 x float] zeroinitializer, align 4
12 @lds1 = addrspace(3) global [512 x float] zeroinitializer, align 4
13
14
15 ; Make sure the (add tid, 2) << 2 gets folded into the ds's offset as (tid << 2) + 8
16
17 ; SI-LABEL: {{^}}load_shl_base_lds_0:
18 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
19 ; SI: DS_READ_B32 {{v[0-9]+}}, [[PTR]] offset:8 [M0]
20 ; SI: S_ENDPGM
21 define void @load_shl_base_lds_0(float addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
22   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
23   %idx.0 = add nsw i32 %tid.x, 2
24   %arrayidx0 = getelementptr inbounds [512 x float] addrspace(3)* @lds0, i32 0, i32 %idx.0
25   %val0 = load float addrspace(3)* %arrayidx0, align 4
26   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
27   store float %val0, float addrspace(1)* %out
28   ret void
29 }
30
31 ; Make sure once the first use is folded into the addressing mode, the
32 ; remaining add use goes through the normal shl + add constant fold.
33
34 ; SI-LABEL: {{^}}load_shl_base_lds_1:
35 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
36 ; SI: DS_READ_B32 [[RESULT:v[0-9]+]], [[PTR]] offset:8 [M0]
37 ; SI: V_ADD_I32_e32 [[ADDUSE:v[0-9]+]], 8, v{{[0-9]+}}
38 ; SI-DAG: BUFFER_STORE_DWORD [[RESULT]]
39 ; SI-DAG: BUFFER_STORE_DWORD [[ADDUSE]]
40 ; SI: S_ENDPGM
41 define void @load_shl_base_lds_1(float addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
42   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
43   %idx.0 = add nsw i32 %tid.x, 2
44   %arrayidx0 = getelementptr inbounds [512 x float] addrspace(3)* @lds0, i32 0, i32 %idx.0
45   %val0 = load float addrspace(3)* %arrayidx0, align 4
46   %shl_add_use = shl i32 %idx.0, 2
47   store i32 %shl_add_use, i32 addrspace(1)* %add_use, align 4
48   store float %val0, float addrspace(1)* %out
49   ret void
50 }
51
52 @maxlds = addrspace(3) global [65536 x i8] zeroinitializer, align 4
53
54 ; SI-LABEL: {{^}}load_shl_base_lds_max_offset
55 ; SI: DS_READ_U8 v{{[0-9]+}}, v{{[0-9]+}} offset:65535
56 ; SI: S_ENDPGM
57 define void @load_shl_base_lds_max_offset(i8 addrspace(1)* %out, i8 addrspace(3)* %lds, i32 addrspace(1)* %add_use) #0 {
58   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
59   %idx.0 = add nsw i32 %tid.x, 65535
60   %arrayidx0 = getelementptr inbounds [65536 x i8] addrspace(3)* @maxlds, i32 0, i32 %idx.0
61   %val0 = load i8 addrspace(3)* %arrayidx0
62   store i32 %idx.0, i32 addrspace(1)* %add_use
63   store i8 %val0, i8 addrspace(1)* %out
64   ret void
65 }
66
67 ; The two globals are placed adjacent in memory, so the same base
68 ; pointer can be used with an offset into the second one.
69
70 ; SI-LABEL: {{^}}load_shl_base_lds_2:
71 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
72 ; SI-NEXT: DS_READ2ST64_B32 {{v\[[0-9]+:[0-9]+\]}}, [[PTR]] offset0:1 offset1:9 [M0]
73 ; SI: S_ENDPGM
74 define void @load_shl_base_lds_2(float addrspace(1)* %out) #0 {
75   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
76   %idx.0 = add nsw i32 %tid.x, 64
77   %arrayidx0 = getelementptr inbounds [512 x float] addrspace(3)* @lds0, i32 0, i32 %idx.0
78   %val0 = load float addrspace(3)* %arrayidx0, align 4
79   %arrayidx1 = getelementptr inbounds [512 x float] addrspace(3)* @lds1, i32 0, i32 %idx.0
80   %val1 = load float addrspace(3)* %arrayidx1, align 4
81   %sum = fadd float %val0, %val1
82   store float %sum, float addrspace(1)* %out, align 4
83   ret void
84 }
85
86 ; SI-LABEL: {{^}}store_shl_base_lds_0:
87 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
88 ; SI: DS_WRITE_B32 [[PTR]], {{v[0-9]+}} offset:8 [M0]
89 ; SI: S_ENDPGM
90 define void @store_shl_base_lds_0(float addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
91   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
92   %idx.0 = add nsw i32 %tid.x, 2
93   %arrayidx0 = getelementptr inbounds [512 x float] addrspace(3)* @lds0, i32 0, i32 %idx.0
94   store float 1.0, float addrspace(3)* %arrayidx0, align 4
95   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
96   ret void
97 }
98
99
100 ; --------------------------------------------------------------------------------
101 ; Atomics.
102
103 @lds2 = addrspace(3) global [512 x i32] zeroinitializer, align 4
104
105 ; define void @atomic_load_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
106 ;   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
107 ;   %idx.0 = add nsw i32 %tid.x, 2
108 ;   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
109 ;   %val = load atomic i32 addrspace(3)* %arrayidx0 seq_cst, align 4
110 ;   store i32 %val, i32 addrspace(1)* %out, align 4
111 ;   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
112 ;   ret void
113 ; }
114
115
116 ; SI-LABEL: {{^}}atomic_cmpxchg_shl_base_lds_0:
117 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
118 ; SI: DS_CMPST_RTN_B32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}}, {{v[0-9]+}} offset:8
119 ; SI: S_ENDPGM
120 define void @atomic_cmpxchg_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use, i32 %swap) #0 {
121   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
122   %idx.0 = add nsw i32 %tid.x, 2
123   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
124   %pair = cmpxchg i32 addrspace(3)* %arrayidx0, i32 7, i32 %swap seq_cst monotonic
125   %result = extractvalue { i32, i1 } %pair, 0
126   store i32 %result, i32 addrspace(1)* %out, align 4
127   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
128   ret void
129 }
130
131 ; SI-LABEL: {{^}}atomic_swap_shl_base_lds_0:
132 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
133 ; SI: DS_WRXCHG_RTN_B32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
134 ; SI: S_ENDPGM
135 define void @atomic_swap_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
136   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
137   %idx.0 = add nsw i32 %tid.x, 2
138   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
139   %val = atomicrmw xchg i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
140   store i32 %val, i32 addrspace(1)* %out, align 4
141   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
142   ret void
143 }
144
145 ; SI-LABEL: {{^}}atomic_add_shl_base_lds_0:
146 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
147 ; SI: DS_ADD_RTN_U32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
148 ; SI: S_ENDPGM
149 define void @atomic_add_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
150   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
151   %idx.0 = add nsw i32 %tid.x, 2
152   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
153   %val = atomicrmw add i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
154   store i32 %val, i32 addrspace(1)* %out, align 4
155   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
156   ret void
157 }
158
159 ; SI-LABEL: {{^}}atomic_sub_shl_base_lds_0:
160 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
161 ; SI: DS_SUB_RTN_U32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
162 ; SI: S_ENDPGM
163 define void @atomic_sub_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
164   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
165   %idx.0 = add nsw i32 %tid.x, 2
166   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
167   %val = atomicrmw sub i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
168   store i32 %val, i32 addrspace(1)* %out, align 4
169   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
170   ret void
171 }
172
173 ; SI-LABEL: {{^}}atomic_and_shl_base_lds_0:
174 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
175 ; SI: DS_AND_RTN_B32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
176 ; SI: S_ENDPGM
177 define void @atomic_and_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
178   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
179   %idx.0 = add nsw i32 %tid.x, 2
180   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
181   %val = atomicrmw and i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
182   store i32 %val, i32 addrspace(1)* %out, align 4
183   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
184   ret void
185 }
186
187 ; SI-LABEL: {{^}}atomic_or_shl_base_lds_0:
188 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
189 ; SI: DS_OR_RTN_B32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
190 ; SI: S_ENDPGM
191 define void @atomic_or_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
192   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
193   %idx.0 = add nsw i32 %tid.x, 2
194   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
195   %val = atomicrmw or i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
196   store i32 %val, i32 addrspace(1)* %out, align 4
197   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
198   ret void
199 }
200
201 ; SI-LABEL: {{^}}atomic_xor_shl_base_lds_0:
202 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
203 ; SI: DS_XOR_RTN_B32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
204 ; SI: S_ENDPGM
205 define void @atomic_xor_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
206   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
207   %idx.0 = add nsw i32 %tid.x, 2
208   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
209   %val = atomicrmw xor i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
210   store i32 %val, i32 addrspace(1)* %out, align 4
211   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
212   ret void
213 }
214
215 ; define void @atomic_nand_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
216 ;   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
217 ;   %idx.0 = add nsw i32 %tid.x, 2
218 ;   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
219 ;   %val = atomicrmw nand i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
220 ;   store i32 %val, i32 addrspace(1)* %out, align 4
221 ;   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
222 ;   ret void
223 ; }
224
225 ; SI-LABEL: {{^}}atomic_min_shl_base_lds_0:
226 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
227 ; SI: DS_MIN_RTN_I32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
228 ; SI: S_ENDPGM
229 define void @atomic_min_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
230   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
231   %idx.0 = add nsw i32 %tid.x, 2
232   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
233   %val = atomicrmw min i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
234   store i32 %val, i32 addrspace(1)* %out, align 4
235   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
236   ret void
237 }
238
239 ; SI-LABEL: {{^}}atomic_max_shl_base_lds_0:
240 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
241 ; SI: DS_MAX_RTN_I32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
242 ; SI: S_ENDPGM
243 define void @atomic_max_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
244   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
245   %idx.0 = add nsw i32 %tid.x, 2
246   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
247   %val = atomicrmw max i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
248   store i32 %val, i32 addrspace(1)* %out, align 4
249   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
250   ret void
251 }
252
253 ; SI-LABEL: {{^}}atomic_umin_shl_base_lds_0:
254 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
255 ; SI: DS_MIN_RTN_U32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
256 ; SI: S_ENDPGM
257 define void @atomic_umin_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
258   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
259   %idx.0 = add nsw i32 %tid.x, 2
260   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
261   %val = atomicrmw umin i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
262   store i32 %val, i32 addrspace(1)* %out, align 4
263   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
264   ret void
265 }
266
267 ; SI-LABEL: {{^}}atomic_umax_shl_base_lds_0:
268 ; SI: V_LSHLREV_B32_e32 [[PTR:v[0-9]+]], 2, {{v[0-9]+}}
269 ; SI: DS_MAX_RTN_U32 {{v[0-9]+}}, [[PTR]], {{v[0-9]+}} offset:8
270 ; SI: S_ENDPGM
271 define void @atomic_umax_shl_base_lds_0(i32 addrspace(1)* %out, i32 addrspace(1)* %add_use) #0 {
272   %tid.x = tail call i32 @llvm.r600.read.tidig.x() #1
273   %idx.0 = add nsw i32 %tid.x, 2
274   %arrayidx0 = getelementptr inbounds [512 x i32] addrspace(3)* @lds2, i32 0, i32 %idx.0
275   %val = atomicrmw umax i32 addrspace(3)* %arrayidx0, i32 3 seq_cst
276   store i32 %val, i32 addrspace(1)* %out, align 4
277   store i32 %idx.0, i32 addrspace(1)* %add_use, align 4
278   ret void
279 }
280
281 attributes #0 = { nounwind }
282 attributes #1 = { nounwind readnone }