1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumb-macho | FileCheck %s --check-prefix=ENABLE-V4T
3; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumbv5-macho | FileCheck %s --check-prefix=ENABLE-V5T
4; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumb-macho | FileCheck %s --check-prefix=DISABLE-V4T
5; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumbv5-macho | FileCheck %s --check-prefix=DISABLE-V5T
6
7;
8; Note: Lots of tests use inline asm instead of regular calls.
9; This allows to have a better control on what the allocation will do.
10; Otherwise, we may have spill right in the entry block, defeating
11; shrink-wrapping. Moreover, some of the inline asm statements (nop)
12; are here to ensure that the related paths do not end up as critical
13; edges.
14; Also disable the late if-converter as it makes harder to reason on
15; the diffs.
16; Disable tail-duplication during placement, as v4t vs v5t get different
17; results due to branches not being analyzable under v5
18
19; Initial motivating example: Simple diamond with a call just on one side.
20define i32 @foo(i32 %a, i32 %b) {
21; ENABLE-V4T-LABEL: foo:
22; ENABLE-V4T:       @ %bb.0:
23; ENABLE-V4T-NEXT:    cmp r0, r1
24; ENABLE-V4T-NEXT:    bge LBB0_2
25; ENABLE-V4T-NEXT:  @ %bb.1: @ %true
26; ENABLE-V4T-NEXT:    push {r7, lr}
27; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
28; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
29; ENABLE-V4T-NEXT:    .cfi_offset r7, -8
30; ENABLE-V4T-NEXT:    sub sp, #8
31; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 16
32; ENABLE-V4T-NEXT:    str r0, [sp, #4]
33; ENABLE-V4T-NEXT:    ldr r0, LCPI0_0
34; ENABLE-V4T-NEXT:  LPC0_0:
35; ENABLE-V4T-NEXT:    add r0, pc
36; ENABLE-V4T-NEXT:    ldr r2, [r0]
37; ENABLE-V4T-NEXT:    movs r0, #0
38; ENABLE-V4T-NEXT:    add r1, sp, #4
39; ENABLE-V4T-NEXT:    bl Ltmp0
40; ENABLE-V4T-NEXT:    add sp, #8
41; ENABLE-V4T-NEXT:    pop {r7}
42; ENABLE-V4T-NEXT:    pop {r1}
43; ENABLE-V4T-NEXT:    mov lr, r1
44; ENABLE-V4T-NEXT:  LBB0_2: @ %false
45; ENABLE-V4T-NEXT:    bx lr
46; ENABLE-V4T-NEXT:    .p2align 2
47; ENABLE-V4T-NEXT:  @ %bb.3:
48; ENABLE-V4T-NEXT:    .data_region
49; ENABLE-V4T-NEXT:  LCPI0_0:
50; ENABLE-V4T-NEXT:    .long L_doSomething$non_lazy_ptr-(LPC0_0+4)
51; ENABLE-V4T-NEXT:    .end_data_region
52;
53; ENABLE-V5T-LABEL: foo:
54; ENABLE-V5T:       @ %bb.0:
55; ENABLE-V5T-NEXT:    cmp r0, r1
56; ENABLE-V5T-NEXT:    bge LBB0_2
57; ENABLE-V5T-NEXT:  @ %bb.1: @ %true
58; ENABLE-V5T-NEXT:    push {r7, lr}
59; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
60; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
61; ENABLE-V5T-NEXT:    .cfi_offset r7, -8
62; ENABLE-V5T-NEXT:    sub sp, #8
63; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 16
64; ENABLE-V5T-NEXT:    str r0, [sp, #4]
65; ENABLE-V5T-NEXT:    movs r0, #0
66; ENABLE-V5T-NEXT:    add r1, sp, #4
67; ENABLE-V5T-NEXT:    bl _doSomething
68; ENABLE-V5T-NEXT:    add sp, #8
69; ENABLE-V5T-NEXT:    pop {r7, pc}
70; ENABLE-V5T-NEXT:  LBB0_2: @ %false
71; ENABLE-V5T-NEXT:    bx lr
72;
73; DISABLE-V4T-LABEL: foo:
74; DISABLE-V4T:       @ %bb.0:
75; DISABLE-V4T-NEXT:    push {r7, lr}
76; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
77; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
78; DISABLE-V4T-NEXT:    .cfi_offset r7, -8
79; DISABLE-V4T-NEXT:    sub sp, #8
80; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 16
81; DISABLE-V4T-NEXT:    cmp r0, r1
82; DISABLE-V4T-NEXT:    bge LBB0_2
83; DISABLE-V4T-NEXT:  @ %bb.1: @ %true
84; DISABLE-V4T-NEXT:    str r0, [sp, #4]
85; DISABLE-V4T-NEXT:    ldr r0, LCPI0_0
86; DISABLE-V4T-NEXT:  LPC0_0:
87; DISABLE-V4T-NEXT:    add r0, pc
88; DISABLE-V4T-NEXT:    ldr r2, [r0]
89; DISABLE-V4T-NEXT:    movs r0, #0
90; DISABLE-V4T-NEXT:    add r1, sp, #4
91; DISABLE-V4T-NEXT:    bl Ltmp0
92; DISABLE-V4T-NEXT:  LBB0_2: @ %false
93; DISABLE-V4T-NEXT:    add sp, #8
94; DISABLE-V4T-NEXT:    pop {r7}
95; DISABLE-V4T-NEXT:    pop {r1}
96; DISABLE-V4T-NEXT:    bx r1
97; DISABLE-V4T-NEXT:    .p2align 2
98; DISABLE-V4T-NEXT:  @ %bb.3:
99; DISABLE-V4T-NEXT:    .data_region
100; DISABLE-V4T-NEXT:  LCPI0_0:
101; DISABLE-V4T-NEXT:    .long L_doSomething$non_lazy_ptr-(LPC0_0+4)
102; DISABLE-V4T-NEXT:    .end_data_region
103;
104; DISABLE-V5T-LABEL: foo:
105; DISABLE-V5T:       @ %bb.0:
106; DISABLE-V5T-NEXT:    push {r7, lr}
107; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
108; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
109; DISABLE-V5T-NEXT:    .cfi_offset r7, -8
110; DISABLE-V5T-NEXT:    sub sp, #8
111; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 16
112; DISABLE-V5T-NEXT:    cmp r0, r1
113; DISABLE-V5T-NEXT:    bge LBB0_2
114; DISABLE-V5T-NEXT:  @ %bb.1: @ %true
115; DISABLE-V5T-NEXT:    str r0, [sp, #4]
116; DISABLE-V5T-NEXT:    movs r0, #0
117; DISABLE-V5T-NEXT:    add r1, sp, #4
118; DISABLE-V5T-NEXT:    bl _doSomething
119; DISABLE-V5T-NEXT:  LBB0_2: @ %false
120; DISABLE-V5T-NEXT:    add sp, #8
121; DISABLE-V5T-NEXT:    pop {r7, pc}
122  %tmp = alloca i32, align 4
123  %tmp2 = icmp slt i32 %a, %b
124  br i1 %tmp2, label %true, label %false
125
126true:
127  store i32 %a, i32* %tmp, align 4
128  %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
129  br label %false
130
131false:
132  %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
133  ret i32 %tmp.0
134}
135
136
137; Same, but the final BB is non-trivial, so we don't duplicate the return inst.
138define i32 @bar(i32 %a, i32 %b) {
139; ENABLE-V4T-LABEL: bar:
140; ENABLE-V4T:       @ %bb.0:
141; ENABLE-V4T-NEXT:    cmp r0, r1
142; ENABLE-V4T-NEXT:    bge LBB1_2
143; ENABLE-V4T-NEXT:  @ %bb.1: @ %true
144; ENABLE-V4T-NEXT:    push {r7, lr}
145; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
146; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
147; ENABLE-V4T-NEXT:    .cfi_offset r7, -8
148; ENABLE-V4T-NEXT:    sub sp, #8
149; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 16
150; ENABLE-V4T-NEXT:    str r0, [sp, #4]
151; ENABLE-V4T-NEXT:    ldr r0, LCPI1_0
152; ENABLE-V4T-NEXT:  LPC1_0:
153; ENABLE-V4T-NEXT:    add r0, pc
154; ENABLE-V4T-NEXT:    ldr r2, [r0]
155; ENABLE-V4T-NEXT:    movs r0, #0
156; ENABLE-V4T-NEXT:    add r1, sp, #4
157; ENABLE-V4T-NEXT:    bl Ltmp1
158; ENABLE-V4T-NEXT:    add sp, #8
159; ENABLE-V4T-NEXT:    pop {r7}
160; ENABLE-V4T-NEXT:    pop {r0}
161; ENABLE-V4T-NEXT:    mov lr, r0
162; ENABLE-V4T-NEXT:  LBB1_2: @ %false
163; ENABLE-V4T-NEXT:    movs r0, #42
164; ENABLE-V4T-NEXT:    bx lr
165; ENABLE-V4T-NEXT:    .p2align 2
166; ENABLE-V4T-NEXT:  @ %bb.3:
167; ENABLE-V4T-NEXT:    .data_region
168; ENABLE-V4T-NEXT:  LCPI1_0:
169; ENABLE-V4T-NEXT:    .long L_doSomething$non_lazy_ptr-(LPC1_0+4)
170; ENABLE-V4T-NEXT:    .end_data_region
171;
172; ENABLE-V5T-LABEL: bar:
173; ENABLE-V5T:       @ %bb.0:
174; ENABLE-V5T-NEXT:    cmp r0, r1
175; ENABLE-V5T-NEXT:    bge LBB1_2
176; ENABLE-V5T-NEXT:  @ %bb.1: @ %true
177; ENABLE-V5T-NEXT:    push {r7, lr}
178; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
179; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
180; ENABLE-V5T-NEXT:    .cfi_offset r7, -8
181; ENABLE-V5T-NEXT:    sub sp, #8
182; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 16
183; ENABLE-V5T-NEXT:    str r0, [sp, #4]
184; ENABLE-V5T-NEXT:    movs r0, #0
185; ENABLE-V5T-NEXT:    add r1, sp, #4
186; ENABLE-V5T-NEXT:    bl _doSomething
187; ENABLE-V5T-NEXT:    add sp, #8
188; ENABLE-V5T-NEXT:    pop {r7}
189; ENABLE-V5T-NEXT:    pop {r0}
190; ENABLE-V5T-NEXT:    mov lr, r0
191; ENABLE-V5T-NEXT:  LBB1_2: @ %false
192; ENABLE-V5T-NEXT:    movs r0, #42
193; ENABLE-V5T-NEXT:    bx lr
194;
195; DISABLE-V4T-LABEL: bar:
196; DISABLE-V4T:       @ %bb.0:
197; DISABLE-V4T-NEXT:    push {r7, lr}
198; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
199; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
200; DISABLE-V4T-NEXT:    .cfi_offset r7, -8
201; DISABLE-V4T-NEXT:    sub sp, #8
202; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 16
203; DISABLE-V4T-NEXT:    cmp r0, r1
204; DISABLE-V4T-NEXT:    bge LBB1_2
205; DISABLE-V4T-NEXT:  @ %bb.1: @ %true
206; DISABLE-V4T-NEXT:    str r0, [sp, #4]
207; DISABLE-V4T-NEXT:    ldr r0, LCPI1_0
208; DISABLE-V4T-NEXT:  LPC1_0:
209; DISABLE-V4T-NEXT:    add r0, pc
210; DISABLE-V4T-NEXT:    ldr r2, [r0]
211; DISABLE-V4T-NEXT:    movs r0, #0
212; DISABLE-V4T-NEXT:    add r1, sp, #4
213; DISABLE-V4T-NEXT:    bl Ltmp1
214; DISABLE-V4T-NEXT:  LBB1_2: @ %false
215; DISABLE-V4T-NEXT:    movs r0, #42
216; DISABLE-V4T-NEXT:    add sp, #8
217; DISABLE-V4T-NEXT:    pop {r7}
218; DISABLE-V4T-NEXT:    pop {r1}
219; DISABLE-V4T-NEXT:    bx r1
220; DISABLE-V4T-NEXT:    .p2align 2
221; DISABLE-V4T-NEXT:  @ %bb.3:
222; DISABLE-V4T-NEXT:    .data_region
223; DISABLE-V4T-NEXT:  LCPI1_0:
224; DISABLE-V4T-NEXT:    .long L_doSomething$non_lazy_ptr-(LPC1_0+4)
225; DISABLE-V4T-NEXT:    .end_data_region
226;
227; DISABLE-V5T-LABEL: bar:
228; DISABLE-V5T:       @ %bb.0:
229; DISABLE-V5T-NEXT:    push {r7, lr}
230; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
231; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
232; DISABLE-V5T-NEXT:    .cfi_offset r7, -8
233; DISABLE-V5T-NEXT:    sub sp, #8
234; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 16
235; DISABLE-V5T-NEXT:    cmp r0, r1
236; DISABLE-V5T-NEXT:    bge LBB1_2
237; DISABLE-V5T-NEXT:  @ %bb.1: @ %true
238; DISABLE-V5T-NEXT:    str r0, [sp, #4]
239; DISABLE-V5T-NEXT:    movs r0, #0
240; DISABLE-V5T-NEXT:    add r1, sp, #4
241; DISABLE-V5T-NEXT:    bl _doSomething
242; DISABLE-V5T-NEXT:  LBB1_2: @ %false
243; DISABLE-V5T-NEXT:    movs r0, #42
244; DISABLE-V5T-NEXT:    add sp, #8
245; DISABLE-V5T-NEXT:    pop {r7, pc}
246  %tmp = alloca i32, align 4
247  %tmp2 = icmp slt i32 %a, %b
248  br i1 %tmp2, label %true, label %false
249
250true:
251  store i32 %a, i32* %tmp, align 4
252  %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
253  br label %false
254
255false:
256  ret i32 42
257}
258
259; Function Attrs: optsize
260declare i32 @doSomething(i32, i32*)
261
262
263; Check that we do not perform the restore inside the loop whereas the save
264; is outside.
265define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
266; ENABLE-V4T-LABEL: freqSaveAndRestoreOutsideLoop:
267; ENABLE-V4T:       @ %bb.0: @ %entry
268; ENABLE-V4T-NEXT:    cmp r0, #0
269; ENABLE-V4T-NEXT:    beq LBB2_4
270; ENABLE-V4T-NEXT:  @ %bb.1: @ %for.preheader
271; ENABLE-V4T-NEXT:    push {r4, lr}
272; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
273; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
274; ENABLE-V4T-NEXT:    .cfi_offset r4, -8
275; ENABLE-V4T-NEXT:    @ InlineAsm Start
276; ENABLE-V4T-NEXT:    mov r8, r8
277; ENABLE-V4T-NEXT:    @ InlineAsm End
278; ENABLE-V4T-NEXT:    movs r0, #0
279; ENABLE-V4T-NEXT:    movs r1, #10
280; ENABLE-V4T-NEXT:  LBB2_2: @ %for.body
281; ENABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
282; ENABLE-V4T-NEXT:    @ InlineAsm Start
283; ENABLE-V4T-NEXT:    movs r2, #1
284; ENABLE-V4T-NEXT:    @ InlineAsm End
285; ENABLE-V4T-NEXT:    adds r0, r2, r0
286; ENABLE-V4T-NEXT:    subs r1, r1, #1
287; ENABLE-V4T-NEXT:    bne LBB2_2
288; ENABLE-V4T-NEXT:  @ %bb.3: @ %for.end
289; ENABLE-V4T-NEXT:    lsls r0, r0, #3
290; ENABLE-V4T-NEXT:    pop {r4}
291; ENABLE-V4T-NEXT:    pop {r1}
292; ENABLE-V4T-NEXT:    bx r1
293; ENABLE-V4T-NEXT:  LBB2_4: @ %if.else
294; ENABLE-V4T-NEXT:    lsls r0, r1, #1
295; ENABLE-V4T-NEXT:    bx lr
296;
297; ENABLE-V5T-LABEL: freqSaveAndRestoreOutsideLoop:
298; ENABLE-V5T:       @ %bb.0: @ %entry
299; ENABLE-V5T-NEXT:    cmp r0, #0
300; ENABLE-V5T-NEXT:    beq LBB2_4
301; ENABLE-V5T-NEXT:  @ %bb.1: @ %for.preheader
302; ENABLE-V5T-NEXT:    push {r4, lr}
303; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
304; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
305; ENABLE-V5T-NEXT:    .cfi_offset r4, -8
306; ENABLE-V5T-NEXT:    @ InlineAsm Start
307; ENABLE-V5T-NEXT:    mov r8, r8
308; ENABLE-V5T-NEXT:    @ InlineAsm End
309; ENABLE-V5T-NEXT:    movs r0, #0
310; ENABLE-V5T-NEXT:    movs r1, #10
311; ENABLE-V5T-NEXT:  LBB2_2: @ %for.body
312; ENABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
313; ENABLE-V5T-NEXT:    @ InlineAsm Start
314; ENABLE-V5T-NEXT:    movs r2, #1
315; ENABLE-V5T-NEXT:    @ InlineAsm End
316; ENABLE-V5T-NEXT:    adds r0, r2, r0
317; ENABLE-V5T-NEXT:    subs r1, r1, #1
318; ENABLE-V5T-NEXT:    bne LBB2_2
319; ENABLE-V5T-NEXT:  @ %bb.3: @ %for.end
320; ENABLE-V5T-NEXT:    lsls r0, r0, #3
321; ENABLE-V5T-NEXT:    pop {r4, pc}
322; ENABLE-V5T-NEXT:  LBB2_4: @ %if.else
323; ENABLE-V5T-NEXT:    lsls r0, r1, #1
324; ENABLE-V5T-NEXT:  LBB2_5: @ %if.end
325; ENABLE-V5T-NEXT:    bx lr
326;
327; DISABLE-V4T-LABEL: freqSaveAndRestoreOutsideLoop:
328; DISABLE-V4T:       @ %bb.0: @ %entry
329; DISABLE-V4T-NEXT:    push {r4, lr}
330; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
331; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
332; DISABLE-V4T-NEXT:    .cfi_offset r4, -8
333; DISABLE-V4T-NEXT:    cmp r0, #0
334; DISABLE-V4T-NEXT:    beq LBB2_4
335; DISABLE-V4T-NEXT:  @ %bb.1: @ %for.preheader
336; DISABLE-V4T-NEXT:    @ InlineAsm Start
337; DISABLE-V4T-NEXT:    mov r8, r8
338; DISABLE-V4T-NEXT:    @ InlineAsm End
339; DISABLE-V4T-NEXT:    movs r0, #0
340; DISABLE-V4T-NEXT:    movs r1, #10
341; DISABLE-V4T-NEXT:  LBB2_2: @ %for.body
342; DISABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
343; DISABLE-V4T-NEXT:    @ InlineAsm Start
344; DISABLE-V4T-NEXT:    movs r2, #1
345; DISABLE-V4T-NEXT:    @ InlineAsm End
346; DISABLE-V4T-NEXT:    adds r0, r2, r0
347; DISABLE-V4T-NEXT:    subs r1, r1, #1
348; DISABLE-V4T-NEXT:    bne LBB2_2
349; DISABLE-V4T-NEXT:  @ %bb.3: @ %for.end
350; DISABLE-V4T-NEXT:    lsls r0, r0, #3
351; DISABLE-V4T-NEXT:    b LBB2_5
352; DISABLE-V4T-NEXT:  LBB2_4: @ %if.else
353; DISABLE-V4T-NEXT:    lsls r0, r1, #1
354; DISABLE-V4T-NEXT:  LBB2_5: @ %if.end
355; DISABLE-V4T-NEXT:    pop {r4}
356; DISABLE-V4T-NEXT:    pop {r1}
357; DISABLE-V4T-NEXT:    bx r1
358;
359; DISABLE-V5T-LABEL: freqSaveAndRestoreOutsideLoop:
360; DISABLE-V5T:       @ %bb.0: @ %entry
361; DISABLE-V5T-NEXT:    push {r4, lr}
362; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
363; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
364; DISABLE-V5T-NEXT:    .cfi_offset r4, -8
365; DISABLE-V5T-NEXT:    cmp r0, #0
366; DISABLE-V5T-NEXT:    beq LBB2_4
367; DISABLE-V5T-NEXT:  @ %bb.1: @ %for.preheader
368; DISABLE-V5T-NEXT:    @ InlineAsm Start
369; DISABLE-V5T-NEXT:    mov r8, r8
370; DISABLE-V5T-NEXT:    @ InlineAsm End
371; DISABLE-V5T-NEXT:    movs r0, #0
372; DISABLE-V5T-NEXT:    movs r1, #10
373; DISABLE-V5T-NEXT:  LBB2_2: @ %for.body
374; DISABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
375; DISABLE-V5T-NEXT:    @ InlineAsm Start
376; DISABLE-V5T-NEXT:    movs r2, #1
377; DISABLE-V5T-NEXT:    @ InlineAsm End
378; DISABLE-V5T-NEXT:    adds r0, r2, r0
379; DISABLE-V5T-NEXT:    subs r1, r1, #1
380; DISABLE-V5T-NEXT:    bne LBB2_2
381; DISABLE-V5T-NEXT:  @ %bb.3: @ %for.end
382; DISABLE-V5T-NEXT:    lsls r0, r0, #3
383; DISABLE-V5T-NEXT:    pop {r4, pc}
384; DISABLE-V5T-NEXT:  LBB2_4: @ %if.else
385; DISABLE-V5T-NEXT:    lsls r0, r1, #1
386; DISABLE-V5T-NEXT:    pop {r4, pc}
387entry:
388  %tobool = icmp eq i32 %cond, 0
389  br i1 %tobool, label %if.else, label %for.preheader
390
391for.preheader:
392  tail call void asm "nop", ""()
393  br label %for.body
394
395for.body:                                         ; preds = %entry, %for.body
396  %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
397  %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
398  %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
399  %add = add nsw i32 %call, %sum.04
400  %inc = add nuw nsw i32 %i.05, 1
401  %exitcond = icmp eq i32 %inc, 10
402  br i1 %exitcond, label %for.end, label %for.body
403
404for.end:                                          ; preds = %for.body
405  %shl = shl i32 %add, 3
406  br label %if.end
407
408if.else:                                          ; preds = %entry
409  %mul = shl nsw i32 %N, 1
410  br label %if.end
411
412if.end:                                           ; preds = %if.else, %for.end
413  %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
414  ret i32 %sum.1
415}
416
417declare i32 @something(...)
418
419; Check that we do not perform the shrink-wrapping inside the loop even
420; though that would be legal. The cost model must prevent that.
421define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
422; ENABLE-V4T-LABEL: freqSaveAndRestoreOutsideLoop2:
423; ENABLE-V4T:       @ %bb.0: @ %entry
424; ENABLE-V4T-NEXT:    push {r4, lr}
425; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
426; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
427; ENABLE-V4T-NEXT:    .cfi_offset r4, -8
428; ENABLE-V4T-NEXT:    @ InlineAsm Start
429; ENABLE-V4T-NEXT:    mov r8, r8
430; ENABLE-V4T-NEXT:    @ InlineAsm End
431; ENABLE-V4T-NEXT:    movs r0, #0
432; ENABLE-V4T-NEXT:    movs r1, #10
433; ENABLE-V4T-NEXT:  LBB3_1: @ %for.body
434; ENABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
435; ENABLE-V4T-NEXT:    @ InlineAsm Start
436; ENABLE-V4T-NEXT:    movs r2, #1
437; ENABLE-V4T-NEXT:    @ InlineAsm End
438; ENABLE-V4T-NEXT:    adds r0, r2, r0
439; ENABLE-V4T-NEXT:    subs r1, r1, #1
440; ENABLE-V4T-NEXT:    bne LBB3_1
441; ENABLE-V4T-NEXT:  @ %bb.2: @ %for.exit
442; ENABLE-V4T-NEXT:    @ InlineAsm Start
443; ENABLE-V4T-NEXT:    mov r8, r8
444; ENABLE-V4T-NEXT:    @ InlineAsm End
445; ENABLE-V4T-NEXT:    pop {r4}
446; ENABLE-V4T-NEXT:    pop {r1}
447; ENABLE-V4T-NEXT:    bx r1
448;
449; ENABLE-V5T-LABEL: freqSaveAndRestoreOutsideLoop2:
450; ENABLE-V5T:       @ %bb.0: @ %entry
451; ENABLE-V5T-NEXT:    push {r4, lr}
452; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
453; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
454; ENABLE-V5T-NEXT:    .cfi_offset r4, -8
455; ENABLE-V5T-NEXT:    @ InlineAsm Start
456; ENABLE-V5T-NEXT:    mov r8, r8
457; ENABLE-V5T-NEXT:    @ InlineAsm End
458; ENABLE-V5T-NEXT:    movs r0, #0
459; ENABLE-V5T-NEXT:    movs r1, #10
460; ENABLE-V5T-NEXT:  LBB3_1: @ %for.body
461; ENABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
462; ENABLE-V5T-NEXT:    @ InlineAsm Start
463; ENABLE-V5T-NEXT:    movs r2, #1
464; ENABLE-V5T-NEXT:    @ InlineAsm End
465; ENABLE-V5T-NEXT:    adds r0, r2, r0
466; ENABLE-V5T-NEXT:    subs r1, r1, #1
467; ENABLE-V5T-NEXT:    bne LBB3_1
468; ENABLE-V5T-NEXT:  @ %bb.2: @ %for.exit
469; ENABLE-V5T-NEXT:    @ InlineAsm Start
470; ENABLE-V5T-NEXT:    mov r8, r8
471; ENABLE-V5T-NEXT:    @ InlineAsm End
472; ENABLE-V5T-NEXT:    pop {r4, pc}
473; ENABLE-V5T-NEXT:  LBB3_3: @ %for.end
474; ENABLE-V5T-NEXT:    bx lr
475;
476; DISABLE-V4T-LABEL: freqSaveAndRestoreOutsideLoop2:
477; DISABLE-V4T:       @ %bb.0: @ %entry
478; DISABLE-V4T-NEXT:    push {r4, lr}
479; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
480; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
481; DISABLE-V4T-NEXT:    .cfi_offset r4, -8
482; DISABLE-V4T-NEXT:    @ InlineAsm Start
483; DISABLE-V4T-NEXT:    mov r8, r8
484; DISABLE-V4T-NEXT:    @ InlineAsm End
485; DISABLE-V4T-NEXT:    movs r0, #0
486; DISABLE-V4T-NEXT:    movs r1, #10
487; DISABLE-V4T-NEXT:  LBB3_1: @ %for.body
488; DISABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
489; DISABLE-V4T-NEXT:    @ InlineAsm Start
490; DISABLE-V4T-NEXT:    movs r2, #1
491; DISABLE-V4T-NEXT:    @ InlineAsm End
492; DISABLE-V4T-NEXT:    adds r0, r2, r0
493; DISABLE-V4T-NEXT:    subs r1, r1, #1
494; DISABLE-V4T-NEXT:    bne LBB3_1
495; DISABLE-V4T-NEXT:  @ %bb.2: @ %for.exit
496; DISABLE-V4T-NEXT:    @ InlineAsm Start
497; DISABLE-V4T-NEXT:    mov r8, r8
498; DISABLE-V4T-NEXT:    @ InlineAsm End
499; DISABLE-V4T-NEXT:    pop {r4}
500; DISABLE-V4T-NEXT:    pop {r1}
501; DISABLE-V4T-NEXT:    bx r1
502;
503; DISABLE-V5T-LABEL: freqSaveAndRestoreOutsideLoop2:
504; DISABLE-V5T:       @ %bb.0: @ %entry
505; DISABLE-V5T-NEXT:    push {r4, lr}
506; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
507; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
508; DISABLE-V5T-NEXT:    .cfi_offset r4, -8
509; DISABLE-V5T-NEXT:    @ InlineAsm Start
510; DISABLE-V5T-NEXT:    mov r8, r8
511; DISABLE-V5T-NEXT:    @ InlineAsm End
512; DISABLE-V5T-NEXT:    movs r0, #0
513; DISABLE-V5T-NEXT:    movs r1, #10
514; DISABLE-V5T-NEXT:  LBB3_1: @ %for.body
515; DISABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
516; DISABLE-V5T-NEXT:    @ InlineAsm Start
517; DISABLE-V5T-NEXT:    movs r2, #1
518; DISABLE-V5T-NEXT:    @ InlineAsm End
519; DISABLE-V5T-NEXT:    adds r0, r2, r0
520; DISABLE-V5T-NEXT:    subs r1, r1, #1
521; DISABLE-V5T-NEXT:    bne LBB3_1
522; DISABLE-V5T-NEXT:  @ %bb.2: @ %for.exit
523; DISABLE-V5T-NEXT:    @ InlineAsm Start
524; DISABLE-V5T-NEXT:    mov r8, r8
525; DISABLE-V5T-NEXT:    @ InlineAsm End
526; DISABLE-V5T-NEXT:    pop {r4, pc}
527entry:
528  br label %for.preheader
529
530for.preheader:
531  tail call void asm "nop", ""()
532  br label %for.body
533
534for.body:                                         ; preds = %for.body, %entry
535  %i.04 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]
536  %sum.03 = phi i32 [ 0, %for.preheader ], [ %add, %for.body ]
537  %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
538  %add = add nsw i32 %call, %sum.03
539  %inc = add nuw nsw i32 %i.04, 1
540  %exitcond = icmp eq i32 %inc, 10
541  br i1 %exitcond, label %for.exit, label %for.body
542
543for.exit:
544  tail call void asm "nop", ""()
545  br label %for.end
546
547for.end:                                          ; preds = %for.body
548  ret i32 %add
549}
550
551; Check with a more complex case that we do not have save within the loop and
552; restore outside.
553define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
554; ENABLE-V4T-LABEL: loopInfoSaveOutsideLoop:
555; ENABLE-V4T:       @ %bb.0: @ %entry
556; ENABLE-V4T-NEXT:    cmp r0, #0
557; ENABLE-V4T-NEXT:    beq LBB4_4
558; ENABLE-V4T-NEXT:  @ %bb.1: @ %for.preheader
559; ENABLE-V4T-NEXT:    push {r4, lr}
560; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
561; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
562; ENABLE-V4T-NEXT:    .cfi_offset r4, -8
563; ENABLE-V4T-NEXT:    @ InlineAsm Start
564; ENABLE-V4T-NEXT:    mov r8, r8
565; ENABLE-V4T-NEXT:    @ InlineAsm End
566; ENABLE-V4T-NEXT:    movs r0, #0
567; ENABLE-V4T-NEXT:    movs r1, #10
568; ENABLE-V4T-NEXT:  LBB4_2: @ %for.body
569; ENABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
570; ENABLE-V4T-NEXT:    @ InlineAsm Start
571; ENABLE-V4T-NEXT:    movs r2, #1
572; ENABLE-V4T-NEXT:    @ InlineAsm End
573; ENABLE-V4T-NEXT:    adds r0, r2, r0
574; ENABLE-V4T-NEXT:    subs r1, r1, #1
575; ENABLE-V4T-NEXT:    bne LBB4_2
576; ENABLE-V4T-NEXT:  @ %bb.3: @ %for.end
577; ENABLE-V4T-NEXT:    @ InlineAsm Start
578; ENABLE-V4T-NEXT:    mov r8, r8
579; ENABLE-V4T-NEXT:    @ InlineAsm End
580; ENABLE-V4T-NEXT:    lsls r0, r0, #3
581; ENABLE-V4T-NEXT:    pop {r4}
582; ENABLE-V4T-NEXT:    pop {r1}
583; ENABLE-V4T-NEXT:    bx r1
584; ENABLE-V4T-NEXT:  LBB4_4: @ %if.else
585; ENABLE-V4T-NEXT:    lsls r0, r1, #1
586; ENABLE-V4T-NEXT:    bx lr
587;
588; ENABLE-V5T-LABEL: loopInfoSaveOutsideLoop:
589; ENABLE-V5T:       @ %bb.0: @ %entry
590; ENABLE-V5T-NEXT:    cmp r0, #0
591; ENABLE-V5T-NEXT:    beq LBB4_4
592; ENABLE-V5T-NEXT:  @ %bb.1: @ %for.preheader
593; ENABLE-V5T-NEXT:    push {r4, lr}
594; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
595; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
596; ENABLE-V5T-NEXT:    .cfi_offset r4, -8
597; ENABLE-V5T-NEXT:    @ InlineAsm Start
598; ENABLE-V5T-NEXT:    mov r8, r8
599; ENABLE-V5T-NEXT:    @ InlineAsm End
600; ENABLE-V5T-NEXT:    movs r0, #0
601; ENABLE-V5T-NEXT:    movs r1, #10
602; ENABLE-V5T-NEXT:  LBB4_2: @ %for.body
603; ENABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
604; ENABLE-V5T-NEXT:    @ InlineAsm Start
605; ENABLE-V5T-NEXT:    movs r2, #1
606; ENABLE-V5T-NEXT:    @ InlineAsm End
607; ENABLE-V5T-NEXT:    adds r0, r2, r0
608; ENABLE-V5T-NEXT:    subs r1, r1, #1
609; ENABLE-V5T-NEXT:    bne LBB4_2
610; ENABLE-V5T-NEXT:  @ %bb.3: @ %for.end
611; ENABLE-V5T-NEXT:    @ InlineAsm Start
612; ENABLE-V5T-NEXT:    mov r8, r8
613; ENABLE-V5T-NEXT:    @ InlineAsm End
614; ENABLE-V5T-NEXT:    lsls r0, r0, #3
615; ENABLE-V5T-NEXT:    pop {r4, pc}
616; ENABLE-V5T-NEXT:  LBB4_4: @ %if.else
617; ENABLE-V5T-NEXT:    lsls r0, r1, #1
618; ENABLE-V5T-NEXT:  LBB4_5: @ %if.end
619; ENABLE-V5T-NEXT:    bx lr
620;
621; DISABLE-V4T-LABEL: loopInfoSaveOutsideLoop:
622; DISABLE-V4T:       @ %bb.0: @ %entry
623; DISABLE-V4T-NEXT:    push {r4, lr}
624; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
625; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
626; DISABLE-V4T-NEXT:    .cfi_offset r4, -8
627; DISABLE-V4T-NEXT:    cmp r0, #0
628; DISABLE-V4T-NEXT:    beq LBB4_4
629; DISABLE-V4T-NEXT:  @ %bb.1: @ %for.preheader
630; DISABLE-V4T-NEXT:    @ InlineAsm Start
631; DISABLE-V4T-NEXT:    mov r8, r8
632; DISABLE-V4T-NEXT:    @ InlineAsm End
633; DISABLE-V4T-NEXT:    movs r0, #0
634; DISABLE-V4T-NEXT:    movs r1, #10
635; DISABLE-V4T-NEXT:  LBB4_2: @ %for.body
636; DISABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
637; DISABLE-V4T-NEXT:    @ InlineAsm Start
638; DISABLE-V4T-NEXT:    movs r2, #1
639; DISABLE-V4T-NEXT:    @ InlineAsm End
640; DISABLE-V4T-NEXT:    adds r0, r2, r0
641; DISABLE-V4T-NEXT:    subs r1, r1, #1
642; DISABLE-V4T-NEXT:    bne LBB4_2
643; DISABLE-V4T-NEXT:  @ %bb.3: @ %for.end
644; DISABLE-V4T-NEXT:    @ InlineAsm Start
645; DISABLE-V4T-NEXT:    mov r8, r8
646; DISABLE-V4T-NEXT:    @ InlineAsm End
647; DISABLE-V4T-NEXT:    lsls r0, r0, #3
648; DISABLE-V4T-NEXT:    b LBB4_5
649; DISABLE-V4T-NEXT:  LBB4_4: @ %if.else
650; DISABLE-V4T-NEXT:    lsls r0, r1, #1
651; DISABLE-V4T-NEXT:  LBB4_5: @ %if.end
652; DISABLE-V4T-NEXT:    pop {r4}
653; DISABLE-V4T-NEXT:    pop {r1}
654; DISABLE-V4T-NEXT:    bx r1
655;
656; DISABLE-V5T-LABEL: loopInfoSaveOutsideLoop:
657; DISABLE-V5T:       @ %bb.0: @ %entry
658; DISABLE-V5T-NEXT:    push {r4, lr}
659; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
660; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
661; DISABLE-V5T-NEXT:    .cfi_offset r4, -8
662; DISABLE-V5T-NEXT:    cmp r0, #0
663; DISABLE-V5T-NEXT:    beq LBB4_4
664; DISABLE-V5T-NEXT:  @ %bb.1: @ %for.preheader
665; DISABLE-V5T-NEXT:    @ InlineAsm Start
666; DISABLE-V5T-NEXT:    mov r8, r8
667; DISABLE-V5T-NEXT:    @ InlineAsm End
668; DISABLE-V5T-NEXT:    movs r0, #0
669; DISABLE-V5T-NEXT:    movs r1, #10
670; DISABLE-V5T-NEXT:  LBB4_2: @ %for.body
671; DISABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
672; DISABLE-V5T-NEXT:    @ InlineAsm Start
673; DISABLE-V5T-NEXT:    movs r2, #1
674; DISABLE-V5T-NEXT:    @ InlineAsm End
675; DISABLE-V5T-NEXT:    adds r0, r2, r0
676; DISABLE-V5T-NEXT:    subs r1, r1, #1
677; DISABLE-V5T-NEXT:    bne LBB4_2
678; DISABLE-V5T-NEXT:  @ %bb.3: @ %for.end
679; DISABLE-V5T-NEXT:    @ InlineAsm Start
680; DISABLE-V5T-NEXT:    mov r8, r8
681; DISABLE-V5T-NEXT:    @ InlineAsm End
682; DISABLE-V5T-NEXT:    lsls r0, r0, #3
683; DISABLE-V5T-NEXT:    pop {r4, pc}
684; DISABLE-V5T-NEXT:  LBB4_4: @ %if.else
685; DISABLE-V5T-NEXT:    lsls r0, r1, #1
686; DISABLE-V5T-NEXT:    pop {r4, pc}
687entry:
688  %tobool = icmp eq i32 %cond, 0
689  br i1 %tobool, label %if.else, label %for.preheader
690
691for.preheader:
692  tail call void asm "nop", ""()
693  br label %for.body
694
695for.body:                                         ; preds = %entry, %for.body
696  %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
697  %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
698  %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
699  %add = add nsw i32 %call, %sum.04
700  %inc = add nuw nsw i32 %i.05, 1
701  %exitcond = icmp eq i32 %inc, 10
702  br i1 %exitcond, label %for.end, label %for.body
703
704for.end:                                          ; preds = %for.body
705  tail call void asm "nop", "~{r4}"()
706  %shl = shl i32 %add, 3
707  br label %if.end
708
709if.else:                                          ; preds = %entry
710  %mul = shl nsw i32 %N, 1
711  br label %if.end
712
713if.end:                                           ; preds = %if.else, %for.end
714  %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
715  ret i32 %sum.1
716}
717
718declare void @somethingElse(...)
719
720; Check with a more complex case that we do not have restore within the loop and
721; save outside.
722define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind {
723; ENABLE-V4T-LABEL: loopInfoRestoreOutsideLoop:
724; ENABLE-V4T:       @ %bb.0: @ %entry
725; ENABLE-V4T-NEXT:    cmp r0, #0
726; ENABLE-V4T-NEXT:    beq LBB5_4
727; ENABLE-V4T-NEXT:  @ %bb.1: @ %if.then
728; ENABLE-V4T-NEXT:    push {r4, lr}
729; ENABLE-V4T-NEXT:    @ InlineAsm Start
730; ENABLE-V4T-NEXT:    mov r8, r8
731; ENABLE-V4T-NEXT:    @ InlineAsm End
732; ENABLE-V4T-NEXT:    movs r0, #0
733; ENABLE-V4T-NEXT:    movs r1, #10
734; ENABLE-V4T-NEXT:  LBB5_2: @ %for.body
735; ENABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
736; ENABLE-V4T-NEXT:    @ InlineAsm Start
737; ENABLE-V4T-NEXT:    movs r2, #1
738; ENABLE-V4T-NEXT:    @ InlineAsm End
739; ENABLE-V4T-NEXT:    adds r0, r2, r0
740; ENABLE-V4T-NEXT:    subs r1, r1, #1
741; ENABLE-V4T-NEXT:    bne LBB5_2
742; ENABLE-V4T-NEXT:  @ %bb.3: @ %for.end
743; ENABLE-V4T-NEXT:    lsls r0, r0, #3
744; ENABLE-V4T-NEXT:    pop {r4}
745; ENABLE-V4T-NEXT:    pop {r1}
746; ENABLE-V4T-NEXT:    bx r1
747; ENABLE-V4T-NEXT:  LBB5_4: @ %if.else
748; ENABLE-V4T-NEXT:    lsls r0, r1, #1
749; ENABLE-V4T-NEXT:    bx lr
750; ENABLE-V4T-NEXT:    @ -- End function
751; ENABLE-V4T-NEXT:    .globl _emptyFrame @ -- Begin function emptyFrame
752; ENABLE-V4T-NEXT:    .p2align 1
753; ENABLE-V4T-NEXT:    .code 16 @ @emptyFrame
754; ENABLE-V4T-NEXT:    .thumb_func _emptyFrame
755; ENABLE-V4T-NEXT:  _emptyFrame:
756; ENABLE-V4T-NEXT:    .cfi_startproc
757; ENABLE-V4T-NEXT:  @ %bb.0: @ %entry
758; ENABLE-V4T-NEXT:    movs r0, #0
759; ENABLE-V4T-NEXT:    bx lr
760;
761; ENABLE-V5T-LABEL: loopInfoRestoreOutsideLoop:
762; ENABLE-V5T:       @ %bb.0: @ %entry
763; ENABLE-V5T-NEXT:    cmp r0, #0
764; ENABLE-V5T-NEXT:    beq LBB5_4
765; ENABLE-V5T-NEXT:  @ %bb.1: @ %if.then
766; ENABLE-V5T-NEXT:    push {r4, lr}
767; ENABLE-V5T-NEXT:    @ InlineAsm Start
768; ENABLE-V5T-NEXT:    mov r8, r8
769; ENABLE-V5T-NEXT:    @ InlineAsm End
770; ENABLE-V5T-NEXT:    movs r0, #0
771; ENABLE-V5T-NEXT:    movs r1, #10
772; ENABLE-V5T-NEXT:  LBB5_2: @ %for.body
773; ENABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
774; ENABLE-V5T-NEXT:    @ InlineAsm Start
775; ENABLE-V5T-NEXT:    movs r2, #1
776; ENABLE-V5T-NEXT:    @ InlineAsm End
777; ENABLE-V5T-NEXT:    adds r0, r2, r0
778; ENABLE-V5T-NEXT:    subs r1, r1, #1
779; ENABLE-V5T-NEXT:    bne LBB5_2
780; ENABLE-V5T-NEXT:  @ %bb.3: @ %for.end
781; ENABLE-V5T-NEXT:    lsls r0, r0, #3
782; ENABLE-V5T-NEXT:    pop {r4, pc}
783; ENABLE-V5T-NEXT:  LBB5_4: @ %if.else
784; ENABLE-V5T-NEXT:    lsls r0, r1, #1
785; ENABLE-V5T-NEXT:  LBB5_5: @ %if.end
786; ENABLE-V5T-NEXT:    bx lr
787; ENABLE-V5T-NEXT:    @ -- End function
788; ENABLE-V5T-NEXT:    .globl _emptyFrame @ -- Begin function emptyFrame
789; ENABLE-V5T-NEXT:    .p2align 1
790; ENABLE-V5T-NEXT:    .code 16 @ @emptyFrame
791; ENABLE-V5T-NEXT:    .thumb_func _emptyFrame
792; ENABLE-V5T-NEXT:  _emptyFrame:
793; ENABLE-V5T-NEXT:    .cfi_startproc
794; ENABLE-V5T-NEXT:  @ %bb.0: @ %entry
795; ENABLE-V5T-NEXT:    movs r0, #0
796; ENABLE-V5T-NEXT:    bx lr
797;
798; DISABLE-V4T-LABEL: loopInfoRestoreOutsideLoop:
799; DISABLE-V4T:       @ %bb.0: @ %entry
800; DISABLE-V4T-NEXT:    push {r4, lr}
801; DISABLE-V4T-NEXT:    cmp r0, #0
802; DISABLE-V4T-NEXT:    beq LBB5_4
803; DISABLE-V4T-NEXT:  @ %bb.1: @ %if.then
804; DISABLE-V4T-NEXT:    @ InlineAsm Start
805; DISABLE-V4T-NEXT:    mov r8, r8
806; DISABLE-V4T-NEXT:    @ InlineAsm End
807; DISABLE-V4T-NEXT:    movs r0, #0
808; DISABLE-V4T-NEXT:    movs r1, #10
809; DISABLE-V4T-NEXT:  LBB5_2: @ %for.body
810; DISABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
811; DISABLE-V4T-NEXT:    @ InlineAsm Start
812; DISABLE-V4T-NEXT:    movs r2, #1
813; DISABLE-V4T-NEXT:    @ InlineAsm End
814; DISABLE-V4T-NEXT:    adds r0, r2, r0
815; DISABLE-V4T-NEXT:    subs r1, r1, #1
816; DISABLE-V4T-NEXT:    bne LBB5_2
817; DISABLE-V4T-NEXT:  @ %bb.3: @ %for.end
818; DISABLE-V4T-NEXT:    lsls r0, r0, #3
819; DISABLE-V4T-NEXT:    b LBB5_5
820; DISABLE-V4T-NEXT:  LBB5_4: @ %if.else
821; DISABLE-V4T-NEXT:    lsls r0, r1, #1
822; DISABLE-V4T-NEXT:  LBB5_5: @ %if.end
823; DISABLE-V4T-NEXT:    pop {r4}
824; DISABLE-V4T-NEXT:    pop {r1}
825; DISABLE-V4T-NEXT:    bx r1
826; DISABLE-V4T-NEXT:    @ -- End function
827; DISABLE-V4T-NEXT:    .globl _emptyFrame @ -- Begin function emptyFrame
828; DISABLE-V4T-NEXT:    .p2align 1
829; DISABLE-V4T-NEXT:    .code 16 @ @emptyFrame
830; DISABLE-V4T-NEXT:    .thumb_func _emptyFrame
831; DISABLE-V4T-NEXT:  _emptyFrame:
832; DISABLE-V4T-NEXT:    .cfi_startproc
833; DISABLE-V4T-NEXT:  @ %bb.0: @ %entry
834; DISABLE-V4T-NEXT:    movs r0, #0
835; DISABLE-V4T-NEXT:    bx lr
836;
837; DISABLE-V5T-LABEL: loopInfoRestoreOutsideLoop:
838; DISABLE-V5T:       @ %bb.0: @ %entry
839; DISABLE-V5T-NEXT:    push {r4, lr}
840; DISABLE-V5T-NEXT:    cmp r0, #0
841; DISABLE-V5T-NEXT:    beq LBB5_4
842; DISABLE-V5T-NEXT:  @ %bb.1: @ %if.then
843; DISABLE-V5T-NEXT:    @ InlineAsm Start
844; DISABLE-V5T-NEXT:    mov r8, r8
845; DISABLE-V5T-NEXT:    @ InlineAsm End
846; DISABLE-V5T-NEXT:    movs r0, #0
847; DISABLE-V5T-NEXT:    movs r1, #10
848; DISABLE-V5T-NEXT:  LBB5_2: @ %for.body
849; DISABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
850; DISABLE-V5T-NEXT:    @ InlineAsm Start
851; DISABLE-V5T-NEXT:    movs r2, #1
852; DISABLE-V5T-NEXT:    @ InlineAsm End
853; DISABLE-V5T-NEXT:    adds r0, r2, r0
854; DISABLE-V5T-NEXT:    subs r1, r1, #1
855; DISABLE-V5T-NEXT:    bne LBB5_2
856; DISABLE-V5T-NEXT:  @ %bb.3: @ %for.end
857; DISABLE-V5T-NEXT:    lsls r0, r0, #3
858; DISABLE-V5T-NEXT:    pop {r4, pc}
859; DISABLE-V5T-NEXT:  LBB5_4: @ %if.else
860; DISABLE-V5T-NEXT:    lsls r0, r1, #1
861; DISABLE-V5T-NEXT:    pop {r4, pc}
862; DISABLE-V5T-NEXT:    @ -- End function
863; DISABLE-V5T-NEXT:    .globl _emptyFrame @ -- Begin function emptyFrame
864; DISABLE-V5T-NEXT:    .p2align 1
865; DISABLE-V5T-NEXT:    .code 16 @ @emptyFrame
866; DISABLE-V5T-NEXT:    .thumb_func _emptyFrame
867; DISABLE-V5T-NEXT:  _emptyFrame:
868; DISABLE-V5T-NEXT:    .cfi_startproc
869; DISABLE-V5T-NEXT:  @ %bb.0: @ %entry
870; DISABLE-V5T-NEXT:    movs r0, #0
871; DISABLE-V5T-NEXT:    bx lr
872entry:
873  %tobool = icmp eq i32 %cond, 0
874  br i1 %tobool, label %if.else, label %if.then
875
876if.then:                                          ; preds = %entry
877  tail call void asm "nop", "~{r4}"()
878  br label %for.body
879
880for.body:                                         ; preds = %for.body, %if.then
881  %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ]
882  %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
883  %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
884  %add = add nsw i32 %call, %sum.04
885  %inc = add nuw nsw i32 %i.05, 1
886  %exitcond = icmp eq i32 %inc, 10
887  br i1 %exitcond, label %for.end, label %for.body
888
889for.end:                                          ; preds = %for.body
890  %shl = shl i32 %add, 3
891  br label %if.end
892
893if.else:                                          ; preds = %entry
894  %mul = shl nsw i32 %N, 1
895  br label %if.end
896
897if.end:                                           ; preds = %if.else, %for.end
898  %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
899  ret i32 %sum.1
900}
901
902; Check that we handle function with no frame information correctly.
903define i32 @emptyFrame() {
904entry:
905  ret i32 0
906}
907
908; Check that we handle inline asm correctly.
909define i32 @inlineAsm(i32 %cond, i32 %N) {
910; ENABLE-V4T-LABEL: inlineAsm:
911; ENABLE-V4T:       @ %bb.0: @ %entry
912; ENABLE-V4T-NEXT:    cmp r0, #0
913; ENABLE-V4T-NEXT:    beq LBB7_4
914; ENABLE-V4T-NEXT:  @ %bb.1: @ %for.preheader
915; ENABLE-V4T-NEXT:    push {r4, lr}
916; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
917; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
918; ENABLE-V4T-NEXT:    .cfi_offset r4, -8
919; ENABLE-V4T-NEXT:    @ InlineAsm Start
920; ENABLE-V4T-NEXT:    mov r8, r8
921; ENABLE-V4T-NEXT:    @ InlineAsm End
922; ENABLE-V4T-NEXT:    movs r0, #10
923; ENABLE-V4T-NEXT:  LBB7_2: @ %for.body
924; ENABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
925; ENABLE-V4T-NEXT:    @ InlineAsm Start
926; ENABLE-V4T-NEXT:    movs r4, #1
927; ENABLE-V4T-NEXT:    @ InlineAsm End
928; ENABLE-V4T-NEXT:    subs r0, r0, #1
929; ENABLE-V4T-NEXT:    bne LBB7_2
930; ENABLE-V4T-NEXT:  @ %bb.3: @ %for.exit
931; ENABLE-V4T-NEXT:    @ InlineAsm Start
932; ENABLE-V4T-NEXT:    mov r8, r8
933; ENABLE-V4T-NEXT:    @ InlineAsm End
934; ENABLE-V4T-NEXT:    movs r0, #0
935; ENABLE-V4T-NEXT:    pop {r4}
936; ENABLE-V4T-NEXT:    pop {r1}
937; ENABLE-V4T-NEXT:    bx r1
938; ENABLE-V4T-NEXT:  LBB7_4: @ %if.else
939; ENABLE-V4T-NEXT:    lsls r0, r1, #1
940; ENABLE-V4T-NEXT:    bx lr
941;
942; ENABLE-V5T-LABEL: inlineAsm:
943; ENABLE-V5T:       @ %bb.0: @ %entry
944; ENABLE-V5T-NEXT:    cmp r0, #0
945; ENABLE-V5T-NEXT:    beq LBB7_4
946; ENABLE-V5T-NEXT:  @ %bb.1: @ %for.preheader
947; ENABLE-V5T-NEXT:    push {r4, lr}
948; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
949; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
950; ENABLE-V5T-NEXT:    .cfi_offset r4, -8
951; ENABLE-V5T-NEXT:    @ InlineAsm Start
952; ENABLE-V5T-NEXT:    mov r8, r8
953; ENABLE-V5T-NEXT:    @ InlineAsm End
954; ENABLE-V5T-NEXT:    movs r0, #10
955; ENABLE-V5T-NEXT:  LBB7_2: @ %for.body
956; ENABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
957; ENABLE-V5T-NEXT:    @ InlineAsm Start
958; ENABLE-V5T-NEXT:    movs r4, #1
959; ENABLE-V5T-NEXT:    @ InlineAsm End
960; ENABLE-V5T-NEXT:    subs r0, r0, #1
961; ENABLE-V5T-NEXT:    bne LBB7_2
962; ENABLE-V5T-NEXT:  @ %bb.3: @ %for.exit
963; ENABLE-V5T-NEXT:    @ InlineAsm Start
964; ENABLE-V5T-NEXT:    mov r8, r8
965; ENABLE-V5T-NEXT:    @ InlineAsm End
966; ENABLE-V5T-NEXT:    movs r0, #0
967; ENABLE-V5T-NEXT:    pop {r4, pc}
968; ENABLE-V5T-NEXT:  LBB7_4: @ %if.else
969; ENABLE-V5T-NEXT:    lsls r0, r1, #1
970; ENABLE-V5T-NEXT:  LBB7_5: @ %if.end
971; ENABLE-V5T-NEXT:    bx lr
972;
973; DISABLE-V4T-LABEL: inlineAsm:
974; DISABLE-V4T:       @ %bb.0: @ %entry
975; DISABLE-V4T-NEXT:    push {r4, lr}
976; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
977; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
978; DISABLE-V4T-NEXT:    .cfi_offset r4, -8
979; DISABLE-V4T-NEXT:    cmp r0, #0
980; DISABLE-V4T-NEXT:    beq LBB7_4
981; DISABLE-V4T-NEXT:  @ %bb.1: @ %for.preheader
982; DISABLE-V4T-NEXT:    @ InlineAsm Start
983; DISABLE-V4T-NEXT:    mov r8, r8
984; DISABLE-V4T-NEXT:    @ InlineAsm End
985; DISABLE-V4T-NEXT:    movs r0, #10
986; DISABLE-V4T-NEXT:  LBB7_2: @ %for.body
987; DISABLE-V4T-NEXT:    @ =>This Inner Loop Header: Depth=1
988; DISABLE-V4T-NEXT:    @ InlineAsm Start
989; DISABLE-V4T-NEXT:    movs r4, #1
990; DISABLE-V4T-NEXT:    @ InlineAsm End
991; DISABLE-V4T-NEXT:    subs r0, r0, #1
992; DISABLE-V4T-NEXT:    bne LBB7_2
993; DISABLE-V4T-NEXT:  @ %bb.3: @ %for.exit
994; DISABLE-V4T-NEXT:    @ InlineAsm Start
995; DISABLE-V4T-NEXT:    mov r8, r8
996; DISABLE-V4T-NEXT:    @ InlineAsm End
997; DISABLE-V4T-NEXT:    movs r0, #0
998; DISABLE-V4T-NEXT:    b LBB7_5
999; DISABLE-V4T-NEXT:  LBB7_4: @ %if.else
1000; DISABLE-V4T-NEXT:    lsls r0, r1, #1
1001; DISABLE-V4T-NEXT:  LBB7_5: @ %if.end
1002; DISABLE-V4T-NEXT:    pop {r4}
1003; DISABLE-V4T-NEXT:    pop {r1}
1004; DISABLE-V4T-NEXT:    bx r1
1005;
1006; DISABLE-V5T-LABEL: inlineAsm:
1007; DISABLE-V5T:       @ %bb.0: @ %entry
1008; DISABLE-V5T-NEXT:    push {r4, lr}
1009; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
1010; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
1011; DISABLE-V5T-NEXT:    .cfi_offset r4, -8
1012; DISABLE-V5T-NEXT:    cmp r0, #0
1013; DISABLE-V5T-NEXT:    beq LBB7_4
1014; DISABLE-V5T-NEXT:  @ %bb.1: @ %for.preheader
1015; DISABLE-V5T-NEXT:    @ InlineAsm Start
1016; DISABLE-V5T-NEXT:    mov r8, r8
1017; DISABLE-V5T-NEXT:    @ InlineAsm End
1018; DISABLE-V5T-NEXT:    movs r0, #10
1019; DISABLE-V5T-NEXT:  LBB7_2: @ %for.body
1020; DISABLE-V5T-NEXT:    @ =>This Inner Loop Header: Depth=1
1021; DISABLE-V5T-NEXT:    @ InlineAsm Start
1022; DISABLE-V5T-NEXT:    movs r4, #1
1023; DISABLE-V5T-NEXT:    @ InlineAsm End
1024; DISABLE-V5T-NEXT:    subs r0, r0, #1
1025; DISABLE-V5T-NEXT:    bne LBB7_2
1026; DISABLE-V5T-NEXT:  @ %bb.3: @ %for.exit
1027; DISABLE-V5T-NEXT:    @ InlineAsm Start
1028; DISABLE-V5T-NEXT:    mov r8, r8
1029; DISABLE-V5T-NEXT:    @ InlineAsm End
1030; DISABLE-V5T-NEXT:    movs r0, #0
1031; DISABLE-V5T-NEXT:    pop {r4, pc}
1032; DISABLE-V5T-NEXT:  LBB7_4: @ %if.else
1033; DISABLE-V5T-NEXT:    lsls r0, r1, #1
1034; DISABLE-V5T-NEXT:    pop {r4, pc}
1035entry:
1036  %tobool = icmp eq i32 %cond, 0
1037  br i1 %tobool, label %if.else, label %for.preheader
1038
1039for.preheader:
1040  tail call void asm "nop", ""()
1041  br label %for.body
1042
1043for.body:                                         ; preds = %entry, %for.body
1044  %i.03 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
1045  tail call void asm sideeffect "movs r4, #1", "~{r4}"()
1046  %inc = add nuw nsw i32 %i.03, 1
1047  %exitcond = icmp eq i32 %inc, 10
1048  br i1 %exitcond, label %for.exit, label %for.body
1049
1050for.exit:
1051  tail call void asm "nop", ""()
1052  br label %if.end
1053
1054if.else:                                          ; preds = %entry
1055  %mul = shl nsw i32 %N, 1
1056  br label %if.end
1057
1058if.end:                                           ; preds = %for.body, %if.else
1059  %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.exit ]
1060  ret i32 %sum.0
1061}
1062
1063; Check that we handle calls to variadic functions correctly.
1064define i32 @callVariadicFunc(i32 %cond, i32 %N) {
1065; ENABLE-V4T-LABEL: callVariadicFunc:
1066; ENABLE-V4T:       @ %bb.0: @ %entry
1067; ENABLE-V4T-NEXT:    cmp r0, #0
1068; ENABLE-V4T-NEXT:    beq LBB8_2
1069; ENABLE-V4T-NEXT:  @ %bb.1: @ %if.then
1070; ENABLE-V4T-NEXT:    push {r4, lr}
1071; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
1072; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
1073; ENABLE-V4T-NEXT:    .cfi_offset r4, -8
1074; ENABLE-V4T-NEXT:    sub sp, #16
1075; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 24
1076; ENABLE-V4T-NEXT:    str r1, [sp]
1077; ENABLE-V4T-NEXT:    str r1, [sp, #4]
1078; ENABLE-V4T-NEXT:    str r1, [sp, #8]
1079; ENABLE-V4T-NEXT:    ldr r0, LCPI8_0
1080; ENABLE-V4T-NEXT:  LPC8_0:
1081; ENABLE-V4T-NEXT:    add r0, pc
1082; ENABLE-V4T-NEXT:    ldr r4, [r0]
1083; ENABLE-V4T-NEXT:    movs r0, r1
1084; ENABLE-V4T-NEXT:    movs r2, r1
1085; ENABLE-V4T-NEXT:    movs r3, r1
1086; ENABLE-V4T-NEXT:    bl Ltmp2
1087; ENABLE-V4T-NEXT:    lsls r0, r0, #3
1088; ENABLE-V4T-NEXT:    add sp, #16
1089; ENABLE-V4T-NEXT:    pop {r4}
1090; ENABLE-V4T-NEXT:    pop {r1}
1091; ENABLE-V4T-NEXT:    bx r1
1092; ENABLE-V4T-NEXT:  LBB8_2: @ %if.else
1093; ENABLE-V4T-NEXT:    lsls r0, r1, #1
1094; ENABLE-V4T-NEXT:    bx lr
1095; ENABLE-V4T-NEXT:    .p2align 2
1096; ENABLE-V4T-NEXT:  @ %bb.3:
1097; ENABLE-V4T-NEXT:    .data_region
1098; ENABLE-V4T-NEXT:  LCPI8_0:
1099; ENABLE-V4T-NEXT:    .long L_someVariadicFunc$non_lazy_ptr-(LPC8_0+4)
1100; ENABLE-V4T-NEXT:    .end_data_region
1101;
1102; ENABLE-V5T-LABEL: callVariadicFunc:
1103; ENABLE-V5T:       @ %bb.0: @ %entry
1104; ENABLE-V5T-NEXT:    cmp r0, #0
1105; ENABLE-V5T-NEXT:    beq LBB8_2
1106; ENABLE-V5T-NEXT:  @ %bb.1: @ %if.then
1107; ENABLE-V5T-NEXT:    push {r7, lr}
1108; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
1109; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
1110; ENABLE-V5T-NEXT:    .cfi_offset r7, -8
1111; ENABLE-V5T-NEXT:    sub sp, #16
1112; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 24
1113; ENABLE-V5T-NEXT:    str r1, [sp]
1114; ENABLE-V5T-NEXT:    str r1, [sp, #4]
1115; ENABLE-V5T-NEXT:    str r1, [sp, #8]
1116; ENABLE-V5T-NEXT:    movs r0, r1
1117; ENABLE-V5T-NEXT:    movs r2, r1
1118; ENABLE-V5T-NEXT:    movs r3, r1
1119; ENABLE-V5T-NEXT:    bl _someVariadicFunc
1120; ENABLE-V5T-NEXT:    lsls r0, r0, #3
1121; ENABLE-V5T-NEXT:    add sp, #16
1122; ENABLE-V5T-NEXT:    pop {r7, pc}
1123; ENABLE-V5T-NEXT:  LBB8_2: @ %if.else
1124; ENABLE-V5T-NEXT:    lsls r0, r1, #1
1125; ENABLE-V5T-NEXT:  LBB8_3: @ %if.end
1126; ENABLE-V5T-NEXT:    bx lr
1127;
1128; DISABLE-V4T-LABEL: callVariadicFunc:
1129; DISABLE-V4T:       @ %bb.0: @ %entry
1130; DISABLE-V4T-NEXT:    push {r4, lr}
1131; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
1132; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
1133; DISABLE-V4T-NEXT:    .cfi_offset r4, -8
1134; DISABLE-V4T-NEXT:    sub sp, #16
1135; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 24
1136; DISABLE-V4T-NEXT:    cmp r0, #0
1137; DISABLE-V4T-NEXT:    beq LBB8_2
1138; DISABLE-V4T-NEXT:  @ %bb.1: @ %if.then
1139; DISABLE-V4T-NEXT:    str r1, [sp]
1140; DISABLE-V4T-NEXT:    str r1, [sp, #4]
1141; DISABLE-V4T-NEXT:    str r1, [sp, #8]
1142; DISABLE-V4T-NEXT:    ldr r0, LCPI8_0
1143; DISABLE-V4T-NEXT:  LPC8_0:
1144; DISABLE-V4T-NEXT:    add r0, pc
1145; DISABLE-V4T-NEXT:    ldr r4, [r0]
1146; DISABLE-V4T-NEXT:    movs r0, r1
1147; DISABLE-V4T-NEXT:    movs r2, r1
1148; DISABLE-V4T-NEXT:    movs r3, r1
1149; DISABLE-V4T-NEXT:    bl Ltmp2
1150; DISABLE-V4T-NEXT:    lsls r0, r0, #3
1151; DISABLE-V4T-NEXT:    b LBB8_3
1152; DISABLE-V4T-NEXT:  LBB8_2: @ %if.else
1153; DISABLE-V4T-NEXT:    lsls r0, r1, #1
1154; DISABLE-V4T-NEXT:  LBB8_3: @ %if.end
1155; DISABLE-V4T-NEXT:    add sp, #16
1156; DISABLE-V4T-NEXT:    pop {r4}
1157; DISABLE-V4T-NEXT:    pop {r1}
1158; DISABLE-V4T-NEXT:    bx r1
1159; DISABLE-V4T-NEXT:    .p2align 2
1160; DISABLE-V4T-NEXT:  @ %bb.4:
1161; DISABLE-V4T-NEXT:    .data_region
1162; DISABLE-V4T-NEXT:  LCPI8_0:
1163; DISABLE-V4T-NEXT:    .long L_someVariadicFunc$non_lazy_ptr-(LPC8_0+4)
1164; DISABLE-V4T-NEXT:    .end_data_region
1165;
1166; DISABLE-V5T-LABEL: callVariadicFunc:
1167; DISABLE-V5T:       @ %bb.0: @ %entry
1168; DISABLE-V5T-NEXT:    push {r7, lr}
1169; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
1170; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
1171; DISABLE-V5T-NEXT:    .cfi_offset r7, -8
1172; DISABLE-V5T-NEXT:    sub sp, #16
1173; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 24
1174; DISABLE-V5T-NEXT:    cmp r0, #0
1175; DISABLE-V5T-NEXT:    beq LBB8_2
1176; DISABLE-V5T-NEXT:  @ %bb.1: @ %if.then
1177; DISABLE-V5T-NEXT:    str r1, [sp]
1178; DISABLE-V5T-NEXT:    str r1, [sp, #4]
1179; DISABLE-V5T-NEXT:    str r1, [sp, #8]
1180; DISABLE-V5T-NEXT:    movs r0, r1
1181; DISABLE-V5T-NEXT:    movs r2, r1
1182; DISABLE-V5T-NEXT:    movs r3, r1
1183; DISABLE-V5T-NEXT:    bl _someVariadicFunc
1184; DISABLE-V5T-NEXT:    lsls r0, r0, #3
1185; DISABLE-V5T-NEXT:    add sp, #16
1186; DISABLE-V5T-NEXT:    pop {r7, pc}
1187; DISABLE-V5T-NEXT:  LBB8_2: @ %if.else
1188; DISABLE-V5T-NEXT:    lsls r0, r1, #1
1189; DISABLE-V5T-NEXT:    add sp, #16
1190; DISABLE-V5T-NEXT:    pop {r7, pc}
1191entry:
1192  %tobool = icmp eq i32 %cond, 0
1193  br i1 %tobool, label %if.else, label %if.then
1194
1195if.then:                                          ; preds = %entry
1196  %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N)
1197  %shl = shl i32 %call, 3
1198  br label %if.end
1199
1200if.else:                                          ; preds = %entry
1201  %mul = shl nsw i32 %N, 1
1202  br label %if.end
1203
1204if.end:                                           ; preds = %if.else, %if.then
1205  %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
1206  ret i32 %sum.0
1207}
1208
1209declare i32 @someVariadicFunc(i32, ...)
1210
1211; Make sure we do not insert unreachable code after noreturn function.
1212; Although this is not incorrect to insert such code, it is useless
1213; and it hurts the binary size.
1214;
1215define i32 @noreturn(i8 signext %bad_thing) {
1216; ENABLE-V4T-LABEL: noreturn:
1217; ENABLE-V4T:       @ %bb.0: @ %entry
1218; ENABLE-V4T-NEXT:    cmp r0, #0
1219; ENABLE-V4T-NEXT:    bne LBB9_2
1220; ENABLE-V4T-NEXT:  @ %bb.1: @ %if.end
1221; ENABLE-V4T-NEXT:    movs r0, #42
1222; ENABLE-V4T-NEXT:    bx lr
1223; ENABLE-V4T-NEXT:  LBB9_2: @ %if.abort
1224; ENABLE-V4T-NEXT:    push {r4, lr}
1225; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
1226; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
1227; ENABLE-V4T-NEXT:    .cfi_offset r4, -8
1228; ENABLE-V4T-NEXT:    ldr r0, LCPI9_0
1229; ENABLE-V4T-NEXT:  LPC9_0:
1230; ENABLE-V4T-NEXT:    add r0, pc
1231; ENABLE-V4T-NEXT:    ldr r0, [r0]
1232; ENABLE-V4T-NEXT:    @ InlineAsm Start
1233; ENABLE-V4T-NEXT:    movs r1, #1
1234; ENABLE-V4T-NEXT:    @ InlineAsm End
1235; ENABLE-V4T-NEXT:    bl Ltmp3
1236; ENABLE-V4T-NEXT:    .p2align 2
1237; ENABLE-V4T-NEXT:  @ %bb.3:
1238; ENABLE-V4T-NEXT:    .data_region
1239; ENABLE-V4T-NEXT:  LCPI9_0:
1240; ENABLE-V4T-NEXT:    .long L_abort$non_lazy_ptr-(LPC9_0+4)
1241; ENABLE-V4T-NEXT:    .end_data_region
1242;
1243; ENABLE-V5T-LABEL: noreturn:
1244; ENABLE-V5T:       @ %bb.0: @ %entry
1245; ENABLE-V5T-NEXT:    cmp r0, #0
1246; ENABLE-V5T-NEXT:    bne LBB9_2
1247; ENABLE-V5T-NEXT:  @ %bb.1: @ %if.end
1248; ENABLE-V5T-NEXT:    movs r0, #42
1249; ENABLE-V5T-NEXT:    bx lr
1250; ENABLE-V5T-NEXT:  LBB9_2: @ %if.abort
1251; ENABLE-V5T-NEXT:    push {r4, lr}
1252; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
1253; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
1254; ENABLE-V5T-NEXT:    .cfi_offset r4, -8
1255; ENABLE-V5T-NEXT:    @ InlineAsm Start
1256; ENABLE-V5T-NEXT:    movs r0, #1
1257; ENABLE-V5T-NEXT:    @ InlineAsm End
1258; ENABLE-V5T-NEXT:    bl _abort
1259;
1260; DISABLE-V4T-LABEL: noreturn:
1261; DISABLE-V4T:       @ %bb.0: @ %entry
1262; DISABLE-V4T-NEXT:    push {r4, lr}
1263; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
1264; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
1265; DISABLE-V4T-NEXT:    .cfi_offset r4, -8
1266; DISABLE-V4T-NEXT:    cmp r0, #0
1267; DISABLE-V4T-NEXT:    bne LBB9_2
1268; DISABLE-V4T-NEXT:  @ %bb.1: @ %if.end
1269; DISABLE-V4T-NEXT:    movs r0, #42
1270; DISABLE-V4T-NEXT:    pop {r4}
1271; DISABLE-V4T-NEXT:    pop {r1}
1272; DISABLE-V4T-NEXT:    bx r1
1273; DISABLE-V4T-NEXT:  LBB9_2: @ %if.abort
1274; DISABLE-V4T-NEXT:    ldr r0, LCPI9_0
1275; DISABLE-V4T-NEXT:  LPC9_0:
1276; DISABLE-V4T-NEXT:    add r0, pc
1277; DISABLE-V4T-NEXT:    ldr r0, [r0]
1278; DISABLE-V4T-NEXT:    @ InlineAsm Start
1279; DISABLE-V4T-NEXT:    movs r1, #1
1280; DISABLE-V4T-NEXT:    @ InlineAsm End
1281; DISABLE-V4T-NEXT:    bl Ltmp3
1282; DISABLE-V4T-NEXT:    .p2align 2
1283; DISABLE-V4T-NEXT:  @ %bb.3:
1284; DISABLE-V4T-NEXT:    .data_region
1285; DISABLE-V4T-NEXT:  LCPI9_0:
1286; DISABLE-V4T-NEXT:    .long L_abort$non_lazy_ptr-(LPC9_0+4)
1287; DISABLE-V4T-NEXT:    .end_data_region
1288;
1289; DISABLE-V5T-LABEL: noreturn:
1290; DISABLE-V5T:       @ %bb.0: @ %entry
1291; DISABLE-V5T-NEXT:    push {r4, lr}
1292; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
1293; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
1294; DISABLE-V5T-NEXT:    .cfi_offset r4, -8
1295; DISABLE-V5T-NEXT:    cmp r0, #0
1296; DISABLE-V5T-NEXT:    bne LBB9_2
1297; DISABLE-V5T-NEXT:  @ %bb.1: @ %if.end
1298; DISABLE-V5T-NEXT:    movs r0, #42
1299; DISABLE-V5T-NEXT:    pop {r4, pc}
1300; DISABLE-V5T-NEXT:  LBB9_2: @ %if.abort
1301; DISABLE-V5T-NEXT:    @ InlineAsm Start
1302; DISABLE-V5T-NEXT:    movs r0, #1
1303; DISABLE-V5T-NEXT:    @ InlineAsm End
1304; DISABLE-V5T-NEXT:    bl _abort
1305entry:
1306  %tobool = icmp eq i8 %bad_thing, 0
1307  br i1 %tobool, label %if.end, label %if.abort
1308
1309if.abort:
1310  %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"()
1311  tail call void @abort() #0
1312  unreachable
1313
1314if.end:
1315  ret i32 42
1316}
1317
1318declare void @abort() #0
1319
1320define i32 @b_to_bx(i32 %value) {
1321; ENABLE-V4T-LABEL: b_to_bx:
1322; ENABLE-V4T:       @ %bb.0: @ %entry
1323; ENABLE-V4T-NEXT:    movs r1, r0
1324; ENABLE-V4T-NEXT:    cmp r0, #49
1325; ENABLE-V4T-NEXT:    bgt LBB10_2
1326; ENABLE-V4T-NEXT:  @ %bb.1: @ %if.then
1327; ENABLE-V4T-NEXT:    push {r7, lr}
1328; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
1329; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
1330; ENABLE-V4T-NEXT:    .cfi_offset r7, -8
1331; ENABLE-V4T-NEXT:    ldr r0, LCPI10_0
1332; ENABLE-V4T-NEXT:    ldr r2, LCPI10_1
1333; ENABLE-V4T-NEXT:  LPC10_0:
1334; ENABLE-V4T-NEXT:    add r2, pc
1335; ENABLE-V4T-NEXT:    bl Ltmp4
1336; ENABLE-V4T-NEXT:    pop {r7}
1337; ENABLE-V4T-NEXT:    pop {r1}
1338; ENABLE-V4T-NEXT:    bx r1
1339; ENABLE-V4T-NEXT:  LBB10_2: @ %if.else
1340; ENABLE-V4T-NEXT:    lsls r0, r1, #1
1341; ENABLE-V4T-NEXT:    bx lr
1342; ENABLE-V4T-NEXT:    .p2align 2
1343; ENABLE-V4T-NEXT:  @ %bb.3:
1344; ENABLE-V4T-NEXT:    .data_region
1345; ENABLE-V4T-NEXT:  LCPI10_0:
1346; ENABLE-V4T-NEXT:    .long 5000 @ 0x1388
1347; ENABLE-V4T-NEXT:  LCPI10_1:
1348; ENABLE-V4T-NEXT:    .long ___divsi3-(LPC10_0+4)
1349; ENABLE-V4T-NEXT:    .end_data_region
1350;
1351; ENABLE-V5T-LABEL: b_to_bx:
1352; ENABLE-V5T:       @ %bb.0: @ %entry
1353; ENABLE-V5T-NEXT:    movs r1, r0
1354; ENABLE-V5T-NEXT:    cmp r0, #49
1355; ENABLE-V5T-NEXT:    bgt LBB10_2
1356; ENABLE-V5T-NEXT:  @ %bb.1: @ %if.then
1357; ENABLE-V5T-NEXT:    push {r7, lr}
1358; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
1359; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
1360; ENABLE-V5T-NEXT:    .cfi_offset r7, -8
1361; ENABLE-V5T-NEXT:    ldr r0, LCPI10_0
1362; ENABLE-V5T-NEXT:    bl ___divsi3
1363; ENABLE-V5T-NEXT:    pop {r7, pc}
1364; ENABLE-V5T-NEXT:  LBB10_2: @ %if.else
1365; ENABLE-V5T-NEXT:    lsls r0, r1, #1
1366; ENABLE-V5T-NEXT:  LBB10_3: @ %if.end
1367; ENABLE-V5T-NEXT:    bx lr
1368; ENABLE-V5T-NEXT:    .p2align 2
1369; ENABLE-V5T-NEXT:  @ %bb.4:
1370; ENABLE-V5T-NEXT:    .data_region
1371; ENABLE-V5T-NEXT:  LCPI10_0:
1372; ENABLE-V5T-NEXT:    .long 5000 @ 0x1388
1373; ENABLE-V5T-NEXT:    .end_data_region
1374;
1375; DISABLE-V4T-LABEL: b_to_bx:
1376; DISABLE-V4T:       @ %bb.0: @ %entry
1377; DISABLE-V4T-NEXT:    push {r7, lr}
1378; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
1379; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
1380; DISABLE-V4T-NEXT:    .cfi_offset r7, -8
1381; DISABLE-V4T-NEXT:    movs r1, r0
1382; DISABLE-V4T-NEXT:    cmp r0, #49
1383; DISABLE-V4T-NEXT:    bgt LBB10_2
1384; DISABLE-V4T-NEXT:  @ %bb.1: @ %if.then
1385; DISABLE-V4T-NEXT:    ldr r0, LCPI10_0
1386; DISABLE-V4T-NEXT:    ldr r2, LCPI10_1
1387; DISABLE-V4T-NEXT:  LPC10_0:
1388; DISABLE-V4T-NEXT:    add r2, pc
1389; DISABLE-V4T-NEXT:    bl Ltmp4
1390; DISABLE-V4T-NEXT:    b LBB10_3
1391; DISABLE-V4T-NEXT:  LBB10_2: @ %if.else
1392; DISABLE-V4T-NEXT:    lsls r0, r1, #1
1393; DISABLE-V4T-NEXT:  LBB10_3: @ %if.end
1394; DISABLE-V4T-NEXT:    pop {r7}
1395; DISABLE-V4T-NEXT:    pop {r1}
1396; DISABLE-V4T-NEXT:    bx r1
1397; DISABLE-V4T-NEXT:    .p2align 2
1398; DISABLE-V4T-NEXT:  @ %bb.4:
1399; DISABLE-V4T-NEXT:    .data_region
1400; DISABLE-V4T-NEXT:  LCPI10_0:
1401; DISABLE-V4T-NEXT:    .long 5000 @ 0x1388
1402; DISABLE-V4T-NEXT:  LCPI10_1:
1403; DISABLE-V4T-NEXT:    .long ___divsi3-(LPC10_0+4)
1404; DISABLE-V4T-NEXT:    .end_data_region
1405;
1406; DISABLE-V5T-LABEL: b_to_bx:
1407; DISABLE-V5T:       @ %bb.0: @ %entry
1408; DISABLE-V5T-NEXT:    push {r7, lr}
1409; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
1410; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
1411; DISABLE-V5T-NEXT:    .cfi_offset r7, -8
1412; DISABLE-V5T-NEXT:    movs r1, r0
1413; DISABLE-V5T-NEXT:    cmp r0, #49
1414; DISABLE-V5T-NEXT:    bgt LBB10_2
1415; DISABLE-V5T-NEXT:  @ %bb.1: @ %if.then
1416; DISABLE-V5T-NEXT:    ldr r0, LCPI10_0
1417; DISABLE-V5T-NEXT:    bl ___divsi3
1418; DISABLE-V5T-NEXT:    pop {r7, pc}
1419; DISABLE-V5T-NEXT:  LBB10_2: @ %if.else
1420; DISABLE-V5T-NEXT:    lsls r0, r1, #1
1421; DISABLE-V5T-NEXT:    pop {r7, pc}
1422; DISABLE-V5T-NEXT:    .p2align 2
1423; DISABLE-V5T-NEXT:  @ %bb.3:
1424; DISABLE-V5T-NEXT:    .data_region
1425; DISABLE-V5T-NEXT:  LCPI10_0:
1426; DISABLE-V5T-NEXT:    .long 5000 @ 0x1388
1427; DISABLE-V5T-NEXT:    .end_data_region
1428entry:
1429  %cmp = icmp slt i32 %value, 50
1430  br i1 %cmp, label %if.then, label %if.else
1431
1432if.then:
1433  %div = sdiv i32 5000, %value
1434  br label %if.end
1435
1436if.else:
1437  %mul = shl nsw i32 %value, 1
1438  br label %if.end
1439
1440if.end:
1441  %value.addr.0 = phi i32 [ %div, %if.then ], [ %mul, %if.else ]
1442  ret i32 %value.addr.0
1443}
1444
1445define i1 @beq_to_bx(i32* %y, i32 %head) {
1446; ENABLE-V4T-LABEL: beq_to_bx:
1447; ENABLE-V4T:       @ %bb.0: @ %entry
1448; ENABLE-V4T-NEXT:    push {r4, lr}
1449; ENABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
1450; ENABLE-V4T-NEXT:    .cfi_offset lr, -4
1451; ENABLE-V4T-NEXT:    .cfi_offset r4, -8
1452; ENABLE-V4T-NEXT:    movs r2, r0
1453; ENABLE-V4T-NEXT:    movs r0, #1
1454; ENABLE-V4T-NEXT:    cmp r2, #0
1455; ENABLE-V4T-NEXT:    beq LBB11_3
1456; ENABLE-V4T-NEXT:  @ %bb.1: @ %if.end
1457; ENABLE-V4T-NEXT:    ldr r3, [r2]
1458; ENABLE-V4T-NEXT:    lsls r4, r3, #30
1459; ENABLE-V4T-NEXT:    bpl LBB11_3
1460; ENABLE-V4T-NEXT:  @ %bb.2: @ %if.end4
1461; ENABLE-V4T-NEXT:    str r1, [r2]
1462; ENABLE-V4T-NEXT:    str r3, [r2]
1463; ENABLE-V4T-NEXT:    movs r0, #0
1464; ENABLE-V4T-NEXT:  LBB11_3: @ %cleanup
1465; ENABLE-V4T-NEXT:    pop {r4}
1466; ENABLE-V4T-NEXT:    pop {r1}
1467; ENABLE-V4T-NEXT:    bx r1
1468;
1469; ENABLE-V5T-LABEL: beq_to_bx:
1470; ENABLE-V5T:       @ %bb.0: @ %entry
1471; ENABLE-V5T-NEXT:    push {r4, lr}
1472; ENABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
1473; ENABLE-V5T-NEXT:    .cfi_offset lr, -4
1474; ENABLE-V5T-NEXT:    .cfi_offset r4, -8
1475; ENABLE-V5T-NEXT:    movs r2, r0
1476; ENABLE-V5T-NEXT:    movs r0, #1
1477; ENABLE-V5T-NEXT:    cmp r2, #0
1478; ENABLE-V5T-NEXT:    beq LBB11_3
1479; ENABLE-V5T-NEXT:  @ %bb.1: @ %if.end
1480; ENABLE-V5T-NEXT:    ldr r3, [r2]
1481; ENABLE-V5T-NEXT:    lsls r4, r3, #30
1482; ENABLE-V5T-NEXT:    bpl LBB11_3
1483; ENABLE-V5T-NEXT:  @ %bb.2: @ %if.end4
1484; ENABLE-V5T-NEXT:    str r1, [r2]
1485; ENABLE-V5T-NEXT:    str r3, [r2]
1486; ENABLE-V5T-NEXT:    movs r0, #0
1487; ENABLE-V5T-NEXT:  LBB11_3: @ %cleanup
1488; ENABLE-V5T-NEXT:    pop {r4, pc}
1489;
1490; DISABLE-V4T-LABEL: beq_to_bx:
1491; DISABLE-V4T:       @ %bb.0: @ %entry
1492; DISABLE-V4T-NEXT:    push {r4, lr}
1493; DISABLE-V4T-NEXT:    .cfi_def_cfa_offset 8
1494; DISABLE-V4T-NEXT:    .cfi_offset lr, -4
1495; DISABLE-V4T-NEXT:    .cfi_offset r4, -8
1496; DISABLE-V4T-NEXT:    movs r2, r0
1497; DISABLE-V4T-NEXT:    movs r0, #1
1498; DISABLE-V4T-NEXT:    cmp r2, #0
1499; DISABLE-V4T-NEXT:    beq LBB11_3
1500; DISABLE-V4T-NEXT:  @ %bb.1: @ %if.end
1501; DISABLE-V4T-NEXT:    ldr r3, [r2]
1502; DISABLE-V4T-NEXT:    lsls r4, r3, #30
1503; DISABLE-V4T-NEXT:    bpl LBB11_3
1504; DISABLE-V4T-NEXT:  @ %bb.2: @ %if.end4
1505; DISABLE-V4T-NEXT:    str r1, [r2]
1506; DISABLE-V4T-NEXT:    str r3, [r2]
1507; DISABLE-V4T-NEXT:    movs r0, #0
1508; DISABLE-V4T-NEXT:  LBB11_3: @ %cleanup
1509; DISABLE-V4T-NEXT:    pop {r4}
1510; DISABLE-V4T-NEXT:    pop {r1}
1511; DISABLE-V4T-NEXT:    bx r1
1512;
1513; DISABLE-V5T-LABEL: beq_to_bx:
1514; DISABLE-V5T:       @ %bb.0: @ %entry
1515; DISABLE-V5T-NEXT:    push {r4, lr}
1516; DISABLE-V5T-NEXT:    .cfi_def_cfa_offset 8
1517; DISABLE-V5T-NEXT:    .cfi_offset lr, -4
1518; DISABLE-V5T-NEXT:    .cfi_offset r4, -8
1519; DISABLE-V5T-NEXT:    movs r2, r0
1520; DISABLE-V5T-NEXT:    movs r0, #1
1521; DISABLE-V5T-NEXT:    cmp r2, #0
1522; DISABLE-V5T-NEXT:    beq LBB11_3
1523; DISABLE-V5T-NEXT:  @ %bb.1: @ %if.end
1524; DISABLE-V5T-NEXT:    ldr r3, [r2]
1525; DISABLE-V5T-NEXT:    lsls r4, r3, #30
1526; DISABLE-V5T-NEXT:    bpl LBB11_3
1527; DISABLE-V5T-NEXT:  @ %bb.2: @ %if.end4
1528; DISABLE-V5T-NEXT:    str r1, [r2]
1529; DISABLE-V5T-NEXT:    str r3, [r2]
1530; DISABLE-V5T-NEXT:    movs r0, #0
1531; DISABLE-V5T-NEXT:  LBB11_3: @ %cleanup
1532; DISABLE-V5T-NEXT:    pop {r4, pc}
1533entry:
1534  %cmp = icmp eq i32* %y, null
1535  br i1 %cmp, label %cleanup, label %if.end
1536
1537if.end:
1538  %z = load i32, i32* %y, align 4
1539  %and = and i32 %z, 2
1540  %cmp2 = icmp eq i32 %and, 0
1541  br i1 %cmp2, label %cleanup, label %if.end4
1542
1543if.end4:
1544  store i32 %head, i32* %y, align 4
1545  store volatile i32 %z, i32* %y, align 4
1546  br label %cleanup
1547
1548cleanup:
1549  %retval.0 = phi i1 [ 0, %if.end4 ], [ 1, %entry ], [ 1, %if.end ]
1550  ret i1 %retval.0
1551}
1552
1553attributes #0 = { noreturn nounwind }
1554