Index: lib/Target/PowerPC/PPCFrameLowering.cpp
===================================================================
--- lib/Target/PowerPC/PPCFrameLowering.cpp	(revision 316360)
+++ lib/Target/PowerPC/PPCFrameLowering.cpp	(working copy)
@@ -1424,7 +1424,7 @@
   // if RBReg is anything other than SP. We shouldn't use ScratchReg as
   // a base register anyway, because it may happen to be R0.
   bool LoadedLR = false;
-  if (MustSaveLR && RBReg == SPReg && isInt<16>(LROffset+SPAdd)) {
+  if (MustSaveLR && RBReg == SPReg && isInt<16>(LROffset+SPAdd) && !FI->isEHReturnUsed()) {
     BuildMI(MBB, MBBI, dl, LoadInst, ScratchReg)
       .addImm(LROffset+SPAdd)
       .addReg(RBReg);
@@ -1465,7 +1465,7 @@
 
   // There is nothing more to be loaded from the stack, so now we can
   // restore SP: SP = RBReg + SPAdd.
-  if (RBReg != SPReg || SPAdd != 0) {
+  if ((RBReg != SPReg || SPAdd != 0) && !FI->isEHReturnUsed()) {
     assert(!HasRedZone && "This should not happen with red zone");
     // If SPAdd is 0, generate a copy.
     if (SPAdd == 0)
@@ -1496,7 +1496,7 @@
       BuildMI(MBB, MBBI, dl, TII.get(PPC::MTOCRF8), MustSaveCRs[i])
         .addReg(TempReg, getKillRegState(i == e-1));
 
-  if (MustSaveLR)
+  if (MustSaveLR && !FI->isEHReturnUsed())
     BuildMI(MBB, MBBI, dl, MTLRInst).addReg(ScratchReg);
 
   // Callee pop calling convention. Pop parameter/linkage area. Used for tail
@@ -1523,6 +1523,18 @@
           .addReg(FPReg)
           .addReg(ScratchReg);
       }
+    } else if (RetOpcode == PPC::BL8_EH) {
+      auto Offset = MBBI->getOperand(0).getReg();
+      auto Handler = MBBI->getOperand(1).getReg();
+      // Add offset to SP
+      BuildMI(MBB, MBBI, dl, AddInst)
+        .addReg(SPReg)
+        .addReg(SPReg)
+        .addReg(Offset);
+
+      BuildMI(MBB, MBBI, dl, MTLRInst).addReg(Handler);
+
+      BuildMI(MBB, MBBI, dl, TII.get(PPC::BLR8));
     } else {
       createTailCallBranchInstr(MBB);
     }
Index: lib/Target/PowerPC/PPCISelLowering.cpp
===================================================================
--- lib/Target/PowerPC/PPCISelLowering.cpp	(revision 316360)
+++ lib/Target/PowerPC/PPCISelLowering.cpp	(working copy)
@@ -357,6 +357,7 @@
   // We cannot sextinreg(i1).  Expand to shifts.
   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
 
+  setOperationAction(ISD::EH_RETURN       , MVT::Other, Custom);
   // NOTE: EH_SJLJ_SETJMP/_LONGJMP supported here is NOT intended to support
   // SjLj exception handling but a light-weight setjmp/longjmp replacement to
   // support continuation, user-level threading, and etc.. As a result, no
@@ -1159,6 +1160,7 @@
   case PPCISD::BCTRL_LOAD_TOC:  return "PPCISD::BCTRL_LOAD_TOC";
   case PPCISD::RET_FLAG:        return "PPCISD::RET_FLAG";
   case PPCISD::READ_TIME_BASE:  return "PPCISD::READ_TIME_BASE";
+  case PPCISD::EH_RETURN:       return "PPCISD::EH_RETURN";
   case PPCISD::EH_SJLJ_SETJMP:  return "PPCISD::EH_SJLJ_SETJMP";
   case PPCISD::EH_SJLJ_LONGJMP: return "PPCISD::EH_SJLJ_LONGJMP";
   case PPCISD::MFOCRF:          return "PPCISD::MFOCRF";
@@ -6567,6 +6569,41 @@
   return DAG.getFrameIndex(FI, PtrVT);
 }
 
+SDValue PPCTargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
+  MachineFunction &MF = DAG.getMachineFunction();
+  SDValue Chain     = Op.getOperand(0);
+  SDValue Offset    = Op.getOperand(1);
+  SDValue Handler   = Op.getOperand(2);
+  SDLoc dl      (Op);
+
+  PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
+  FuncInfo->setEHReturnUsed();
+
+#if 0
+  EVT PtrVT = getPointerTy(DAG.getDataLayout());
+  const PPCRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
+  unsigned FrameReg = RegInfo->getFrameRegister(DAG.getMachineFunction());
+  SDValue Frame = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, PtrVT);
+  unsigned StoreAddrReg = (PtrVT == MVT::i64) ? PPC::X1 : PPC::R1;
+  unsigned ScratchAddrReg = (PtrVT == MVT::i64) ? PPC::X0 : PPC::R0;
+
+  SDValue SPPlusOffset = DAG.getNode(ISD::ADD, dl, PtrVT, Frame, Offset);
+  SDValue OutChains[] = {
+    DAG.getCopyToReg(Chain, dl, ScratchAddrReg, Handler),
+    DAG.getCopyToReg(Chain, dl, StoreAddrReg, SPPlusOffset)
+  };
+
+  Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
+
+
+  return DAG.getNode(PPCISD::EH_RETURN, dl, MVT::Other, Chain,
+                     DAG.getRegister(StoreAddrReg, PtrVT), DAG.getRegister(ScratchAddrReg, PtrVT));
+#endif
+  return DAG.getNode(PPCISD::EH_RETURN, dl, MVT::Other, Chain, Offset, Handler);
+}
+
+
+
 SDValue PPCTargetLowering::lowerEH_SJLJ_SETJMP(SDValue Op,
                                                SelectionDAG &DAG) const {
   SDLoc DL(Op);
@@ -8986,6 +9023,7 @@
   case ISD::EH_DWARF_CFA:
     return LowerEH_DWARF_CFA(Op, DAG);
 
+  case ISD::EH_RETURN:          return LowerEH_RETURN(Op, DAG);
   case ISD::EH_SJLJ_SETJMP:     return lowerEH_SJLJ_SETJMP(Op, DAG);
   case ISD::EH_SJLJ_LONGJMP:    return lowerEH_SJLJ_LONGJMP(Op, DAG);
 
Index: lib/Target/PowerPC/PPCISelLowering.h
===================================================================
--- lib/Target/PowerPC/PPCISelLowering.h	(revision 316360)
+++ lib/Target/PowerPC/PPCISelLowering.h	(working copy)
@@ -206,6 +206,8 @@
       // target (returns (Lo, Hi)). It takes a chain operand.
       READ_TIME_BASE,
 
+      EH_RETURN,
+
       // EH_SJLJ_SETJMP - SjLj exception handling setjmp.
       EH_SJLJ_SETJMP,
 
@@ -1044,6 +1046,7 @@
                              SmallVectorImpl<SDValue> &InVals,
                              ImmutableCallSite CS) const;
 
+    SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
     SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;
     SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const;
 
Index: lib/Target/PowerPC/PPCInstr64Bit.td
===================================================================
--- lib/Target/PowerPC/PPCInstr64Bit.td	(revision 316360)
+++ lib/Target/PowerPC/PPCInstr64Bit.td	(working copy)
@@ -121,6 +121,24 @@
     def BL8  : IForm<18, 0, 1, (outs), (ins calltarget:$func),
                      "bl $func", IIC_BrB, []>;  // See Pat patterns below.
 
+/*
+let Interpretation64Bit = 1, isCodeGenOnly = 1 in
+let isTerminator = 1, isBarrier = 1, PPC970_Unit = 7 in
+  let isReturn = 1, Uses = [LR8, RM] in
+    def BL8_EH : XLForm_2_ext<19, 16, 20, 0, 0, (outs), (ins g8rc:$a, g8rc:$b), "blr # EH_RETURN $a, $b", IIC_BrB,
+                            [(PPCehret i64:$a, i64:$b)]>, Requires<[In64BitMode]>;
+*/
+
+let Interpretation64Bit = 1, isCodeGenOnly = 1 in {
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [RM] in
+def BL8_EH:Pseudo< (outs),
+                        (ins calltarget:$offset, g8rc:$dst),
+                 "#BL8_EH $dst $offset",
+                 [(PPCehret i64:$offset, i64:$dst)]>;
+}
+
+
+
     def BL8_TLS  : IForm<18, 0, 1, (outs), (ins tlscall:$func),
                          "bl $func", IIC_BrB, []>;
 
Index: lib/Target/PowerPC/PPCInstrInfo.td
===================================================================
--- lib/Target/PowerPC/PPCInstrInfo.td	(revision 316360)
+++ lib/Target/PowerPC/PPCInstrInfo.td	(working copy)
@@ -233,6 +233,11 @@
 def PPCtc_return : SDNode<"PPCISD::TC_RETURN", SDT_PPCTC_ret,
                         [SDNPHasChain,  SDNPOptInGlue, SDNPVariadic]>;
 
+def SDT_PPCEHRET : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>;
+
+def PPCehret : SDNode<"PPCISD::EH_RETURN", SDT_PPCEHRET,
+                        [SDNPHasChain]>;
+
 def PPCeh_sjlj_setjmp  : SDNode<"PPCISD::EH_SJLJ_SETJMP",
                                 SDTypeProfile<1, 1, [SDTCisInt<0>,
                                                      SDTCisPtrTy<1>]>,
Index: lib/Target/PowerPC/PPCMachineFunctionInfo.h
===================================================================
--- lib/Target/PowerPC/PPCMachineFunctionInfo.h	(revision 316360)
+++ lib/Target/PowerPC/PPCMachineFunctionInfo.h	(working copy)
@@ -58,6 +58,8 @@
   /// Indicates whether VRSAVE is spilled in the current function.
   bool SpillsVRSAVE = false;
 
+  bool EHReturnUsed = false;
+
   /// LRStoreRequired - The bool indicates whether there is some explicit use of
   /// the LR/LR8 stack slot that is not obvious from scanning the code.  This
   /// requires that the code generator produce a store of LR to the stack on
@@ -162,6 +164,9 @@
   void setLRStoreRequired() { LRStoreRequired = true; }
   bool isLRStoreRequired() const { return LRStoreRequired; }
 
+  void setEHReturnUsed() { EHReturnUsed = true; }
+  bool isEHReturnUsed() const { return EHReturnUsed; }
+
   void setUsesTOCBasePtr()    { UsesTOCBasePtr = true; }
   bool usesTOCBasePtr() const { return UsesTOCBasePtr; }
 
