[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
diff --git a/llvm/test/CodeGen/WinEH/cppeh-demote-liveout.ll b/llvm/test/CodeGen/WinEH/cppeh-demote-liveout.ll
new file mode 100644
index 0000000..8be0fbc
--- /dev/null
+++ b/llvm/test/CodeGen/WinEH/cppeh-demote-liveout.ll
@@ -0,0 +1,72 @@
+; 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)
diff --git a/llvm/test/CodeGen/WinEH/cppeh-inalloca.ll b/llvm/test/CodeGen/WinEH/cppeh-inalloca.ll
index 93ec600..927aeed 100644
--- a/llvm/test/CodeGen/WinEH/cppeh-inalloca.ll
+++ b/llvm/test/CodeGen/WinEH/cppeh-inalloca.ll
@@ -39,8 +39,7 @@
 ; CHECK: define i32 @"\01?test@@YAHUA@@@Z"(<{ %struct.A }>* inalloca)
 ; CHECK: entry:
 ; CHECK:   [[TMP_REGMEM:\%.+]] = alloca <{ %struct.A }>*
-; CHECK:   [[TMP:\%.+]] = select i1 true, <{ %struct.A }>* %0, <{ %struct.A }>* undef
-; CHECK:   store <{ %struct.A }>* [[TMP]], <{ %struct.A }>** [[TMP_REGMEM]]
+; CHECK:   store <{ %struct.A }>* %0, <{ %struct.A }>** [[TMP_REGMEM]]
 ; CHECK:   [[RETVAL:\%.+]] = alloca i32, align 4
 ; CHECK:   [[E_PTR:\%.+]] = alloca i32, align 4
 ; CHECK:   [[CLEANUP_SLOT:\%.+]] = alloca i32
@@ -109,10 +108,8 @@
 
 ; The cleanup block should be re-written like this.
 ; CHECK: cleanup:{{[ ]+}}; preds = %[[LPAD_LABEL]], %try.cont
-; CHECK-NOT:  %a2 = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* %0, i32 0, i32 0
-; CHECK:   [[TMP_RELOAD:\%.+]] = load volatile <{ %struct.A }>*, <{ %struct.A }>** [[TMP_REGMEM]]
-; CHECK:   [[A2:\%.+]] = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* [[TMP_RELOAD]], i32 0, i32 0
-; CHECK:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* [[A2]])
+; CHECK:   %a2 = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* %0, i32 0, i32 0
+; CHECK:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %a2)
 ; CHECK:   [[TMP1:\%.+]] = load i32, i32* [[RETVAL]]
 ; CHECK:   ret i32 [[TMP1]]
 
@@ -148,12 +145,12 @@
 ; CHECK:   [[E_PTR:\%.+]] = bitcast i8* [[RECOVER_E]] to i32*
 ; CHECK:   [[RECOVER_EH_TEMP:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 1)
 ; CHECK:   [[EH_TEMP:\%.+]] = bitcast i8* [[RECOVER_EH_TEMP]] to <{ %struct.A }>**
-; CHECK:   [[TMP_RELOAD:\%.+]] = load <{ %struct.A }>*, <{ %struct.A }>** [[EH_TEMP]]
 ; CHECK:   [[RECOVER_RETVAL:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 2)
 ; CHECK:   [[RETVAL1:\%.+]] = bitcast i8* [[RECOVER_RETVAL]] to i32*
 ; CHECK:   [[RECOVER_CLEANUPSLOT:\%.+]] = call i8* @llvm.framerecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 3)
 ; CHECK:   [[CLEANUPSLOT1:\%.+]] = bitcast i8* [[RECOVER_CLEANUPSLOT]] to i32*
 ; CHECK:   [[E_I8PTR:\%.+]] = bitcast i32* [[E_PTR]] to i8*
+; CHECK:   [[TMP_RELOAD:\%.+]] = load <{ %struct.A }>*, <{ %struct.A }>** [[EH_TEMP]]
 ; CHECK:   [[RECOVER_A:\%.+]] = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* [[TMP_RELOAD]], i32 0, i32 0
 ; CHECK:   [[A1:\%.+]] = getelementptr inbounds %struct.A, %struct.A* [[RECOVER_A]], i32 0, i32 0
 ; CHECK:   [[TMP2:\%.+]] = load i32, i32* [[A1]], align 4
diff --git a/llvm/test/CodeGen/WinEH/cppeh-multi-catch.ll b/llvm/test/CodeGen/WinEH/cppeh-multi-catch.ll
index 6052629..9844eb5 100644
--- a/llvm/test/CodeGen/WinEH/cppeh-multi-catch.ll
+++ b/llvm/test/CodeGen/WinEH/cppeh-multi-catch.ll
@@ -79,7 +79,7 @@
 ; CHECK-SAME:        i32 1, i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry._J to i8*), i32 1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch1",
 ; CHECK-SAME:        i32 1, i8* bitcast (%eh.HandlerMapEntry* @"llvm.eh.handlermapentry.reference.?AVSomeClass@@" to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch2",
 ; CHECK-SAME:        i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch3")
-; CHECK-NEXT:   indirectbr i8* [[RECOVER]], [label %catch14.split, label %catch10.split, label %catch6.split, label %catch.split]
+; CHECK-NEXT:   indirectbr i8* [[RECOVER]], [label %ret]
 
 lpad:                                             ; preds = %entry
   %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
@@ -100,8 +100,11 @@
   %matches = icmp eq i32 %sel, %3
   br i1 %matches, label %catch14, label %catch.fallthrough
 
+ret:
+  ret void
+
 ; CHECK-NOT: catch14:
-; CHECK: catch14.split:
+; CHECK: ret:
 ; CHECK-NEXT:   ret void
 catch14:                                          ; preds = %catch.dispatch
   %exn15 = load i8*, i8** %exn.slot
@@ -110,10 +113,10 @@
   %5 = load i32, i32* %i, align 4
   call void @"\01?handle_int@@YAXH@Z"(i32 %5)
   call void @llvm.eh.endcatch() #3
-  ret void
+  br label %ret
 
 try.cont:                                         ; preds = %invoke.cont
-  ret void
+  br label %ret
 
 ; CHECK-NOT: catch.fallthrough:
 catch.fallthrough:                                ; preds = %catch.dispatch
@@ -122,8 +125,6 @@
   br i1 %matches1, label %catch10, label %catch.fallthrough2
 
 ; CHECK-NOT: catch10:
-; CHECK: catch10.split:
-; CHECK-NEXT:   ret void
 catch10:                                          ; preds = %catch.fallthrough
   %exn11 = load i8*, i8** %exn.slot
   %7 = bitcast i64* %ll to i8*
@@ -131,7 +132,7 @@
   %8 = load i64, i64* %ll, align 8
   call void @"\01?handle_long_long@@YAX_J@Z"(i64 %8)
   call void @llvm.eh.endcatch() #3
-  ret void
+  br label %ret
 
 ; CHECK-NOT: catch.fallthrough2:
 catch.fallthrough2:                               ; preds = %catch.fallthrough
@@ -140,8 +141,6 @@
   br i1 %matches3, label %catch6, label %catch
 
 ; CHECK-NOT: catch6:
-; CHECK: catch6.split:
-; CHECK-NEXT:   ret void
 catch6:                                           ; preds = %catch.fallthrough2
   %exn7 = load i8*, i8** %exn.slot
   %10 = bitcast %class.SomeClass** %obj to i8*
@@ -149,16 +148,14 @@
   %11 = load %class.SomeClass*, %class.SomeClass** %obj, align 8
   call void @"\01?handle_obj@@YAXPEAVSomeClass@@@Z"(%class.SomeClass* %11)
   call void @llvm.eh.endcatch() #3
-  ret void
+  br label %ret
 
 ; CHECK-NOT: catch:
-; CHECK: catch.split:
-; CHECK-NEXT:   ret void
 catch:                                            ; preds = %catch.fallthrough2
   %exn = load i8*, i8** %exn.slot
   call void @llvm.eh.begincatch(i8* %exn, i8* null) #3
   call void @"\01?handle_exception@@YAXXZ"()  call void @llvm.eh.endcatch() #3
-  ret void
+  br label %ret
 ; CHECK: }
 }
 
@@ -168,7 +165,7 @@
 ; CHECK:   [[I_PTR:\%.+]] = bitcast i8* [[RECOVER_I]] to i32*
 ; CHECK:   [[TMP1:\%.+]] = load i32, i32* [[I_PTR]], align 4
 ; CHECK:   call void @"\01?handle_int@@YAXH@Z"(i32 [[TMP1]])
-; CHECK:   ret i8* blockaddress(@"\01?test@@YAXXZ", %catch14.split)
+; CHECK:   ret i8* blockaddress(@"\01?test@@YAXXZ", %ret)
 ; CHECK: }
 
 ; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch1"(i8*, i8*)
@@ -177,7 +174,7 @@
 ; CHECK:   [[LL_PTR:\%.+]] = bitcast i8* [[RECOVER_LL]] to i64*
 ; CHECK:   [[TMP2:\%.+]] = load i64, i64* [[LL_PTR]], align 8
 ; CHECK:   call void @"\01?handle_long_long@@YAX_J@Z"(i64 [[TMP2]])
-; CHECK:   ret i8* blockaddress(@"\01?test@@YAXXZ", %catch10.split)
+; CHECK:   ret i8* blockaddress(@"\01?test@@YAXXZ", %ret)
 ; CHECK: }
 
 ; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch2"(i8*, i8*)
@@ -186,13 +183,13 @@
 ; CHECK:   [[OBJ_PTR:\%.+]] = bitcast i8* [[RECOVER_OBJ]] to %class.SomeClass**
 ; CHECK:   [[TMP3:\%.+]] = load %class.SomeClass*, %class.SomeClass** [[OBJ_PTR]], align 8
 ; CHECK:   call void @"\01?handle_obj@@YAXPEAVSomeClass@@@Z"(%class.SomeClass* [[TMP3]])
-; CHECK:   ret i8* blockaddress(@"\01?test@@YAXXZ", %catch6.split)
+; CHECK:   ret i8* blockaddress(@"\01?test@@YAXXZ", %ret)
 ; CHECK: }
 
 ; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch3"(i8*, i8*)
 ; CHECK: entry:
 ; CHECK:   call void @"\01?handle_exception@@YAXXZ"()
-; CHECK:   ret i8* blockaddress(@"\01?test@@YAXXZ", %catch.split)
+; CHECK:   ret i8* blockaddress(@"\01?test@@YAXXZ", %ret)
 ; CHECK: }
 
 
diff --git a/llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll b/llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll
index de873d1..15f6bfb 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 @@
 ; 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 @@
 ; 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 @@
   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 @@
           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 @@
 ; 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 @@
   %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 @@
   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 @@
 ; 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
diff --git a/llvm/test/CodeGen/WinEH/seh-simple.ll b/llvm/test/CodeGen/WinEH/seh-simple.ll
index 344a0c8..6d9ee1c 100644
--- a/llvm/test/CodeGen/WinEH/seh-simple.ll
+++ b/llvm/test/CodeGen/WinEH/seh-simple.ll
@@ -94,11 +94,60 @@
 ; CHECK-LABEL: define i32 @except_phi()
 ; CHECK: landingpad { i8*, i32 }
 ; CHECK-NEXT: catch i32 ()* @filt
-; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_phi, %return))
-; CHECK-NEXT: indirectbr {{.*}} [label %return]
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_phi, %lpad.return_crit_edge))
+; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
+;
+; CHECK: lpad.return_crit_edge:
+; CHECK: br label %return
 ;
 ; CHECK: return:
-; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
+; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
+; CHECK-NEXT: ret i32 %r
+
+define i32 @lpad_phi() {
+entry:
+  invoke void @might_crash()
+          to label %cont unwind label %lpad
+
+cont:
+  invoke void @might_crash()
+          to label %return unwind label %lpad
+
+lpad:
+  %ncalls.1 = phi i32 [ 0, %entry ], [ 1, %cont ]
+  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
+          catch i32 ()* @filt
+  %sel = extractvalue { i8*, i32 } %ehvals, 1
+  %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
+  %matches = icmp eq i32 %sel, %filt_sel
+  br i1 %matches, label %return, label %eh.resume
+
+return:
+  %r = phi i32 [2, %cont], [%ncalls.1, %lpad]
+  ret i32 %r
+
+eh.resume:
+  resume { i8*, i32 } %ehvals
+}
+
+; CHECK-LABEL: define i32 @lpad_phi()
+; CHECK: alloca i32
+; CHECK: store i32 0, i32*
+; CHECK: invoke void @might_crash()
+; CHECK: store i32 1, i32*
+; CHECK: invoke void @might_crash()
+; CHECK: landingpad { i8*, i32 }
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i32 ()* @filt
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @lpad_phi.cleanup, i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@lpad_phi, %lpad.return_crit_edge))
+; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
+;
+; CHECK: lpad.return_crit_edge:
+; CHECK: load i32, i32*
+; CHECK: br label %return
+;
+; CHECK: return:
+; CHECK-NEXT: %r = phi i32 [ 2, %cont ], [ %{{.*}}, %lpad.return_crit_edge ]
 ; CHECK-NEXT: ret i32 %r
 
 define i32 @cleanup_and_except() {
@@ -130,9 +179,17 @@
 ; CHECK-NEXT: catch i32 ()* @filt
 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(
 ; CHECK: i32 0, void (i8*, i8*)* @cleanup_and_except.cleanup,
-; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %return))
-; CHECK-NEXT: indirectbr {{.*}} [label %return]
+; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %lpad.return_crit_edge))
+; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
+;
+; CHECK: lpad.return_crit_edge:
+; CHECK: br label %return
 ;
 ; CHECK: return:
-; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
+; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
 ; CHECK-NEXT: ret i32 %r
+
+; FIXME: This cleanup is an artifact of bad demotion.
+; CHECK-LABEL: define internal void @lpad_phi.cleanup(i8*, i8*)
+; CHECK: load i32
+; CHECK: store i32 %{{.*}}, i32*