| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 |
| ; RUN: llc -mtriple=x86_64-apple-darwin10.6 < %s | FileCheck %s |
| ; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s --check-prefix=NOCOMPACTUNWIND |
| ; |
| ; 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. |
| |
| ; The current compact unwind scheme does not work when the prologue is not at |
| ; the start (the instructions before the prologue cannot be described). |
| ; Currently we choose to not perform shrink-wrapping for functions without FP |
| ; not marked as nounwind. PR25614 |
| ; |
| ; No shrink-wrapping should occur here, until the CFI information are fixed. |
| |
| define i32 @framelessUnwind(i32 %a, i32 %b) #0 { |
| ; CHECK-LABEL: framelessUnwind: |
| ; CHECK: ## %bb.0: |
| ; CHECK-NEXT: pushq %rax |
| ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| ; CHECK-NEXT: movl %edi, %eax |
| ; CHECK-NEXT: cmpl %esi, %edi |
| ; CHECK-NEXT: jge LBB0_2 |
| ; CHECK-NEXT: ## %bb.1: ## %true |
| ; CHECK-NEXT: movl %eax, {{[0-9]+}}(%rsp) |
| ; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rsi |
| ; CHECK-NEXT: xorl %edi, %edi |
| ; CHECK-NEXT: callq _doSomething |
| ; CHECK-NEXT: LBB0_2: ## %false |
| ; CHECK-NEXT: popq %rcx |
| ; CHECK-NEXT: retq |
| ; |
| ; NOCOMPACTUNWIND-LABEL: framelessUnwind: |
| ; NOCOMPACTUNWIND: # %bb.0: |
| ; NOCOMPACTUNWIND-NEXT: movl %edi, %eax |
| ; NOCOMPACTUNWIND-NEXT: cmpl %esi, %edi |
| ; NOCOMPACTUNWIND-NEXT: jge .LBB0_2 |
| ; NOCOMPACTUNWIND-NEXT: # %bb.1: # %true |
| ; NOCOMPACTUNWIND-NEXT: pushq %rax |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 |
| ; NOCOMPACTUNWIND-NEXT: movl %eax, {{[0-9]+}}(%rsp) |
| ; NOCOMPACTUNWIND-NEXT: leaq {{[0-9]+}}(%rsp), %rsi |
| ; NOCOMPACTUNWIND-NEXT: xorl %edi, %edi |
| ; NOCOMPACTUNWIND-NEXT: callq doSomething@PLT |
| ; NOCOMPACTUNWIND-NEXT: addq $8, %rsp |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 |
| ; NOCOMPACTUNWIND-NEXT: .LBB0_2: # %false |
| ; NOCOMPACTUNWIND-NEXT: retq |
| %tmp = alloca i32, align 4 |
| %tmp2 = icmp slt i32 %a, %b |
| br i1 %tmp2, label %true, label %false |
| |
| true: |
| store i32 %a, ptr %tmp, align 4 |
| %tmp4 = call i32 @doSomething(i32 0, ptr %tmp) |
| br label %false |
| |
| false: |
| %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] |
| ret i32 %tmp.0 |
| } |
| |
| declare i32 @doSomething(i32, ptr) |
| |
| attributes #0 = { "frame-pointer"="none" } |
| |
| ; Shrink-wrapping should occur here. We have a frame pointer. |
| define i32 @frameUnwind(i32 %a, i32 %b) #1 { |
| ; CHECK-LABEL: frameUnwind: |
| ; CHECK: ## %bb.0: |
| ; CHECK-NEXT: movl %edi, %eax |
| ; CHECK-NEXT: cmpl %esi, %edi |
| ; CHECK-NEXT: jge LBB1_2 |
| ; CHECK-NEXT: ## %bb.1: ## %true |
| ; CHECK-NEXT: pushq %rbp |
| ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| ; CHECK-NEXT: .cfi_offset %rbp, -16 |
| ; CHECK-NEXT: movq %rsp, %rbp |
| ; CHECK-NEXT: .cfi_def_cfa_register %rbp |
| ; CHECK-NEXT: subq $16, %rsp |
| ; CHECK-NEXT: movl %eax, -4(%rbp) |
| ; CHECK-NEXT: leaq -4(%rbp), %rsi |
| ; CHECK-NEXT: xorl %edi, %edi |
| ; CHECK-NEXT: callq _doSomething |
| ; CHECK-NEXT: addq $16, %rsp |
| ; CHECK-NEXT: popq %rbp |
| ; CHECK-NEXT: LBB1_2: ## %false |
| ; CHECK-NEXT: retq |
| ; |
| ; NOCOMPACTUNWIND-LABEL: frameUnwind: |
| ; NOCOMPACTUNWIND: # %bb.0: |
| ; NOCOMPACTUNWIND-NEXT: movl %edi, %eax |
| ; NOCOMPACTUNWIND-NEXT: cmpl %esi, %edi |
| ; NOCOMPACTUNWIND-NEXT: jge .LBB1_2 |
| ; NOCOMPACTUNWIND-NEXT: # %bb.1: # %true |
| ; NOCOMPACTUNWIND-NEXT: pushq %rbp |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 |
| ; NOCOMPACTUNWIND-NEXT: .cfi_offset %rbp, -16 |
| ; NOCOMPACTUNWIND-NEXT: movq %rsp, %rbp |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_register %rbp |
| ; NOCOMPACTUNWIND-NEXT: subq $16, %rsp |
| ; NOCOMPACTUNWIND-NEXT: movl %eax, -4(%rbp) |
| ; NOCOMPACTUNWIND-NEXT: leaq -4(%rbp), %rsi |
| ; NOCOMPACTUNWIND-NEXT: xorl %edi, %edi |
| ; NOCOMPACTUNWIND-NEXT: callq doSomething@PLT |
| ; NOCOMPACTUNWIND-NEXT: addq $16, %rsp |
| ; NOCOMPACTUNWIND-NEXT: popq %rbp |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa %rsp, 8 |
| ; NOCOMPACTUNWIND-NEXT: .cfi_restore %rbp |
| ; NOCOMPACTUNWIND-NEXT: .LBB1_2: # %false |
| ; NOCOMPACTUNWIND-NEXT: retq |
| %tmp = alloca i32, align 4 |
| %tmp2 = icmp slt i32 %a, %b |
| br i1 %tmp2, label %true, label %false |
| |
| true: |
| store i32 %a, ptr %tmp, align 4 |
| %tmp4 = call i32 @doSomething(i32 0, ptr %tmp) |
| br label %false |
| |
| false: |
| %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] |
| ret i32 %tmp.0 |
| } |
| |
| attributes #1 = { "frame-pointer"="all" } |
| |
| ; Shrink-wrapping should occur here. We do not have to unwind. |
| define i32 @framelessnoUnwind(i32 %a, i32 %b) #2 { |
| ; CHECK-LABEL: framelessnoUnwind: |
| ; CHECK: ## %bb.0: |
| ; CHECK-NEXT: movl %edi, %eax |
| ; CHECK-NEXT: cmpl %esi, %edi |
| ; CHECK-NEXT: jge LBB2_2 |
| ; CHECK-NEXT: ## %bb.1: ## %true |
| ; CHECK-NEXT: pushq %rax |
| ; CHECK-NEXT: movl %eax, {{[0-9]+}}(%rsp) |
| ; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rsi |
| ; CHECK-NEXT: xorl %edi, %edi |
| ; CHECK-NEXT: callq _doSomething |
| ; CHECK-NEXT: addq $8, %rsp |
| ; CHECK-NEXT: LBB2_2: ## %false |
| ; CHECK-NEXT: retq |
| ; |
| ; NOCOMPACTUNWIND-LABEL: framelessnoUnwind: |
| ; NOCOMPACTUNWIND: # %bb.0: |
| ; NOCOMPACTUNWIND-NEXT: movl %edi, %eax |
| ; NOCOMPACTUNWIND-NEXT: cmpl %esi, %edi |
| ; NOCOMPACTUNWIND-NEXT: jge .LBB2_2 |
| ; NOCOMPACTUNWIND-NEXT: # %bb.1: # %true |
| ; NOCOMPACTUNWIND-NEXT: pushq %rax |
| ; NOCOMPACTUNWIND-NEXT: movl %eax, {{[0-9]+}}(%rsp) |
| ; NOCOMPACTUNWIND-NEXT: leaq {{[0-9]+}}(%rsp), %rsi |
| ; NOCOMPACTUNWIND-NEXT: xorl %edi, %edi |
| ; NOCOMPACTUNWIND-NEXT: callq doSomething@PLT |
| ; NOCOMPACTUNWIND-NEXT: addq $8, %rsp |
| ; NOCOMPACTUNWIND-NEXT: .LBB2_2: # %false |
| ; NOCOMPACTUNWIND-NEXT: retq |
| %tmp = alloca i32, align 4 |
| %tmp2 = icmp slt i32 %a, %b |
| br i1 %tmp2, label %true, label %false |
| |
| true: |
| store i32 %a, ptr %tmp, align 4 |
| %tmp4 = call i32 @doSomething(i32 0, ptr %tmp) |
| br label %false |
| |
| false: |
| %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] |
| ret i32 %tmp.0 |
| } |
| |
| attributes #2 = { "frame-pointer"="none" 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. |
| define zeroext i1 @segmentedStack(ptr readonly %vk1, ptr readonly %vk2, i64 %key_size) #5 { |
| ; CHECK-LABEL: segmentedStack: |
| ; CHECK: ## %bb.0: |
| ; CHECK-NEXT: cmpq %gs:816, %rsp |
| ; CHECK-NEXT: jbe LBB3_6 |
| ; CHECK-NEXT: LBB3_1: ## %entry |
| ; CHECK-NEXT: pushq %rax |
| ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| ; CHECK-NEXT: testq %rdi, %rdi |
| ; CHECK-NEXT: sete %al |
| ; CHECK-NEXT: testq %rsi, %rsi |
| ; CHECK-NEXT: sete %cl |
| ; CHECK-NEXT: orb %al, %cl |
| ; CHECK-NEXT: movq %rdi, %rax |
| ; CHECK-NEXT: orq %rsi, %rax |
| ; CHECK-NEXT: sete %al |
| ; CHECK-NEXT: testb %cl, %cl |
| ; CHECK-NEXT: jne LBB3_4 |
| ; CHECK-NEXT: ## %bb.2: ## %if.end4.i |
| ; CHECK-NEXT: movq 8(%rdi), %rdx |
| ; CHECK-NEXT: cmpq 8(%rsi), %rdx |
| ; CHECK-NEXT: jne LBB3_5 |
| ; CHECK-NEXT: ## %bb.3: ## %land.rhs.i.i |
| ; CHECK-NEXT: movq (%rsi), %rsi |
| ; CHECK-NEXT: movq (%rdi), %rdi |
| ; CHECK-NEXT: callq _memcmp |
| ; CHECK-NEXT: testl %eax, %eax |
| ; CHECK-NEXT: sete %al |
| ; CHECK-NEXT: LBB3_4: ## %__go_ptr_strings_equal.exit |
| ; CHECK-NEXT: ## kill: def $al killed $al killed $eax |
| ; CHECK-NEXT: popq %rcx |
| ; CHECK-NEXT: retq |
| ; CHECK-NEXT: LBB3_5: |
| ; CHECK-NEXT: xorl %eax, %eax |
| ; CHECK-NEXT: ## kill: def $al killed $al killed $eax |
| ; CHECK-NEXT: popq %rcx |
| ; CHECK-NEXT: retq |
| ; CHECK-NEXT: LBB3_6: |
| ; CHECK-NEXT: movl $8, %r10d |
| ; CHECK-NEXT: movl $0, %r11d |
| ; CHECK-NEXT: callq ___morestack |
| ; CHECK-NEXT: retq |
| ; CHECK-NEXT: jmp LBB3_1 |
| ; |
| ; NOCOMPACTUNWIND-LABEL: segmentedStack: |
| ; NOCOMPACTUNWIND: # %bb.0: |
| ; NOCOMPACTUNWIND-NEXT: cmpq %fs:112, %rsp |
| ; NOCOMPACTUNWIND-NEXT: jbe .LBB3_6 |
| ; NOCOMPACTUNWIND-NEXT: .LBB3_1: # %entry |
| ; NOCOMPACTUNWIND-NEXT: pushq %rax |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 |
| ; NOCOMPACTUNWIND-NEXT: testq %rdi, %rdi |
| ; NOCOMPACTUNWIND-NEXT: sete %al |
| ; NOCOMPACTUNWIND-NEXT: testq %rsi, %rsi |
| ; NOCOMPACTUNWIND-NEXT: sete %cl |
| ; NOCOMPACTUNWIND-NEXT: orb %al, %cl |
| ; NOCOMPACTUNWIND-NEXT: movq %rdi, %rax |
| ; NOCOMPACTUNWIND-NEXT: orq %rsi, %rax |
| ; NOCOMPACTUNWIND-NEXT: sete %al |
| ; NOCOMPACTUNWIND-NEXT: testb %cl, %cl |
| ; NOCOMPACTUNWIND-NEXT: jne .LBB3_4 |
| ; NOCOMPACTUNWIND-NEXT: # %bb.2: # %if.end4.i |
| ; NOCOMPACTUNWIND-NEXT: movq 8(%rdi), %rdx |
| ; NOCOMPACTUNWIND-NEXT: cmpq 8(%rsi), %rdx |
| ; NOCOMPACTUNWIND-NEXT: jne .LBB3_5 |
| ; NOCOMPACTUNWIND-NEXT: # %bb.3: # %land.rhs.i.i |
| ; NOCOMPACTUNWIND-NEXT: movq (%rsi), %rsi |
| ; NOCOMPACTUNWIND-NEXT: movq (%rdi), %rdi |
| ; NOCOMPACTUNWIND-NEXT: callq memcmp@PLT |
| ; NOCOMPACTUNWIND-NEXT: testl %eax, %eax |
| ; NOCOMPACTUNWIND-NEXT: sete %al |
| ; NOCOMPACTUNWIND-NEXT: .LBB3_4: # %__go_ptr_strings_equal.exit |
| ; NOCOMPACTUNWIND-NEXT: # kill: def $al killed $al killed $eax |
| ; NOCOMPACTUNWIND-NEXT: popq %rcx |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 |
| ; NOCOMPACTUNWIND-NEXT: retq |
| ; NOCOMPACTUNWIND-NEXT: .LBB3_5: |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 |
| ; NOCOMPACTUNWIND-NEXT: xorl %eax, %eax |
| ; NOCOMPACTUNWIND-NEXT: # kill: def $al killed $al killed $eax |
| ; NOCOMPACTUNWIND-NEXT: popq %rcx |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 |
| ; NOCOMPACTUNWIND-NEXT: retq |
| ; NOCOMPACTUNWIND-NEXT: .LBB3_6: |
| ; NOCOMPACTUNWIND-NEXT: movl $8, %r10d |
| ; NOCOMPACTUNWIND-NEXT: movl $0, %r11d |
| ; NOCOMPACTUNWIND-NEXT: callq __morestack |
| ; NOCOMPACTUNWIND-NEXT: retq |
| ; NOCOMPACTUNWIND-NEXT: jmp .LBB3_1 |
| entry: |
| %cmp.i = icmp eq ptr %vk1, null |
| %cmp1.i = icmp eq ptr %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, ptr %vk1, i64 8 |
| %tmp2 = load i64, ptr %tmp, align 8 |
| %tmp3 = getelementptr inbounds i8, ptr %vk2, i64 8 |
| %tmp5 = load i64, ptr %tmp3, 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 |
| %tmp7 = load ptr, ptr %vk2, align 8 |
| %tmp9 = load ptr, ptr %vk1, align 8 |
| %call.i.i = tail call i32 @memcmp(ptr %tmp9, ptr %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(ptr nocapture, ptr 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 |
| define void @with_nounwind(i1 %cond) nounwind personality ptr @my_personality { |
| ; CHECK-LABEL: with_nounwind: |
| ; CHECK: ## %bb.0: ## %entry |
| ; CHECK-NEXT: pushq %rax |
| ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| ; CHECK-NEXT: testb $1, %dil |
| ; CHECK-NEXT: jne LBB4_1 |
| ; CHECK-NEXT: ## %bb.4: ## %return |
| ; CHECK-NEXT: popq %rax |
| ; CHECK-NEXT: retq |
| ; CHECK-NEXT: LBB4_1: ## %throw |
| ; CHECK-NEXT: Ltmp0: |
| ; CHECK-NEXT: callq _throw_exception |
| ; CHECK-NEXT: Ltmp1: |
| ; CHECK-NEXT: ## %bb.2: ## %unreachable |
| ; CHECK-NEXT: ud2 |
| ; CHECK-NEXT: LBB4_3: ## %landing |
| ; CHECK-NEXT: Ltmp2: |
| ; CHECK-NEXT: popq %rax |
| ; CHECK-NEXT: retq |
| ; CHECK-NEXT: Lfunc_end0: |
| ; |
| ; NOCOMPACTUNWIND-LABEL: with_nounwind: |
| ; NOCOMPACTUNWIND: # %bb.0: # %entry |
| ; NOCOMPACTUNWIND-NEXT: pushq %rax |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 |
| ; NOCOMPACTUNWIND-NEXT: testb $1, %dil |
| ; NOCOMPACTUNWIND-NEXT: jne .LBB4_1 |
| ; NOCOMPACTUNWIND-NEXT: # %bb.4: # %return |
| ; NOCOMPACTUNWIND-NEXT: popq %rax |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 |
| ; NOCOMPACTUNWIND-NEXT: retq |
| ; NOCOMPACTUNWIND-NEXT: .LBB4_1: # %throw |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 |
| ; NOCOMPACTUNWIND-NEXT: .Ltmp0: |
| ; NOCOMPACTUNWIND-NEXT: callq throw_exception@PLT |
| ; NOCOMPACTUNWIND-NEXT: .Ltmp1: |
| ; NOCOMPACTUNWIND-NEXT: # %bb.2: # %unreachable |
| ; NOCOMPACTUNWIND-NEXT: .LBB4_3: # %landing |
| ; NOCOMPACTUNWIND-NEXT: .Ltmp2: |
| ; NOCOMPACTUNWIND-NEXT: popq %rax |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 |
| ; NOCOMPACTUNWIND-NEXT: retq |
| entry: |
| br i1 %cond, label %throw, label %return |
| |
| throw: |
| invoke void @throw_exception() |
| to label %unreachable unwind label %landing |
| |
| unreachable: |
| unreachable |
| |
| landing: |
| %pad = landingpad { ptr, i32 } |
| catch ptr 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. |
| define void @with_nounwind_same_succ(i1 %cond) nounwind personality ptr @my_personality2 { |
| ; CHECK-LABEL: with_nounwind_same_succ: |
| ; CHECK: ## %bb.0: ## %entry |
| ; CHECK-NEXT: testb $1, %dil |
| ; CHECK-NEXT: je LBB5_4 |
| ; CHECK-NEXT: ## %bb.1: ## %throw |
| ; CHECK-NEXT: pushq %rax |
| ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| ; CHECK-NEXT: Ltmp3: |
| ; CHECK-NEXT: callq _throw_exception |
| ; CHECK-NEXT: Ltmp4: |
| ; CHECK-NEXT: LBB5_3: ## %fallthrough |
| ; CHECK-NEXT: ## InlineAsm Start |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: ## InlineAsm End |
| ; CHECK-NEXT: popq %rax |
| ; CHECK-NEXT: LBB5_4: ## %return |
| ; CHECK-NEXT: retq |
| ; CHECK-NEXT: LBB5_2: ## %landing |
| ; CHECK-NEXT: Ltmp5: |
| ; CHECK-NEXT: jmp LBB5_3 |
| ; CHECK-NEXT: Lfunc_end1: |
| ; |
| ; NOCOMPACTUNWIND-LABEL: with_nounwind_same_succ: |
| ; NOCOMPACTUNWIND: # %bb.0: # %entry |
| ; NOCOMPACTUNWIND-NEXT: testb $1, %dil |
| ; NOCOMPACTUNWIND-NEXT: je .LBB5_4 |
| ; NOCOMPACTUNWIND-NEXT: # %bb.1: # %throw |
| ; NOCOMPACTUNWIND-NEXT: pushq %rax |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 |
| ; NOCOMPACTUNWIND-NEXT: .Ltmp3: |
| ; NOCOMPACTUNWIND-NEXT: callq throw_exception@PLT |
| ; NOCOMPACTUNWIND-NEXT: .Ltmp4: |
| ; NOCOMPACTUNWIND-NEXT: .LBB5_3: # %fallthrough |
| ; NOCOMPACTUNWIND-NEXT: #APP |
| ; NOCOMPACTUNWIND-NEXT: nop |
| ; NOCOMPACTUNWIND-NEXT: #NO_APP |
| ; NOCOMPACTUNWIND-NEXT: popq %rax |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 |
| ; NOCOMPACTUNWIND-NEXT: .LBB5_4: # %return |
| ; NOCOMPACTUNWIND-NEXT: retq |
| ; NOCOMPACTUNWIND-NEXT: .LBB5_2: # %landing |
| ; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 |
| ; NOCOMPACTUNWIND-NEXT: .Ltmp5: |
| ; NOCOMPACTUNWIND-NEXT: jmp .LBB5_3 |
| entry: |
| br i1 %cond, label %throw, label %return |
| |
| throw: |
| invoke void @throw_exception() |
| to label %fallthrough unwind label %landing |
| landing: |
| %pad = landingpad { ptr, i32 } |
| catch ptr 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(...) |