| # RUN: llc -start-before=x86-avoid-trailing-call %s -o - | FileCheck %s |
| |
| # If there is a trailing unreachable block, make sure it is non-empty. |
| |
| # Manually modified the IR of the following C++ to share one unreachable block, |
| # as clang does for the real C++ throw: |
| # void __declspec(noreturn) mythrow(); |
| # int multi_throw(bool c1, bool c2, bool c3) { |
| # try { |
| # if (c1) |
| # mythrow(); |
| # if (c2) |
| # mythrow(); |
| # if (c3) |
| # mythrow(); |
| # } catch (...) { |
| # return 1; |
| # } |
| # return 0; |
| # } |
| |
| # CHECK-LABEL: "?multi_throw@@YAH_N00@Z": # @"?multi_throw@@YAH_N00@Z" |
| # CHECK: retq |
| # CHECK: .LBB{{.*}} # %if.then |
| # CHECK: callq mythrow |
| # CHECK: .LBB{{.*}} # %if.then4 |
| # CHECK: callq mythrow |
| # CHECK: .LBB{{.*}} # %if.then8 |
| # CHECK: callq mythrow |
| # CHECK: .LBB{{.*}} # %unreachable |
| # CHECK-NEXT: int3 |
| # CHECK: .seh_endproc |
| # CHECK: # %catch |
| |
| --- | |
| ; ModuleID = '../llvm/test/CodeGen/X86/win64-eh-empty-block-2.ll' |
| source_filename = "t.cpp" |
| target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" |
| target triple = "x86_64-unknown-windows-msvc19.11.0" |
| |
| ; Function Attrs: uwtable |
| define dso_local i32 @"?multi_throw@@YAH_N00@Z"(i1 zeroext %c1, i1 zeroext %c2, i1 zeroext %c3) local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { |
| entry: |
| br i1 %c1, label %if.then, label %if.end |
| |
| if.then: ; preds = %entry |
| invoke void @mythrow() |
| to label %unreachable unwind label %catch.dispatch |
| |
| unreachable: ; preds = %if.then8, %if.then4, %if.then |
| unreachable |
| |
| if.end: ; preds = %entry |
| br i1 %c2, label %if.then4, label %if.end6 |
| |
| if.then4: ; preds = %if.end |
| invoke void @mythrow() |
| to label %unreachable unwind label %catch.dispatch |
| |
| if.end6: ; preds = %if.end |
| br i1 %c3, label %if.then8, label %return |
| |
| if.then8: ; preds = %if.end6 |
| invoke void @mythrow() |
| to label %unreachable unwind label %catch.dispatch |
| |
| catch.dispatch: ; preds = %if.then8, %if.then4, %if.then |
| %0 = catchswitch within none [label %catch] unwind to caller |
| |
| catch: ; preds = %catch.dispatch |
| %1 = catchpad within %0 [i8* null, i32 64, i8* null] |
| catchret from %1 to label %return |
| |
| return: ; preds = %catch, %if.end6 |
| %retval.0 = phi i32 [ 1, %catch ], [ 0, %if.end6 ] |
| ret i32 %retval.0 |
| } |
| |
| declare dso_local void @mythrow() |
| |
| declare dso_local i32 @__CxxFrameHandler3(...) |
| |
| attributes #0 = { uwtable } |
| |
| !llvm.module.flags = !{!0, !1} |
| |
| !0 = !{i32 1, !"wchar_size", i32 2} |
| !1 = !{i32 7, !"PIC Level", i32 2} |
| |
| ... |
| --- |
| name: '?multi_throw@@YAH_N00@Z' |
| alignment: 16 |
| exposesReturnsTwice: false |
| legalized: false |
| regBankSelected: false |
| selected: false |
| failedISel: false |
| tracksRegLiveness: true |
| hasWinCFI: true |
| registers: [] |
| liveins: |
| - { reg: '$cl', virtual-reg: '' } |
| - { reg: '$dl', virtual-reg: '' } |
| - { reg: '$r8b', virtual-reg: '' } |
| frameInfo: |
| isFrameAddressTaken: false |
| isReturnAddressTaken: false |
| hasStackMap: false |
| hasPatchPoint: false |
| stackSize: 56 |
| offsetAdjustment: -56 |
| maxAlignment: 8 |
| adjustsStack: true |
| hasCalls: true |
| stackProtector: '' |
| maxCallFrameSize: 32 |
| cvBytesOfCalleeSavedRegisters: 0 |
| hasOpaqueSPAdjustment: true |
| hasVAStart: false |
| hasMustTailInVarArgFunc: false |
| localFrameSize: 0 |
| savePoint: '' |
| restorePoint: '' |
| fixedStack: |
| - { id: 0, type: default, offset: -24, size: 8, alignment: 8, stack-id: default, |
| isImmutable: false, isAliased: false, callee-saved-register: '', |
| callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '', |
| debug-info-location: '' } |
| - { id: 1, type: spill-slot, offset: -16, size: 8, alignment: 16, stack-id: default, |
| callee-saved-register: '', callee-saved-restored: true, debug-info-variable: '', |
| debug-info-expression: '', debug-info-location: '' } |
| stack: |
| - { id: 0, name: '', type: spill-slot, offset: -28, size: 4, alignment: 4, |
| stack-id: default, callee-saved-register: '', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| callSites: [] |
| constants: [] |
| machineFunctionInfo: {} |
| body: | |
| bb.0.entry: |
| successors: %bb.1(0x00000001), %bb.3(0x7fffffff) |
| liveins: $cl, $dl, $r8b |
| |
| frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp |
| frame-setup SEH_PushReg 50 |
| $rsp = frame-setup SUB64ri8 $rsp, 48, implicit-def dead $eflags |
| frame-setup SEH_StackAlloc 48 |
| $rbp = LEA64r $rsp, 1, $noreg, 48, $noreg |
| frame-setup SEH_SetFrame 50, 48 |
| frame-setup SEH_EndPrologue |
| MOV64mi32 $rbp, 1, $noreg, -8, $noreg, -2 :: (store (s64) into %fixed-stack.0) |
| TEST8rr killed renamable $cl, renamable $cl, implicit-def $eflags |
| JCC_1 %bb.1, 5, implicit $eflags |
| |
| bb.3.if.end: |
| successors: %bb.4(0x00000001), %bb.5(0x7fffffff) |
| liveins: $dl, $r8b |
| |
| TEST8rr killed renamable $dl, renamable $dl, implicit-def $eflags |
| JCC_1 %bb.4, 5, implicit $eflags |
| |
| bb.5.if.end6: |
| successors: %bb.6(0x00000001), %bb.8(0x7fffffff) |
| liveins: $r8b |
| |
| MOV32mi $rbp, 1, $noreg, -12, $noreg, 0 :: (store (s32) into %stack.0) |
| TEST8rr killed renamable $r8b, renamable $r8b, implicit-def $eflags |
| JCC_1 %bb.6, 5, implicit $eflags |
| |
| bb.8.return (address-taken): |
| $eax = MOV32rm $rbp, 1, $noreg, -12, $noreg :: (load (s32) from %stack.0) |
| SEH_Epilogue |
| $rsp = frame-destroy ADD64ri8 $rsp, 48, implicit-def dead $eflags |
| $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp |
| RET64 $eax |
| |
| bb.1.if.then: |
| successors: %bb.2(0x7ffff800), %bb.7(0x00000800) |
| |
| EH_LABEL <mcsymbol .Leh1> |
| CALL64pcrel32 @mythrow, csr_win64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp |
| EH_LABEL <mcsymbol .Leh2> |
| JMP_1 %bb.2 |
| |
| bb.4.if.then4: |
| successors: %bb.2(0x7ffff800), %bb.7(0x00000800) |
| |
| EH_LABEL <mcsymbol .Leh3> |
| CALL64pcrel32 @mythrow, csr_win64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp |
| EH_LABEL <mcsymbol .Leh4> |
| JMP_1 %bb.2 |
| |
| bb.6.if.then8: |
| successors: %bb.2(0x7ffff800), %bb.7(0x00000800) |
| |
| EH_LABEL <mcsymbol .Leh5> |
| CALL64pcrel32 @mythrow, csr_win64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp |
| EH_LABEL <mcsymbol .Leh6> |
| |
| bb.2.unreachable: |
| successors: |
| |
| |
| bb.7.catch (landing-pad, ehfunclet-entry): |
| successors: %bb.8(0x80000000) |
| liveins: $rdx |
| |
| frame-setup MOV64mr killed $rsp, 1, $noreg, 16, $noreg, $rdx |
| frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp |
| frame-setup SEH_PushReg 50 |
| $rsp = frame-setup SUB64ri8 $rsp, 32, implicit-def dead $eflags |
| frame-setup SEH_StackAlloc 32 |
| $rbp = LEA64r $rdx, 1, $noreg, 48, $noreg |
| frame-setup SEH_EndPrologue |
| MOV32mi $rbp, 1, $noreg, -12, $noreg, 1 :: (store (s32) into %stack.0) |
| $rax = LEA64r $rip, 0, $noreg, %bb.8, $noreg |
| SEH_Epilogue |
| $rsp = frame-destroy ADD64ri8 $rsp, 32, implicit-def dead $eflags |
| $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp |
| CATCHRET %bb.8, %bb.0 |
| |
| ... |