mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-13 22:58:50 +00:00
Avoid infinite loops in branch folding
Differential Revision: https://reviews.llvm.org/D27582 llvm-svn: 289486
This commit is contained in:
parent
d1ed49bbb2
commit
bfc4ce4b74
@ -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());
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user