diff options
| author | Reid Kleckner <reid@kleckner.net> | 2015-04-22 21:05:21 +0000 |
|---|---|---|
| committer | Reid Kleckner <reid@kleckner.net> | 2015-04-22 21:05:21 +0000 |
| commit | fd7df284b801bd37af68f1f1a9e0b23c37744d47 (patch) | |
| tree | 2944a5c2fcf6c4ae69e37bc0eb619c276a00438a /llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll | |
| parent | fe58d13a17a2824fe891274e1396e5fc1ca5ab38 (diff) | |
| download | bcm5719-llvm-fd7df284b801bd37af68f1f1a9e0b23c37744d47.tar.gz bcm5719-llvm-fd7df284b801bd37af68f1f1a9e0b23c37744d47.zip | |
[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
llvm-svn: 235545
Diffstat (limited to 'llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll')
| -rw-r--r-- | llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll | 69 |
1 files changed, 37 insertions, 32 deletions
diff --git a/llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll b/llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll index de873d1170f..15f6bfb4680 100644 --- a/llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll +++ b/llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll @@ -55,8 +55,8 @@ $"\01??_R0H@8" = comdat any ; CHECK: entry: ; CHECK: [[NUMEXCEPTIONS_REGMEM:\%.+]] = alloca i32 ; CHECK: [[I_REGMEM:\%.+]] = alloca i32 -; CHECK: [[A_REGMEM:\%.+]] = alloca i32* ; CHECK: [[B_REGMEM:\%.+]] = alloca i32* +; CHECK: [[A_REGMEM:\%.+]] = alloca i32* ; CHECK: [[E_PTR:\%.+]] = alloca i32, align 4 ; CHECK: [[EXCEPTIONVAL:\%.+]] = alloca [10 x i32], align 16 ; CHECK: [[DATA_PTR:\%.+]] = alloca i64, align 8 @@ -68,9 +68,7 @@ $"\01??_R0H@8" = comdat any ; CHECK: store i32* [[A_PTR]], i32** [[A_REGMEM]] ; CHECK: [[B_PTR:\%.+]] = getelementptr inbounds %struct.SomeData, %struct.SomeData* [[TMPCAST]], i64 0, i32 1 ; CHECK: store i32* [[B_PTR]], i32** [[B_REGMEM]] -; CHECK: store i32 0, i32* [[NUMEXCEPTIONS_REGMEM]] -; CHECK: store i32 0, i32* [[I_REGMEM]] -; CHECK: call void (...) @llvm.frameescape(i32* %e, i32* %NumExceptions.020.reg2mem, [10 x i32]* [[EXCEPTIONVAL]], i32* [[I_REGMEM]], i32** [[A_REGMEM]], i32** [[B_REGMEM]]) +; CHECK: call void (...) @llvm.frameescape(i32* %e, i32* %NumExceptions.020.reg2mem, [10 x i32]* [[EXCEPTIONVAL]], i32* %inc.reg2mem, i32* [[I_REGMEM]], i32** [[A_REGMEM]], i32** [[B_REGMEM]]) ; CHECK: br label %for.body ; Function Attrs: uwtable @@ -88,10 +86,11 @@ entry: br label %for.body ; CHECK: for.body: -; CHECK-NOT: phi i32 [ 0, %entry ], [ {{\%NumExceptions.*}}, %try.cont ] -; CHECK-NOT: phi i32 [ 0, %entry ], [ {{\%inc.*}}, %try.cont ] -; CHECK: [[I_RELOAD:\%.+]] = load i32, i32* [[I_REGMEM]] -; CHECK: [[NUMEXCEPTIONS_RELOAD:\%.+]] = load i32, i32* [[NUMEXCEPTIONS_REGMEM]] +; CHECK: [[NUMEXCEPTIONS_PHI:\%.*]] = phi i32 [ 0, %entry ], [ {{\%NumExceptions.*}}, %try.cont ] +; CHECK: [[I_PHI:\%.*]] = phi i32 [ 0, %entry ], [ {{\%inc.*}}, %try.cont ] +; CHECK: store i32 [[I_PHI]], i32* [[I_REGMEM]] +; CHECK: store i32 [[NUMEXCEPTIONS_PHI]], i32* [[NUMEXCEPTIONS_REGMEM]] +; CHECK: invoke void @"\01?may_throw@@YAXXZ"() for.body: ; preds = %entry, %try.cont %NumExceptions.020 = phi i32 [ 0, %entry ], [ %NumExceptions.1, %try.cont ] %i.019 = phi i32 [ 0, %entry ], [ %inc5, %try.cont ] @@ -99,11 +98,12 @@ for.body: ; preds = %entry, %try.cont to label %invoke.cont unwind label %lpad ; CHECK: invoke.cont: ; preds = %for.body -; CHECK: [[A_RELOAD:\%.+]] = load volatile i32*, i32** [[A_REGMEM]] +; CHECK: [[A_RELOAD:\%.+]] = load i32*, i32** [[A_REGMEM]] ; CHECK: [[TMP1:\%.+]] = load i32, i32* [[A_RELOAD]], align 8 +; CHECK: [[I_RELOAD:\%.+]] = load i32, i32* [[I_REGMEM]] ; CHECK: [[ADD:\%.+]] = add nsw i32 [[TMP1]], [[I_RELOAD]] -; CHECK: [[A_RELOAD1:\%.+]] = load volatile i32*, i32** [[A_REGMEM]] -; CHECK: store i32 [[ADD]], i32* [[A_RELOAD1]], align 8 +; CHECK: [[A_RELOAD1:\%.+]] = load i32*, i32** [[A_REGMEM]] +; CHECK: [[NUMEXCEPTIONS_RELOAD:\%.+]] = load i32, i32* [[NUMEXCEPTIONS_REGMEM]] ; CHECK: br label %try.cont invoke.cont: ; preds = %for.body %1 = load i32, i32* %a, align 8, !tbaa !2 @@ -115,7 +115,7 @@ invoke.cont: ; preds = %for.body ; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) ; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) ; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch") -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont] +; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %[[SPLIT_RECOVER_BB:.*]]] lpad: ; preds = %for.body %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) @@ -139,8 +139,6 @@ catch: ; preds = %lpad %cmp1 = icmp eq i32 %tmp8, %i.019 br i1 %cmp1, label %if.then, label %if.else -; CHECK-NOT: if.then: - if.then: ; preds = %catch %tmp9 = load i32, i32* %b, align 4, !tbaa !8 %add2 = add nsw i32 %tmp9, %i.019 @@ -156,18 +154,20 @@ if.else: ; preds = %catch br label %if.end ; CHECK-NOT: if.end: +; CHECK: [[SPLIT_RECOVER_BB]]: +; CHECK: [[INC_RELOAD:\%.*]] = load i32, i32* +; CHECK: br label %try.cont if.end: ; preds = %if.else, %if.then tail call void @llvm.eh.endcatch() #1 br label %try.cont -; CHECK: try.cont:{{[ ]+}}; preds = %[[LPAD_LABEL]], %invoke.cont -; CHECK-NOT: phi i32 -; CHECK: tail call void @"\01?does_not_throw@@YAXH@Z"(i32 [[NUMEXCEPTIONS_RELOAD]]) +; CHECK: try.cont:{{[ ]+}}; preds = %[[SPLIT_RECOVER_BB]], %invoke.cont +; CHECK: [[NUMEXCEPTIONS_PHI:\%.*]] = phi i32 [ [[NUMEXCEPTIONS_RELOAD]], %invoke.cont ], [ [[INC_RELOAD]], %[[SPLIT_RECOVER_BB]] ] +; CHECK: tail call void @"\01?does_not_throw@@YAXH@Z"(i32 [[NUMEXCEPTIONS_PHI]]) +; CHECK: [[I_RELOAD:\%.+]] = load i32, i32* [[I_REGMEM]] ; CHECK: [[INC:\%.+]] = add nuw nsw i32 [[I_RELOAD]], 1 ; CHECK: [[CMP:\%.+]] = icmp slt i32 [[INC]], 10 -; CHECK: store i32 [[NUMEXCEPTIONS_RELOAD]], i32* [[NUMEXCEPTIONS_REGMEM]] -; CHECK: store i32 [[INC]], i32* [[I_REGMEM]] ; CHECK: br i1 [[CMP]], label %for.body, label %for.end try.cont: ; preds = %if.end, %invoke.cont @@ -194,43 +194,48 @@ eh.resume: ; preds = %lpad ; CHECK: entry: ; CHECK: [[RECOVER_E:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0) ; CHECK: [[E_PTR:\%.+]] = bitcast i8* [[RECOVER_E]] to i32* -; CHECK: [[RECOVER_EH_TEMP:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1) -; CHECK: [[EH_TEMP:\%.+]] = bitcast i8* [[RECOVER_EH_TEMP]] to i32* -; CHECK: [[NUMEXCEPTIONS_RELOAD:\%.+]] = load i32, i32* [[EH_TEMP]] +; CHECK: [[RECOVER_NUMEXCEPTIONS:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1) +; CHECK: [[NUMEXCEPTIONS_REGMEM:\%.+]] = bitcast i8* [[RECOVER_NUMEXCEPTIONS]] to i32* ; CHECK: [[RECOVER_EXCEPTIONVAL:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2) ; CHECK: [[EXCEPTIONVAL:\%.+]] = bitcast i8* [[RECOVER_EXCEPTIONVAL]] to [10 x i32]* -; CHECK: [[RECOVER_EH_TEMP1:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 3) -; CHECK: [[EH_TEMP1:\%.+]] = bitcast i8* [[RECOVER_EH_TEMP1]] to i32* -; CHECK: [[I_RELOAD:\%.+]] = load i32, i32* [[EH_TEMP1]] -; CHECK: [[RECOVER_EH_TEMP2:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 4) -; CHECK: [[EH_TEMP2:\%.+]] = bitcast i8* [[RECOVER_EH_TEMP2]] to i32** -; CHECK: [[A_RELOAD:\%.+]] = load i32*, i32** [[EH_TEMP2]] -; CHECK: [[RECOVER_EH_TEMP3:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 5) -; CHECK: [[EH_TEMP3:\%.+]] = bitcast i8* [[RECOVER_EH_TEMP3]] to i32** -; CHECK: [[B_RELOAD:\%.+]] = load i32*, i32** [[EH_TEMP3]] +; CHECK: [[RECOVER_INC:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 3) +; CHECK: [[INC_REGMEM:\%.+]] = bitcast i8* [[RECOVER_INC]] to i32* +; CHECK: [[RECOVER_I:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 4) +; CHECK: [[I_REGMEM:\%.+]] = bitcast i8* [[RECOVER_I]] to i32* +; CHECK: [[RECOVER_A:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 5) +; CHECK: [[A_REGMEM:\%.+]] = bitcast i8* [[RECOVER_A]] to i32** +; CHECK: [[RECOVER_B:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 6) +; CHECK: [[B_REGMEM:\%.+]] = bitcast i8* [[RECOVER_B]] to i32** ; CHECK: [[E_I8PTR:\%.+]] = bitcast i32* [[E_PTR]] to i8* ; CHECK: [[TMP:\%.+]] = load i32, i32* [[E_PTR]], align 4 +; CHECK: [[NUMEXCEPTIONS_RELOAD:\%.+]] = load i32, i32* [[NUMEXCEPTIONS_REGMEM]] ; CHECK: [[IDXPROM:\%.+]] = sext i32 [[NUMEXCEPTIONS_RELOAD]] to i64 ; CHECK: [[ARRAYIDX:\%.+]] = getelementptr inbounds [10 x i32], [10 x i32]* [[EXCEPTIONVAL]], i64 0, i64 [[IDXPROM]] ; CHECK: store i32 [[TMP]], i32* [[ARRAYIDX]], align 4 +; CHECK: [[NUMEXCEPTIONS_RELOAD:\%.+]] = load i32, i32* [[NUMEXCEPTIONS_REGMEM]] ; CHECK: [[INC:\%.+]] = add nsw i32 [[NUMEXCEPTIONS_RELOAD]], 1 ; CHECK: [[CMP:\%.+]] = icmp eq i32 [[TMP]], [[I_RELOAD]] ; CHECK: br i1 [[CMP]], label %if.then, label %if.else ; ; CHECK: if.then:{{[ ]+}}; preds = %entry +; CHECK: [[B_RELOAD:\%.+]] = load i32*, i32** [[B_REGMEM]] ; CHECK: [[TMP1:\%.+]] = load i32, i32* [[B_RELOAD]], align 4 +; CHECK: [[I_RELOAD:\%.+]] = load i32, i32* [[I_REGMEM]] ; CHECK: [[ADD:\%.+]] = add nsw i32 [[TMP1]], [[I_RELOAD]] +; CHECK: [[B_RELOAD:\%.+]] = load i32*, i32** [[B_REGMEM]] ; CHECK: store i32 [[ADD]], i32* [[B_RELOAD]], align 4 ; CHECK: br label %if.end ; ; CHECK: if.else:{{[ ]+}}; preds = %entry +; CHECK: [[A_RELOAD:\%.+]] = load i32*, i32** [[A_REGMEM]] ; CHECK: [[TMP2:\%.+]] = load i32, i32* [[A_RELOAD]], align 8 ; CHECK: [[ADD2:\%.+]] = add nsw i32 [[TMP2]], [[TMP]] +; CHECK: [[A_RELOAD:\%.+]] = load i32*, i32** [[A_REGMEM]] ; CHECK: store i32 [[ADD2]], i32* [[A_RELOAD]], align 8 ; CHECK: br label %if.end ; ; CHECK: if.end:{{[ ]+}}; preds = %if.else, %if.then -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont) +; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %[[SPLIT_RECOVER_BB]]) ; CHECK: } ; Function Attrs: nounwind |

