[WinEH] Remove unreachable blocks before preparation

We remove unreachable blocks because it is pointless to consider them
for coloring.  However, we still had stale pointers to these blocks in
some data structures after we removed them from the function.

Instead, remove the unreachable blocks before attempting to do anything
with the function.

This fixes PR25099.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249617 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer 2015-10-07 21:08:25 +00:00
parent 10b15bcfb2
commit fae66468fd
4 changed files with 16 additions and 137 deletions

View File

@ -437,6 +437,11 @@ bool WinEHPrepare::runOnFunction(Function &Fn) {
if (!isFuncletEHPersonality(Personality))
return false;
// Remove unreachable blocks. It is not valuable to assign them a color and
// their existence can trick us into thinking values are alive when they are
// not.
removeUnreachableBlocks(Fn);
SmallVector<LandingPadInst *, 4> LPads;
SmallVector<ResumeInst *, 4> Resumes;
SmallVector<BasicBlock *, 4> EntryBlocks;
@ -3408,11 +3413,6 @@ void WinEHPrepare::verifyPreparedFunclets(Function &F) {
bool WinEHPrepare::prepareExplicitEH(
Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks) {
// Remove unreachable blocks. It is not valuable to assign them a color and
// their existence can trick us into thinking values are alive when they are
// not.
removeUnreachableBlocks(F);
replaceTerminatePadWithCleanup(F);
// Determine which blocks are reachable from which funclet entries.

View File

@ -1,97 +0,0 @@
; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s
; This test is based on the following code:
;
; void test()
; {
; try {
; may_throw();
; } catch (...) {
; handle_exception();
; }
; }
;
; Parts of the IR have been hand-edited to simplify the test case.
; The full IR will be restored when Windows C++ EH support is complete.
; ModuleID = 'catch-all.cpp'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"
; The function entry in this case remains unchanged.
; CHECK: define void @_Z4testv()
; CHECK: entry:
; CHECK: invoke void @_Z9may_throwv()
; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]]
; Function Attrs: uwtable
define void @_Z4testv() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
entry:
%exn.slot = alloca i8*
%ehselector.slot = alloca i32
invoke void @_Z9may_throwv()
to label %invoke.cont unwind label %lpad
invoke.cont: ; preds = %entry
br label %try.cont
; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry
; CHECK: landingpad { i8*, i32 }
; CHECK-NEXT: catch i8* null
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @_Z4testv.catch)
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont]
lpad: ; preds = %entry
%tmp = landingpad { i8*, i32 }
catch i8* null
%tmp1 = extractvalue { i8*, i32 } %tmp, 0
store i8* %tmp1, i8** %exn.slot
%tmp2 = extractvalue { i8*, i32 } %tmp, 1
store i32 %tmp2, i32* %ehselector.slot
br label %catch
; CHECK-NOT: catch:
catch: ; preds = %lpad
%exn = load i8*, i8** %exn.slot
call void @llvm.eh.begincatch(i8* %exn, i8* null) #2
call void @_Z16handle_exceptionv()
br label %invoke.cont2
; CHECK-NOT: invoke.cont2:
invoke.cont2: ; preds = %catch
call void @llvm.eh.endcatch()
br label %try.cont
try.cont: ; preds = %invoke.cont2, %invoke.cont
ret void
; CHECK: }
}
; CHECK: define internal i8* @_Z4testv.catch(i8*, i8*)
; CHECK: entry:
; CHECK: call void @_Z16handle_exceptionv()
; CHECK: ret i8* blockaddress(@_Z4testv, %try.cont)
; CHECK: }
declare void @_Z9may_throwv() #1
declare i32 @__CxxFrameHandler3(...)
declare void @llvm.eh.begincatch(i8*, i8*)
declare void @_Z16handle_exceptionv() #1
declare void @llvm.eh.endcatch()
attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { noinline noreturn nounwind }
attributes #3 = { nounwind }
attributes #4 = { noreturn nounwind }
!llvm.ident = !{!0}
!0 = !{!"clang version 3.7.0 (trunk 226027)"}

View File

@ -475,6 +475,17 @@ exit:
ret void
}
; CHECK-LABEL: define void @test13()
; CHECK: ret void
define void @test13() personality i32 (...)* @__CxxFrameHandler3 {
entry:
ret void
unreachable:
cleanuppad []
unreachable
}
; Make sure the DISubprogram doesn't get cloned
; CHECK-LABEL: !llvm.module.flags
; CHECK-NOT: !DISubprogram

View File

@ -1,35 +0,0 @@
; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck %s
; Sometimes invokes of nounwind functions make it through to CodeGen, especially
; at -O0, where Clang sometimes optimistically annotates functions as nounwind.
; WinEHPrepare ends up outlining functions, and emitting references to LSDA
; labels. Make sure we emit the LSDA in that case.
declare i32 @__CxxFrameHandler3(...)
declare void @nounwind_func() nounwind
declare void @cleanup()
define void @should_emit_tables() personality i32 (...)* @__CxxFrameHandler3 {
entry:
invoke void @nounwind_func()
to label %done unwind label %lpad
done:
ret void
lpad:
%vals = landingpad { i8*, i32 }
cleanup
call void @cleanup()
resume { i8*, i32 } %vals
}
; CHECK: _should_emit_tables:
; CHECK: calll _nounwind_func
; CHECK: retl
; CHECK: L__ehtable$should_emit_tables:
; CHECK: ___ehhandler$should_emit_tables:
; CHECK: movl $L__ehtable$should_emit_tables, %eax
; CHECK: jmp ___CxxFrameHandler3 # TAILCALL