llvm.org GIT mirror llvm / 8189e3d
ARM: stop emitting blx instructions for most calls on MachO. I'm really not sure why we were in the first place, it's the linker's job to convert between BL/BLX as necessary. Even worse, using BLX left Thumb calls that could be locally resolved completely unencodable since all offsets to BLX are multiples of 4. rdar://26182344 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269101 91177308-0d34-0410-b5e6-96231b3b80d8 Tim Northover 3 years ago
29 changed file(s) with 129 addition(s) and 180 deletion(s). Raw diff Collapse all Expand all
11181118 case ARMISD::CALL: return "ARMISD::CALL";
11191119 case ARMISD::CALL_PRED: return "ARMISD::CALL_PRED";
11201120 case ARMISD::CALL_NOLINK: return "ARMISD::CALL_NOLINK";
1121 case ARMISD::tCALL: return "ARMISD::tCALL";
11221121 case ARMISD::BRCOND: return "ARMISD::BRCOND";
11231122 case ARMISD::BR_JT: return "ARMISD::BR_JT";
11241123 case ARMISD::BR2_JT: return "ARMISD::BR2_JT";
19151914 if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
19161915 CallOpc = ARMISD::CALL_NOLINK;
19171916 else
1918 CallOpc = isARMFunc ? ARMISD::CALL : ARMISD::tCALL;
1917 CallOpc = ARMISD::CALL;
19191918 } else {
19201919 if (!isDirect && !Subtarget->hasV5TOps())
19211920 CallOpc = ARMISD::CALL_NOLINK;
4242 CALL, // Function call.
4343 CALL_PRED, // Function call that's predicable.
4444 CALL_NOLINK, // Function call with branch not branch-and-link.
45 tCALL, // Thumb function call.
4645 BRCOND, // Conditional branch.
4746 BR_JT, // Jumptable branch.
4847 BR2_JT, // Jumptable branch (2 level - jumptable entry is a jump).
1313 //===----------------------------------------------------------------------===//
1414 // Thumb specific DAG Nodes.
1515 //
16
17 def ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall,
18 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
19 SDNPVariadic]>;
2016
2117 def imm_sr_XFORM: SDNodeXForm
2218 unsigned Imm = N->getZExtValue();
467463 def tBL : TIx2<0b11110, 0b11, 1,
468464 (outs), (ins pred:$p, t_bltarget:$func), IIC_Br,
469465 "bl${p}\t$func",
470 [(ARMtcall tglobaladdr:$func)]>,
466 [(ARMcall tglobaladdr:$func)]>,
471467 Requires<[IsThumb]>, Sched<[WriteBrL]> {
472468 bits<24> func;
473469 let Inst{26} = func{23};
480476 // ARMv5T and above, also used for Thumb2
481477 def tBLXi : TIx2<0b11110, 0b11, 0,
482478 (outs), (ins pred:$p, t_blxtarget:$func), IIC_Br,
483 "blx${p}\t$func",
484 [(ARMcall tglobaladdr:$func)]>,
479 "blx${p}\t$func", []>,
485480 Requires<[IsThumb, HasV5T, IsNotMClass]>, Sched<[WriteBrL]> {
486481 bits<24> func;
487482 let Inst{26} = func{23};
495490 // Also used for Thumb2
496491 def tBLXr : TI<(outs), (ins pred:$p, GPR:$func), IIC_Br,
497492 "blx${p}\t$func",
498 [(ARMtcall GPR:$func)]>,
493 [(ARMcall GPR:$func)]>,
499494 Requires<[IsThumb, HasV5T]>,
500495 T1Special<{1,1,1,?}>, Sched<[WriteBrL]> { // A6.2.3 & A8.6.24;
501496 bits<4> func;
14051400 (tLEApcrelJT tjumptable:$dst)>;
14061401
14071402 // Direct calls
1408 def : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>,
1403 def : T1Pat<(ARMcall texternalsym:$func), (tBL texternalsym:$func)>,
14091404 Requires<[IsThumb]>;
14101405
1411 def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>,
1412 Requires<[IsThumb, HasV5T, IsNotMClass]>;
14131406
14141407 // Indirect calls to ARM routines
14151408 def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>,
None ; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=ARM
1 ; RUN: llc < %s -mtriple=thumbv7-apple-ios | FileCheck %s --check-prefix=THUMB2
0 ; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s
1 ; RUN: llc < %s -mtriple=thumbv7-apple-ios | FileCheck %s
22 ; rdar://8690640
33
44 define i32* @t(i32* %x) nounwind {
55 entry:
6 ; ARM-LABEL: t:
7 ; ARM: push
8 ; ARM: mov r7, sp
9 ; ARM: bl _foo
10 ; ARM: bl _foo
11 ; ARM: bl _foo
12 ; ARM: pop {r7, pc}
6 ; CHECK-LABEL: t:
7 ; CHECK: push
8 ; CHECK: mov r7, sp
9 ; CHECK: bl _foo
10 ; CHECK: bl _foo
11 ; CHECK: bl _foo
12 ; CHECK: pop {r7, pc}
1313
14 ; THUMB2-LABEL: t:
15 ; THUMB2: push
16 ; THUMB2: mov r7, sp
17 ; THUMB2: blx _foo
18 ; THUMB2: blx _foo
19 ; THUMB2: blx _foo
20 ; THUMB2: pop
2114 %0 = tail call i32* @foo(i32* %x) nounwind
2215 %1 = tail call i32* @foo(i32* %0) nounwind
2316 %2 = tail call i32* @foo(i32* %1) nounwind
22 ; CHECK: _f
33 ; CHECK-NOT: ands
44 ; CHECK: cmp
5 ; CHECK: blxle _g
5 ; CHECK: blle _g
66
77 define i32 @f(i32 %a, i32 %b) nounwind ssp {
88 entry:
22 ; CHECK: _f
33 ; CHECK: adds
44 ; CHECK-NOT: cmp
5 ; CHECK: blxeq _h
5 ; CHECK: bleq _h
66
77 define i32 @f(i32 %a, i32 %b) nounwind ssp {
88 entry:
2121 ; CHECK: _g
2222 ; CHECK: orrs
2323 ; CHECK-NOT: cmp
24 ; CHECK: blxeq _h
24 ; CHECK: bleq _h
2525
2626 define i32 @g(i32 %a, i32 %b) nounwind ssp {
2727 entry:
3737 bb1:
3838 ; CHECK: %bb1
3939 ; CHECK-NOT: umull
40 ; CHECK: blx _Get
40 ; CHECK: bl _Get
4141 ; CHECK: umull
42 ; CHECK: blx _foo
42 ; CHECK: bl _foo
4343 %tmp5 = load i32, i32* %block_size, align 4
4444 %tmp6 = load i32, i32* %block_count, align 4
4545 %tmp7 = call %struct.FF* @Get() nounwind
2828 @"\01_fnmatch.initial" = external constant %union.__mbstate_t, align 4
2929
3030 ; CHECK: _fnmatch
31 ; CHECK: blx _fnmatch1
31 ; CHECK: bl _fnmatch1
3232
3333 define i32 @"\01_fnmatch"(i8* %pattern, i8* %string, i32 %flags) nounwind optsize {
3434 entry:
0 ; RUN: llc < %s -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix CHECK-ARMV7
11 ; RUN: llc < %s -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-T2
22 ; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-T1
3 ; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs -mcpu=cortex-m0 | FileCheck %s --check-prefix=CHECK-M0
3 ; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs -mcpu=cortex-m0 | FileCheck %s --check-prefix=CHECK-T1
44 ; RUN: llc < %s -mtriple=thumbv7--none-eabi -thread-model single -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-BAREMETAL
55
66 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
2828 ; CHECK: ldrex
2929 ; CHECK: add
3030 ; CHECK: strex
31 ; CHECK-T1: blx ___sync_fetch_and_add_4
32 ; CHECK-M0: bl ___sync_fetch_and_add_4
31 ; CHECK-T1: bl ___sync_fetch_and_add_4
3332 ; CHECK-BAREMETAL: add
3433 ; CHECK-BAREMETAL-NOT: __sync
3534 %0 = atomicrmw add i32* %val1, i32 %tmp monotonic
3736 ; CHECK: ldrex
3837 ; CHECK: sub
3938 ; CHECK: strex
40 ; CHECK-T1: blx ___sync_fetch_and_sub_4
41 ; CHECK-M0: bl ___sync_fetch_and_sub_4
39 ; CHECK-T1: bl ___sync_fetch_and_sub_4
4240 ; CHECK-BAREMETAL: sub
4341 ; CHECK-BAREMETAL-NOT: __sync
4442 %1 = atomicrmw sub i32* %val2, i32 30 monotonic
4644 ; CHECK: ldrex
4745 ; CHECK: add
4846 ; CHECK: strex
49 ; CHECK-T1: blx ___sync_fetch_and_add_4
50 ; CHECK-M0: bl ___sync_fetch_and_add_4
47 ; CHECK-T1: bl ___sync_fetch_and_add_4
5148 ; CHECK-BAREMETAL: add
5249 ; CHECK-BAREMETAL-NOT: __sync
5350 %2 = atomicrmw add i32* %val2, i32 1 monotonic
5552 ; CHECK: ldrex
5653 ; CHECK: sub
5754 ; CHECK: strex
58 ; CHECK-T1: blx ___sync_fetch_and_sub_4
59 ; CHECK-M0: bl ___sync_fetch_and_sub_4
55 ; CHECK-T1: bl ___sync_fetch_and_sub_4
6056 ; CHECK-BAREMETAL: sub
6157 ; CHECK-BAREMETAL-NOT: __sync
6258 %3 = atomicrmw sub i32* %val2, i32 1 monotonic
6460 ; CHECK: ldrex
6561 ; CHECK: and
6662 ; CHECK: strex
67 ; CHECK-T1: blx ___sync_fetch_and_and_4
68 ; CHECK-M0: bl ___sync_fetch_and_and_4
63 ; CHECK-T1: bl ___sync_fetch_and_and_4
6964 ; CHECK-BAREMETAL: and
7065 ; CHECK-BAREMETAL-NOT: __sync
7166 %4 = atomicrmw and i32* %andt, i32 4080 monotonic
7368 ; CHECK: ldrex
7469 ; CHECK: or
7570 ; CHECK: strex
76 ; CHECK-T1: blx ___sync_fetch_and_or_4
77 ; CHECK-M0: bl ___sync_fetch_and_or_4
71 ; CHECK-T1: bl ___sync_fetch_and_or_4
7872 ; CHECK-BAREMETAL: or
7973 ; CHECK-BAREMETAL-NOT: __sync
8074 %5 = atomicrmw or i32* %ort, i32 4080 monotonic
8276 ; CHECK: ldrex
8377 ; CHECK: eor
8478 ; CHECK: strex
85 ; CHECK-T1: blx ___sync_fetch_and_xor_4
86 ; CHECK-M0: bl ___sync_fetch_and_xor_4
79 ; CHECK-T1: bl ___sync_fetch_and_xor_4
8780 ; CHECK-BAREMETAL: eor
8881 ; CHECK-BAREMETAL-NOT: __sync
8982 %6 = atomicrmw xor i32* %xort, i32 4080 monotonic
9184 ; CHECK: ldrex
9285 ; CHECK: cmp
9386 ; CHECK: strex
94 ; CHECK-T1: blx ___sync_fetch_and_min_4
95 ; CHECK-M0: bl ___sync_fetch_and_min_4
87 ; CHECK-T1: bl ___sync_fetch_and_min_4
9688 ; CHECK-BAREMETAL: cmp
9789 ; CHECK-BAREMETAL-NOT: __sync
9890 %7 = atomicrmw min i32* %val2, i32 16 monotonic
10193 ; CHECK: ldrex
10294 ; CHECK: cmp
10395 ; CHECK: strex
104 ; CHECK-T1: blx ___sync_fetch_and_min_4
105 ; CHECK-M0: bl ___sync_fetch_and_min_4
96 ; CHECK-T1: bl ___sync_fetch_and_min_4
10697 ; CHECK-BAREMETAL: cmp
10798 ; CHECK-BAREMETAL-NOT: __sync
10899 %8 = atomicrmw min i32* %val2, i32 %neg monotonic
110101 ; CHECK: ldrex
111102 ; CHECK: cmp
112103 ; CHECK: strex
113 ; CHECK-T1: blx ___sync_fetch_and_max_4
114 ; CHECK-M0: bl ___sync_fetch_and_max_4
104 ; CHECK-T1: bl ___sync_fetch_and_max_4
115105 ; CHECK-BAREMETAL: cmp
116106 ; CHECK-BAREMETAL-NOT: __sync
117107 %9 = atomicrmw max i32* %val2, i32 1 monotonic
119109 ; CHECK: ldrex
120110 ; CHECK: cmp
121111 ; CHECK: strex
122 ; CHECK-T1: blx ___sync_fetch_and_max_4
123 ; CHECK-M0: bl ___sync_fetch_and_max_4
112 ; CHECK-T1: bl ___sync_fetch_and_max_4
124113 ; CHECK-BAREMETAL: cmp
125114 ; CHECK-BAREMETAL-NOT: __sync
126115 %10 = atomicrmw max i32* %val2, i32 0 monotonic
128117 ; CHECK: ldrex
129118 ; CHECK: cmp
130119 ; CHECK: strex
131 ; CHECK-T1: blx ___sync_fetch_and_umin_4
132 ; CHECK-M0: bl ___sync_fetch_and_umin_4
120 ; CHECK-T1: bl ___sync_fetch_and_umin_4
133121 ; CHECK-BAREMETAL: cmp
134122 ; CHECK-BAREMETAL-NOT: __sync
135123 %11 = atomicrmw umin i32* %val2, i32 16 monotonic
138126 ; CHECK: ldrex
139127 ; CHECK: cmp
140128 ; CHECK: strex
141 ; CHECK-T1: blx ___sync_fetch_and_umin_4
142 ; CHECK-M0: bl ___sync_fetch_and_umin_4
129 ; CHECK-T1: bl ___sync_fetch_and_umin_4
143130 ; CHECK-BAREMETAL: cmp
144131 ; CHECK-BAREMETAL-NOT: __sync
145132 %12 = atomicrmw umin i32* %val2, i32 %uneg monotonic
147134 ; CHECK: ldrex
148135 ; CHECK: cmp
149136 ; CHECK: strex
150 ; CHECK-T1: blx ___sync_fetch_and_umax_4
151 ; CHECK-M0: bl ___sync_fetch_and_umax_4
137 ; CHECK-T1: bl ___sync_fetch_and_umax_4
152138 ; CHECK-BAREMETAL: cmp
153139 ; CHECK-BAREMETAL-NOT: __sync
154140 %13 = atomicrmw umax i32* %val2, i32 1 monotonic
156142 ; CHECK: ldrex
157143 ; CHECK: cmp
158144 ; CHECK: strex
159 ; CHECK-T1: blx ___sync_fetch_and_umax_4
160 ; CHECK-M0: bl ___sync_fetch_and_umax_4
145 ; CHECK-T1: bl ___sync_fetch_and_umax_4
161146 ; CHECK-BAREMETAL: cmp
162147 ; CHECK-BAREMETAL-NOT: __sync
163148 %14 = atomicrmw umax i32* %val2, i32 0 monotonic
174159 ; CHECK: ldrex
175160 ; CHECK: cmp
176161 ; CHECK: strex
177 ; CHECK-T1: blx ___sync_fetch_and_umin_2
178 ; CHECK-M0: bl ___sync_fetch_and_umin_2
162 ; CHECK-T1: bl ___sync_fetch_and_umin_2
179163 ; CHECK-BAREMETAL: cmp
180164 ; CHECK-BAREMETAL-NOT: __sync
181165 %0 = atomicrmw umin i16* %val, i16 16 monotonic
184168 ; CHECK: ldrex
185169 ; CHECK: cmp
186170 ; CHECK: strex
187 ; CHECK-T1: blx ___sync_fetch_and_umin_2
188 ; CHECK-M0: bl ___sync_fetch_and_umin_2
171 ; CHECK-T1: bl ___sync_fetch_and_umin_2
189172 ; CHECK-BAREMETAL: cmp
190173 ; CHECK-BAREMETAL-NOT: __sync
191174 %1 = atomicrmw umin i16* %val, i16 %uneg monotonic
193176 ; CHECK: ldrex
194177 ; CHECK: cmp
195178 ; CHECK: strex
196 ; CHECK-T1: blx ___sync_fetch_and_umax_2
197 ; CHECK-M0: bl ___sync_fetch_and_umax_2
179 ; CHECK-T1: bl ___sync_fetch_and_umax_2
198180 ; CHECK-BAREMETAL: cmp
199181 ; CHECK-BAREMETAL-NOT: __sync
200182 %2 = atomicrmw umax i16* %val, i16 1 monotonic
202184 ; CHECK: ldrex
203185 ; CHECK: cmp
204186 ; CHECK: strex
205 ; CHECK-T1: blx ___sync_fetch_and_umax_2
206 ; CHECK-M0: bl ___sync_fetch_and_umax_2
187 ; CHECK-T1: bl ___sync_fetch_and_umax_2
207188 ; CHECK-BAREMETAL: cmp
208189 ; CHECK-BAREMETAL-NOT: __sync
209190 %3 = atomicrmw umax i16* %val, i16 0 monotonic
219200 ; CHECK: ldrex
220201 ; CHECK: cmp
221202 ; CHECK: strex
222 ; CHECK-T1: blx ___sync_fetch_and_umin_1
223 ; CHECK-M0: bl ___sync_fetch_and_umin_1
203 ; CHECK-T1: bl ___sync_fetch_and_umin_1
224204 ; CHECK-BAREMETAL: cmp
225205 ; CHECK-BAREMETAL-NOT: __sync
226206 %0 = atomicrmw umin i8* %val, i8 16 monotonic
228208 ; CHECK: ldrex
229209 ; CHECK: cmp
230210 ; CHECK: strex
231 ; CHECK-T1: blx ___sync_fetch_and_umin_1
232 ; CHECK-M0: bl ___sync_fetch_and_umin_1
211 ; CHECK-T1: bl ___sync_fetch_and_umin_1
233212 ; CHECK-BAREMETAL: cmp
234213 ; CHECK-BAREMETAL-NOT: __sync
235214 %uneg = sub i8 0, 1
238217 ; CHECK: ldrex
239218 ; CHECK: cmp
240219 ; CHECK: strex
241 ; CHECK-T1: blx ___sync_fetch_and_umax_1
242 ; CHECK-M0: bl ___sync_fetch_and_umax_1
220 ; CHECK-T1: bl ___sync_fetch_and_umax_1
243221 ; CHECK-BAREMETAL: cmp
244222 ; CHECK-BAREMETAL-NOT: __sync
245223 %2 = atomicrmw umax i8* %val, i8 1 monotonic
247225 ; CHECK: ldrex
248226 ; CHECK: cmp
249227 ; CHECK: strex
250 ; CHECK-T1: blx ___sync_fetch_and_umax_1
251 ; CHECK-M0: bl ___sync_fetch_and_umax_1
228 ; CHECK-T1: bl ___sync_fetch_and_umax_1
252229 ; CHECK-BAREMETAL: cmp
253230 ; CHECK-BAREMETAL-NOT: __sync
254231 %3 = atomicrmw umax i8* %val, i8 0 monotonic
341318 ; CHECK: dmb
342319 ; CHECK: add r0,
343320
344 ; CHECK-M0: ___sync_val_compare_and_swap_4
345 ; CHECK-M0: ___sync_val_compare_and_swap_4
321 ; CHECK-T1: ___sync_val_compare_and_swap_4
322 ; CHECK-T1: ___sync_val_compare_and_swap_4
346323
347324 ; CHECK-BAREMETAL: ldr {{r[0-9]}}, [r0]
348325 ; CHECK-BAREMETAL-NOT: dmb
363340 ; CHECK: dmb
364341 ; CHECK: str r3, [r2]
365342
366 ; CHECK-M0: ___sync_lock_test_and_set
367 ; CHECK-M0: ___sync_lock_test_and_set
343 ; CHECK-T1: ___sync_lock_test_and_set
344 ; CHECK-T1: ___sync_lock_test_and_set
368345
369346 ; CHECK-BAREMETAL-NOT: dmb
370347 ; CHECK-BAREMTEAL: str r1, [r0]
384361 ; CHECK: dmb
385362 ; CHECK: str [[R0]], [r1]
386363
387 ; CHECK-M0: ldr [[R0:r[0-9]]], [r0]
388 ; CHECK-M0: dmb
389 ; CHECK-M0: str [[R0]], [r1]
364 ; CHECK-T1: ldr [[R0:r[0-9]]], [{{r[0-9]+}}]
365 ; CHECK-T1: {{dmb|bl ___sync_synchronize}}
366 ; CHECK-T1: str [[R0]], [{{r[0-9]+}}]
390367
391368 ; CHECK-BAREMETAL: ldr [[R0:r[0-9]]], [r0]
392369 ; CHECK-BAREMETAL-NOT: dmb
8686 ; CHECKT2D-NEXT: bne.w _foo
8787 ; CHECKT2D-NEXT: push
8888 ; CHECKT2D-NEXT: mov r7, sp
89 ; CHECKT2D-NEXT: blx _foo
89 ; CHECKT2D-NEXT: bl _foo
9090 br i1 undef, label %bb, label %bb1.lr.ph
9191
9292 bb1.lr.ph:
149149
150150 define i32 @t9() nounwind {
151151 ; CHECKT2D-LABEL: t9:
152 ; CHECKT2D: blx __ZN9MutexLockC1Ev
153 ; CHECKT2D: blx __ZN9MutexLockD1Ev
152 ; CHECKT2D: bl __ZN9MutexLockC1Ev
153 ; CHECKT2D: bl __ZN9MutexLockD1Ev
154154 ; CHECKT2D: b.w ___divsi3
155155 %lock = alloca %class.MutexLock, align 1
156156 %1 = call %class.MutexLock* @_ZN9MutexLockC1Ev(%class.MutexLock* %lock)
169169 ; otherwise the call to floorf is lost.
170170 define float @libcall_tc_test2(float* nocapture %a, float %b) {
171171 ; CHECKT2D-LABEL: libcall_tc_test2:
172 ; CHECKT2D: blx _floorf
172 ; CHECKT2D: bl _floorf
173173 ; CHECKT2D: b.w _truncf
174174 %1 = load float, float* %a, align 4
175175 %call = tail call float @floorf(float %1)
2929 %call85 = tail call double @exp(double %mul84) nounwind
3030 %mul86 = fmul double %conv78, %call85
3131 %add88 = fadd double 0.000000e+00, %mul86
32 ; CHECK: blx _exp
32 ; CHECK: bl _exp
3333 %call100 = tail call double @exp(double %mul84) nounwind
3434 %mul101 = fmul double undef, %call100
3535 %add103 = fadd double %add46, %mul101
66 entry:
77 ; THUMB: main
88 call void @printArgsNoRet(i32 1, float 0x4000CCCCC0000000, i8 signext 99, double 4.100000e+00)
9 ; THUMB: blx _printArgsNoRet
9 ; THUMB: bl _printArgsNoRet
1010 ; THUMB-NOT: ldr
1111 ; THUMB-NOT: vldr
1212 ; THUMB-NOT: vmov
4040 define double @test_extend64(half* %addr) {
4141 ; CHECK-LABEL: test_extend64:
4242
43 ; CHECK-OLD: blx ___extendhfsf2
43 ; CHECK-OLD: bl ___extendhfsf2
4444 ; CHECK-OLD: vcvt.f64.f32
4545 ; CHECK-F16: vcvtb.f32.f16
4646 ; CHECK-F16: vcvt.f64.f32
5353 define void @test_trunc32(float %in, half* %addr) {
5454 ; CHECK-LABEL: test_trunc32:
5555
56 ; CHECK-OLD: blx ___truncsfhf2
56 ; CHECK-OLD: bl ___truncsfhf2
5757 ; CHECK-F16: vcvtb.f16.f32
5858 ; CHECK-V8: vcvtb.f16.f32
5959 %val16 = fptrunc float %in to half
6464 define void @test_trunc64(double %in, half* %addr) {
6565 ; CHECK-LABEL: test_trunc64:
6666
67 ; CHECK-OLD: blx ___truncdfhf2
68 ; CHECK-F16: blx ___truncdfhf2
67 ; CHECK-OLD: bl ___truncdfhf2
68 ; CHECK-F16: bl ___truncdfhf2
6969 ; CHECK-V8: vcvtb.f16.f64
7070 %val16 = fptrunc double %in to half
7171 store half %val16, half* %addr
2626 ; CHECK-NEXT: LBB{{[0-9_]+}}:
2727 ; CHECK-NEXT: movw r0, #4567
2828 ; CHECK-NEXT: [[FOOCALL]]:
29 ; CHECK-NEXT: blx _foo
29 ; CHECK-NEXT: bl _foo
3030 ;
3131 ; CHECK-PROB: BB#0:
3232 ; CHECK-PROB: Successors according to CFG: BB#1({{[0-9a-fx/= ]+}}50.00%) BB#2({{[0-9a-fx/= ]+}}25.00%) BB#4({{[0-9a-fx/= ]+}}25.00%)
0 ; RUN: llc -mtriple=thumbv7-apple-ios -filetype=obj %s -o %t
1 ; RUN: llvm-objdump -macho -d %t | FileCheck %s
2
3 ; This function just messes up the offsets enough to make the libcall in
4 ; test_local_call unencodable with a blx.
5 define void @thing() {
6 ret void
7 }
8
9 define i64 @__udivdi3(i64 %a, i64 %b) {
10 ret i64 %b
11 }
12
13 define i64 @test_local_call(i64 %a, i64 %b) {
14 ; CHECK-LABEL: test_local_call:
15 ; CHECK: bl ___udivdi3
16
17 %res = udiv i64 %a, %b
18 ret i64 %res
19 }
1717 ; CHECKELF: mov r0, [[SAVEX]]
1818 ; CHECKT2D-LABEL: test_identity:
1919 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
20 ; CHECKT2D: blx _identity16
20 ; CHECKT2D: bl _identity16
2121 ; CHECKT2D: uxth r0, r0
22 ; CHECKT2D: blx _identity32
22 ; CHECKT2D: bl _identity32
2323 ; CHECKT2D: mov r0, [[SAVEX]]
2424 %call = tail call i16 @identity16(i16 %x)
2525 %b = zext i16 %call to i32
4848 ; This shouldn't be required
4949 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
5050
51 ; CHECKT2D: blx _retzext16
51 ; CHECKT2D: bl _retzext16
5252 ; CHECKT2D-NOT: uxth r0, {{r[0-9]+}}
53 ; CHECKT2D: blx _identity32
53 ; CHECKT2D: bl _identity32
5454
5555 ; This shouldn't be required
5656 ; CHECKT2D: mov r0, [[SAVEX]]
7171 ; CHECKELF: mov r0, [[SAVEX]]
7272 ; CHECKT2D-LABEL: test_mismatched_ret:
7373 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
74 ; CHECKT2D: blx _retzext16
74 ; CHECKT2D: bl _retzext16
7575 ; CHECKT2D: sxth r0, {{r[0-9]+}}
76 ; CHECKT2D: blx _identity32
76 ; CHECKT2D: bl _identity32
7777 ; CHECKT2D: mov r0, [[SAVEX]]
7878 %call = tail call i16 @retzext16(i16 %x)
7979 %b = sext i16 %call to i32
9191 ; CHECKELF: b paramzext16
9292 ; CHECKT2D-LABEL: test_matched_paramext:
9393 ; CHECKT2D: uxth r0, r0
94 ; CHECKT2D: blx _paramzext16
94 ; CHECKT2D: bl _paramzext16
9595 ; CHECKT2D: uxth r0, r0
96 ; CHECKT2D: blx _identity32
96 ; CHECKT2D: bl _identity32
9797 ; CHECKT2D: b.w _paramzext16
9898 %call = tail call i16 @paramzext16(i16 %x)
9999 %b = zext i16 %call to i32
117117 ; CHECKELF: bl identity32
118118 ; CHECKELF: b paramzext16
119119 ; CHECKT2D-LABEL: test_matched_paramext2:
120 ; CHECKT2D: blx _paramzext16
121 ; CHECKT2D: blx _identity32
120 ; CHECKT2D: bl _paramzext16
121 ; CHECKT2D: bl _identity32
122122 ; CHECKT2D: b.w _paramzext16
123123 %call = tail call i16 @paramzext16(i16 %x)
124124
142142
143143 ; CHECKT2D-LABEL: test_matched_bothext:
144144 ; CHECKT2D: uxth r0, r0
145 ; CHECKT2D: blx _bothzext16
145 ; CHECKT2D: bl _bothzext16
146146 ; CHECKT2D-NOT: uxth r0, r0
147147
148148 ; FIXME: Tail call should be OK here
149 ; CHECKT2D: blx _identity32
149 ; CHECKT2D: bl _identity32
150150
151151 %call = tail call i16 @bothzext16(i16 %x)
152152 %b = zext i16 %x to i32
166166 ; CHECKT2D-LABEL: test_mismatched_bothext:
167167 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
168168 ; CHECKT2D: uxth r0, {{r[0-9]+}}
169 ; CHECKT2D: blx _bothzext16
169 ; CHECKT2D: bl _bothzext16
170170 ; CHECKT2D: sxth r0, [[SAVEX]]
171 ; CHECKT2D: blx _identity32
171 ; CHECKT2D: bl _identity32
172172 ; CHECKT2D: mov r0, [[SAVEX]]
173173 %call = tail call i16 @bothzext16(i16 %x)
174174 %b = sext i16 %x to i32
7373 ; %do.body.i.i.i.
7474
7575 ; CHECK-LABEL: __Z4foo1c:
76 ; CHECK: blx __Znwm
76 ; CHECK: bl __Znwm
7777 ; CHECK: {{.*}}@ %do.body.i.i.i.preheader
7878 ; CHECK: str r0, [sp, [[OFFSET:#[0-9]+]]]
7979 ; CHECK: {{.*}}@ %do.body.i.i.i
0 ; RUN: llc < %s -mtriple=armv7-apple-ios6.0 | FileCheck %s
1 ; RUN: llc < %s -mtriple=thumbv7-apple-ios6.0 | FileCheck %s -check-prefix=THUMB
1 ; RUN: llc < %s -mtriple=thumbv7-apple-ios6.0 | FileCheck %s
22 ; RUN: llc < %s -mtriple=armv7-unknown-nacl-gnueabi | FileCheck %s -check-prefix=NACL
33 ; RUN: llc < %s -mtriple=armv5-none-linux-gnueabi | FileCheck %s -check-prefix=NOMOVT
44
1414 ; CHECK: ldr
1515 ; CHECK: str
1616 ; CHECK-NOT:bne
17 ; THUMB-LABEL: f:
18 ; THUMB: ldr
19 ; THUMB: str
20 ; THUMB-NOT:bne
2117 %st = alloca %struct.SmallStruct, align 4
2218 %call = call i32 @e1(%struct.SmallStruct* byval %st)
2319 ret i32 0
3127 ; CHECK: sub
3228 ; CHECK: str
3329 ; CHECK: bne
34 ; THUMB-LABEL: g:
35 ; THUMB: ldr
36 ; THUMB: sub
37 ; THUMB: str
38 ; THUMB: bne
3930 ; NACL-LABEL: g:
4031 ; Ensure that use movw instead of constpool for the loop trip count. But don't
4132 ; match the __stack_chk_guard movw
5748 ; CHECK: sub
5849 ; CHECK: vst1
5950 ; CHECK: bne
60 ; THUMB-LABEL: h:
61 ; THUMB: vld1
62 ; THUMB: sub
63 ; THUMB: vst1
64 ; THUMB: bne
6551 ; NACL: movw r{{[1-9]}}, #
6652 ; NACL: vld1
6753 ; NACL: sub
8268 define void @f3(%struct.SmallStruct* nocapture byval %s) nounwind optsize {
8369 ; CHECK-LABEL: f3
8470 ; CHECK: bl _consumestruct
85 ; THUMB-LABEL: f3
86 ; THUMB: blx _consumestruct
8771 entry:
8872 %0 = bitcast %struct.SmallStruct* %s to i8*
8973 tail call void @consumestruct(i8* %0, i32 80) optsize
9377 define void @f4(%struct.SmallStruct* nocapture byval %s) nounwind optsize {
9478 ; CHECK-LABEL: f4
9579 ; CHECK: bl _consumestruct
96 ; THUMB-LABEL: f4
97 ; THUMB: blx _consumestruct
9880 entry:
9981 %addr = getelementptr inbounds %struct.SmallStruct, %struct.SmallStruct* %s, i32 0, i32 0
10082 %0 = bitcast i32* %addr to i8*
10587 ; We can do tail call here since s is in the incoming argument area.
10688 define void @f5(i32 %a, i32 %b, i32 %c, i32 %d, %struct.SmallStruct* nocapture byval %s) nounwind optsize {
10789 ; CHECK-LABEL: f5
108 ; CHECK: b _consumestruct
109 ; THUMB-LABEL: f5
110 ; THUMB: b.w _consumestruct
90 ; CHECK: b{{(\.w)?}} _consumestruct
11191 entry:
11292 %0 = bitcast %struct.SmallStruct* %s to i8*
11393 tail call void @consumestruct(i8* %0, i32 80) optsize
11696
11797 define void @f6(i32 %a, i32 %b, i32 %c, i32 %d, %struct.SmallStruct* nocapture byval %s) nounwind optsize {
11898 ; CHECK-LABEL: f6
119 ; CHECK: b _consumestruct
120 ; THUMB-LABEL: f6
121 ; THUMB: b.w _consumestruct
99 ; CHECK: b{{(\.w)?}} _consumestruct
122100 entry:
123101 %addr = getelementptr inbounds %struct.SmallStruct, %struct.SmallStruct* %s, i32 0, i32 0
124102 %0 = bitcast i32* %addr to i8*
136114 ; CHECK-LABEL: test_I_16
137115 ; CHECK: ldrb
138116 ; CHECK: strb
139 ; THUMB-LABEL: test_I_16
140 ; THUMB: ldrb
141 ; THUMB: strb
142117 entry:
143118 call void @use_I(%struct.I.8* byval align 16 undef)
144119 ret void
0 ; RUN: llc -mtriple thumbv7-windows-coff -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-COFF
1 ; RUN: llc -mtriple thumbv7-elf -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-ELF
2 ; RUN: llc -mtriple thumbv7-macho -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MACHO
1 ; RUN: llc -mtriple thumbv7-elf -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-OTHER
2 ; RUN: llc -mtriple thumbv7-macho -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-OTHER
33
44 declare i8* @f()
55 declare extern_weak i8* @g(i8*)
1313 }
1414
1515 ; CHECK-COFF: b g
16 ; CHECK-ELF: bl g
17 ; CHECK-MACHO: blx _g
16 ; CHECK-OTHER: bl {{_?}}g
1817
2323 ; CHECKELF: b B_ctor_base
2424 ; CHECKT2D-LABEL: C_ctor_base:
2525 ; CHECKT2D-NOT: mov {{r[0-9]+}}, r0
26 ; CHECKT2D: blx _A_ctor_base
26 ; CHECKT2D: bl _A_ctor_base
2727 ; CHECKT2D-NOT: mov r0, {{r[0-9]+}}
2828 ; CHECKT2D: b.w _B_ctor_base
2929 %0 = bitcast %struct.C* %this to %struct.A*
4242 ; CHECKELF-NOT: b B_ctor_base_nothisret
4343 ; CHECKT2D-LABEL: C_ctor_base_nothisret:
4444 ; CHECKT2D: mov [[SAVETHIS:r[0-9]+]], r0
45 ; CHECKT2D: blx _A_ctor_base_nothisret
45 ; CHECKT2D: bl _A_ctor_base_nothisret
4646 ; CHECKT2D: mov r0, [[SAVETHIS]]
4747 ; CHECKT2D-NOT: b.w _B_ctor_base_nothisret
4848 %0 = bitcast %struct.C* %this to %struct.A*
8181 ; CHECKELF: b B_ctor_complete
8282 ; CHECKT2D-LABEL: D_ctor_base:
8383 ; CHECKT2D-NOT: mov {{r[0-9]+}}, r0
84 ; CHECKT2D: blx _B_ctor_complete
84 ; CHECKT2D: bl _B_ctor_complete
8585 ; CHECKT2D-NOT: mov r0, {{r[0-9]+}}
8686 ; CHECKT2D: b.w _B_ctor_complete
8787 %b = getelementptr inbounds %struct.D, %struct.D* %this, i32 0, i32 0
5151
5252 ; CHECK: mov r0, sp
5353 ; CHECK-NOT: adds r0
54 ; CHECK: blx
54 ; CHECK: bl
5555 call void @take_ptr(i8* %addr8)
5656 ret void
5757 }
6666 %addr2 = bitcast i32* %addr2.32 to i8*
6767
6868 ; CHECK: add r0, sp, #{{[0-9]+}}
69 ; CHECK: blx
69 ; CHECK: bl
7070 call void @take_ptr(i8* %addr1)
7171
7272 ; CHECK: mov r0, sp
7373 ; CHECK-NOT: add r0
74 ; CHECK: blx
74 ; CHECK: bl
7575 call void @take_ptr(i8* %addr2)
7676
7777 ret void
8686
8787 ; CHECK: add [[RTMP:r[0-9]+]], sp, #1020
8888 ; CHECK: adds [[RTMP]], #8
89 ; CHECK: blx
89 ; CHECK: bl
9090 call void @take_ptr(i8* %addr1)
9191
9292 ret void
9999 %addr2 = alloca i8, i32 1020
100100
101101 ; CHECK: add r0, sp, #1020
102 ; CHECK-NEXT: blx
102 ; CHECK-NEXT: bl
103103 call void @take_ptr(i8* %addr1)
104104
105105 ret void
115115
116116 ; CHECK: add r0, sp, #1020
117117 ; CHECK: adds r0, #248
118 ; CHECK-NEXT: blx
118 ; CHECK-NEXT: bl
119119 call void @take_ptr(i8* %addr1)
120120
121121 ret void
44
55 define double @test_stret(double %in) {
66 ; CHECK-LABEL: test_stret:
7 ; CHECK: blx ___sincos_stret
7 ; CHECK: bl ___sincos_stret
88 ; CHECK-NOT: ldr
99 ; CHECK: vadd.f64 d0, d0, d1
1010
33
44 define float @test_call(float %a, float %b) {
55 ; CHECK-HARD: vadd.f32 {{s[0-9]+}}, {{s[0-9]+}}, {{s[0-9]+}}
6 ; CHECK-SOFTISH: blx ___addsf3vfp
6 ; CHECK-SOFTISH: bl ___addsf3vfp
77 ; CHECK-SOFT: bl ___addsf3{{$}}
88 %sum = fadd float %a, %b
99 ret float %sum
77 @llvm.used = appending global [1 x i8*] [i8* bitcast (void (%0*, i32, i32)* @_Z19getClosestDiagonal3ii to i8*)], section "llvm.metadata" ; <[1 x i8*]*> [#uses=0]
88
99 define void @_Z19getClosestDiagonal3ii(%0* noalias sret, i32, i32) nounwind {
10 ; CHECK: blx ___muldf3
11 ; CHECK: blx ___muldf3
10 ; CHECK: bl ___muldf3
11 ; CHECK: bl ___muldf3
1212 ; CHECK: beq LBB0
13 ; CHECK: blx ___muldf3
13 ; CHECK: bl ___muldf3
1414 ;
1515 switch i32 %1, label %4 [
1616 i32 0, label %5
33
44 define void @t1() {
55 ; V6-LABEL: t1:
6 ; V6: blx {{_*}}sync_synchronize
6 ; V6: bl {{_*}}sync_synchronize
77
88 ; V6M-LABEL: t1:
99 ; V6M: dmb sy
3030
3131 define i32 @test_dead_cycle(i32 %n) nounwind {
3232 ; CHECK-LABEL: test_dead_cycle:
33 ; CHECK: blx
33 ; CHECK: bl
3434 ; CHECK-NOT: mov
35 ; CHECK: blx
35 ; CHECK: bl
3636 entry:
3737 %0 = icmp eq i32 %n, 1 ; [#uses=1]
3838 br i1 %0, label %return, label %bb.nph
1313 %s5 = type { i32 }
1414
1515 ; Make sure the cmp is not scheduled before the InlineAsm that clobbers cc.
16 ; CHECK: blx _f2
16 ; CHECK: bl _f2
1717 ; CHECK: cmp r0, #0
1818 ; CHECK-NOT: cmp
1919 ; CHECK: InlineAsm Start
None ; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mattr=+thumb2 | FileCheck %s -check-prefix=DARWIN
1 ; RUN: llc < %s -mtriple=thumbv7-linux -mattr=+thumb2 | FileCheck %s -check-prefix=LINUX
0 ; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mattr=+thumb2 | FileCheck %s
1 ; RUN: llc < %s -mtriple=thumbv7-linux -mattr=+thumb2 | FileCheck %s
22
33 @t = weak global i32 ()* null ; [#uses=1]
44
55 declare void @g(i32, i32, i32, i32)
66
77 define void @f() {
8 ; DARWIN-LABEL: f:
9 ; DARWIN: blx _g
10
11 ; LINUX-LABEL: f:
12 ; LINUX: bl g
8 ; CHECK-LABEL: f:
9 ; CHECK: bl {{_?}}g
1310 call void @g( i32 1, i32 2, i32 3, i32 4 )
1411 ret void
1512 }
1613
1714 define void @h() {
18 ; DARWIN-LABEL: h:
19 ; DARWIN: blx r0
20
21 ; LINUX-LABEL: h:
22 ; LINUX: blx r0
15 ; CHECK-LABEL: h:
16 ; CHECK: blx r0
2317 %tmp = load i32 ()*, i32 ()** @t ; [#uses=1]
2418 %tmp.upgrd.2 = call i32 %tmp( ) ; [#uses=0]
2519 ret void
4848 define void @t4(i32 %a0, i32 %a1, i32 %a2) {
4949 ; ALL-LABEL: t4:
5050 ; ALL: stm.w sp, {r0, r1, r2}
51 ; ALL: blx _ext
51 ; ALL: bl _ext
5252 ; ALL: ldm.w sp, {r0, r1, r2}
53 ; ALL: blx _f2
53 ; ALL: bl _f2
5454 %arr = alloca [4 x i32], align 4
5555 %p0 = getelementptr inbounds [4 x i32], [4 x i32]* %arr, i64 0, i64 0
5656 %p1 = getelementptr inbounds [4 x i32], [4 x i32]* %arr, i64 0, i64 1