| ; RUN: llc %s -o - | FileCheck %s --check-prefix=CHECK |
| ; |
| ; This test checks that we do not use shrink-wrapping when |
| ; the function does not have any frame pointer and may unwind. |
| ; This is a workaround for a limitation in the emission of |
| ; the CFI directives, that are not correct in such case. |
| ; PR25614 |
| ; |
| ; Note: This test cannot be merged with the shrink-wrapping tests |
| ; because the booleans set on the command line take precedence on |
| ; the target logic that disable shrink-wrapping. |
| target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" |
| target triple = "x86_64-apple-macosx" |
| |
| |
| ; No shrink-wrapping should occur here, until the CFI information are fixed. |
| ; CHECK-LABEL: framelessUnwind: |
| ; |
| ; Prologue code. |
| ; (What we push does not matter. It should be some random sratch register.) |
| ; CHECK: pushq |
| ; |
| ; Compare the arguments and jump to exit. |
| ; After the prologue is set. |
| ; CHECK: movl %edi, [[ARG0CPY:%e[a-z]+]] |
| ; CHECK-NEXT: cmpl %esi, [[ARG0CPY]] |
| ; CHECK-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]] |
| ; |
| ; Store %a in the alloca. |
| ; CHECK: movl [[ARG0CPY]], 4(%rsp) |
| ; Set the alloca address in the second argument. |
| ; CHECK-NEXT: leaq 4(%rsp), %rsi |
| ; Set the first argument to zero. |
| ; CHECK-NEXT: xorl %edi, %edi |
| ; CHECK-NEXT: callq _doSomething |
| ; |
| ; CHECK: [[EXIT_LABEL]]: |
| ; |
| ; Without shrink-wrapping, epilogue is in the exit block. |
| ; Epilogue code. (What we pop does not matter.) |
| ; CHECK-NEXT: popq |
| ; |
| ; CHECK-NEXT: retq |
| define i32 @framelessUnwind(i32 %a, i32 %b) #0 { |
| %tmp = alloca i32, align 4 |
| %tmp2 = icmp slt i32 %a, %b |
| br i1 %tmp2, label %true, label %false |
| |
| true: |
| store i32 %a, i32* %tmp, align 4 |
| %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) |
| br label %false |
| |
| false: |
| %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] |
| ret i32 %tmp.0 |
| } |
| |
| declare i32 @doSomething(i32, i32*) |
| |
| attributes #0 = { "no-frame-pointer-elim"="false" } |
| |
| ; Shrink-wrapping should occur here. We have a frame pointer. |
| ; CHECK-LABEL: frameUnwind: |
| ; |
| ; Compare the arguments and jump to exit. |
| ; No prologue needed. |
| ; |
| ; Compare the arguments and jump to exit. |
| ; After the prologue is set. |
| ; CHECK: movl %edi, [[ARG0CPY:%e[a-z]+]] |
| ; CHECK-NEXT: cmpl %esi, [[ARG0CPY]] |
| ; CHECK-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]] |
| ; |
| ; Prologue code. |
| ; CHECK: pushq %rbp |
| ; CHECK: movq %rsp, %rbp |
| ; |
| ; Store %a in the alloca. |
| ; CHECK: movl [[ARG0CPY]], -4(%rbp) |
| ; Set the alloca address in the second argument. |
| ; CHECK-NEXT: leaq -4(%rbp), %rsi |
| ; Set the first argument to zero. |
| ; CHECK-NEXT: xorl %edi, %edi |
| ; CHECK-NEXT: callq _doSomething |
| ; |
| ; Epilogue code. (What we pop does not matter.) |
| ; CHECK: popq %rbp |
| ; |
| ; CHECK: [[EXIT_LABEL]]: |
| ; CHECK-NEXT: retq |
| define i32 @frameUnwind(i32 %a, i32 %b) #1 { |
| %tmp = alloca i32, align 4 |
| %tmp2 = icmp slt i32 %a, %b |
| br i1 %tmp2, label %true, label %false |
| |
| true: |
| store i32 %a, i32* %tmp, align 4 |
| %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) |
| br label %false |
| |
| false: |
| %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] |
| ret i32 %tmp.0 |
| } |
| |
| attributes #1 = { "no-frame-pointer-elim"="true" } |
| |
| ; Shrink-wrapping should occur here. We do not have to unwind. |
| ; CHECK-LABEL: framelessnoUnwind: |
| ; |
| ; Compare the arguments and jump to exit. |
| ; No prologue needed. |
| ; |
| ; Compare the arguments and jump to exit. |
| ; After the prologue is set. |
| ; CHECK: movl %edi, [[ARG0CPY:%e[a-z]+]] |
| ; CHECK-NEXT: cmpl %esi, [[ARG0CPY]] |
| ; CHECK-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]] |
| ; |
| ; Prologue code. |
| ; (What we push does not matter. It should be some random sratch register.) |
| ; CHECK: pushq |
| ; |
| ; Store %a in the alloca. |
| ; CHECK: movl [[ARG0CPY]], 4(%rsp) |
| ; Set the alloca address in the second argument. |
| ; CHECK-NEXT: leaq 4(%rsp), %rsi |
| ; Set the first argument to zero. |
| ; CHECK-NEXT: xorl %edi, %edi |
| ; CHECK-NEXT: callq _doSomething |
| ; |
| ; Epilogue code. |
| ; CHECK-NEXT: addq |
| ; |
| ; CHECK: [[EXIT_LABEL]]: |
| ; CHECK-NEXT: retq |
| define i32 @framelessnoUnwind(i32 %a, i32 %b) #2 { |
| %tmp = alloca i32, align 4 |
| %tmp2 = icmp slt i32 %a, %b |
| br i1 %tmp2, label %true, label %false |
| |
| true: |
| store i32 %a, i32* %tmp, align 4 |
| %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) |
| br label %false |
| |
| false: |
| %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] |
| ret i32 %tmp.0 |
| } |
| |
| attributes #2 = { "no-frame-pointer-elim"="false" nounwind } |