; RUN: llc %s -o - | FileCheck %s ; ; 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" ; 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 ; ; 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, %edi ; 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, %edi ; 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, %edi ; 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 } ; Check that we generate correct code for segmented stack. ; We used to emit the code at the entry point of the function ; instead of just before the prologue. ; For now, shrink-wrapping is disabled on segmented stack functions: PR26107. ; ; CHECK-LABEL: segmentedStack: ; CHECK: cmpq ; CHECK-NEXT: ja [[ENTRY_LABEL:LBB[0-9_]+]] ; ; CHECK: callq ___morestack ; CHECK-NEXT: retq ; ; CHECK: [[ENTRY_LABEL]]: ; Prologue ; CHECK: push ; ; In PR26107, we use to drop these two basic blocks, because ; the segmentedStack entry block was jumping directly to ; the place where the prologue is actually needed, which is ; the call to memcmp. ; Then, those two basic blocks did not have any predecessors ; anymore and were removed. ; ; Check if vk1 is null ; CHECK: testq %rdi, %rdi ; CHECK-NEXT: je [[STRINGS_EQUAL:LBB[0-9_]+]] ; ; Check if vk2 is null ; CHECK: testq %rsi, %rsi ; CHECK-NEXT: je [[STRINGS_EQUAL]] ; ; CHECK: [[STRINGS_EQUAL]] ; CHECK: popq define zeroext i1 @segmentedStack(i8* readonly %vk1, i8* readonly %vk2, i64 %key_size) #5 { entry: %cmp.i = icmp eq i8* %vk1, null %cmp1.i = icmp eq i8* %vk2, null %brmerge.i = or i1 %cmp.i, %cmp1.i %cmp1.mux.i = and i1 %cmp.i, %cmp1.i br i1 %brmerge.i, label %__go_ptr_strings_equal.exit, label %if.end4.i if.end4.i: ; preds = %entry %tmp = getelementptr inbounds i8, i8* %vk1, i64 8 %tmp1 = bitcast i8* %tmp to i64* %tmp2 = load i64, i64* %tmp1, align 8 %tmp3 = getelementptr inbounds i8, i8* %vk2, i64 8 %tmp4 = bitcast i8* %tmp3 to i64* %tmp5 = load i64, i64* %tmp4, align 8 %cmp.i.i = icmp eq i64 %tmp2, %tmp5 br i1 %cmp.i.i, label %land.rhs.i.i, label %__go_ptr_strings_equal.exit land.rhs.i.i: ; preds = %if.end4.i %tmp6 = bitcast i8* %vk2 to i8** %tmp7 = load i8*, i8** %tmp6, align 8 %tmp8 = bitcast i8* %vk1 to i8** %tmp9 = load i8*, i8** %tmp8, align 8 %call.i.i = tail call i32 @memcmp(i8* %tmp9, i8* %tmp7, i64 %tmp2) #5 %cmp4.i.i = icmp eq i32 %call.i.i, 0 br label %__go_ptr_strings_equal.exit __go_ptr_strings_equal.exit: ; preds = %land.rhs.i.i, %if.end4.i, %entry %retval.0.i = phi i1 [ %cmp1.mux.i, %entry ], [ false, %if.end4.i ], [ %cmp4.i.i, %land.rhs.i.i ] ret i1 %retval.0.i } ; Function Attrs: nounwind readonly declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) #5 attributes #5 = { nounwind readonly ssp uwtable "split-stack" } ; Check that correctly take into account the jumps to landing pad. ; We used to consider function that may throw like regular ; function calls. ; Therefore, in this example, we were happily inserting the epilogue ; right after the call to throw_exception. Because of that we would not ; execute the epilogue when an execption occur and bad things will ; happen. ; PR36513 ; ; CHECK-LABEL: with_nounwind: ; Prologue ; CHECK: push ; ; Jump to throw_exception: ; CHECK-NEXT: .cfi_def_cfa_offset ; CHECK-NEXT: testb $1, %dil ; CHECK-NEXT: jne [[THROW_LABEL:LBB[0-9_]+]] ; Else return exit ; CHECK: popq ; CHECK-NEXT: retq ; ; CHECK-NEXT: [[THROW_LABEL]]: ; CHECK: callq _throw_exception ; Unreachable block... ; ; Epilogue must be after the landing pad. ; CHECK-NOT: popq ; ; Look for the landing pad label. ; CHECK: LBB{{[0-9_]+}}: ; Epilogue on the landing pad ; CHECK: popq ; CHECK-NEXT: retq define void @with_nounwind(i1 %cond) nounwind personality i32 (...)* @my_personality { entry: br i1 %cond, label %throw, label %return throw: invoke void @throw_exception() to label %unreachable unwind label %landing unreachable: unreachable landing: %pad = landingpad { i8*, i32 } catch i8* null ret void return: ret void } ; Check landing pad again. ; This time checks that we can shrink-wrap when the epilogue does not ; span accross several blocks. ; ; CHECK-LABEL: with_nounwind_same_succ: ; ; Jump to throw_exception: ; CHECK: testb $1, %dil ; CHECK-NEXT: je [[RET_LABEL:LBB[0-9_]+]] ; ; Prologue ; CHECK: push ; CHECK: callq _throw_exception ; ; Fallthrough label ; CHECK: [[FALLTHROUGH_LABEL:LBB[0-9_]+]] ; CHECK: nop ; CHECK: popq ; ; CHECK: [[RET_LABEL]] ; CHECK: retq ; ; Look for the landing pad label. ; CHECK: LBB{{[0-9_]+}}: ; Landing pad jumps to fallthrough ; CHECK: jmp [[FALLTHROUGH_LABEL]] define void @with_nounwind_same_succ(i1 %cond) nounwind personality i32 (...)* @my_personality2 { entry: br i1 %cond, label %throw, label %return throw: invoke void @throw_exception() to label %fallthrough unwind label %landing landing: %pad = landingpad { i8*, i32 } catch i8* null br label %fallthrough fallthrough: tail call void asm "nop", ""() br label %return return: ret void } declare void @throw_exception() declare i32 @my_personality(...) declare i32 @my_personality2(...)