[InstCombine] Signed saturation patterns
[llvm-core.git] / test / CodeGen / ARM / ParallelDSP / multi-use-loads.ll
blob6949b4a7048c1a42cc8f768c7c8b518cf8b5f1f2
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -O3 -mtriple=arm-arm-eabi -mcpu=cortex-m33 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-LE
3 ; RUN: llc -O3 -mtriple=armeb-arm-eabi -mcpu=cortex-m33 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-BE
5 define i32 @add_user(i32 %arg, i32* nocapture readnone %arg1, i16* nocapture readonly %arg2, i16* nocapture readonly %arg3) {
6 ; CHECK-LE-LABEL: add_user:
7 ; CHECK-LE:       @ %bb.0: @ %entry
8 ; CHECK-LE-NEXT:    .save {r4, lr}
9 ; CHECK-LE-NEXT:    push {r4, lr}
10 ; CHECK-LE-NEXT:    cmp r0, #1
11 ; CHECK-LE-NEXT:    blt .LBB0_4
12 ; CHECK-LE-NEXT:  @ %bb.1: @ %for.body.preheader
13 ; CHECK-LE-NEXT:    subs r2, #2
14 ; CHECK-LE-NEXT:    subs r3, #2
15 ; CHECK-LE-NEXT:    mov.w r12, #0
16 ; CHECK-LE-NEXT:    movs r1, #0
17 ; CHECK-LE-NEXT:    .p2align 2
18 ; CHECK-LE-NEXT:  .LBB0_2: @ %for.body
19 ; CHECK-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
20 ; CHECK-LE-NEXT:    ldr lr, [r3, #2]!
21 ; CHECK-LE-NEXT:    ldr r4, [r2, #2]!
22 ; CHECK-LE-NEXT:    subs r0, #1
23 ; CHECK-LE-NEXT:    smlad r12, r4, lr, r12
24 ; CHECK-LE-NEXT:    sxtah r1, r1, lr
25 ; CHECK-LE-NEXT:    bne .LBB0_2
26 ; CHECK-LE-NEXT:  @ %bb.3: @ %for.cond.cleanup
27 ; CHECK-LE-NEXT:    add.w r0, r12, r1
28 ; CHECK-LE-NEXT:    pop {r4, pc}
29 ; CHECK-LE-NEXT:  .LBB0_4:
30 ; CHECK-LE-NEXT:    mov.w r12, #0
31 ; CHECK-LE-NEXT:    movs r1, #0
32 ; CHECK-LE-NEXT:    add.w r0, r12, r1
33 ; CHECK-LE-NEXT:    pop {r4, pc}
35 ; CHECK-BE-LABEL: add_user:
36 ; CHECK-BE:       @ %bb.0: @ %entry
37 ; CHECK-BE-NEXT:    .save {r4, r5, r6, lr}
38 ; CHECK-BE-NEXT:    push {r4, r5, r6, lr}
39 ; CHECK-BE-NEXT:    cmp r0, #1
40 ; CHECK-BE-NEXT:    blt .LBB0_4
41 ; CHECK-BE-NEXT:  @ %bb.1: @ %for.body.preheader
42 ; CHECK-BE-NEXT:    subs r2, #2
43 ; CHECK-BE-NEXT:    subs r3, #2
44 ; CHECK-BE-NEXT:    mov.w r12, #0
45 ; CHECK-BE-NEXT:    movs r1, #0
46 ; CHECK-BE-NEXT:    .p2align 2
47 ; CHECK-BE-NEXT:  .LBB0_2: @ %for.body
48 ; CHECK-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
49 ; CHECK-BE-NEXT:    ldrsh lr, [r3, #2]!
50 ; CHECK-BE-NEXT:    ldrsh r5, [r2, #2]!
51 ; CHECK-BE-NEXT:    ldrsh.w r4, [r3, #2]
52 ; CHECK-BE-NEXT:    ldrsh.w r6, [r2, #2]
53 ; CHECK-BE-NEXT:    smlabb r5, r5, lr, r12
54 ; CHECK-BE-NEXT:    add r1, lr
55 ; CHECK-BE-NEXT:    subs r0, #1
56 ; CHECK-BE-NEXT:    smlabb r12, r6, r4, r5
57 ; CHECK-BE-NEXT:    bne .LBB0_2
58 ; CHECK-BE-NEXT:  @ %bb.3: @ %for.cond.cleanup
59 ; CHECK-BE-NEXT:    add.w r0, r12, r1
60 ; CHECK-BE-NEXT:    pop {r4, r5, r6, pc}
61 ; CHECK-BE-NEXT:  .LBB0_4:
62 ; CHECK-BE-NEXT:    mov.w r12, #0
63 ; CHECK-BE-NEXT:    movs r1, #0
64 ; CHECK-BE-NEXT:    add.w r0, r12, r1
65 ; CHECK-BE-NEXT:    pop {r4, r5, r6, pc}
66 entry:
67   %cmp24 = icmp sgt i32 %arg, 0
68   br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup
70 for.body.preheader:
71   %.pre = load i16, i16* %arg3, align 2
72   %.pre27 = load i16, i16* %arg2, align 2
73   br label %for.body
75 for.cond.cleanup:
76   %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
77   %count.final = phi i32 [ 0, %entry ], [ %count.next, %for.body ]
78   %res = add i32 %mac1.0.lcssa, %count.final
79   ret i32 %res
81 for.body:
82   %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
83   %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
84   %count = phi i32 [ %count.next, %for.body ], [ 0, %for.body.preheader ]
85   %arrayidx = getelementptr inbounds i16, i16* %arg3, i32 %i.025
86   %0 = load i16, i16* %arrayidx, align 2
87   %add = add nuw nsw i32 %i.025, 1
88   %arrayidx1 = getelementptr inbounds i16, i16* %arg3, i32 %add
89   %1 = load i16, i16* %arrayidx1, align 2
90   %arrayidx3 = getelementptr inbounds i16, i16* %arg2, i32 %i.025
91   %2 = load i16, i16* %arrayidx3, align 2
92   %conv = sext i16 %2 to i32
93   %conv4 = sext i16 %0 to i32
94   %count.next = add i32 %conv4, %count
95   %mul = mul nsw i32 %conv, %conv4
96   %arrayidx6 = getelementptr inbounds i16, i16* %arg2, i32 %add
97   %3 = load i16, i16* %arrayidx6, align 2
98   %conv7 = sext i16 %3 to i32
99   %conv8 = sext i16 %1 to i32
100   %mul9 = mul nsw i32 %conv7, %conv8
101   %add10 = add i32 %mul, %mac1.026
102   %add11 = add i32 %mul9, %add10
103   %exitcond = icmp ne i32 %add, %arg
104   br i1 %exitcond, label %for.body, label %for.cond.cleanup
107 define i32 @mul_bottom_user(i32 %arg, i32* nocapture readnone %arg1, i16* nocapture readonly %arg2, i16* nocapture readonly %arg3) {
108 ; CHECK-LE-LABEL: mul_bottom_user:
109 ; CHECK-LE:       @ %bb.0: @ %entry
110 ; CHECK-LE-NEXT:    .save {r4, r5, r7, lr}
111 ; CHECK-LE-NEXT:    push {r4, r5, r7, lr}
112 ; CHECK-LE-NEXT:    cmp r0, #1
113 ; CHECK-LE-NEXT:    blt .LBB1_4
114 ; CHECK-LE-NEXT:  @ %bb.1: @ %for.body.preheader
115 ; CHECK-LE-NEXT:    sub.w lr, r2, #2
116 ; CHECK-LE-NEXT:    subs r3, #2
117 ; CHECK-LE-NEXT:    mov.w r12, #0
118 ; CHECK-LE-NEXT:    movs r1, #0
119 ; CHECK-LE-NEXT:    .p2align 2
120 ; CHECK-LE-NEXT:  .LBB1_2: @ %for.body
121 ; CHECK-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
122 ; CHECK-LE-NEXT:    ldr r2, [r3, #2]!
123 ; CHECK-LE-NEXT:    ldr r4, [lr, #2]!
124 ; CHECK-LE-NEXT:    sxth r5, r2
125 ; CHECK-LE-NEXT:    smlad r12, r4, r2, r12
126 ; CHECK-LE-NEXT:    subs r0, #1
127 ; CHECK-LE-NEXT:    mul r1, r5, r1
128 ; CHECK-LE-NEXT:    bne .LBB1_2
129 ; CHECK-LE-NEXT:  @ %bb.3: @ %for.cond.cleanup
130 ; CHECK-LE-NEXT:    add.w r0, r12, r1
131 ; CHECK-LE-NEXT:    pop {r4, r5, r7, pc}
132 ; CHECK-LE-NEXT:  .LBB1_4:
133 ; CHECK-LE-NEXT:    mov.w r12, #0
134 ; CHECK-LE-NEXT:    movs r1, #0
135 ; CHECK-LE-NEXT:    add.w r0, r12, r1
136 ; CHECK-LE-NEXT:    pop {r4, r5, r7, pc}
138 ; CHECK-BE-LABEL: mul_bottom_user:
139 ; CHECK-BE:       @ %bb.0: @ %entry
140 ; CHECK-BE-NEXT:    .save {r4, r5, r6, lr}
141 ; CHECK-BE-NEXT:    push {r4, r5, r6, lr}
142 ; CHECK-BE-NEXT:    cmp r0, #1
143 ; CHECK-BE-NEXT:    blt .LBB1_4
144 ; CHECK-BE-NEXT:  @ %bb.1: @ %for.body.preheader
145 ; CHECK-BE-NEXT:    subs r2, #2
146 ; CHECK-BE-NEXT:    subs r3, #2
147 ; CHECK-BE-NEXT:    mov.w r12, #0
148 ; CHECK-BE-NEXT:    movs r1, #0
149 ; CHECK-BE-NEXT:    .p2align 2
150 ; CHECK-BE-NEXT:  .LBB1_2: @ %for.body
151 ; CHECK-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
152 ; CHECK-BE-NEXT:    ldrsh lr, [r3, #2]!
153 ; CHECK-BE-NEXT:    ldrsh r4, [r2, #2]!
154 ; CHECK-BE-NEXT:    ldrsh.w r5, [r3, #2]
155 ; CHECK-BE-NEXT:    ldrsh.w r6, [r2, #2]
156 ; CHECK-BE-NEXT:    smlabb r4, r4, lr, r12
157 ; CHECK-BE-NEXT:    smlabb r12, r6, r5, r4
158 ; CHECK-BE-NEXT:    subs r0, #1
159 ; CHECK-BE-NEXT:    mul r1, lr, r1
160 ; CHECK-BE-NEXT:    bne .LBB1_2
161 ; CHECK-BE-NEXT:  @ %bb.3: @ %for.cond.cleanup
162 ; CHECK-BE-NEXT:    add.w r0, r12, r1
163 ; CHECK-BE-NEXT:    pop {r4, r5, r6, pc}
164 ; CHECK-BE-NEXT:  .LBB1_4:
165 ; CHECK-BE-NEXT:    mov.w r12, #0
166 ; CHECK-BE-NEXT:    movs r1, #0
167 ; CHECK-BE-NEXT:    add.w r0, r12, r1
168 ; CHECK-BE-NEXT:    pop {r4, r5, r6, pc}
169 entry:
170   %cmp24 = icmp sgt i32 %arg, 0
171   br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup
173 for.body.preheader:
174   %.pre = load i16, i16* %arg3, align 2
175   %.pre27 = load i16, i16* %arg2, align 2
176   br label %for.body
178 for.cond.cleanup:
179   %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
180   %count.final = phi i32 [ 0, %entry ], [ %count.next, %for.body ]
181   %res = add i32 %mac1.0.lcssa, %count.final
182   ret i32 %res
184 for.body:
185   %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
186   %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
187   %count = phi i32 [ %count.next, %for.body ], [ 0, %for.body.preheader ]
188   %arrayidx = getelementptr inbounds i16, i16* %arg3, i32 %i.025
189   %0 = load i16, i16* %arrayidx, align 2
190   %add = add nuw nsw i32 %i.025, 1
191   %arrayidx1 = getelementptr inbounds i16, i16* %arg3, i32 %add
192   %1 = load i16, i16* %arrayidx1, align 2
193   %arrayidx3 = getelementptr inbounds i16, i16* %arg2, i32 %i.025
194   %2 = load i16, i16* %arrayidx3, align 2
195   %conv = sext i16 %2 to i32
196   %conv4 = sext i16 %0 to i32
197   %mul = mul nsw i32 %conv, %conv4
198   %arrayidx6 = getelementptr inbounds i16, i16* %arg2, i32 %add
199   %3 = load i16, i16* %arrayidx6, align 2
200   %conv7 = sext i16 %3 to i32
201   %conv8 = sext i16 %1 to i32
202   %mul9 = mul nsw i32 %conv7, %conv8
203   %add10 = add i32 %mul, %mac1.026
204   %add11 = add i32 %mul9, %add10
205   %count.next = mul i32 %conv4, %count
206   %exitcond = icmp ne i32 %add, %arg
207   br i1 %exitcond, label %for.body, label %for.cond.cleanup
210 define i32 @mul_top_user(i32 %arg, i32* nocapture readnone %arg1, i16* nocapture readonly %arg2, i16* nocapture readonly %arg3) {
211 ; CHECK-LE-LABEL: mul_top_user:
212 ; CHECK-LE:       @ %bb.0: @ %entry
213 ; CHECK-LE-NEXT:    .save {r4, lr}
214 ; CHECK-LE-NEXT:    push {r4, lr}
215 ; CHECK-LE-NEXT:    cmp r0, #1
216 ; CHECK-LE-NEXT:    blt .LBB2_4
217 ; CHECK-LE-NEXT:  @ %bb.1: @ %for.body.preheader
218 ; CHECK-LE-NEXT:    subs r2, #2
219 ; CHECK-LE-NEXT:    subs r3, #2
220 ; CHECK-LE-NEXT:    mov.w r12, #0
221 ; CHECK-LE-NEXT:    movs r1, #0
222 ; CHECK-LE-NEXT:    .p2align 2
223 ; CHECK-LE-NEXT:  .LBB2_2: @ %for.body
224 ; CHECK-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
225 ; CHECK-LE-NEXT:    ldr lr, [r3, #2]!
226 ; CHECK-LE-NEXT:    ldr r4, [r2, #2]!
227 ; CHECK-LE-NEXT:    subs r0, #1
228 ; CHECK-LE-NEXT:    smlad r12, r4, lr, r12
229 ; CHECK-LE-NEXT:    asr.w r4, r4, #16
230 ; CHECK-LE-NEXT:    mul r1, r4, r1
231 ; CHECK-LE-NEXT:    bne .LBB2_2
232 ; CHECK-LE-NEXT:  @ %bb.3: @ %for.cond.cleanup
233 ; CHECK-LE-NEXT:    add.w r0, r12, r1
234 ; CHECK-LE-NEXT:    pop {r4, pc}
235 ; CHECK-LE-NEXT:  .LBB2_4:
236 ; CHECK-LE-NEXT:    mov.w r12, #0
237 ; CHECK-LE-NEXT:    movs r1, #0
238 ; CHECK-LE-NEXT:    add.w r0, r12, r1
239 ; CHECK-LE-NEXT:    pop {r4, pc}
241 ; CHECK-BE-LABEL: mul_top_user:
242 ; CHECK-BE:       @ %bb.0: @ %entry
243 ; CHECK-BE-NEXT:    .save {r4, r5, r6, lr}
244 ; CHECK-BE-NEXT:    push {r4, r5, r6, lr}
245 ; CHECK-BE-NEXT:    cmp r0, #1
246 ; CHECK-BE-NEXT:    blt .LBB2_4
247 ; CHECK-BE-NEXT:  @ %bb.1: @ %for.body.preheader
248 ; CHECK-BE-NEXT:    subs r2, #2
249 ; CHECK-BE-NEXT:    subs r3, #2
250 ; CHECK-BE-NEXT:    mov.w r12, #0
251 ; CHECK-BE-NEXT:    movs r1, #0
252 ; CHECK-BE-NEXT:    .p2align 2
253 ; CHECK-BE-NEXT:  .LBB2_2: @ %for.body
254 ; CHECK-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
255 ; CHECK-BE-NEXT:    ldrsh lr, [r3, #2]!
256 ; CHECK-BE-NEXT:    ldrsh r4, [r2, #2]!
257 ; CHECK-BE-NEXT:    ldrsh.w r5, [r3, #2]
258 ; CHECK-BE-NEXT:    ldrsh.w r6, [r2, #2]
259 ; CHECK-BE-NEXT:    smlabb r4, r4, lr, r12
260 ; CHECK-BE-NEXT:    smlabb r12, r6, r5, r4
261 ; CHECK-BE-NEXT:    subs r0, #1
262 ; CHECK-BE-NEXT:    mul r1, r6, r1
263 ; CHECK-BE-NEXT:    bne .LBB2_2
264 ; CHECK-BE-NEXT:  @ %bb.3: @ %for.cond.cleanup
265 ; CHECK-BE-NEXT:    add.w r0, r12, r1
266 ; CHECK-BE-NEXT:    pop {r4, r5, r6, pc}
267 ; CHECK-BE-NEXT:  .LBB2_4:
268 ; CHECK-BE-NEXT:    mov.w r12, #0
269 ; CHECK-BE-NEXT:    movs r1, #0
270 ; CHECK-BE-NEXT:    add.w r0, r12, r1
271 ; CHECK-BE-NEXT:    pop {r4, r5, r6, pc}
272 entry:
273   %cmp24 = icmp sgt i32 %arg, 0
274   br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup
276 for.body.preheader:
277   %.pre = load i16, i16* %arg3, align 2
278   %.pre27 = load i16, i16* %arg2, align 2
279   br label %for.body
281 for.cond.cleanup:
282   %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
283   %count.final = phi i32 [ 0, %entry ], [ %count.next, %for.body ]
284   %res = add i32 %mac1.0.lcssa, %count.final
285   ret i32 %res
287 for.body:
288   %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
289   %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
290   %count = phi i32 [ %count.next, %for.body ], [ 0, %for.body.preheader ]
291   %arrayidx = getelementptr inbounds i16, i16* %arg3, i32 %i.025
292   %0 = load i16, i16* %arrayidx, align 2
293   %add = add nuw nsw i32 %i.025, 1
294   %arrayidx1 = getelementptr inbounds i16, i16* %arg3, i32 %add
295   %1 = load i16, i16* %arrayidx1, align 2
296   %arrayidx3 = getelementptr inbounds i16, i16* %arg2, i32 %i.025
297   %2 = load i16, i16* %arrayidx3, align 2
298   %conv = sext i16 %2 to i32
299   %conv4 = sext i16 %0 to i32
300   %mul = mul nsw i32 %conv, %conv4
301   %arrayidx6 = getelementptr inbounds i16, i16* %arg2, i32 %add
302   %3 = load i16, i16* %arrayidx6, align 2
303   %conv7 = sext i16 %3 to i32
304   %conv8 = sext i16 %1 to i32
305   %mul9 = mul nsw i32 %conv7, %conv8
306   %add10 = add i32 %mul, %mac1.026
307   %add11 = add i32 %mul9, %add10
308   %count.next = mul i32 %conv7, %count
309   %exitcond = icmp ne i32 %add, %arg
310   br i1 %exitcond, label %for.body, label %for.cond.cleanup
313 define i32 @and_user(i32 %arg, i32* nocapture readnone %arg1, i16* nocapture readonly %arg2, i16* nocapture readonly %arg3) {
314 ; CHECK-LE-LABEL: and_user:
315 ; CHECK-LE:       @ %bb.0: @ %entry
316 ; CHECK-LE-NEXT:    .save {r4, lr}
317 ; CHECK-LE-NEXT:    push {r4, lr}
318 ; CHECK-LE-NEXT:    cmp r0, #1
319 ; CHECK-LE-NEXT:    blt .LBB3_4
320 ; CHECK-LE-NEXT:  @ %bb.1: @ %for.body.preheader
321 ; CHECK-LE-NEXT:    sub.w lr, r2, #2
322 ; CHECK-LE-NEXT:    subs r3, #2
323 ; CHECK-LE-NEXT:    mov.w r12, #0
324 ; CHECK-LE-NEXT:    movs r1, #0
325 ; CHECK-LE-NEXT:    .p2align 2
326 ; CHECK-LE-NEXT:  .LBB3_2: @ %for.body
327 ; CHECK-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
328 ; CHECK-LE-NEXT:    ldr r2, [r3, #2]!
329 ; CHECK-LE-NEXT:    ldr r4, [lr, #2]!
330 ; CHECK-LE-NEXT:    subs r0, #1
331 ; CHECK-LE-NEXT:    smlad r12, r4, r2, r12
332 ; CHECK-LE-NEXT:    uxth r2, r2
333 ; CHECK-LE-NEXT:    mul r1, r2, r1
334 ; CHECK-LE-NEXT:    bne .LBB3_2
335 ; CHECK-LE-NEXT:  @ %bb.3: @ %for.cond.cleanup
336 ; CHECK-LE-NEXT:    add.w r0, r12, r1
337 ; CHECK-LE-NEXT:    pop {r4, pc}
338 ; CHECK-LE-NEXT:  .LBB3_4:
339 ; CHECK-LE-NEXT:    mov.w r12, #0
340 ; CHECK-LE-NEXT:    movs r1, #0
341 ; CHECK-LE-NEXT:    add.w r0, r12, r1
342 ; CHECK-LE-NEXT:    pop {r4, pc}
344 ; CHECK-BE-LABEL: and_user:
345 ; CHECK-BE:       @ %bb.0: @ %entry
346 ; CHECK-BE-NEXT:    .save {r4, r5, r6, r7, lr}
347 ; CHECK-BE-NEXT:    push {r4, r5, r6, r7, lr}
348 ; CHECK-BE-NEXT:    cmp r0, #1
349 ; CHECK-BE-NEXT:    blt .LBB3_4
350 ; CHECK-BE-NEXT:  @ %bb.1: @ %for.body.preheader
351 ; CHECK-BE-NEXT:    subs r2, #2
352 ; CHECK-BE-NEXT:    subs r3, #2
353 ; CHECK-BE-NEXT:    mov.w r12, #0
354 ; CHECK-BE-NEXT:    movs r1, #0
355 ; CHECK-BE-NEXT:    .p2align 2
356 ; CHECK-BE-NEXT:  .LBB3_2: @ %for.body
357 ; CHECK-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
358 ; CHECK-BE-NEXT:    ldrsh lr, [r3, #2]!
359 ; CHECK-BE-NEXT:    ldrsh r5, [r2, #2]!
360 ; CHECK-BE-NEXT:    ldrsh.w r4, [r3, #2]
361 ; CHECK-BE-NEXT:    ldrsh.w r7, [r2, #2]
362 ; CHECK-BE-NEXT:    uxth.w r6, lr
363 ; CHECK-BE-NEXT:    smlabb r5, r5, lr, r12
364 ; CHECK-BE-NEXT:    smlabb r12, r7, r4, r5
365 ; CHECK-BE-NEXT:    subs r0, #1
366 ; CHECK-BE-NEXT:    mul r1, r6, r1
367 ; CHECK-BE-NEXT:    bne .LBB3_2
368 ; CHECK-BE-NEXT:  @ %bb.3: @ %for.cond.cleanup
369 ; CHECK-BE-NEXT:    add.w r0, r12, r1
370 ; CHECK-BE-NEXT:    pop {r4, r5, r6, r7, pc}
371 ; CHECK-BE-NEXT:  .LBB3_4:
372 ; CHECK-BE-NEXT:    mov.w r12, #0
373 ; CHECK-BE-NEXT:    movs r1, #0
374 ; CHECK-BE-NEXT:    add.w r0, r12, r1
375 ; CHECK-BE-NEXT:    pop {r4, r5, r6, r7, pc}
376 entry:
377   %cmp24 = icmp sgt i32 %arg, 0
378   br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup
380 for.body.preheader:
381   %.pre = load i16, i16* %arg3, align 2
382   %.pre27 = load i16, i16* %arg2, align 2
383   br label %for.body
385 for.cond.cleanup:
386   %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
387   %count.final = phi i32 [ 0, %entry ], [ %count.next, %for.body ]
388   %res = add i32 %mac1.0.lcssa, %count.final
389   ret i32 %res
391 for.body:
392   %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
393   %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
394   %count = phi i32 [ %count.next, %for.body ], [ 0, %for.body.preheader ]
395   %arrayidx = getelementptr inbounds i16, i16* %arg3, i32 %i.025
396   %0 = load i16, i16* %arrayidx, align 2
397   %add = add nuw nsw i32 %i.025, 1
398   %arrayidx1 = getelementptr inbounds i16, i16* %arg3, i32 %add
399   %arrayidx3 = getelementptr inbounds i16, i16* %arg2, i32 %i.025
400   %arrayidx6 = getelementptr inbounds i16, i16* %arg2, i32 %add
401   %1 = load i16, i16* %arrayidx1, align 2
402   %2 = load i16, i16* %arrayidx3, align 2
403   %conv = sext i16 %2 to i32
404   %conv4 = sext i16 %0 to i32
405   %bottom = and i32 %conv4, 65535
406   %mul = mul nsw i32 %conv, %conv4
407   %3 = load i16, i16* %arrayidx6, align 2
408   %conv7 = sext i16 %3 to i32
409   %conv8 = sext i16 %1 to i32
410   %mul9 = mul nsw i32 %conv7, %conv8
411   %add10 = add i32 %mul, %mac1.026
412   %add11 = add i32 %mul9, %add10
413   %count.next = mul i32 %bottom, %count
414   %exitcond = icmp ne i32 %add, %arg
415   br i1 %exitcond, label %for.body, label %for.cond.cleanup
418 define i32 @multi_uses(i32 %arg, i32* nocapture readnone %arg1, i16* nocapture readonly %arg2, i16* nocapture readonly %arg3) {
419 ; CHECK-LE-LABEL: multi_uses:
420 ; CHECK-LE:       @ %bb.0: @ %entry
421 ; CHECK-LE-NEXT:    .save {r4, lr}
422 ; CHECK-LE-NEXT:    push {r4, lr}
423 ; CHECK-LE-NEXT:    cmp r0, #1
424 ; CHECK-LE-NEXT:    blt .LBB4_4
425 ; CHECK-LE-NEXT:  @ %bb.1: @ %for.body.preheader
426 ; CHECK-LE-NEXT:    subs r2, #2
427 ; CHECK-LE-NEXT:    subs r3, #2
428 ; CHECK-LE-NEXT:    mov.w lr, #0
429 ; CHECK-LE-NEXT:    mov.w r12, #0
430 ; CHECK-LE-NEXT:    .p2align 2
431 ; CHECK-LE-NEXT:  .LBB4_2: @ %for.body
432 ; CHECK-LE-NEXT:    @ =>This Inner Loop Header: Depth=1
433 ; CHECK-LE-NEXT:    ldr r1, [r3, #2]!
434 ; CHECK-LE-NEXT:    ldr r4, [r2, #2]!
435 ; CHECK-LE-NEXT:    subs r0, #1
436 ; CHECK-LE-NEXT:    smlad lr, r4, r1, lr
437 ; CHECK-LE-NEXT:    eor.w r4, r1, r12
438 ; CHECK-LE-NEXT:    mul r1, r4, r1
439 ; CHECK-LE-NEXT:    lsl.w r12, r1, #16
440 ; CHECK-LE-NEXT:    bne .LBB4_2
441 ; CHECK-LE-NEXT:  @ %bb.3: @ %for.cond.cleanup
442 ; CHECK-LE-NEXT:    add.w r0, lr, r12
443 ; CHECK-LE-NEXT:    pop {r4, pc}
444 ; CHECK-LE-NEXT:  .LBB4_4:
445 ; CHECK-LE-NEXT:    mov.w lr, #0
446 ; CHECK-LE-NEXT:    mov.w r12, #0
447 ; CHECK-LE-NEXT:    add.w r0, lr, r12
448 ; CHECK-LE-NEXT:    pop {r4, pc}
450 ; CHECK-BE-LABEL: multi_uses:
451 ; CHECK-BE:       @ %bb.0: @ %entry
452 ; CHECK-BE-NEXT:    .save {r4, r5, r6, lr}
453 ; CHECK-BE-NEXT:    push {r4, r5, r6, lr}
454 ; CHECK-BE-NEXT:    cmp r0, #1
455 ; CHECK-BE-NEXT:    blt .LBB4_4
456 ; CHECK-BE-NEXT:  @ %bb.1: @ %for.body.preheader
457 ; CHECK-BE-NEXT:    subs r2, #2
458 ; CHECK-BE-NEXT:    subs r3, #2
459 ; CHECK-BE-NEXT:    mov.w r12, #0
460 ; CHECK-BE-NEXT:    mov.w lr, #0
461 ; CHECK-BE-NEXT:    .p2align 2
462 ; CHECK-BE-NEXT:  .LBB4_2: @ %for.body
463 ; CHECK-BE-NEXT:    @ =>This Inner Loop Header: Depth=1
464 ; CHECK-BE-NEXT:    ldrsh r1, [r3, #2]!
465 ; CHECK-BE-NEXT:    ldrsh r4, [r2, #2]!
466 ; CHECK-BE-NEXT:    ldrsh.w r5, [r3, #2]
467 ; CHECK-BE-NEXT:    ldrsh.w r6, [r2, #2]
468 ; CHECK-BE-NEXT:    smlabb r4, r4, r1, r12
469 ; CHECK-BE-NEXT:    smlabb r12, r6, r5, r4
470 ; CHECK-BE-NEXT:    eor.w r6, r1, lr
471 ; CHECK-BE-NEXT:    muls r1, r6, r1
472 ; CHECK-BE-NEXT:    subs r0, #1
473 ; CHECK-BE-NEXT:    lsl.w lr, r1, #16
474 ; CHECK-BE-NEXT:    bne .LBB4_2
475 ; CHECK-BE-NEXT:  @ %bb.3: @ %for.cond.cleanup
476 ; CHECK-BE-NEXT:    add.w r0, r12, lr
477 ; CHECK-BE-NEXT:    pop {r4, r5, r6, pc}
478 ; CHECK-BE-NEXT:  .LBB4_4:
479 ; CHECK-BE-NEXT:    mov.w r12, #0
480 ; CHECK-BE-NEXT:    mov.w lr, #0
481 ; CHECK-BE-NEXT:    add.w r0, r12, lr
482 ; CHECK-BE-NEXT:    pop {r4, r5, r6, pc}
483 entry:
484   %cmp24 = icmp sgt i32 %arg, 0
485   br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup
487 for.body.preheader:
488   %.pre = load i16, i16* %arg3, align 2
489   %.pre27 = load i16, i16* %arg2, align 2
490   br label %for.body
492 for.cond.cleanup:
493   %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
494   %count.final = phi i32 [ 0, %entry ], [ %count.next, %for.body ]
495   %res = add i32 %mac1.0.lcssa, %count.final
496   ret i32 %res
498 for.body:
499   %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
500   %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
501   %count = phi i32 [ %count.next, %for.body ], [ 0, %for.body.preheader ]
502   %arrayidx = getelementptr inbounds i16, i16* %arg3, i32 %i.025
503   %0 = load i16, i16* %arrayidx, align 2
504   %add = add nuw nsw i32 %i.025, 1
505   %arrayidx1 = getelementptr inbounds i16, i16* %arg3, i32 %add
506   %arrayidx3 = getelementptr inbounds i16, i16* %arg2, i32 %i.025
507   %arrayidx6 = getelementptr inbounds i16, i16* %arg2, i32 %add
508   %1 = load i16, i16* %arrayidx1, align 2
509   %2 = load i16, i16* %arrayidx3, align 2
510   %conv = sext i16 %2 to i32
511   %conv4 = sext i16 %0 to i32
512   %bottom = and i32 %conv4, 65535
513   %mul = mul nsw i32 %conv, %conv4
514   %3 = load i16, i16* %arrayidx6, align 2
515   %conv7 = sext i16 %3 to i32
516   %conv8 = sext i16 %1 to i32
517   %mul9 = mul nsw i32 %conv7, %conv8
518   %add10 = add i32 %mul, %mac1.026
519   %shl = shl i32 %conv4, 16
520   %add11 = add i32 %mul9, %add10
521   %xor = xor i32 %bottom, %count
522   %count.next = mul i32 %xor, %shl
523   %exitcond = icmp ne i32 %add, %arg
524   br i1 %exitcond, label %for.body, label %for.cond.cleanup