Avoid infinite loops in branch folding

Differential Revision: https://reviews.llvm.org/D27582

llvm-svn: 289486
This commit is contained in:
Andrew Kaylor 2016-12-12 23:05:38 +00:00
parent d1ed49bbb2
commit bfc4ce4b74
3 changed files with 83 additions and 7 deletions

View File

@ -1624,10 +1624,22 @@ ReoptimizeBlock:
// Okay, there is no really great place to put this block. If, however,
// the block before this one would be a fall-through if this block were
// removed, move this block to the end of the function.
// removed, move this block to the end of the function. There is no real
// advantage in "falling through" to an EH block, so we don't want to
// perform this transformation for that case.
//
// Also, Windows EH introduced the possibility of an arbitrary number of
// successors to a given block. The analyzeBranch call does not consider
// exception handling and so we can get in a state where a block
// containing a call is followed by multiple EH blocks that would be
// rotated infinitely at the end of the function if the transformation
// below were performed for EH "FallThrough" blocks. Therefore, even if
// that appears not to be happening anymore, we should assume that it is
// possible and not remove the "!FallThrough()->isEHPad" condition below.
MachineBasicBlock *PrevTBB = nullptr, *PrevFBB = nullptr;
SmallVector<MachineOperand, 4> PrevCond;
if (FallThrough != MF.end() &&
!FallThrough->isEHPad() &&
!TII->analyzeBranch(PrevBB, PrevTBB, PrevFBB, PrevCond, true) &&
PrevBB.isSuccessor(&*FallThrough)) {
MBB->moveAfter(&MF.back());

View File

@ -50,13 +50,13 @@ catch.body.2:
; CXX-NEXT: .long 1
; CXX-NEXT: .long .Ltmp1@IMGREL+1
; CXX-NEXT: .long -1
; CXX-NEXT: .long "?catch$2@?0?test@4HA"@IMGREL
; CXX-NEXT: .long "?catch$3@?0?test@4HA"@IMGREL
; CXX-NEXT: .long 2
; CXX-NEXT: .long .Ltmp2@IMGREL+1
; CXX-NEXT: .long 3
; CXX-NEXT: .long .Ltmp3@IMGREL+1
; CXX-NEXT: .long 2
; CXX-NEXT: .long "?catch$4@?0?test@4HA"@IMGREL
; CXX-NEXT: .long "?catch$5@?0?test@4HA"@IMGREL
; CXX-NEXT: .long 4
; SEH-LABEL: test:
@ -64,17 +64,17 @@ catch.body.2:
; SEH-NEXT: .long .Ltmp0@IMGREL+1
; SEH-NEXT: .long .Ltmp1@IMGREL+1
; SEH-NEXT: .long dummy_filter@IMGREL
; SEH-NEXT: .long .LBB0_2@IMGREL
; SEH-NEXT: .long .LBB0_3@IMGREL
; SEH-NEXT: .long .Ltmp0@IMGREL+1
; SEH-NEXT: .long .Ltmp1@IMGREL+1
; SEH-NEXT: .long dummy_filter@IMGREL
; SEH-NEXT: .long .LBB0_4@IMGREL
; SEH-NEXT: .long .LBB0_5@IMGREL
; SEH-NEXT: .long .Ltmp2@IMGREL+1
; SEH-NEXT: .long .Ltmp3@IMGREL+1
; SEH-NEXT: .long "?dtor$5@?0?test@4HA"@IMGREL
; SEH-NEXT: .long "?dtor$2@?0?test@4HA"@IMGREL
; SEH-NEXT: .long 0
; SEH-NEXT: .long .Ltmp2@IMGREL+1
; SEH-NEXT: .long .Ltmp3@IMGREL+1
; SEH-NEXT: .long dummy_filter@IMGREL
; SEH-NEXT: .long .LBB0_4@IMGREL
; SEH-NEXT: .long .LBB0_5@IMGREL
; SEH-NEXT: .Llsda_end0:

View File

@ -93,3 +93,67 @@ unreachable:
;
; CHECK-LABEL: .def test2;
declare void @g()
define void @test3() optsize personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
entry:
switch i32 undef, label %if.end57 [
i32 64, label %sw.bb
i32 128, label %sw.epilog
i32 256, label %if.then56
i32 1024, label %sw.bb
i32 4096, label %sw.bb33
i32 16, label %sw.epilog
i32 8, label %sw.epilog
i32 32, label %sw.bb44
]
sw.bb:
unreachable
sw.bb33:
br i1 undef, label %if.end57, label %while.cond.i163.preheader
while.cond.i163.preheader:
unreachable
sw.bb44:
%temp0 = load void ()*, void ()** undef
invoke void %temp0()
to label %if.end57 unwind label %catch.dispatch
sw.epilog:
%temp1 = load i8*, i8** undef
br label %if.end57
catch.dispatch:
%cs = catchswitch within none [label %catch1, label %catch2, label %catch3] unwind to caller
catch1:
%c1 = catchpad within %cs [i8* null, i32 8, i8* null]
unreachable
catch2:
%c2 = catchpad within %cs [i8* null, i32 32, i8* null]
unreachable
catch3:
%c3 = catchpad within %cs [i8* null, i32 64, i8* null]
unreachable
if.then56:
call void @g()
br label %if.end57
if.end57:
ret void
}
; This test exercises a complex case that produced an infinite loop during
; compilation when the two cases above did not. The multiple targets from the
; entry switch are not actually fundamental to the failure, but they are
; necessary to suppress various control flow optimizations that would prevent
; the conditions that lead to the failure.
;
; CHECK-LABEL: .def test3;