llvm-6502/test/CodeGen/WinEH/cppeh-demote-liveout.ll
Reid Kleckner de3495610d [WinEH] Demote values and phis live across exception handlers up front
In particular, this handles SSA values that are live *out* of a handler.
The existing code only handles values that are live *in* to a handler.

It also handles phi nodes in the block where normal control should
resume after the end of a catch handler.  When EH return points have phi
nodes, we need to split the return edge. It is impossible for phi
elimination to emit copies in the previous block if that block gets
outlined. The indirectbr that we leave in the function is only notional,
and is eliminated from the MachineFunction CFG early on.

Reviewers: majnemer, andrew.w.kaylor

Differential Revision: http://reviews.llvm.org/D9158

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235545 91177308-0d34-0410-b5e6-96231b3b80d8
2015-04-22 21:05:21 +00:00

73 lines
1.9 KiB
LLVM

; RUN: opt -winehprepare -S < %s | FileCheck %s
; Notionally based on this C++ source:
; int liveout_catch(int p) {
; int val = p + 1;
; try {
; might_throw();
; } catch (int) {
; val++;
; }
; return val;
; }
declare void @llvm.eh.begincatch(i8*, i8*)
declare void @llvm.eh.endcatch()
declare void @might_throw()
declare i32 @__CxxFrameHandler3(...)
declare i32 @llvm.eh.typeid.for(i8*)
@typeinfo.int = external global i32
define i32 @liveout_catch(i32 %p) {
entry:
%val.entry = add i32 %p, 1
invoke void @might_throw()
to label %ret unwind label %lpad
lpad:
%ehvals = landingpad { i8*, i32 } personality i32 (...)* @__CxxFrameHandler3
cleanup
catch i32* @typeinfo.int
%ehptr = extractvalue { i8*, i32 } %ehvals, 0
%sel = extractvalue { i8*, i32 } %ehvals, 1
%int_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32* @typeinfo.int to i8*))
%match = icmp eq i32 %sel, %int_sel
br i1 %match, label %catchit, label %resume
catchit:
call void @llvm.eh.begincatch(i8* %ehptr, i8* null)
%val.lpad = add i32 %val.entry, 1
call void @llvm.eh.endcatch()
br label %ret
ret:
%rv = phi i32 [%val.entry, %entry], [%val.lpad, %catchit]
ret i32 %rv
resume:
resume {i8*, i32} %ehvals
}
; CHECK-LABEL: define i32 @liveout_catch(i32 %p)
; CHECK: %val.entry = add i32 %p, 1
; CHECK-NEXT: store i32 %val.entry, i32* %val.entry.reg2mem
; CHECK: invoke void @might_throw()
;
; CHECK: landingpad
; CHECK: indirectbr i8* {{.*}}, [label %ehreturn]
;
; CHECK: ehreturn:
; CHECK: load i32, i32* %val.lpad.reg2mem
; CHECK: br label %ret
;
; CHECK: ret:
; CHECK: %rv = phi i32 [ {{.*}}, %entry ], [ {{.*}}, %ehreturn ]
; CHECK: ret i32
; CHECK-LABEL: define internal i8* @liveout_catch.catch(i8*, i8*)
; CHECK: %[[val:[^ ]*]] = load i32, i32*
; CHECK-NEXT: %[[val_lpad:[^ ]*]] = add i32 %[[val]], 1
; CHECK-NEXT: store i32 %[[val_lpad]], i32*
; CHECK: ret i8* blockaddress(@liveout_catch, %ehreturn)