diff -urp -x.svn -x'*~' -x'*.orig' gcc-bernd/gcc/config/rs6000/rs6000.c gcc-current/gcc/config/rs6000/rs6000.c
--- gcc-bernd/gcc/config/rs6000/rs6000.c	2011-09-16 11:52:15.000000000 +0930
+++ gcc-current/gcc/config/rs6000/rs6000.c	2011-09-15 22:25:50.000000000 +0930
@@ -899,8 +900,6 @@ static const char *rs6000_mangle_type (c
 static void rs6000_set_default_type_attributes (tree);
 static rtx rs6000_savres_routine_sym (rs6000_stack_t *, bool, bool, bool);
 static rtx rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool);
-static rtx rs6000_make_savres_rtx (rs6000_stack_t *, rtx, int,
-				   enum machine_mode, bool, bool, bool);
 static bool rs6000_reg_live_or_pic_offset_p (int);
 static tree rs6000_builtin_vectorized_libmass (tree, tree, tree);
 static tree rs6000_builtin_vectorized_function (tree, tree, tree);
@@ -19729,10 +19764,11 @@ rs6000_emit_stack_reset (rs6000_stack_t 
 }
 
 /* Construct a parallel rtx describing the effect of a call to an
-   out-of-line register save/restore routine.  */
+   out-of-line register save/restore routine, and emit the insn
+   or jump_insn as appropriate.  */
 
 static rtx
-rs6000_make_savres_rtx (rs6000_stack_t *info,
+rs6000_emit_savres_rtx (rs6000_stack_t *info,
 			rtx frame_reg_rtx, int save_area_offset,
 			enum machine_mode reg_mode,
 			bool savep, bool gpr, bool lr)
@@ -19742,6 +19778,7 @@ rs6000_make_savres_rtx (rs6000_stack_t *
   int reg_size = GET_MODE_SIZE (reg_mode);
   rtx sym;
   rtvec p;
+  rtx par, insn;
 
   offset = 0;
   start_reg = (gpr
@@ -19752,7 +19789,7 @@ rs6000_make_savres_rtx (rs6000_stack_t *
   p = rtvec_alloc ((lr ? 4 : 3) + n_regs);
 
   if (!savep && lr)
-    RTVEC_ELT (p, offset++) = ret_rtx;
+    RTVEC_ELT (p, offset++) = simple_return_rtx;
 
   RTVEC_ELT (p, offset++)
     = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65));
@@ -19788,7 +19825,16 @@ rs6000_make_savres_rtx (rs6000_stack_t *
       RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode, mem, reg);
     }
 
-  return gen_rtx_PARALLEL (VOIDmode, p);
+  par = gen_rtx_PARALLEL (VOIDmode, p);
+
+  if (!savep && lr)
+    {
+      insn = emit_jump_insn (par);
+      JUMP_LABEL (insn) = simple_return_rtx;
+    }
+  else
+    insn = emit_insn (par);
+  return insn;
 }
 
 /* Determine whether the gp REG is really used.  */
@@ -20087,16 +20133,13 @@ rs6000_emit_prologue (void)
     }
   else if (!WORLD_SAVE_P (info) && info->first_fp_reg_save != 64)
     {
-      rtx par;
-
-      par = rs6000_make_savres_rtx (info, frame_reg_rtx,
-				    info->fp_save_offset + sp_offset,
-				    DFmode,
-				    /*savep=*/true, /*gpr=*/false,
-				    /*lr=*/(strategy
-					    & SAVE_NOINLINE_FPRS_SAVES_LR)
-					   != 0);
-      insn = emit_insn (par);
+      insn = rs6000_emit_savres_rtx (info, frame_reg_rtx,
+				     info->fp_save_offset + sp_offset,
+				     DFmode,
+				     /*savep=*/true, /*gpr=*/false,
+				     /*lr=*/((strategy
+					      & SAVE_NOINLINE_FPRS_SAVES_LR)
+					     != 0));
       rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
 			    NULL_RTX, NULL_RTX);
     }
@@ -20186,13 +20229,10 @@ rs6000_emit_prologue (void)
 	}
       else
 	{
-	  rtx par;
-
-	  par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
-					0, reg_mode,
-					/*savep=*/true, /*gpr=*/true,
-					/*lr=*/false);
-	  insn = emit_insn (par);
+	  insn = rs6000_emit_savres_rtx (info, gen_rtx_REG (Pmode, 11),
+					 0, reg_mode,
+					 /*savep=*/true, /*gpr=*/true,
+					 /*lr=*/false);
 	  rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
 				NULL_RTX, NULL_RTX);
 	}
@@ -20204,8 +20244,6 @@ rs6000_emit_prologue (void)
     }
   else if (!WORLD_SAVE_P (info) && !saving_GPRs_inline)
     {
-      rtx par;
-
       /* Need to adjust r11 (r12) if we saved any FPRs.  */
       if (info->first_fp_reg_save != 64)
         {
@@ -20216,14 +20254,13 @@ rs6000_emit_prologue (void)
 	  emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset));
         }
 
-      par = rs6000_make_savres_rtx (info, frame_reg_rtx,
-				    info->gp_save_offset + sp_offset,
-				    reg_mode,
-				    /*savep=*/true, /*gpr=*/true,
-				    /*lr=*/(strategy
-					    & SAVE_NOINLINE_GPRS_SAVES_LR)
-					   != 0);
-      insn = emit_insn (par);
+      insn = rs6000_emit_savres_rtx (info, frame_reg_rtx,
+				     info->gp_save_offset + sp_offset,
+				     reg_mode,
+				     /*savep=*/true, /*gpr=*/true,
+				     /*lr=*/((strategy
+					      & SAVE_NOINLINE_GPRS_SAVES_LR)
+					     != 0));
       rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
 			    NULL_RTX, NULL_RTX);
     }
@@ -20750,7 +20805,7 @@ rs6000_emit_epilogue (int sibcall)
       alloc_rname = ggc_strdup (rname);
 
       j = 0;
-      RTVEC_ELT (p, j++) = ret_rtx;
+      RTVEC_ELT (p, j++) = simple_return_rtx;
       RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
 					gen_rtx_REG (Pmode,
 						     LR_REGNO));
@@ -21165,13 +21214,11 @@ rs6000_emit_epilogue (int sibcall)
 	}
       else
 	{
-	  rtx par;
+	  rs6000_emit_savres_rtx (info, gen_rtx_REG (Pmode, 11),
+				  0, reg_mode,
+				  /*savep=*/false, /*gpr=*/true,
+				  /*lr=*/true);
 
-	  par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
-					0, reg_mode,
-					/*savep=*/false, /*gpr=*/true,
-					/*lr=*/true);
-	  emit_jump_insn (par);
 	  /* We don't want anybody else emitting things after we jumped
 	     back.  */
 	  return;
@@ -21181,12 +21228,22 @@ rs6000_emit_epilogue (int sibcall)
     {
       /* We are jumping to an out-of-line function.  */
       bool can_use_exit = info->first_fp_reg_save == 64;
-      rtx par;
 
       /* Emit stack reset code if we need it.  */
       if (can_use_exit)
-	rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
-				 sp_offset, can_use_exit);
+	{
+	  rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
+				   sp_offset, can_use_exit);
+	  if (info->cr_save_p)
+	    {
+	      rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
+	      if (DEFAULT_ABI == ABI_V4)
+		cfa_restores
+		  = alloc_reg_note (REG_CFA_RESTORE,
+				    gen_rtx_REG (SImode, CR2_REGNO),
+				    cfa_restores);
+	    }
+	}
       else
 	{
 	  emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, DEFAULT_ABI == ABI_AIX
@@ -21197,31 +21254,18 @@ rs6000_emit_epilogue (int sibcall)
 	    sp_offset += info->fp_size;
 	}
 
-      par = rs6000_make_savres_rtx (info, frame_reg_rtx,
-				    info->gp_save_offset, reg_mode,
-				    /*savep=*/false, /*gpr=*/true,
-				    /*lr=*/can_use_exit);
+      insn = rs6000_emit_savres_rtx (info, frame_reg_rtx,
+				     info->gp_save_offset, reg_mode,
+				     /*savep=*/false, /*gpr=*/true,
+				     /*lr=*/can_use_exit);
 
       if (can_use_exit)
 	{
-	  if (info->cr_save_p)
-	    {
-	      rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
-	      if (DEFAULT_ABI == ABI_V4)
-		cfa_restores
-		  = alloc_reg_note (REG_CFA_RESTORE,
-				    gen_rtx_REG (SImode, CR2_REGNO),
-				    cfa_restores);
-	    }
-
-	  emit_jump_insn (par);
-
 	  /* We don't want anybody else emitting things after we jumped
 	     back.  */
 	  return;
 	}
 
-      insn = emit_insn (par);
       if (DEFAULT_ABI == ABI_V4)
 	{
 	  if (frame_pointer_needed)
@@ -21366,7 +21410,7 @@ rs6000_emit_epilogue (int sibcall)
       else
 	p = rtvec_alloc (2);
 
-      RTVEC_ELT (p, 0) = ret_rtx;
+      RTVEC_ELT (p, 0) = simple_return_rtx;
       RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
 			  ? gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 65))
 			  : gen_rtx_CLOBBER (VOIDmode,
@@ -21768,7 +21812,7 @@ rs6000_output_mi_thunk (FILE *file, tree
 			gen_rtx_USE (VOIDmode,
 				     gen_rtx_REG (SImode,
 						  LR_REGNO)),
-			ret_rtx)));
+			simple_return_rtx)));
   SIBLING_CALL_P (insn) = 1;
   emit_barrier ();
 
diff -urp -x.svn -x'*~' -x'*.orig' gcc-bernd/gcc/config/rs6000/altivec.md gcc-current/gcc/config/rs6000/altivec.md
--- gcc-bernd/gcc/config/rs6000/altivec.md	2011-09-16 11:52:15.000000000 +0930
+++ gcc-current/gcc/config/rs6000/altivec.md	2011-09-15 18:28:43.000000000 +0930
@@ -306,7 +306,7 @@
 
 (define_insn "*restore_world"
  [(match_parallel 0 "restore_world_operation"
-                  [(return)
+                  [(simple_return)
 		   (use (reg:SI 65))
                    (use (match_operand:SI 1 "call_operand" "s"))
                    (clobber (match_operand:SI 2 "gpc_reg_operand" "=r"))])]
diff -urp -x.svn -x'*~' -x'*.orig' gcc-bernd/gcc/config/rs6000/rs6000.md gcc-current/gcc/config/rs6000/rs6000.md
--- gcc-bernd/gcc/config/rs6000/rs6000.md	2011-09-16 11:52:15.000000000 +0930
+++ gcc-current/gcc/config/rs6000/rs6000.md	2011-09-16 11:32:31.000000000 +0930
@@ -264,6 +265,12 @@
 ; Iterator for just SF/DF
 (define_mode_iterator SFDF [SF DF])
 
+; Conditional returns.
+(define_code_iterator any_return [return simple_return])
+(define_code_attr return_pred [(return "direct_return ()")
+			       (simple_return "")])
+(define_code_attr return_str [(return "") (simple_return "simple_")])
+
 ; Various instructions that come in SI and DI forms.
 ; A generic w/d attribute, for things like cmpw/cmpd.
 (define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")])
@@ -12814,7 +12831,7 @@
 		    (match_operand 1 "" ""))
 	      (use (match_operand 2 "" ""))
 	      (use (reg:SI LR_REGNO))
-	      (return)])]
+	      (simple_return)])]
   ""
   "
 {
@@ -12838,7 +12855,7 @@
 	 (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
    (use (reg:SI LR_REGNO))
-   (return)]
+   (simple_return)]
   "(INTVAL (operands[2]) & CALL_LONG) == 0"
   "*
 {
@@ -12858,7 +12875,7 @@
 	 (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
    (use (reg:SI LR_REGNO))
-   (return)]
+   (simple_return)]
   "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
   "*
 {
@@ -12879,7 +12896,7 @@
 	      (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
    (use (reg:SI LR_REGNO))
-   (return)]
+   (simple_return)]
   "(INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
 {
@@ -12901,7 +12918,7 @@
 	      (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
    (use (reg:SI LR_REGNO))
-   (return)]
+   (simple_return)]
   "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
 {
@@ -12921,7 +12938,7 @@
 	 (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,O"))
    (use (reg:SI LR_REGNO))
-   (return)]
+   (simple_return)]
   "DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[2]) & CALL_LONG) == 0"
   "@
@@ -12936,7 +12953,7 @@
 	      (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,O"))
    (use (reg:SI LR_REGNO))
-   (return)]
+   (simple_return)]
   "DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[3]) & CALL_LONG) == 0"
   "@
@@ -12950,7 +12967,7 @@
 	 (match_operand 1 "" ""))
    (use (match_operand 2 "immediate_operand" "O,n,O,n"))
    (use (reg:SI LR_REGNO))
-   (return)]
+   (simple_return)]
   "(DEFAULT_ABI == ABI_DARWIN
     || DEFAULT_ABI == ABI_V4)
    && (INTVAL (operands[2]) & CALL_LONG) == 0"
@@ -12981,7 +12998,7 @@
 		      (match_operand 2 "" "")))
 	      (use (match_operand 3 "" ""))
 	      (use (reg:SI LR_REGNO))
-	      (return)])]
+	      (simple_return)])]
   ""
   "
 {
@@ -13002,7 +13019,7 @@
 	      (match_operand 2 "" "")))
    (use (match_operand:SI 3 "immediate_operand" "O,n,O,n"))
    (use (reg:SI LR_REGNO))
-   (return)]
+   (simple_return)]
   "(DEFAULT_ABI == ABI_DARWIN
     || DEFAULT_ABI == ABI_V4)
    && (INTVAL (operands[3]) & CALL_LONG) == 0"
@@ -15328,9 +15345,9 @@
 				      [(match_operand 1
 						      "cc_reg_operand" "y")
 				       (const_int 0)])
-		      (return)
+		      (any_return)
 		      (pc)))]
-  "direct_return ()"
+  "<return_pred>"
   "*
 {
   return output_cbranch (operands[0], NULL, 0, insn);
@@ -15360,8 +15377,8 @@
 						      "cc_reg_operand" "y")
 				       (const_int 0)])
 		      (pc)
-		      (return)))]
-  "direct_return ()"
+		      (any_return)))]
+  "<return_pred>"
   "*
 {
   return output_cbranch (operands[0], NULL, 1, insn);
@@ -15491,9 +15508,9 @@
   "b %l0"
   [(set_attr "type" "branch")])
 
-(define_insn "return"
-  [(return)]
-  "direct_return ()"
+(define_insn "<return_str>return"
+  [(any_return)]
+  "<return_pred>"
   "{br|blr}"
   [(set_attr "type" "jmpreg")])
 
@@ -16015,7 +16032,7 @@
    (set_attr "cell_micro" "always")])
 
 (define_insn "*return_internal_<mode>"
-  [(return)
+  [(simple_return)
    (use (match_operand:P 0 "register_operand" "lc"))]
   ""
   "b%T0"
@@ -16077,7 +16094,7 @@
 
 (define_insn "*return_and_restore_gpregs_<mode>_r11"
  [(match_parallel 0 "any_parallel_operand"
-                  [(return)
+                  [(simple_return)
 		   (clobber (match_operand:P 1 "register_operand" "=l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
                    (use (reg:P 11))
@@ -16090,7 +16107,7 @@
 
 (define_insn "*return_and_restore_gpregs_<mode>_r12"
  [(match_parallel 0 "any_parallel_operand"
-                  [(return)
+                  [(simple_return)
 		   (clobber (match_operand:P 1 "register_operand" "=l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
                    (use (reg:P 12))
@@ -16103,7 +16120,7 @@
 
 (define_insn "*return_and_restore_gpregs_<mode>_r1"
  [(match_parallel 0 "any_parallel_operand"
-                  [(return)
+                  [(simple_return)
 		   (clobber (match_operand:P 1 "register_operand" "=l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
                    (use (reg:P 1))
@@ -16116,7 +16133,7 @@
 
 (define_insn "*return_and_restore_fpregs_<mode>_r11"
  [(match_parallel 0 "any_parallel_operand"
-                  [(return)
+                  [(simple_return)
 		   (clobber (match_operand:P 1 "register_operand" "=l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
                    (use (reg:P 11))
@@ -16129,7 +16146,7 @@
 
 (define_insn "*return_and_restore_fpregs_<mode>_r12"
  [(match_parallel 0 "any_parallel_operand"
-                  [(return)
+                  [(simple_return)
 		   (clobber (match_operand:P 1 "register_operand" "=l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
                    (use (reg:P 12))
@@ -16142,7 +16159,7 @@
 
 (define_insn "*return_and_restore_fpregs_<mode>_r1"
  [(match_parallel 0 "any_parallel_operand"
-                  [(return)
+                  [(simple_return)
 		   (clobber (match_operand:P 1 "register_operand" "=l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
                    (use (reg:P 1))
@@ -16155,7 +16172,7 @@
 
 (define_insn "*return_and_restore_fpregs_aix_<mode>_r11"
  [(match_parallel 0 "any_parallel_operand"
-		  [(return)
+		  [(simple_return)
 		   (use (match_operand:P 1 "register_operand" "l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
 		   (use (reg:P 11))
@@ -16168,7 +16185,7 @@
 
 (define_insn "*return_and_restore_fpregs_aix_<mode>_r1"
  [(match_parallel 0 "any_parallel_operand"
-		  [(return)
+		  [(simple_return)
 		   (use (match_operand:P 1 "register_operand" "l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
 		   (use (reg:P 1))
diff -urp -x.svn -x'*~' -x'*.orig' gcc-bernd/gcc/config/rs6000/spe.md gcc-current/gcc/config/rs6000/spe.md
--- gcc-bernd/gcc/config/rs6000/spe.md	2011-09-16 11:52:15.000000000 +0930
+++ gcc-current/gcc/config/rs6000/spe.md	2011-09-15 18:28:43.000000000 +0930
@@ -3178,7 +3178,7 @@
 
 (define_insn "*return_and_restore_gpregs_spe"
  [(match_parallel 0 "any_parallel_operand"
-		  [(return)
+		  [(simple_return)
 		   (clobber (reg:P 65))
 		   (use (match_operand:P 1 "symbol_ref_operand" "s"))
 		   (use (reg:P 11))
