llvm.org GIT mirror llvm / a04e9e4
[ARM] Generate consistent frame records for Thumb2 There is not an official documented ABI for frame pointers in Thumb2, but we should try to emit something which is useful. We use r7 as the frame pointer for Thumb code, which currently means that if a function needs to save a high register (r8-r11), it will get pushed to the stack between the frame pointer (r7) and link register (r14). This means that while a stack unwinder can follow the chain of frame pointers up the stack, it cannot know the offset to lr, so does not know which functions correspond to the stack frames. To fix this, we need to push the callee-saved registers in two batches, with the first push saving the low registers, fp and lr, and the second push saving the high registers. This is already implemented, but previously only used for iOS. This patch turns it on for all Thumb2 targets when frame pointers are required by the ABI, and the frame pointer is r7 (Windows uses r11, so this isn't a problem there). If frame pointer elimination is enabled we still emit a single push/pop even if we need a frame pointer for other reasons, to avoid increasing code size. We must also ensure that lr is pushed to the stack when using a frame pointer, so that we end up with a complete frame record. Situations that could cause this were rare, because we already push lr in most situations so that we can return using the pop instruction. Differential Revision: https://reviews.llvm.org/D23516 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@279506 91177308-0d34-0410-b5e6-96231b3b80d8 Oliver Stannard 3 years ago
35 changed file(s) with 454 addition(s) and 198 deletion(s). Raw diff Collapse all Expand all
4848 : ARMGenRegisterInfo(ARM::LR, 0, 0, ARM::PC), BasePtr(ARM::R6) {}
4949
5050 static unsigned getFramePointerReg(const ARMSubtarget &STI) {
51 if (STI.isTargetMachO())
52 return ARM::R7;
53 else if (STI.isTargetWindows())
54 return ARM::R11;
55 else // ARM EABI
56 return STI.isThumb() ? ARM::R7 : ARM::R11;
51 return STI.useR7AsFramePointer() ? ARM::R7 : ARM::R11;
5752 }
5853
5954 const MCPhysReg*
6055 ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
6156 const ARMSubtarget &STI = MF->getSubtarget();
62 bool UseSplitPush = STI.splitFramePushPop();
57 bool UseSplitPush = STI.splitFramePushPop(*MF);
6358 const MCPhysReg *RegList =
6459 STI.isTargetDarwin()
6560 ? CSR_iOS_SaveList
5656 /// or if frame pointer elimination is disabled.
5757 bool ARMFrameLowering::hasFP(const MachineFunction &MF) const {
5858 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
59
60 // iOS requires FP not to be clobbered for backtracing purpose.
61 if (STI.isTargetIOS() || STI.isTargetWatchOS())
59 const MachineFrameInfo &MFI = MF.getFrameInfo();
60
61 // ABI-required frame pointer.
62 if (MF.getTarget().Options.DisableFramePointerElim(MF))
6263 return true;
6364
64 const MachineFrameInfo &MFI = MF.getFrameInfo();
65 // Always eliminate non-leaf frame pointers.
66 return ((MF.getTarget().Options.DisableFramePointerElim(MF) &&
67 MFI.hasCalls()) ||
68 RegInfo->needsStackRealignment(MF) ||
65 // Frame pointer required for use within this function.
66 return (RegInfo->needsStackRealignment(MF) ||
6967 MFI.hasVarSizedObjects() ||
7068 MFI.isFrameAddressTaken());
7169 }
351349 case ARM::R10:
352350 case ARM::R11:
353351 case ARM::R12:
354 if (STI.splitFramePushPop()) {
352 if (STI.splitFramePushPop(MF)) {
355353 GPRCS2Size += 4;
356354 break;
357355 }
556554 case ARM::R10:
557555 case ARM::R11:
558556 case ARM::R12:
559 if (STI.splitFramePushPop())
557 if (STI.splitFramePushPop(MF))
560558 break;
561559 LLVM_FALLTHROUGH;
562560 case ARM::R0:
589587 case ARM::R10:
590588 case ARM::R11:
591589 case ARM::R12:
592 if (STI.splitFramePushPop()) {
590 if (STI.splitFramePushPop(MF)) {
593591 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
594592 unsigned Offset = MFI.getObjectOffset(FI);
595593 unsigned CFIIndex = MMI.addFrameInst(
901899 unsigned LastReg = 0;
902900 for (; i != 0; --i) {
903901 unsigned Reg = CSI[i-1].getReg();
904 if (!(Func)(Reg, STI.splitFramePushPop())) continue;
902 if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue;
905903
906904 // D-registers in the aligned area DPRCS2 are NOT spilled here.
907905 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
982980 bool DeleteRet = false;
983981 for (; i != 0; --i) {
984982 unsigned Reg = CSI[i-1].getReg();
985 if (!(Func)(Reg, STI.splitFramePushPop())) continue;
983 if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue;
986984
987985 // The aligned reloads from area DPRCS2 are not inserted here.
988986 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
15461544 if (Spilled) {
15471545 NumGPRSpills++;
15481546
1549 if (!STI.splitFramePushPop()) {
1547 if (!STI.splitFramePushPop(MF)) {
15501548 if (Reg == ARM::LR)
15511549 LRSpilled = true;
15521550 CS1Spilled = true;
15681566 break;
15691567 }
15701568 } else {
1571 if (!STI.splitFramePushPop()) {
1569 if (!STI.splitFramePushPop(MF)) {
15721570 UnspilledCS1GPRs.push_back(Reg);
15731571 continue;
15741572 }
16331631 if (BigStack || !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
16341632 AFI->setHasStackFrame(true);
16351633
1634 if (hasFP(MF)) {
1635 SavedRegs.set(FramePtr);
1636 // If the frame pointer is required by the ABI, also spill LR so that we
1637 // emit a complete frame record.
1638 if (MF.getTarget().Options.DisableFramePointerElim(MF) && !LRSpilled) {
1639 SavedRegs.set(ARM::LR);
1640 LRSpilled = true;
1641 NumGPRSpills++;
1642 }
1643 auto FPPos = find(UnspilledCS1GPRs, FramePtr);
1644 if (FPPos != UnspilledCS1GPRs.end())
1645 UnspilledCS1GPRs.erase(FPPos);
1646 NumGPRSpills++;
1647 if (FramePtr == ARM::R7)
1648 CS1Spilled = true;
1649 }
1650
16361651 // If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled.
16371652 // Spill LR as well so we can fold BX_RET to the registers restore (LDM).
16381653 if (!LRSpilled && CS1Spilled) {
16451660
16461661 ForceLRSpill = false;
16471662 ExtraCSSpill = true;
1648 }
1649
1650 if (hasFP(MF)) {
1651 SavedRegs.set(FramePtr);
1652 auto FPPos = find(UnspilledCS1GPRs, FramePtr);
1653 if (FPPos != UnspilledCS1GPRs.end())
1654 UnspilledCS1GPRs.erase(FPPos);
1655 NumGPRSpills++;
16561663 }
16571664
16581665 // If stack and double are 8-byte aligned and we are spilling an odd number
559559 return isTargetMachO() ? (ReserveR9 || !HasV6Ops) : ReserveR9;
560560 }
561561
562 bool useR7AsFramePointer() const {
563 return isTargetDarwin() || (!isTargetWindows() && isThumb());
564 }
562565 /// Returns true if the frame setup is split into two separate pushes (first
563566 /// r0-r7,lr then r8-r11), principally so that the frame pointer is adjacent
564567 /// to lr.
565 bool splitFramePushPop() const {
566 return isTargetMachO();
568 bool splitFramePushPop(const MachineFunction &MF) const {
569 return useR7AsFramePointer() &&
570 MF.getTarget().Options.DisableFramePointerElim(MF);
567571 }
568572
569573 bool useStride4VFPs(const MachineFunction &MF) const;
149149 case ARM::R9:
150150 case ARM::R10:
151151 case ARM::R11:
152 if (STI.splitFramePushPop()) {
152 if (STI.splitFramePushPop(MF)) {
153153 GPRCS2Size += 4;
154154 break;
155155 }
211211 case ARM::R10:
212212 case ARM::R11:
213213 case ARM::R12:
214 if (STI.splitFramePushPop())
214 if (STI.splitFramePushPop(MF))
215215 break;
216216 // fallthough
217217 case ARM::R0:
88 @A = external global [4 x [4 x i32]] ; <[4 x [4 x i32]]*> [#uses=1]
99
1010 ; CHECK-LABEL: dct_luma_sp:
11 define fastcc i32 @dct_luma_sp(i32 %block_x, i32 %block_y, i32* %coeff_cost) {
11 define fastcc i32 @dct_luma_sp(i32 %block_x, i32 %block_y, i32* %coeff_cost) "no-frame-pointer-elim"="true" {
1212 entry:
1313 ; Make sure to use base-updating stores for saving callee-saved registers.
1414 ; CHECK: push
11 ; RUN: llc < %s -mtriple=thumbv7-apple-ios | FileCheck %s
22 ; rdar://8690640
33
4 define i32* @t(i32* %x) nounwind {
4 define i32* @t(i32* %x) nounwind "no-frame-pointer-elim"="true" {
55 entry:
66 ; CHECK-LABEL: t:
77 ; CHECK: push
0 ; RUN: llc < %s -mtriple=thumbv7-apple-ios -mcpu=cortex-a9 | FileCheck %s
11 ; rdar://8728956
22
3 define hidden void @foo() nounwind ssp {
3 define hidden void @foo() nounwind ssp "no-frame-pointer-elim"="true" {
44 entry:
55 ; CHECK-LABEL: foo:
66 ; CHECK: mov r7, sp
1313 declare void @foo(i32)
1414 declare i32 @bar(i32)
1515
16 define i32 @test(i32 %in1, i32 %in2) nounwind {
16 define i32 @test(i32 %in1, i32 %in2) nounwind "no-frame-pointer-elim"="true" {
1717 entry:
1818 %call = tail call zeroext i1 @getbool() nounwind
1919 br i1 %call, label %sw.bb18, label %sw.bb2
5858 ; DISABLE-NEXT: pop {r7, pc}
5959 ;
6060 ; ENABLE-NEXT: bx lr
61 define i32 @foo(i32 %a, i32 %b) {
61 define i32 @foo(i32 %a, i32 %b) "no-frame-pointer-elim"="true" {
6262 %tmp = alloca i32, align 4
6363 %tmp2 = icmp slt i32 %a, %b
6464 br i1 %tmp2, label %true, label %false
123123 ; DISABLE-NEXT: pop {r4, r7, pc}
124124 ;
125125 ; ENABLE-NEXT: bx lr
126 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
126 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) "no-frame-pointer-elim"="true" {
127127 entry:
128128 %tobool = icmp eq i32 %cond, 0
129129 br i1 %tobool, label %if.else, label %for.preheader
177177 ; CHECK: @ %for.exit
178178 ; CHECK: nop
179179 ; CHECK: pop {r4
180 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
180 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) "no-frame-pointer-elim"="true" {
181181 entry:
182182 br label %for.preheader
183183
247247 ; DISABLE-NEXT: pop {r4, r7, pc}
248248 ;
249249 ; ENABLE-NEXT: bx lr
250 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
250 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) "no-frame-pointer-elim"="true" {
251251 entry:
252252 %tobool = icmp eq i32 %cond, 0
253253 br i1 %tobool, label %if.else, label %for.preheader
326326 ; DISABLE-NEXT: pop {r4, r7, pc}
327327 ;
328328 ; ENABLE-NEXT: bx lr
329 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {
329 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) "no-frame-pointer-elim"="true" #0 {
330330 entry:
331331 %tobool = icmp eq i32 %cond, 0
332332 br i1 %tobool, label %if.else, label %if.then
404404 ; DISABLE-NEXT: pop {r4, r7, pc}
405405 ;
406406 ; ENABLE-NEXT: bx lr
407 define i32 @inlineAsm(i32 %cond, i32 %N) {
407 define i32 @inlineAsm(i32 %cond, i32 %N) "no-frame-pointer-elim"="true" {
408408 entry:
409409 %tobool = icmp eq i32 %cond, 0
410410 br i1 %tobool, label %if.else, label %for.preheader
473473 ; ARM-DISABLE-NEXT: mov sp, r7
474474 ; THUMB-DISABLE-NEXT: add sp, #12
475475 ; DISABLE-NEXT: pop {r7, pc}
476 define i32 @callVariadicFunc(i32 %cond, i32 %N) {
476 define i32 @callVariadicFunc(i32 %cond, i32 %N) "no-frame-pointer-elim"="true" {
477477 entry:
478478 %tobool = icmp eq i32 %cond, 0
479479 br i1 %tobool, label %if.else, label %if.then
520520 ;
521521 ; CHECK: bl{{x?}} _abort
522522 ; ENABLE-NOT: pop
523 define i32 @noreturn(i8 signext %bad_thing) {
523 define i32 @noreturn(i8 signext %bad_thing) "no-frame-pointer-elim"="true" {
524524 entry:
525525 %tobool = icmp eq i8 %bad_thing, 0
526526 br i1 %tobool, label %if.end, label %if.abort
547547 ; The only condition for this test is the compilation finishes correctly.
548548 ; CHECK-LABEL: infiniteloop
549549 ; CHECK: pop
550 define void @infiniteloop() {
550 define void @infiniteloop() "no-frame-pointer-elim"="true" {
551551 entry:
552552 br i1 undef, label %if.then, label %if.end
553553
569569 ; Another infinite loop test this time with a body bigger than just one block.
570570 ; CHECK-LABEL: infiniteloop2
571571 ; CHECK: pop
572 define void @infiniteloop2() {
572 define void @infiniteloop2() "no-frame-pointer-elim"="true" {
573573 entry:
574574 br i1 undef, label %if.then, label %if.end
575575
599599 ; Another infinite loop test this time with two nested infinite loop.
600600 ; CHECK-LABEL: infiniteloop3
601601 ; CHECK: bx lr
602 define void @infiniteloop3() {
602 define void @infiniteloop3() "no-frame-pointer-elim"="true" {
603603 entry:
604604 br i1 undef, label %loop2a, label %body
605605
656656 ; DISABLE: pop
657657 ;
658658 ; CHECK: bl
659 define float @debug_info(float %gamma, float %slopeLimit, i1 %or.cond, double %tmp) {
659 define float @debug_info(float %gamma, float %slopeLimit, i1 %or.cond, double %tmp) "no-frame-pointer-elim"="true" {
660660 bb:
661661 br i1 %or.cond, label %bb3, label %bb13
662662
99
1010 declare void @g(i32, i32, i32, i32)
1111
12 define void @t1() {
12 define void @t1() "no-frame-pointer-elim"="true" {
1313 ; CHECKELF-LABEL: t1:
1414 ; CHECKELF: bl g
1515 call void @g( i32 1, i32 2, i32 3, i32 4 )
1616 ret void
1717 }
1818
19 define void @t2() {
19 define void @t2() "no-frame-pointer-elim"="true" {
2020 ; CHECKV6-LABEL: t2:
2121 ; CHECKV6: bx r0
2222 ; CHECKT2D-LABEL: t2:
2828 ret void
2929 }
3030
31 define void @t3() {
31 define void @t3() "no-frame-pointer-elim"="true" {
3232 ; CHECKV6-LABEL: t3:
3333 ; CHECKV6: b _t2
3434 ; CHECKELF-LABEL: t3:
4141 }
4242
4343 ; Sibcall optimization of expanded libcalls. rdar://8707777
44 define double @t4(double %a) nounwind readonly ssp {
44 define double @t4(double %a) nounwind readonly ssp "no-frame-pointer-elim"="true" {
4545 entry:
4646 ; CHECKV6-LABEL: t4:
4747 ; CHECKV6: b _sin
5151 ret double %0
5252 }
5353
54 define float @t5(float %a) nounwind readonly ssp {
54 define float @t5(float %a) nounwind readonly ssp "no-frame-pointer-elim"="true" {
5555 entry:
5656 ; CHECKV6-LABEL: t5:
5757 ; CHECKV6: b _sinf
6565
6666 declare double @sin(double) nounwind readonly
6767
68 define i32 @t6(i32 %a, i32 %b) nounwind readnone {
68 define i32 @t6(i32 %a, i32 %b) nounwind readnone "no-frame-pointer-elim"="true" {
6969 entry:
7070 ; CHECKV6-LABEL: t6:
7171 ; CHECKV6: b ___divsi3
7979 ; rdar://8309338
8080 declare void @foo() nounwind
8181
82 define void @t7() nounwind {
82 define void @t7() nounwind "no-frame-pointer-elim"="true" {
8383 entry:
8484 ; CHECKT2D-LABEL: t7:
8585 ; CHECKT2D: it ne
100100
101101 ; Make sure codegenprep is duplicating ret instructions to enable tail calls.
102102 ; rdar://11140249
103 define i32 @t8(i32 %x) nounwind ssp {
103 define i32 @t8(i32 %x) nounwind ssp "no-frame-pointer-elim"="true" {
104104 entry:
105105 ; CHECKT2D-LABEL: t8:
106106 ; CHECKT2D-NOT: push
147147
148148 @x = external global i32, align 4
149149
150 define i32 @t9() nounwind {
150 define i32 @t9() nounwind "no-frame-pointer-elim"="true" {
151151 ; CHECKT2D-LABEL: t9:
152152 ; CHECKT2D: bl __ZN9MutexLockC1Ev
153153 ; CHECKT2D: bl __ZN9MutexLockD1Ev
167167 ; rdar://13827621
168168 ; Correctly preserve the input chain for the tailcall node in the bitcast case,
169169 ; otherwise the call to floorf is lost.
170 define float @libcall_tc_test2(float* nocapture %a, float %b) {
170 define float @libcall_tc_test2(float* nocapture %a, float %b) "no-frame-pointer-elim"="true" {
171171 ; CHECKT2D-LABEL: libcall_tc_test2:
172172 ; CHECKT2D: bl _floorf
173173 ; CHECKT2D: b.w _truncf
3232 ; THUMB: blx
3333 ; THUMB: r4
3434 ; THUMB: pop {{.*}}r4
35 define cxx_fast_tlscc nonnull %struct.S* @_ZTW2sg() nounwind {
35 define cxx_fast_tlscc nonnull %struct.S* @_ZTW2sg() nounwind "no-frame-pointer-elim"="true" {
3636 %.b.i = load i1, i1* @__tls_guard, align 1
3737 br i1 %.b.i, label %__tls_init.exit, label %init.i
3838
9494 ; CHECK-O0-NOT: vpop
9595 ; CHECK-O0-NOT: vldr
9696 ; CHECK-O0: pop
97 define cxx_fast_tlscc nonnull i32* @_ZTW4sum1() nounwind {
97 define cxx_fast_tlscc nonnull i32* @_ZTW4sum1() nounwind "no-frame-pointer-elim"="true" {
9898 ret i32* @sum1
9999 }
100100
108108 ; CHECK-O0-NOT: vldr
109109 ; CHECK-O0: pop
110110 declare cxx_fast_tlscc void @tls_helper()
111 define cxx_fast_tlscc %class.C* @tls_test2() #1 {
111 define cxx_fast_tlscc %class.C* @tls_test2() #1 "no-frame-pointer-elim"="true" {
112112 call cxx_fast_tlscc void @tls_helper()
113113 ret %class.C* @tC
114114 }
118118 declare %class.C* @_ZN1CD1Ev(%class.C* readnone returned %this)
119119 ; CHECK-LABEL: tls_test
120120 ; CHECK: bl __tlv_atexit
121 define cxx_fast_tlscc void @__tls_test() {
121 define cxx_fast_tlscc void @__tls_test() "no-frame-pointer-elim"="true" {
122122 entry:
123123 store i32 0, i32* getelementptr inbounds (%class.C, %class.C* @tC, i64 0, i32 0), align 4
124124 %0 = tail call i32 @_tlv_atexit(void (i8*)* bitcast (%class.C* (%class.C*)* @_ZN1CD1Ev to void (i8*)*), i8* bitcast (%class.C* @tC to i8*), i8* nonnull @__dso_handle) #1
126126 }
127127
128128 declare void @somefunc()
129 define cxx_fast_tlscc void @test_ccmismatch_notail() {
129 define cxx_fast_tlscc void @test_ccmismatch_notail() "no-frame-pointer-elim"="true" {
130130 ; A tail call is not possible here because somefunc does not preserve enough
131131 ; registers.
132132 ; CHECK-LABEL: test_ccmismatch_notail:
137137 }
138138
139139 declare cxx_fast_tlscc void @some_fast_tls_func()
140 define void @test_ccmismatch_tail() {
140 define void @test_ccmismatch_tail() "no-frame-pointer-elim"="true" {
141141 ; We can perform a tail call here because some_fast_tls_func preserves all
142142 ; necessary registers (and more).
143143 ; CHECK-LABEL: test_ccmismatch_tail:
2222
2323 ; CHECK-ARM-LABEL: test2:
2424 ; CHECK-ARM: .cfi_startproc
25 ; CHECK-ARM: push {r4, r5}
26 ; CHECK-ARM: .cfi_def_cfa_offset 8
27 ; CHECK-ARM: .cfi_offset r5, -4
28 ; CHECK-ARM: .cfi_offset r4, -8
25 ; CHECK-ARM: push {r4, r5, r11, lr}
26 ; CHECK-ARM: .cfi_def_cfa_offset 16
27 ; CHECK-ARM: .cfi_offset lr, -4
28 ; CHECK-ARM: .cfi_offset r11, -8
29 ; CHECK-ARM: .cfi_offset r5, -12
30 ; CHECK-ARM: .cfi_offset r4, -16
31 ; CHECK-ARM: add r11, sp, #8
32 ; CHECK-ARM: .cfi_def_cfa r11, 8
2933 ; CHECK-ARM: sub sp, sp, #72
3034 ; CHECK-ARM: sub sp, sp, #4096
31 ; CHECK-ARM: .cfi_def_cfa_offset 4176
3235 ; CHECK-ARM: .cfi_endproc
3336
3437 ; CHECK-ARM-FP_ELIM-LABEL: test2:
5356
5457 ; CHECK-ARM-LABEL: test3:
5558 ; CHECK-ARM: .cfi_startproc
56 ; CHECK-ARM: push {r4, r5, r11}
57 ; CHECK-ARM: .cfi_def_cfa_offset 12
58 ; CHECK-ARM: .cfi_offset r11, -4
59 ; CHECK-ARM: .cfi_offset r5, -8
60 ; CHECK-ARM: .cfi_offset r4, -12
59 ; CHECK-ARM: push {r4, r5, r11, lr}
60 ; CHECK-ARM: .cfi_def_cfa_offset 16
61 ; CHECK-ARM: .cfi_offset lr, -4
62 ; CHECK-ARM: .cfi_offset r11, -8
63 ; CHECK-ARM: .cfi_offset r5, -12
64 ; CHECK-ARM: .cfi_offset r4, -16
6165 ; CHECK-ARM: add r11, sp, #8
62 ; CHECK-ARM: .cfi_def_cfa r11, 4
63 ; CHECK-ARM: sub sp, sp, #20
66 ; CHECK-ARM: .cfi_def_cfa r11, 8
67 ; CHECK-ARM: sub sp, sp, #16
6468 ; CHECK-ARM: sub sp, sp, #805306368
6569 ; CHECK-ARM: bic sp, sp, #15
6670 ; CHECK-ARM: .cfi_endproc
55
66 %struct.tag_s = type { i32, i32, i32 }
77
8 define void @foo(%struct.tag_s* nocapture %this, %struct.tag_s* %c, i64 %x, i64 %y, %struct.tag_s* nocapture %ptr1, %struct.tag_s* nocapture %ptr2) nounwind ssp !dbg !1 {
8 define void @foo(%struct.tag_s* nocapture %this, %struct.tag_s* %c, i64 %x, i64 %y, %struct.tag_s* nocapture %ptr1, %struct.tag_s* nocapture %ptr2) nounwind ssp "no-frame-pointer-elim"="true" !dbg !1 {
99 tail call void @llvm.dbg.value(metadata %struct.tag_s* %this, i64 0, metadata !5, metadata !DIExpression()), !dbg !20
1010 tail call void @llvm.dbg.value(metadata %struct.tag_s* %c, i64 0, metadata !13, metadata !DIExpression()), !dbg !21
1111 tail call void @llvm.dbg.value(metadata i64 %x, i64 0, metadata !14, metadata !DIExpression()), !dbg !22
7070
7171 define void @test_frame_pointer_offset() minsize "no-frame-pointer-elim"="true" {
7272 ; CHECK-LABEL: test_frame_pointer_offset:
73 ; CHECK: push.w {r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}
74 ; CHECK: .cfi_def_cfa_offset 40
75 ; CHECK: add r7, sp, #16
76 ; CHECK: .cfi_def_cfa r7, 24
73 ; CHECK: push {r4, r5, r6, r7, lr}
74 ; CHECK: .cfi_def_cfa_offset 20
75 ; CHECK: add r7, sp, #12
76 ; CHECK: .cfi_def_cfa r7, 8
77 ; CHECK-NOT: .cfi_def_cfa_offset
78 ; CHECK: push.w {r7, r8, r9, r10, r11}
7779 ; CHECK-NOT: .cfi_def_cfa_offset
7880 call void asm sideeffect "", "~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{d8}"()
7981 call void @bar()
8082 ret void
81 }
83 }
55 define i8* @frameaddr_index0() nounwind {
66 entry:
77 ; DARWIN-ARM-LABEL: frameaddr_index0:
8 ; DARWIN-ARM: push {r7}
8 ; DARWIN-ARM: push {r7, lr}
99 ; DARWIN-ARM: mov r7, sp
1010 ; DARWIN-ARM: mov r0, r7
1111
1212 ; DARWIN-THUMB2-LABEL: frameaddr_index0:
13 ; DARWIN-THUMB2: str r7, [sp, #-4]!
13 ; DARWIN-THUMB2: push {r7, lr}
1414 ; DARWIN-THUMB2: mov r7, sp
1515 ; DARWIN-THUMB2: mov r0, r7
1616
1717 ; LINUX-ARM-LABEL: frameaddr_index0:
18 ; LINUX-ARM: push {r11}
18 ; LINUX-ARM: push {r11, lr}
1919 ; LINUX-ARM: mov r11, sp
2020 ; LINUX-ARM: mov r0, r11
2121
2222 ; LINUX-THUMB2-LABEL: frameaddr_index0:
23 ; LINUX-THUMB2: str r7, [sp, #-4]!
23 ; LINUX-THUMB2: push {r7, lr}
2424 ; LINUX-THUMB2: mov r7, sp
2525 ; LINUX-THUMB2: mov r0, r7
2626
3131 define i8* @frameaddr_index1() nounwind {
3232 entry:
3333 ; DARWIN-ARM-LABEL: frameaddr_index1:
34 ; DARWIN-ARM: push {r7}
34 ; DARWIN-ARM: push {r7, lr}
3535 ; DARWIN-ARM: mov r7, sp
3636 ; DARWIN-ARM: ldr r0, [r7]
3737
3838 ; DARWIN-THUMB2-LABEL: frameaddr_index1:
39 ; DARWIN-THUMB2: str r7, [sp, #-4]!
39 ; DARWIN-THUMB2: push {r7, lr}
4040 ; DARWIN-THUMB2: mov r7, sp
4141 ; DARWIN-THUMB2: ldr r0, [r7]
4242
4343 ; LINUX-ARM-LABEL: frameaddr_index1:
44 ; LINUX-ARM: push {r11}
44 ; LINUX-ARM: push {r11, lr}
4545 ; LINUX-ARM: mov r11, sp
4646 ; LINUX-ARM: ldr r0, [r11]
4747
4848 ; LINUX-THUMB2-LABEL: frameaddr_index1:
49 ; LINUX-THUMB2: str r7, [sp, #-4]!
49 ; LINUX-THUMB2: push {r7, lr}
5050 ; LINUX-THUMB2: mov r7, sp
5151 ; LINUX-THUMB2: mov r0, r7
5252 ; LINUX-THUMB2: ldr r0, [r0]
5858 define i8* @frameaddr_index3() nounwind {
5959 entry:
6060 ; DARWIN-ARM-LABEL: frameaddr_index3:
61 ; DARWIN-ARM: push {r7}
61 ; DARWIN-ARM: push {r7, lr}
6262 ; DARWIN-ARM: mov r7, sp
6363 ; DARWIN-ARM: ldr r0, [r7]
6464 ; DARWIN-ARM: ldr r0, [r0]
6565 ; DARWIN-ARM: ldr r0, [r0]
6666
6767 ; DARWIN-THUMB2-LABEL: frameaddr_index3:
68 ; DARWIN-THUMB2: str r7, [sp, #-4]!
68 ; DARWIN-THUMB2: push {r7, lr}
6969 ; DARWIN-THUMB2: mov r7, sp
7070 ; DARWIN-THUMB2: ldr r0, [r7]
7171 ; DARWIN-THUMB2: ldr r0, [r0]
7272 ; DARWIN-THUMB2: ldr r0, [r0]
7373
7474 ; LINUX-ARM-LABEL: frameaddr_index3:
75 ; LINUX-ARM: push {r11}
75 ; LINUX-ARM: push {r11, lr}
7676 ; LINUX-ARM: mov r11, sp
7777 ; LINUX-ARM: ldr r0, [r11]
7878 ; LINUX-ARM: ldr r0, [r0]
7979 ; LINUX-ARM: ldr r0, [r0]
8080
8181 ; LINUX-THUMB2-LABEL: frameaddr_index3:
82 ; LINUX-THUMB2: str r7, [sp, #-4]!
82 ; LINUX-THUMB2: push {r7, lr}
8383 ; LINUX-THUMB2: mov r7, sp
8484 ; LINUX-THUMB2: mov r0, r7
8585 ; LINUX-THUMB2: ldr r0, [r0]
88
99 @str = internal constant [12 x i8] c"Hello World\00"
1010
11 define i32 @main() {
11 define i32 @main() "no-frame-pointer-elim"="true" {
1212 %tmp = call i32 @puts( i8* getelementptr ([12 x i8], [12 x i8]* @str, i32 0, i64 0) ) ; [#uses=0]
1313 ret i32 0
1414 }
1616 declare i32 @puts(i8*)
1717
1818 ; CHECK-LABEL: main
19 ; CHECK: mov
19 ; CHECK-NOT: mov
20 ; CHECK: mov r11, sp
21 ; CHECK-NOT: mov
22 ; CHECK: mov r0, #0
2023 ; CHECK-NOT: mov
2124
2225 ; CHECK-FP-ELIM-LABEL: main
1515 ; CHECK-NEXT: moveq pc
1616 ; CHECK-NEXT: LBB{{[0-9_]+}}:
1717 ; CHECK-NEXT: cmp {{.*}}, #42
18 ; CHECK-NEXT: itt ne
19 ; CHECK-NEXT: strne.w
20 ; CHECK-NEXT: movne pc
18 ; CHECK-NEXT: beq [[CALL_FOO_1234:LBB[0-9_]+]]
19 ; CHECK-NEXT: ldr {{.*}}[sp
20 ; CHECK-NEXT: str
21 ; CHECK-NEXT: mov pc
2122 ; CHECK-NEXT: Ltmp
22 ; CHECK-NEXT: LBB0_2:
23 ; CHECK-NEXT: [[CALL_FOO_1234]]:
2324 ; CHECK-NEXT: movw r0, #1234
2425 ; CHECK-NEXT: b [[FOOCALL:LBB[0-9_]+]]
2526 ; CHECK-NEXT: Ltmp
2930 ; CHECK-NEXT: bl _foo
3031 ;
3132 ; CHECK-PROB: BB#0:
32 ; 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%)
33 ; CHECK-PROB: BB#1:
34 ; CHECK-PROB: Successors according to CFG: BB#2({{[0-9a-fx/= ]+}}75.00%) BB#4({{[0-9a-fx/= ]+}}25.00%)
33 ; CHECK-PROB: Successors according to CFG: BB#1({{[0-9a-fx/= ]+}}50.00%) BB#3({{[0-9a-fx/= ]+}}25.00%) BB#5({{[0-9a-fx/= ]+}}25.00%)
34 ; CHECK-PROB: BB#2:
35 ; CHECK-PROB: Successors according to CFG: BB#3({{[0-9a-fx/= ]+}}50.00%) BB#5({{[0-9a-fx/= ]+}}50.00%)
3536
36 define i32 @test(i32 %a, i32 %a2, i32* %p, i32* %p2) {
37 define i32 @test(i32 %a, i32 %a2, i32* %p, i32* %p2) "no-frame-pointer-elim"="true" {
3738 entry:
3839 %dst1 = call i8* @bar(i32 1, i8* blockaddress(@test, %bb1), i8* blockaddress(@test, %bb2))
3940 %dst2 = call i8* @bar(i32 2, i8* blockaddress(@test, %bb1), i8* blockaddress(@test, %bb2))
33 ; micro-coded and would have long issue latency even if predicated on
44 ; false predicate.
55
6 define void @t(double %a, double %b, double %c, double %d, i32* nocapture %solutions, double* nocapture %x) nounwind {
6 define void @t(double %a, double %b, double %c, double %d, i32* nocapture %solutions, double* nocapture %x) nounwind "no-frame-pointer-elim"="true" {
77 entry:
88 ; CHECK-LABEL: t:
99 ; CHECK: vpop {d8}
33
44 @x = external global i32* ; [#uses=1]
55
6 define void @foo(i32 %a) {
6 define void @foo(i32 %a) "no-frame-pointer-elim"="true" {
77 entry:
88 %tmp = load i32*, i32** @x ; [#uses=1]
99 store i32 %a, i32* %tmp
1010 ret void
1111 }
1212
13 define i32 @t1(i32 %a, i32 %b) {
13 define i32 @t1(i32 %a, i32 %b) "no-frame-pointer-elim"="true" {
1414 ; A8-LABEL: t1:
1515 ; A8: bxlt lr
1616
0 ; RUN: llc -mtriple=arm-eabi -mattr=+v6 %s -o /dev/null
11 ; RUN: llc -mtriple=arm-apple-ios -mattr=+v6 %s -o - | FileCheck %s
22
3 define i32 @test(i32 %x) {
3 define i32 @test(i32 %x) "no-frame-pointer-elim"="true" {
44 %tmp = trunc i32 %x to i16 ; [#uses=1]
55 %tmp2 = call i32 @f( i32 1, i16 %tmp ) ; [#uses=1]
66 ret i32 %tmp2
1414 declare i64* @get_ptr()
1515 declare void @use_i64(i64 %v)
1616
17 define void @test_ldrd(i64 %a) nounwind readonly {
17 define void @test_ldrd(i64 %a) nounwind readonly "no-frame-pointer-elim"="true" {
1818 ; CHECK-LABEL: test_ldrd:
1919 ; NORMAL: bl{{x?}} _get_ptr
2020 ; A8: ldrd r0, r1, [r0]
4848 ; GREEDY: %bb
4949 ; GREEDY: ldrd
5050 ; GREEDY: str
51 define void @f(i32* nocapture %a, i32* nocapture %b, i32 %n) nounwind {
51 define void @f(i32* nocapture %a, i32* nocapture %b, i32 %n) nounwind "no-frame-pointer-elim"="true" {
5252 entry:
5353 %0 = add nsw i32 %n, -1 ; [#uses=2]
5454 %1 = icmp sgt i32 %0, 0 ; [#uses=1]
7878 @TestVar = external global %struct.Test
7979
8080 ; CHECK-LABEL: Func1:
81 define void @Func1() nounwind ssp {
81 define void @Func1() nounwind ssp "no-frame-pointer-elim"="true" {
8282 entry:
8383 ; A8: movw [[BASE:r[0-9]+]], :lower16:{{.*}}TestVar{{.*}}
8484 ; A8: movt [[BASE]], :upper16:{{.*}}TestVar{{.*}}
103103 ; A8: ldrd
104104 ; CHECK: bl{{x?}} _extfunc
105105 ; A8: pop
106 define void @Func2(i32* %p) {
106 define void @Func2(i32* %p) "no-frame-pointer-elim"="true" {
107107 entry:
108108 %addr0 = getelementptr i32, i32* %p, i32 0
109109 %addr1 = getelementptr i32, i32* %p, i32 1
128128 ; GREEDY: ldrd r1, r2, [sp]
129129 ; CONSERVATIVE: ldrd r1, r2, [sp]
130130 ; CHECK: bl{{x?}} _extfunc
131 define void @strd_spill_ldrd_reload(i32 %v0, i32 %v1) {
131 define void @strd_spill_ldrd_reload(i32 %v0, i32 %v1) "no-frame-pointer-elim"="true" {
132132 ; force %v0 and %v1 to be spilled
133133 call void asm sideeffect "", "~{r0},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr}"()
134134 ; force the reloaded %v0, %v1 into different registers
142142 ; NORMAL: ldrd r1, r2, [r0], #-8
143143 ; CONSERVATIVE-NOT: ldrd
144144 ; CHECK: bl{{x?}} _extfunc
145 define void @ldrd_postupdate_dec(i32* %p0) {
145 define void @ldrd_postupdate_dec(i32* %p0) "no-frame-pointer-elim"="true" {
146146 %p0.1 = getelementptr i32, i32* %p0, i32 1
147147 %v0 = load i32, i32* %p0
148148 %v1 = load i32, i32* %p0.1
155155 ; NORMAL: ldrd r1, r2, [r0], #8
156156 ; CONSERVATIVE-NOT: ldrd
157157 ; CHECK: bl{{x?}} _extfunc
158 define void @ldrd_postupdate_inc(i32* %p0) {
158 define void @ldrd_postupdate_inc(i32* %p0) "no-frame-pointer-elim"="true" {
159159 %p0.1 = getelementptr i32, i32* %p0, i32 1
160160 %v0 = load i32, i32* %p0
161161 %v1 = load i32, i32* %p0.1
168168 ; NORMAL: strd r1, r2, [r0], #-8
169169 ; CONSERVATIVE-NOT: strd
170170 ; CHECK: bx lr
171 define i32* @strd_postupdate_dec(i32* %p0, i32 %v0, i32 %v1) {
171 define i32* @strd_postupdate_dec(i32* %p0, i32 %v0, i32 %v1) "no-frame-pointer-elim"="true" {
172172 %p0.1 = getelementptr i32, i32* %p0, i32 1
173173 store i32 %v0, i32* %p0
174174 store i32 %v1, i32* %p0.1
180180 ; NORMAL: strd r1, r2, [r0], #8
181181 ; CONSERVATIVE-NOT: strd
182182 ; CHECK: bx lr
183 define i32* @strd_postupdate_inc(i32* %p0, i32 %v0, i32 %v1) {
183 define i32* @strd_postupdate_inc(i32* %p0, i32 %v0, i32 %v1) "no-frame-pointer-elim"="true" {
184184 %p0.1 = getelementptr i32, i32* %p0, i32 1
185185 store i32 %v0, i32* %p0
186186 store i32 %v1, i32* %p0.1
1414
1515 %struct.partition_entry = type { i32, i32, i64, i64 }
1616
17 define i32 @partition_overlap_check(%struct.partition_entry* nocapture %part, i32 %num_entries) nounwind readonly optsize ssp {
17 define i32 @partition_overlap_check(%struct.partition_entry* nocapture %part, i32 %num_entries) nounwind readonly optsize ssp "no-frame-pointer-elim"="true" {
1818 entry:
1919 %cmp79 = icmp sgt i32 %num_entries, 0
2020 br i1 %cmp79, label %outer.loop, label %for.end72
77 ; RUN: llc < %s -mtriple=arm-none-musleabi -disable-post-ra -o - | FileCheck %s --check-prefix=CHECK-GNUEABI --check-prefix=CHECK
88 ; RUN: llc < %s -mtriple=arm-none-musleabihf -disable-post-ra -o - | FileCheck %s --check-prefix=CHECK-GNUEABI --check-prefix=CHECK
99
10 define void @f1(i8* %dest, i8* %src) {
10 define void @f1(i8* %dest, i8* %src) "no-frame-pointer-elim"="true" {
1111 entry:
1212 ; CHECK-LABEL: f1
1313
9797 }
9898
9999 ; Check that alloca arguments to memory intrinsics are automatically aligned if at least 8 bytes in size
100 define void @f2(i8* %dest, i32 %n) {
100 define void @f2(i8* %dest, i32 %n) "no-frame-pointer-elim"="true" {
101101 entry:
102102 ; CHECK-LABEL: f2
103103
106106 ; CHECK-IOS: bl _memmove
107107 ; CHECK-DARWIN: add r1, sp, #28
108108 ; CHECK-DARWIN: bl _memmove
109 ; CHECK-EABI: add r1, sp, #28
110 ; CHECK-EABI: bl __aeabi_memmove
111 ; CHECK-GNUEABI: add r1, sp, #28
109 ; CHECK-EABI: {{add r1, sp, #28|sub r1, r(7|11), #20}}
110 ; CHECK-EABI: bl __aeabi_memmove
111 ; CHECK-GNUEABI: {{add r1, sp, #28|sub r1, r(7|11), #20}}
112112 ; CHECK-GNUEABI: bl memmove
113113 %arr0 = alloca [9 x i8], align 1
114114 %0 = bitcast [9 x i8]* %arr0 to i8*
143143 }
144144
145145 ; Check that alloca arguments are not aligned if less than 8 bytes in size
146 define void @f3(i8* %dest, i32 %n) {
146 define void @f3(i8* %dest, i32 %n) "no-frame-pointer-elim"="true" {
147147 entry:
148148 ; CHECK-LABEL: f3
149149
150 ; CHECK: {{add(.w)? r1, sp, #17|sub(.w)? r1, r7, #15}}
150 ; CHECK: {{add(.w)? r1, sp, #17|sub(.w)? r1, r(7|11), #15}}
151151 ; CHECK-IOS: bl _memmove
152152 ; CHECK-DARWIN: bl _memmove
153153 ; CHECK-EABI: bl __aeabi_memmove
156156 %0 = bitcast [7 x i8]* %arr0 to i8*
157157 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
158158
159 ; CHECK: {{add(.w)? r1, sp, #10}}
159 ; CHECK: {{add(.w)? r1, sp, #10|sub(.w)? r1, r(7|11), #22}}
160160 ; CHECK-IOS: bl _memcpy
161161 ; CHECK-DARWIN: bl _memcpy
162162 ; CHECK-EABI: bl __aeabi_memcpy
165165 %1 = bitcast [7 x i8]* %arr1 to i8*
166166 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
167167
168 ; CHECK: {{add(.w)? r0, sp, #3}}
168 ; CHECK: {{add(.w)? r0, sp, #3|sub(.w)? r0, r(7|11), #29}}
169169 ; CHECK-IOS: mov r1, #1
170170 ; CHECK-IOS: bl _memset
171171 ; CHECK-DARWIN: movs r1, #1
182182 }
183183
184184 ; Check that alloca arguments are not aligned if size+offset is less than 8 bytes
185 define void @f4(i8* %dest, i32 %n) {
185 define void @f4(i8* %dest, i32 %n) "no-frame-pointer-elim"="true" {
186186 entry:
187187 ; CHECK-LABEL: f4
188188
189 ; CHECK: {{add(.w)? r., sp, #23|sub(.w)? r., r7, #17}}
189 ; CHECK: {{add(.w)? r., sp, #23|sub(.w)? r., r(7|11), #17}}
190190 ; CHECK-IOS: bl _memmove
191191 ; CHECK-DARWIN: bl _memmove
192192 ; CHECK-EABI: bl __aeabi_memmove
195195 %0 = getelementptr inbounds [9 x i8], [9 x i8]* %arr0, i32 0, i32 4
196196 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
197197
198 ; CHECK: {{add(.w)? r., sp, #(10|14)}}
198 ; CHECK: {{add(.w)? r., sp, #(10|14)|sub(.w) r., r(7|11), #26}}
199199 ; CHECK-IOS: bl _memcpy
200200 ; CHECK-DARWIN: bl _memcpy
201201 ; CHECK-EABI: bl __aeabi_memcpy
204204 %1 = getelementptr inbounds [9 x i8], [9 x i8]* %arr1, i32 0, i32 4
205205 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
206206
207 ; CHECK: {{add(.w)? r., sp, #(1|5)}}
207 ; CHECK: {{add(.w)? r., sp, #(1|5)|sub(.w) r., r(7|11), #35}}
208208 ; CHECK-IOS: mov r1, #1
209209 ; CHECK-IOS: bl _memset
210210 ; CHECK-DARWIN: movs r1, #1
221221 }
222222
223223 ; Check that alloca arguments are not aligned if the offset is not a multiple of 4
224 define void @f5(i8* %dest, i32 %n) {
224 define void @f5(i8* %dest, i32 %n) "no-frame-pointer-elim"="true" {
225225 entry:
226226 ; CHECK-LABEL: f5
227227
228 ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r7, #21}}
228 ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r(7|11), #21}}
229229 ; CHECK-IOS: bl _memmove
230230 ; CHECK-DARWIN: bl _memmove
231231 ; CHECK-EABI: bl __aeabi_memmove
234234 %0 = getelementptr inbounds [13 x i8], [13 x i8]* %arr0, i32 0, i32 1
235235 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
236236
237 ; CHECK: {{add(.w)? r., sp, #(10|14)}}
237 ; CHECK: {{add(.w)? r., sp, #(10|14)|sub(.w)? r., r(7|11), #34}}
238238 ; CHECK-IOS: bl _memcpy
239239 ; CHECK-DARWIN: bl _memcpy
240240 ; CHECK-EABI: bl __aeabi_memcpy
243243 %1 = getelementptr inbounds [13 x i8], [13 x i8]* %arr1, i32 0, i32 1
244244 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
245245
246 ; CHECK: {{add(.w)? r., sp, #(1|5)}}
246 ; CHECK: {{add(.w)? r., sp, #(1|5)|sub(.w)? r., r(7|11), #47}}
247247 ; CHECK-IOS: mov r1, #1
248248 ; CHECK-IOS: bl _memset
249249 ; CHECK-DARWIN: movs r1, #1
260260 }
261261
262262 ; Check that alloca arguments are not aligned if the offset is unknown
263 define void @f6(i8* %dest, i32 %n, i32 %i) {
263 define void @f6(i8* %dest, i32 %n, i32 %i) "no-frame-pointer-elim"="true" {
264264 entry:
265265 ; CHECK-LABEL: f6
266266
267 ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r7, #25}}
267 ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r(7|11), #(25|29)}}
268268 ; CHECK-IOS: bl _memmove
269269 ; CHECK-DARWIN: bl _memmove
270270 ; CHECK-EABI: bl __aeabi_memmove
273273 %0 = getelementptr inbounds [13 x i8], [13 x i8]* %arr0, i32 0, i32 %i
274274 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
275275
276 ; CHECK: {{add(.w)? r., sp, #(10|14)}}
276 ; CHECK: {{add(.w)? r., sp, #(10|14)|sub(.w)? r., r(7|11), #42}}
277277 ; CHECK-IOS: bl _memcpy
278278 ; CHECK-DARWIN: bl _memcpy
279279 ; CHECK-EABI: bl __aeabi_memcpy
282282 %1 = getelementptr inbounds [13 x i8], [13 x i8]* %arr1, i32 0, i32 %i
283283 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
284284
285 ; CHECK: {{add(.w)? r., sp, #(1|5)}}
285 ; CHECK: {{add(.w)? r., sp, #(1|5)|sub(.w)? r., r(7|11), #55}}
286286 ; CHECK-IOS: mov r1, #1
287287 ; CHECK-IOS: bl _memset
288288 ; CHECK-DARWIN: movs r1, #1
299299 }
300300
301301 ; Check that alloca arguments are not aligned if the GEP is not inbounds
302 define void @f7(i8* %dest, i32 %n) {
302 define void @f7(i8* %dest, i32 %n) "no-frame-pointer-elim"="true" {
303303 entry:
304304 ; CHECK-LABEL: f7
305305
306 ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r7, #21}}
306 ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r(7|11), #21}}
307307 ; CHECK-IOS: bl _memmove
308308 ; CHECK-DARWIN: bl _memmove
309309 ; CHECK-EABI: bl __aeabi_memmove
312312 %0 = getelementptr [13 x i8], [13 x i8]* %arr0, i32 0, i32 4
313313 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
314314
315 ; CHECK: {{add(.w)? r., sp, #(10|14)}}
315 ; CHECK: {{add(.w)? r., sp, #(10|14)|sub(.w)? r., r(7|11), #34}}
316316 ; CHECK-IOS: bl _memcpy
317317 ; CHECK-DARWIN: bl _memcpy
318318 ; CHECK-EABI: bl __aeabi_memcpy
321321 %1 = getelementptr [13 x i8], [13 x i8]* %arr1, i32 0, i32 4
322322 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
323323
324 ; CHECK: {{add(.w)? r., sp, #(1|5)}}
324 ; CHECK: {{add(.w)? r., sp, #(1|5)|sub(.w)? r., r(7|11), #47}}
325325 ; CHECK-IOS: mov r1, #1
326326 ; CHECK-IOS: bl _memset
327327 ; CHECK-DARWIN: movs r1, #1
338338 }
339339
340340 ; Check that alloca arguments are not aligned when the offset is past the end of the allocation
341 define void @f8(i8* %dest, i32 %n) {
341 define void @f8(i8* %dest, i32 %n) "no-frame-pointer-elim"="true" {
342342 entry:
343343 ; CHECK-LABEL: f8
344344
345 ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r7, #21}}
345 ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r(7|11), #21}}
346346 ; CHECK-IOS: bl _memmove
347347 ; CHECK-DARWIN: bl _memmove
348348 ; CHECK-EABI: bl __aeabi_memmove
351351 %0 = getelementptr inbounds [13 x i8], [13 x i8]* %arr0, i32 0, i32 16
352352 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
353353
354 ; CHECK: {{add(.w)? r., sp, #(10|14)}}
354 ; CHECK: {{add(.w)? r., sp, #(10|14)|sub(.w)? r., r(7|11), #34}}
355355 ; CHECK-IOS: bl _memcpy
356356 ; CHECK-DARWIN: bl _memcpy
357357 ; CHECK-EABI: bl __aeabi_memcpy
360360 %1 = getelementptr inbounds [13 x i8], [13 x i8]* %arr1, i32 0, i32 16
361361 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
362362
363 ; CHECK: {{add(.w)? r., sp, #(1|5)}}
363 ; CHECK: {{add(.w)? r., sp, #(1|5)|sub(.w)? r., r(7|11), #47}}
364364 ; CHECK-IOS: mov r1, #1
365365 ; CHECK-IOS: bl _memset
366366 ; CHECK-DARWIN: movs r1, #1
387387 @arr7 = external global [7 x i8], align 1
388388 @arr8 = internal global [128 x i8] undef
389389 @arr9 = weak_odr global [128 x i8] undef
390 define void @f9(i8* %dest, i32 %n) {
390 define void @f9(i8* %dest, i32 %n) "no-frame-pointer-elim"="true" {
391391 entry:
392392 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @arr1, i32 0, i32 0), i32 %n, i32 1, i1 false)
393393 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @arr2, i32 0, i32 0), i32 %n, i32 1, i1 false)
0 ; RUN: llc -O3 -o - %s | FileCheck %s
11 ; Test case from PR16882.
2 target triple = "thumbv7s-apple-ios"
2 target triple = "thumbv7a-none-eabi"
33
44 define i32 @test1() {
55 ; CHECK-LABEL: @test1
5959 unreachable
6060 }
6161
62
63 define i32 @test1_nofpelim() "no-frame-pointer-elim"="true" {
64 ; CHECK-LABEL: @test1_nofpelim
65 ; CHECK: push
66 entry:
67 tail call void @overflow() #0
68 unreachable
69 }
70
71 define i32 @test2_nofpelim(i32 %x, i32 %y) "no-frame-pointer-elim"="true" {
72 ; CHECK-LABEL: @test2_nofpelim
73 ; CHECK: push
74 entry:
75 %conv = sext i32 %x to i64
76 %conv1 = sext i32 %y to i64
77 %mul = mul nsw i64 %conv1, %conv
78 %conv2 = trunc i64 %mul to i32
79 %conv3 = sext i32 %conv2 to i64
80 %cmp = icmp eq i64 %mul, %conv3
81 br i1 %cmp, label %if.end, label %if.then
82
83 if.then: ; preds = %entry
84 tail call void @overflow() #0
85 unreachable
86
87 if.end: ; preds = %entry
88 ret i32 %conv2
89 }
90
91 ; Test case for PR17825.
92 define i32 @test3_nofpelim() "no-frame-pointer-elim"="true" {
93 ; CHECK-LABEL: @test3_nofpelim
94 ; CHECK: push
95 entry:
96 tail call void @overflow_with_unwind() #1
97 unreachable
98 }
99
100 ; Test case for uwtable
101 define i32 @test4_nofpelim() uwtable "no-frame-pointer-elim"="true" {
102 ; CHECK-LABEL: @test4_nofpelim
103 ; CHECK: push
104 entry:
105 tail call void @overflow() #0
106 unreachable
107 }
108
109 define i32 @test5_nofpelim() uwtable "no-frame-pointer-elim"="true" {
110 ; CHECK-LABEL: @test5_nofpelim
111 ; CHECK: push
112 entry:
113 tail call void @overflow_with_unwind() #1
114 unreachable
115 }
116
62117 ; Function Attrs: noreturn
63118 declare void @overflow_with_unwind() #1
64119
66 ; Parameter with swiftself should be allocated to r10.
77 ; CHECK-LABEL: swiftself_param:
88 ; CHECK: mov r0, r10
9 define i8 *@swiftself_param(i8* swiftself %addr0) {
9 define i8 *@swiftself_param(i8* swiftself %addr0) "no-frame-pointer-elim"="true" {
1010 ret i8 *%addr0
1111 }
1212
1414 ; CHECK-LABEL: call_swiftself:
1515 ; CHECK: mov r10, r0
1616 ; CHECK: bl {{_?}}swiftself_param
17 define i8 *@call_swiftself(i8* %arg) {
17 define i8 *@call_swiftself(i8* %arg) "no-frame-pointer-elim"="true" {
1818 %res = call i8 *@swiftself_param(i8* swiftself %arg)
1919 ret i8 *%res
2020 }
2424 ; CHECK: push {r10}
2525 ; ...
2626 ; CHECK: pop {r10}
27 define i8 *@swiftself_clobber(i8* swiftself %addr0) {
27 define i8 *@swiftself_clobber(i8* swiftself %addr0) "no-frame-pointer-elim"="true" {
2828 call void asm sideeffect "", "~{r10}"()
2929 ret i8 *%addr0
3030 }
3636 ; OPT: bl {{_?}}swiftself_param
3737 ; OPT-NOT: mov{{.*}}r10
3838 ; OPT-NEXT: bl {{_?}}swiftself_param
39 define void @swiftself_passthrough(i8* swiftself %addr0) {
39 define void @swiftself_passthrough(i8* swiftself %addr0) "no-frame-pointer-elim"="true" {
4040 call i8 *@swiftself_param(i8* swiftself %addr0)
4141 call i8 *@swiftself_param(i8* swiftself %addr0)
4242 ret void
4646 ; CHECK-LABEL: swiftself_tail:
4747 ; TAILCALL: b {{_?}}swiftself_param
4848 ; TAILCALL-NOT: pop
49 define i8* @swiftself_tail(i8* swiftself %addr0) {
49 define i8* @swiftself_tail(i8* swiftself %addr0) "no-frame-pointer-elim"="true" {
5050 call void asm sideeffect "", "~{r10}"()
5151 %res = tail call i8* @swiftself_param(i8* swiftself %addr0)
5252 ret i8* %res
5858 ; CHECK: mov r10, r0
5959 ; CHECK: bl {{_?}}swiftself_param
6060 ; CHECK: pop
61 define i8* @swiftself_notail(i8* swiftself %addr0, i8* %addr1) nounwind {
61 define i8* @swiftself_notail(i8* swiftself %addr0, i8* %addr1) nounwind "no-frame-pointer-elim"="true" {
6262 %res = tail call i8* @swiftself_param(i8* swiftself %addr1)
6363 ret i8* %res
6464 }
11
22 %struct = type { i8, i64, i8, double, i8, <2 x float>, i8, <4 x float> }
33
4 define i32 @test_i64_align() {
4 define i32 @test_i64_align() "no-frame-pointer-elim"="true" {
55 ; CHECK-LABEL: test_i64_align:
66 ; CHECL: movs r0, #8
77 ret i32 ptrtoint(i64* getelementptr(%struct, %struct* null, i32 0, i32 1) to i32)
88 }
99
10 define i32 @test_f64_align() {
10 define i32 @test_f64_align() "no-frame-pointer-elim"="true" {
1111 ; CHECK-LABEL: test_f64_align:
1212 ; CHECL: movs r0, #24
1313 ret i32 ptrtoint(double* getelementptr(%struct, %struct* null, i32 0, i32 3) to i32)
1414 }
1515
16 define i32 @test_v2f32_align() {
16 define i32 @test_v2f32_align() "no-frame-pointer-elim"="true" {
1717 ; CHECK-LABEL: test_v2f32_align:
1818 ; CHECL: movs r0, #40
1919 ret i32 ptrtoint(<2 x float>* getelementptr(%struct, %struct* null, i32 0, i32 5) to i32)
2020 }
2121
22 define i32 @test_v4f32_align() {
22 define i32 @test_v4f32_align() "no-frame-pointer-elim"="true" {
2323 ; CHECK-LABEL: test_v4f32_align:
2424 ; CHECL: movs r0, #64
2525 ret i32 ptrtoint(<4 x float>* getelementptr(%struct, %struct* null, i32 0, i32 7) to i32)
2727
2828 ; Key point here is than an extra register has to be saved so that the DPRs end
2929 ; up in an aligned location (as prologue/epilogue inserter had calculated).
30 define void @test_dpr_unwind_align() {
30 define void @test_dpr_unwind_align() "no-frame-pointer-elim"="true" {
3131 ; CHECK-LABEL: test_dpr_unwind_align:
3232 ; CHECK: push {r5, r6, r7, lr}
3333 ; CHECK-NOT: sub sp
5050
5151 ; This time, there's no viable way to tack CS-registers onto the list: a real SP
5252 ; adjustment needs to be performed to put d8 and d9 where they should be.
53 define void @test_dpr_unwind_align_manually() {
53 define void @test_dpr_unwind_align_manually() "no-frame-pointer-elim"="true" {
5454 ; CHECK-LABEL: test_dpr_unwind_align_manually:
5555 ; CHECK: push {r4, r5, r6, r7, lr}
5656 ; CHECK-NOT: sub sp
7575 }
7676
7777 ; If there's only a CS1 area, the sub should be in the right place:
78 define void @test_dpr_unwind_align_just_cs1() {
78 define void @test_dpr_unwind_align_just_cs1() "no-frame-pointer-elim"="true" {
7979 ; CHECK-LABEL: test_dpr_unwind_align_just_cs1:
8080 ; CHECK: push {r4, r5, r6, r7, lr}
8181 ; CHECK: sub sp, #4
9898 }
9999
100100 ; If there are no DPRs, we shouldn't try to align the stack in stages anyway
101 define void @test_dpr_unwind_align_no_dprs() {
101 define void @test_dpr_unwind_align_no_dprs() "no-frame-pointer-elim"="true" {
102102 ; CHECK-LABEL: test_dpr_unwind_align_no_dprs:
103103 ; CHECK: push {r4, r5, r6, r7, lr}
104104 ; CHECK: sub sp, #12
116116
117117 ; 128-bit vectors should use 128-bit (i.e. correctly aligned) slots on
118118 ; the stack.
119 define <4 x float> @test_v128_stack_pass([8 x double], float, <4 x float> %in) {
119 define <4 x float> @test_v128_stack_pass([8 x double], float, <4 x float> %in) "no-frame-pointer-elim"="true" {
120120 ; CHECK-LABEL: test_v128_stack_pass:
121121 ; CHECK: add r[[ADDR:[0-9]+]], sp, #16
122122 ; CHECK: vld1.64 {d0, d1}, [r[[ADDR]]:128]
128128
129129 ; When varargs are enabled, we go down a different route. Still want 128-bit
130130 ; alignment though.
131 define void @test_v128_stack_pass_varargs(<4 x float> %in) {
131 define void @test_v128_stack_pass_varargs(<4 x float> %in) "no-frame-pointer-elim"="true" {
132132 ; CHECK-LABEL: test_v128_stack_pass_varargs:
133133 ; CHECK: add r[[ADDR:[0-9]+]], sp, #16
134134 ; CHECK: vst1.64 {d0, d1}, [r[[ADDR]]:128]
139139
140140 ; To be compatible with AAPCS's va_start model (store r0-r3 at incoming SP, give
141141 ; a single pointer), 64-bit quantities must be pass
142 define i64 @test_64bit_gpr_align(i32, i64 %r2_r3, i32 %sp) {
142 define i64 @test_64bit_gpr_align(i32, i64 %r2_r3, i32 %sp) "no-frame-pointer-elim"="true" {
143143 ; CHECK-LABEL: test_64bit_gpr_align:
144144 ; CHECK: ldr [[RHS:r[0-9]+]], [sp]
145145 ; CHECK: adds r0, [[RHS]], r2
33 ;
44
55 ; CHECK-NOT: nowarn
6 define void @nowarn() nounwind ssp {
6 define void @nowarn() nounwind ssp "no-frame-pointer-elim"="true" {
77 entry:
88 %buffer = alloca [12 x i8], align 1
99 %arraydecay = getelementptr inbounds [12 x i8], [12 x i8]* %buffer, i64 0, i64 0
1212 }
1313
1414 ; CHECK: warning: stack size limit exceeded (92) in warn
15 define void @warn() nounwind ssp {
15 define void @warn() nounwind ssp "no-frame-pointer-elim"="true" {
1616 entry:
1717 %buffer = alloca [80 x i8], align 1
1818 %arraydecay = getelementptr inbounds [80 x i8], [80 x i8]* %buffer, i64 0, i64 0
None ; RUN: llc < %s -mtriple=thumb-apple-ios | FileCheck %s --check-prefix=CHECK --check-prefix=IOS
1 ; RUN: llc < %s -mtriple=thumb-none-eabi | FileCheck %s --check-prefix=CHECK --check-prefix=EABI
0 ; RUN: llc < %s -mtriple=thumb-apple-ios | FileCheck %s
1 ; RUN: llc < %s -mtriple=thumb-none-eabi | FileCheck %s
22 ; RUN: llc < %s -o %t -filetype=obj -mtriple=thumbv6-apple-ios
3 ; RUN: llvm-objdump -triple=thumbv6-apple-ios -d %t | FileCheck %s --check-prefix=CHECK --check-prefix=IOS
3 ; RUN: llvm-objdump -triple=thumbv6-apple-ios -d %t | FileCheck %s
44 ; RUN: llc < %s -o %t -filetype=obj -mtriple=thumbv6-none-eabi
5 ; RUN: llvm-objdump -triple=thumbv6-none-eabi -d %t | FileCheck %s --check-prefix=CHECK --check-prefix=EABI
5 ; RUN: llvm-objdump -triple=thumbv6-none-eabi -d %t | FileCheck %s
66
77 ; Largest stack for which a single tADDspi/tSUBspi is enough
88 define void @test1() {
1919 ; CHECK: sub sp, #508
2020 ; CHECK: sub sp, #508
2121 ; CHECK: sub sp, #508
22 ; EABI: add sp, #508
23 ; EABI: add sp, #508
24 ; EABI: add sp, #508
25 ; IOS: subs r4, r7, #4
26 ; IOS: mov sp, r4
22 ; CHECK: add sp, #508
23 ; CHECK: add sp, #508
24 ; CHECK: add sp, #508
25 %tmp = alloca [ 1524 x i8 ] , align 4
26 ret void
27 }
28
29 ; Largest stack for which three tADDspi/tSUBspis are enough
30 define void @test100_nofpelim() "no-frame-pointer-elim"="true" {
31 ; CHECK-LABEL: test100_nofpelim:
32 ; CHECK: sub sp, #508
33 ; CHECK: sub sp, #508
34 ; CHECK: sub sp, #508
35 ; CHECK: subs r4, r7, #4
36 ; CHECK: mov sp, r4
2737 %tmp = alloca [ 1524 x i8 ] , align 4
2838 ret void
2939 }
3343 ; CHECK-LABEL: test2:
3444 ; CHECK: ldr [[TEMP:r[0-7]]],
3545 ; CHECK: add sp, [[TEMP]]
36 ; EABI: ldr [[TEMP:r[0-7]]],
37 ; EABI: add sp, [[TEMP]]
38 ; IOS: subs r4, r7, #4
39 ; IOS: mov sp, r4
46 ; CHECK: ldr [[TEMP:r[0-7]]],
47 ; CHECK: add sp, [[TEMP]]
48 %tmp = alloca [ 1528 x i8 ] , align 4
49 ret void
50 }
51
52 ; Smallest stack for which we use a constant pool
53 define void @test2_nofpelim() "no-frame-pointer-elim"="true" {
54 ; CHECK-LABEL: test2_nofpelim:
55 ; CHECK: ldr [[TEMP:r[0-7]]],
56 ; CHECK: add sp, [[TEMP]]
57 ; CHECK: subs r4, r7, #4
58 ; CHECK: mov sp, r4
4059 %tmp = alloca [ 1528 x i8 ] , align 4
4160 ret void
4261 }
4766 ; CHECK: add sp, [[TEMP]]
4867 ; CHECK: ldr [[TEMP]],
4968 ; CHECK: add [[TEMP]], sp
50 ; EABI: ldr [[TEMP:r[0-7]]],
51 ; EABI: add sp, [[TEMP]]
52 ; IOS: subs r4, r7, #4
53 ; IOS: mov sp, r4
69 ; CHECK: ldr [[TEMP:r[0-7]]],
70 ; CHECK: add sp, [[TEMP]]
71 %retval = alloca i32, align 4
72 %tmp = alloca i32, align 4
73 %a = alloca [805306369 x i8], align 16
74 store i32 0, i32* %tmp
75 %tmp1 = load i32, i32* %tmp
76 ret i32 %tmp1
77 }
78
79 define i32 @test3_nofpelim() "no-frame-pointer-elim"="true" {
80 ; CHECK-LABEL: test3_nofpelim:
81 ; CHECK: ldr [[TEMP:r[0-7]]],
82 ; CHECK: add sp, [[TEMP]]
83 ; CHECK: ldr [[TEMP]],
84 ; CHECK: add [[TEMP]], sp
85 ; CHECK: subs r4, r7,
86 ; CHECK: mov sp, r4
5487 %retval = alloca i32, align 4
5588 %tmp = alloca i32, align 4
5689 %a = alloca [805306369 x i8], align 16
22
33 define void @t() nounwind {
44 ; CHECK-LABEL: t:
5 ; CHECK: push {r7}
5 ; CHECK: push {r7, lr}
66 entry:
77 call void asm sideeffect alignstack ".long 0xe7ffdefe", ""() nounwind
88 ret void
22
33 @"\01LC" = external constant [36 x i8], align 1 ; <[36 x i8]*> [#uses=1]
44
5 define i32 @t(i32, ...) nounwind {
5 define i32 @t(i32, ...) nounwind "no-frame-pointer-elim"="true" {
66 entry:
77 ; CHECK-LABEL: t:
88 ; CHECK: add r7, sp, #12
44
55 declare void @bar() nounwind optsize
66
7 define void @foo() nounwind optsize {
7 define void @foo() nounwind optsize "no-frame-pointer-elim"="true" {
88 ; CHECK-LABEL: foo:
99 ; CHECK: push
1010 ; CHECK: mov r7, sp
1010 ; CHECK: push {r4, r7, lr}
1111 ; CHECK: bfc r4, #0, #3
1212 ; CHECK: mov sp, r4
13 define void @f(double* nocapture %p) nounwind ssp {
13 define void @f(double* nocapture %p) nounwind ssp "no-frame-pointer-elim"="true" {
1414 entry:
1515 %0 = load double, double* %p, align 4
1616 tail call void asm sideeffect "", "~{d8},~{d9},~{d10},~{d11},~{d12},~{d13},~{d14},~{d15}"() nounwind
4444 declare void @g()
4545
4646 ; Spill 7 d-registers.
47 define void @f7(double* nocapture %p) nounwind ssp {
47 define void @f7(double* nocapture %p) nounwind ssp "no-frame-pointer-elim"="true" {
4848 entry:
4949 tail call void asm sideeffect "", "~{d8},~{d9},~{d10},~{d11},~{d12},~{d13},~{d14}"() nounwind
5050 ret void
6868 ; NEON: pop
6969
7070 ; Spill 7 d-registers, leave a hole.
71 define void @f3plus4(double* nocapture %p) nounwind ssp {
71 define void @f3plus4(double* nocapture %p) nounwind ssp "no-frame-pointer-elim"="true" {
7272 entry:
7373 tail call void asm sideeffect "", "~{d8},~{d9},~{d10},~{d12},~{d13},~{d14},~{d15}"() nounwind
7474 ret void
0 ; RUN: llc -mtriple=thumbv7m-none-eabi -o - %s | FileCheck %s
1
2 declare void @foo()
3
4 ; Leaf function, no frame so no need for a frame pointer.
5 define void @leaf() {
6 ; CHECK-LABEL: leaf:
7 ; CHECK-NOT: push
8 ; CHECK-NOT: sp
9 ; CHECK-NOT: pop
10 ; CHECK: bx lr
11 ret void
12 }
13
14 ; Leaf function, frame pointer is requested but we don't need any stack frame,
15 ; so don't create a frame pointer.
16 define void @leaf_nofpelim() "no-frame-pointer-elim"="true" {
17 ; CHECK-LABEL: leaf_nofpelim:
18 ; CHECK-NOT: push
19 ; CHECK-NOT: sp
20 ; CHECK-NOT: pop
21 ; CHECK: bx lr
22 ret void
23 }
24
25 ; Leaf function, frame pointer is requested and we need a stack frame, so we
26 ; need to use a frame pointer.
27 define void @leaf_lowreg_nofpelim() "no-frame-pointer-elim"="true" {
28 ; CHECK-LABEL: leaf_lowreg_nofpelim:
29 ; CHECK: push {r4, r7, lr}
30 ; CHECK: add r7, sp, #4
31 ; CHECK: pop {r4, r7, pc}
32 call void asm sideeffect "", "~{r4}" ()
33 ret void
34 }
35
36 ; Leaf function, frame pointer is requested and we need a stack frame, so we
37 ; need to use a frame pointer. A high register is pushed to the stack, so we
38 ; must use two push/pop instructions to ensure that fp and sp are adjacent on
39 ; the stack.
40 define void @leaf_highreg_nofpelim() "no-frame-pointer-elim"="true" {
41 ; CHECK-LABEL: leaf_highreg_nofpelim:
42 ; CHECK: push {r7, lr}
43 ; CHECK: mov r7, sp
44 ; CHECK: str r8, [sp, #-4]!
45 ; CHECK: ldr r8, [sp], #4
46 ; CHECK: pop {r7, pc}
47 call void asm sideeffect "", "~{r8}" ()
48 ret void
49 }
50
51 ; Leaf function, frame pointer requested for non-leaf functions only, so no
52 ; need for a stack frame.
53 define void @leaf_nononleaffpelim() "no-frame-pointer-elim-non-leaf" {
54 ; CHECK-LABEL: leaf_nononleaffpelim:
55 ; CHECK-NOT: push
56 ; CHECK-NOT: sp
57 ; CHECK-NOT: pop
58 ; CHECK: bx lr
59 ret void
60 }
61
62 ; Has a call, but still no need for a frame pointer.
63 define void @call() {
64 ; CHECK-LABEL: call:
65 ; CHECK: push {[[DUMMYREG:r[0-9]+]], lr}
66 ; CHECK-NOT: sp
67 ; CHECK: bl foo
68 ; CHECK: pop {[[DUMMYREG]], pc}
69 call void @foo()
70 ret void
71 }
72
73 ; Has a call, and frame pointer requested.
74 define void @call_nofpelim() "no-frame-pointer-elim"="true" {
75 ; CHECK-LABEL: call_nofpelim:
76 ; CHECK: push {r7, lr}
77 ; CHECK: mov r7, sp
78 ; CHECK: bl foo
79 ; CHECK: pop {r7, pc}
80 call void @foo()
81 ret void
82 }
83
84 ; Has a call, and frame pointer requested for non-leaf function.
85 define void @call_nononleaffpelim() "no-frame-pointer-elim-non-leaf" {
86 ; CHECK-LABEL: call_nononleaffpelim:
87 ; CHECK: push {r7, lr}
88 ; CHECK: mov r7, sp
89 ; CHECK: bl foo
90 ; CHECK: pop {r7, pc}
91 call void @foo()
92 ret void
93 }
94
95 ; Has a high register clobbered, no need for a frame pointer.
96 define void @highreg() {
97 ; CHECK-LABEL: highreg:
98 ; CHECK: push.w {r8, lr}
99 ; CHECK-NOT: sp
100 ; CHECK: bl foo
101 ; CHECK: pop.w {r8, pc}
102 call void asm sideeffect "", "~{r8}" ()
103 call void @foo()
104 ret void
105 }
106
107 ; Has a high register clobbered, frame pointer requested. We need to split the
108 ; push into two, to ensure that r7 and sp are adjacent on the stack.
109 define void @highreg_nofpelim() "no-frame-pointer-elim"="true" {
110 ; CHECK-LABEL: highreg_nofpelim:
111 ; CHECK: push {[[DUMMYREG:r[0-9]+]], r7, lr}
112 ; CHECK: add r7, sp, #4
113 ; CHECK: str r8, [sp, #-4]!
114 ; CHECK: bl foo
115 ; CHECK: ldr r8, [sp], #4
116 ; CHECK: pop {[[DUMMYREG]], r7, pc}
117 call void asm sideeffect "", "~{r8}" ()
118 call void @foo()
119 ret void
120 }
121
122 ; Has a high register clobbered, frame required due to variable-sized alloca.
123 ; We need a frame pointer to correctly restore the stack, but don't need to
124 ; split the push/pop here, because the frame pointer not required by the ABI.
125 define void @highreg_alloca(i32 %a) {
126 ; CHECK-LABEL: highreg_alloca:
127 ; CHECK: push.w {[[SOMEREGS:.*]], r7, r8, lr}
128 ; CHECK: add r7, sp, #{{[0-9]+}}
129 ; CHECK: bl foo
130 ; CHECK: pop.w {[[SOMEREGS]], r7, r8, pc}
131 %alloca = alloca i32, i32 %a, align 4
132 call void @foo()
133 call void asm sideeffect "", "~{r8}" ()
134 ret void
135 }
136
137 ; Has a high register clobbered, frame required due to both variable-sized
138 ; alloca and ABI. We do need to split the push/pop here.
139 define void @highreg_alloca_nofpelim(i32 %a) "no-frame-pointer-elim"="true" {
140 ; CHECK-LABEL: highreg_alloca_nofpelim:
141 ; CHECK: push {[[SOMEREGS:.*]], r7, lr}
142 ; CHECK: add r7, sp, #{{[0-9]+}}
143 ; CHECK: str r8, [sp, #-4]!
144 ; CHECK: bl foo
145 ; CHECK: ldr r8, [sp], #4
146 ; CHECK: pop {[[SOMEREGS]], r7, pc}
147 %alloca = alloca i32, i32 %a, align 4
148 call void @foo()
149 call void asm sideeffect "", "~{r8}" ()
150 ret void
151 }
22
33 @X = external global [0 x i32] ; <[0 x i32]*> [#uses=5]
44
5 define i32 @t1() {
5 define i32 @t1() "no-frame-pointer-elim"="true" {
66 ; ALL-LABEL: t1:
77 ; ALL: push {r7, lr}
88 ; CHECK: ldrd
1515 ret i32 %tmp4
1616 }
1717
18 define i32 @t2() {
18 define i32 @t2() "no-frame-pointer-elim"="true" {
1919 ; ALL-LABEL: t2:
2020 ; ALL: push {r7, lr}
2121 ; CHECK: ldm
2929 ret i32 %tmp6
3030 }
3131
32 define i32 @t3() {
32 define i32 @t3() "no-frame-pointer-elim"="true" {
3333 ; ALL-LABEL: t3:
3434 ; ALL: push {r7, lr}
3535 ; CHECK: ldm
4545
4646 @g = common global i32* null
4747
48 define void @t4(i32 %a0, i32 %a1, i32 %a2) {
48 define void @t4(i32 %a0, i32 %a1, i32 %a2) "no-frame-pointer-elim"="true" {
4949 ; ALL-LABEL: t4:
5050 ; ALL: stm.w sp, {r0, r1, r2}
5151 ; ALL: bl _ext
1212 target triple = "thumbv7-apple-ios"
1313
1414 ; Function Attrs: nounwind
15 define arm_aapcscc void @_Z1hiiiif(i32, i32, i32, i32, float %x) #0 !dbg !4 {
15 define arm_aapcscc void @_Z1hiiiif(i32, i32, i32, i32, float %x) #0 "no-frame-pointer-elim"="true" !dbg !4 {
1616 entry:
1717 tail call void @llvm.dbg.value(metadata i32 %0, i64 0, metadata !12, metadata !DIExpression()), !dbg !18
1818 tail call void @llvm.dbg.value(metadata i32 %1, i64 0, metadata !13, metadata !DIExpression()), !dbg !18