[llvm-readobj] - Simplify stack-sizes.test test case.
[llvm-complete.git] / test / Transforms / CodeGenPrepare / ARM / sink-addrmode.ll
bloba26edb19da072a10aad607adc086d35e78354203
1 ; RUN: opt -S -codegenprepare -mtriple=thumbv7m -disable-complex-addr-modes=false -addr-sink-new-select=true -addr-sink-new-phis=true < %s | FileCheck %s
3 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
5 @gv1 = common global i32 0, align 4
6 @gv2 = common global i32 0, align 4
8 ; Phi selects between ptr and gep with ptr as base and constant offset
9 define void @test_phi_onegep_offset(i32* %ptr, i32 %value) {
10 ; CHECK-LABEL: @test_phi_onegep_offset
11 ; CHECK-NOT: phi i32* [ %ptr, %entry ], [ %gep, %if.then ]
12 ; CHECK: phi i32 [ 4, %if.then ], [ 0, %entry ]
13 entry:
14   %cmp = icmp sgt i32 %value, 0
15   br i1 %cmp, label %if.then, label %if.end
17 if.then:
18   %gep = getelementptr inbounds i32, i32* %ptr, i32 1
19   br label %if.end
21 if.end:
22   %phi = phi i32* [ %ptr, %entry ], [ %gep, %if.then ]
23   store i32 %value, i32* %phi, align 4
24   ret void
27 ; Phi selects between two geps with same base, different constant offsets
28 define void @test_phi_twogep_offset(i32* %ptr, i32 %value) {
29 ; CHECK-LABEL: @test_phi_twogep_offset
30 ; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
31 ; CHECK: phi i32 [ 8, %if.else ], [ 4, %if.then ]
32 entry:
33   %cmp = icmp sgt i32 %value, 0
34   br i1 %cmp, label %if.then, label %if.else
36 if.then:
37   %gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
38   br label %if.end
40 if.else:
41   %gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
42   br label %if.end
44 if.end:
45   %phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
46   store i32 %value, i32* %phi, align 4
47   ret void
50 ; Phi selects between ptr and gep with ptr as base and nonconstant offset
51 define void @test_phi_onegep_nonconst_offset(i32* %ptr, i32 %value, i32 %off) {
52 ; CHECK-LABEL: @test_phi_onegep_nonconst_offset
53 ; CHECK-NOT: phi i32* [ %ptr, %entry ], [ %gep, %if.then ]
54 ; CHECK: phi i32 [ %off, %if.then ], [ 0, %entry ]
55 entry:
56   %cmp = icmp sgt i32 %value, 0
57   br i1 %cmp, label %if.then, label %if.end
59 if.then:
60   %gep = getelementptr inbounds i32, i32* %ptr, i32 %off
61   br label %if.end
63 if.end:
64   %phi = phi i32* [ %ptr, %entry ], [ %gep, %if.then ]
65   store i32 %value, i32* %phi, align 4
66   ret void
69 ; Phi selects between two geps with same base, different nonconstant offsets
70 define void @test_phi_twogep_nonconst_offset(i32* %ptr, i32 %value, i32 %off1, i32 %off2) {
71 ; CHECK-LABEL: @test_phi_twogep_nonconst_offset
72 ; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
73 ; CHECK: phi i32 [ %off2, %if.else ], [ %off1, %if.then ]
74 entry:
75   %cmp = icmp sgt i32 %value, 0
76   br i1 %cmp, label %if.then, label %if.else
78 if.then:
79   %gep1 = getelementptr inbounds i32, i32* %ptr, i32 %off1
80   br label %if.end
82 if.else:
83   %gep2 = getelementptr inbounds i32, i32* %ptr, i32 %off2
84   br label %if.end
86 if.end:
87   %phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
88   store i32 %value, i32* %phi, align 4
89   ret void
92 ; Phi selects between two geps with different base, same constant offset
93 define void @test_phi_twogep_base(i32* %ptr1, i32* %ptr2, i32 %value) {
94 ; CHECK-LABEL: @test_phi_twogep_base
95 ; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
96 ; CHECK: phi i32* [ %ptr2, %if.else ], [ %ptr1, %if.then ]
97 entry:
98   %cmp = icmp sgt i32 %value, 0
99   br i1 %cmp, label %if.then, label %if.else
101 if.then:
102   %gep1 = getelementptr inbounds i32, i32* %ptr1, i32 1
103   br label %if.end
105 if.else:
106   %gep2 = getelementptr inbounds i32, i32* %ptr2, i32 1
107   br label %if.end
109 if.end:
110   %phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
111   store i32 %value, i32* %phi, align 4
112   ret void
115 ; Phi selects between two geps with different base global variables, same constant offset
116 define void @test_phi_twogep_base_gv(i32 %value) {
117 ; CHECK-LABEL: @test_phi_twogep_base_gv
118 ; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
119 ; CHECK: phi i32* [ @gv2, %if.else ], [ @gv1, %if.then ]
120 entry:
121   %cmp = icmp sgt i32 %value, 0
122   br i1 %cmp, label %if.then, label %if.else
124 if.then:
125   %gep1 = getelementptr inbounds i32, i32* @gv1, i32 1
126   br label %if.end
128 if.else:
129   %gep2 = getelementptr inbounds i32, i32* @gv2, i32 1
130   br label %if.end
132 if.end:
133   %phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
134   store i32 %value, i32* %phi, align 4
135   ret void
138 ; Phi selects between ptr and gep with ptr as base and constant offset
139 define void @test_select_onegep_offset(i32* %ptr, i32 %value) {
140 ; CHECK-LABEL: @test_select_onegep_offset
141 ; CHECK-NOT: select i1 %cmp, i32* %ptr, i32* %gep
142 ; CHECK: select i1 %cmp, i32 0, i32 4
143 entry:
144   %cmp = icmp sgt i32 %value, 0
145   %gep = getelementptr inbounds i32, i32* %ptr, i32 1
146   %select = select i1 %cmp, i32* %ptr, i32* %gep
147   store i32 %value, i32* %select, align 4
148   ret void
151 ; Select between two geps with same base, different constant offsets
152 define void @test_select_twogep_offset(i32* %ptr, i32 %value) {
153 ; CHECK-LABEL: @test_select_twogep_offset
154 ; CHECK-NOT: select i1 %cmp, i32* %gep1, i32* %gep2
155 ; CHECK: select i1 %cmp, i32 4, i32 8
156 entry:
157   %cmp = icmp sgt i32 %value, 0
158   %gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
159   %gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
160   %select = select i1 %cmp, i32* %gep1, i32* %gep2
161   store i32 %value, i32* %select, align 4
162   ret void
165 ; Select between ptr and gep with ptr as base and nonconstant offset
166 define void @test_select_onegep_nonconst_offset(i32* %ptr, i32 %value, i32 %off) {
167 ; CHECK-LABEL: @test_select_onegep_nonconst_offset
168 ; CHECK-NOT: select i1 %cmp, i32* %ptr, i32* %gep
169 ; CHECK: select i1 %cmp, i32 0, i32 %off
170 entry:
171   %cmp = icmp sgt i32 %value, 0
172   %gep = getelementptr inbounds i32, i32* %ptr, i32 %off
173   %select = select i1 %cmp, i32* %ptr, i32* %gep
174   store i32 %value, i32* %select, align 4
175   ret void
178 ; Select between two geps with same base, different nonconstant offsets
179 define void @test_select_twogep_nonconst_offset(i32* %ptr, i32 %value, i32 %off1, i32 %off2) {
180 ; CHECK-LABEL: @test_select_twogep_nonconst_offset
181 ; CHECK-NOT: select i1 %cmp, i32* %gep1, i32* %gep2
182 ; CHECK: select i1 %cmp, i32 %off1, i32 %off2
183 entry:
184   %cmp = icmp sgt i32 %value, 0
185   %gep1 = getelementptr inbounds i32, i32* %ptr, i32 %off1
186   %gep2 = getelementptr inbounds i32, i32* %ptr, i32 %off2
187   %select = select i1 %cmp, i32* %gep1, i32* %gep2
188   store i32 %value, i32* %select, align 4
189   ret void
192 ; Select between two geps with different base, same constant offset
193 define void @test_select_twogep_base(i32* %ptr1, i32* %ptr2, i32 %value) {
194 ; CHECK-LABEL: @test_select_twogep_base
195 ; CHECK-NOT: select i1 %cmp, i32* %gep1, i32* %gep2
196 ; CHECK: select i1 %cmp, i32* %ptr1, i32* %ptr2
197 entry:
198   %cmp = icmp sgt i32 %value, 0
199   %gep1 = getelementptr inbounds i32, i32* %ptr1, i32 1
200   %gep2 = getelementptr inbounds i32, i32* %ptr2, i32 1
201   %select = select i1 %cmp, i32* %gep1, i32* %gep2
202   store i32 %value, i32* %select, align 4
203   ret void
206 ; Select between two geps with different base global variables, same constant offset
207 define void @test_select_twogep_base_gv(i32 %value) {
208 ; CHECK-LABEL: @test_select_twogep_base_gv
209 ; CHECK-NOT: select i1 %cmp, i32* %gep1, i32* %gep2
210 ; CHECK: select i1 %cmp, i32* @gv1, i32* @gv2
211 entry:
212   %cmp = icmp sgt i32 %value, 0
213   %gep1 = getelementptr inbounds i32, i32* @gv1, i32 1
214   %gep2 = getelementptr inbounds i32, i32* @gv2, i32 1
215   %select = select i1 %cmp, i32* %gep1, i32* %gep2
216   store i32 %value, i32* %select, align 4
217   ret void
220 ; If the phi is in a different block to where the gep will be, the phi goes where
221 ; the original phi was not where the gep is.
222 ; CHECK-LABEL: @test_phi_different_block
223 ; CHECK-LABEL: if1.end
224 ; CHECK-NOT: phi i32* [ %ptr, %entry ], [ %gep, %if1.then ]
225 ; CHECK: phi i32 [ 4, %if1.then ], [ 0, %entry ]
226 define void @test_phi_different_block(i32* %ptr, i32 %value1, i32 %value2) {
227 entry:
228   %cmp1 = icmp sgt i32 %value1, 0
229   br i1 %cmp1, label %if1.then, label %if1.end
231 if1.then:
232   %gep = getelementptr inbounds i32, i32* %ptr, i32 1
233   br label %if1.end
235 if1.end:
236   %phi = phi i32* [ %ptr, %entry ], [ %gep, %if1.then ]
237   %cmp2 = icmp sgt i32 %value2, 0
238   br i1 %cmp2, label %if2.then, label %if2.end
240 if2.then:
241   store i32 %value1, i32* %ptr, align 4
242   br label %if2.end
244 if2.end:
245   store i32 %value2, i32* %phi, align 4
246   ret void
249 ; A phi with three incoming values should be optimised
250 ; CHECK-LABEL: @test_phi_threegep
251 ; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]
252 ; CHECK: phi i32 [ 12, %if.else.else ], [ 8, %if.else.then ], [ 4, %if.then ]
253 define void @test_phi_threegep(i32* %ptr, i32 %value1, i32 %value2) {
254 entry:
255   %cmp1 = icmp sgt i32 %value1, 0
256   br i1 %cmp1, label %if.then, label %if.else
258 if.then:
259   %gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
260   br label %if.end
262 if.else:
263   %cmp2 = icmp sgt i32 %value2, 0
264   br i1 %cmp2, label %if.else.then, label %if.else.else
266 if.else.then:
267   %gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
268   br label %if.end
270 if.else.else:
271   %gep3 = getelementptr inbounds i32, i32* %ptr, i32 3
272   br label %if.end
274 if.end:
275   %phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]
276   store i32 %value1, i32* %phi, align 4
277   ret void
280 ; A phi with two incoming values but three geps due to nesting should be
281 ; optimised
282 ; CHECK-LABEL: @test_phi_threegep_nested
283 ; CHECK: %[[PHI:[a-z0-9_]+]] = phi i32 [ 12, %if.else.else ], [ 8, %if.else.then ]
284 ; CHECK: phi i32 [ %[[PHI]], %if.else.end ], [ 4, %if.then ]
285 define void @test_phi_threegep_nested(i32* %ptr, i32 %value1, i32 %value2) {
286 entry:
287   %cmp1 = icmp sgt i32 %value1, 0
288   br i1 %cmp1, label %if.then, label %if.else
290 if.then:
291   %gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
292   br label %if.end
294 if.else:
295   %cmp2 = icmp sgt i32 %value2, 0
296   br i1 %cmp2, label %if.else.then, label %if.else.else
298 if.else.then:
299   %gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
300   br label %if.else.end
302 if.else.else:
303   %gep3 = getelementptr inbounds i32, i32* %ptr, i32 3
304   br label %if.else.end
306 if.else.end:
307   %gep4 = phi i32* [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]
308   store i32 %value2, i32* %ptr, align 4
309   br label %if.end
311 if.end:
312   %phi = phi i32* [ %gep1, %if.then ], [ %gep4, %if.else.end ]
313   store i32 %value1, i32* %phi, align 4
314   ret void
317 ; A nested select is expected to be optimised
318 ; CHECK-LABEL: @test_nested_select
319 ; CHECK: %[[SELECT:[a-z0-9_]+]] = select i1 %cmp2, i32 4, i32 8
320 ; CHECK: select i1 %cmp1, i32 4, i32 %[[SELECT]]
321 define void @test_nested_select(i32* %ptr, i32 %value1, i32 %value2) {
322 entry:
323   %gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
324   %gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
325   %cmp1 = icmp sgt i32 %value1, 0
326   %cmp2 = icmp sgt i32 %value2, 0
327   %select1 = select i1 %cmp2, i32* %gep1, i32* %gep2
328   %select2 = select i1 %cmp1, i32* %gep1, i32* %select1
329   store i32 %value1, i32* %select2, align 4
330   ret void
333 ; Scaling the offset by a different amount is expected not to be optimised
334 ; CHECK-LABEL: @test_select_different_scale
335 ; CHECK: select i1 %cmp, i32* %gep1, i32* %castgep
336 define void @test_select_different_scale(i32* %ptr, i32 %value, i32 %off) {
337 entry:
338   %cmp = icmp sgt i32 %value, 0
339   %castptr = bitcast i32* %ptr to i16*
340   %gep1 = getelementptr inbounds i32, i32* %ptr, i32 %off
341   %gep2 = getelementptr inbounds i16, i16* %castptr, i32 %off
342   %castgep = bitcast i16* %gep2 to i32*
343   %select = select i1 %cmp, i32* %gep1, i32* %castgep
344   store i32 %value, i32* %select, align 4
345   ret void
348 ; A select between two values is already the best we can do
349 ; CHECK-LABEL: @test_select_trivial
350 ; CHECK: select i1 %cmp, i32* %ptr1, i32* %ptr2
351 define void @test_select_trivial(i32* %ptr1, i32* %ptr2, i32 %value) {
352 entey:
353   %cmp = icmp sgt i32 %value, 0
354   %select = select i1 %cmp, i32* %ptr1, i32* %ptr2
355   store i32 %value, i32* %select, align 4
356   ret void
359 ; A select between two global variables is already the best we can do
360 ; CHECK-LABEL: @test_select_trivial_gv
361 ; CHECK: select i1 %cmp, i32* @gv1, i32* @gv2
362 define void @test_select_trivial_gv(i32 %value) {
363 entey:
364   %cmp = icmp sgt i32 %value, 0
365   %select = select i1 %cmp, i32* @gv1, i32* @gv2
366   store i32 %value, i32* %select, align 4
367   ret void
370 ; Same for a select between a value and global variable
371 ; CHECK-LABEL: @test_select_trivial_ptr_gv
372 ; CHECK: select i1 %cmp, i32* %ptr, i32* @gv2
373 define void @test_select_trivial_ptr_gv(i32* %ptr, i32 %value) {
374 entry:
375   %cmp = icmp sgt i32 %value, 0
376   %select = select i1 %cmp, i32* %ptr, i32* @gv2
377   store i32 %value, i32* %select, align 4
378   ret void
381 ; Same for a select between a global variable and null, though the test needs to
382 ; be a little more complicated to avoid dereferencing a potential null pointer
383 ; CHECK-LABEL: @test_select_trivial_gv_null
384 ; CHECK: select i1 %cmp.i, i32* @gv1, i32* null
385 define void @test_select_trivial_gv_null(){
386 entry:
387   %gv1_val = load i32, i32* @gv1, align 4
388   %cmp.i = icmp eq i32 %gv1_val, 0
389   %spec.select.i = select i1 %cmp.i, i32* @gv1, i32* null
390   br i1 %cmp.i, label %if.then, label %if.end
392 if.then:
393   %val = load i32, i32* %spec.select.i, align 4
394   %inc = add nsw i32 %val, 1
395   store i32 %inc, i32* %spec.select.i, align 4
396   br label %if.end
398 if.end:
399   ret void
402 ; Same for a select between a value and null
403 ; CHECK-LABEL: @test_select_trivial_ptr_null
404 ; CHECK: select i1 %cmp.i, i32* %ptr, i32* null
405 define void @test_select_trivial_ptr_null(i32* %ptr){
406 entry:
407   %gv1_val = load i32, i32* %ptr, align 4
408   %cmp.i = icmp eq i32 %gv1_val, 0
409   %spec.select.i = select i1 %cmp.i, i32* %ptr, i32* null
410   br i1 %cmp.i, label %if.then, label %if.end
412 if.then:
413   %val = load i32, i32* %spec.select.i, align 4
414   %inc = add nsw i32 %val, 1
415   store i32 %inc, i32* %spec.select.i, align 4
416   br label %if.end
418 if.end:
419   ret void