diff mbox

rs6000: Don't emit a use of LR in returns and sibcalls

Message ID b33256897aafbb42be342fd3603065456127a80f.1472548635.git.segher@kernel.crashing.org
State New
Headers show

Commit Message

Segher Boessenkool Aug. 30, 2016, 11:17 a.m. UTC
The exit block (to which every return artificially jumps) already has
a use of LR.  The LR use in all returns and sibcalls is an anachronism,
probably made unnecessary by the dataflow merge.  The simple_returns
that shrink-wrapping generates also do not have such a use.  Newer
backends do not do this either it seems.

With this use removed, a normal return is no longer a parallel but just
a return insn, and cfgcleanup then can transform conditional jumps to
those into conditional returns.

This splits the return emission code with restoring_FPRs_inline from
that without it; this is simpler code, fewer lines, and less indentation.

The return_internal_<mode> pattern can now be deleted since nothing uses
it anymore.

Tested on powerpc64-linux (-m32,-m64); will test on powerpc64le-linux
as well.  David and Iain, can you please test on AIX and Darwin?

Or is this okay for trunk without testing?  ;-)


Segher


2016-08-30  Segher Boessenkool  <segher@kernel.crashing.org>

	* config/rs6000/rs6000.c (rs6000_emit_epilogue): Do not emit
	USEs of LR_REGNO in returns and sibcalls.
	(rs6000_output_mi_thunk): Similar.
	(rs6000_sibcall_aix): Similar.
	* config/rs6000/rs6000.md (sibcall, sibcall_value, sibcall_local32,
	sibcall_local64, sibcall_value_local32, sibcall_value_local64,
	sibcall_nonlocal_sysv<mode>, sibcall_value_nonlocal_sysv<mode>):
	Remove the USE of LR_REGNO from the patterns as well.  Delete an
	obsolete comment.
	(return_internal_<mode>): Delete.

---
 gcc/config/rs6000/rs6000.c  | 122 ++++++++++++++++++--------------------------
 gcc/config/rs6000/rs6000.md |  19 -------
 2 files changed, 51 insertions(+), 90 deletions(-)

Comments

David Edelsohn Aug. 30, 2016, 1 p.m. UTC | #1
On Tue, Aug 30, 2016 at 7:17 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> The exit block (to which every return artificially jumps) already has
> a use of LR.  The LR use in all returns and sibcalls is an anachronism,
> probably made unnecessary by the dataflow merge.  The simple_returns
> that shrink-wrapping generates also do not have such a use.  Newer
> backends do not do this either it seems.
>
> With this use removed, a normal return is no longer a parallel but just
> a return insn, and cfgcleanup then can transform conditional jumps to
> those into conditional returns.
>
> This splits the return emission code with restoring_FPRs_inline from
> that without it; this is simpler code, fewer lines, and less indentation.
>
> The return_internal_<mode> pattern can now be deleted since nothing uses
> it anymore.
>
> Tested on powerpc64-linux (-m32,-m64); will test on powerpc64le-linux
> as well.  David and Iain, can you please test on AIX and Darwin?
>
> Or is this okay for trunk without testing?  ;-)
>
>
> Segher
>
>
> 2016-08-30  Segher Boessenkool  <segher@kernel.crashing.org>
>
>         * config/rs6000/rs6000.c (rs6000_emit_epilogue): Do not emit
>         USEs of LR_REGNO in returns and sibcalls.
>         (rs6000_output_mi_thunk): Similar.
>         (rs6000_sibcall_aix): Similar.
>         * config/rs6000/rs6000.md (sibcall, sibcall_value, sibcall_local32,
>         sibcall_local64, sibcall_value_local32, sibcall_value_local64,
>         sibcall_nonlocal_sysv<mode>, sibcall_value_nonlocal_sysv<mode>):
>         Remove the USE of LR_REGNO from the patterns as well.  Delete an
>         obsolete comment.
>         (return_internal_<mode>): Delete.

This is okay.

PPC64 BE Linux uses ABI_AIX, so that AIX logic should be okay.

Thanks, David
diff mbox

Patch

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 4de70ea..2f15a05 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -28277,7 +28277,6 @@  rs6000_emit_epilogue (int sibcall)
 	 longer necessary.  */
 
       p = rtvec_alloc (9
-		       + 1
 		       + 32 - info->first_gp_reg_save
 		       + LAST_ALTIVEC_REGNO + 1 - info->first_altivec_reg_save
 		       + 63 + 1 - info->first_fp_reg_save);
@@ -28288,9 +28287,6 @@  rs6000_emit_epilogue (int sibcall)
 
       j = 0;
       RTVEC_ELT (p, j++) = ret_rtx;
-      RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
-					gen_rtx_REG (Pmode,
-						     LR_REGNO));
       RTVEC_ELT (p, j++)
 	= gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, alloc_rname));
       /* The instruction pattern requires a clobber here;
@@ -29013,73 +29009,63 @@  rs6000_emit_epilogue (int sibcall)
       emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa));
     }
 
-  if (!sibcall)
+  if (!sibcall && restoring_FPRs_inline)
+    {
+      if (cfa_restores)
+	{
+	  /* We can't hang the cfa_restores off a simple return,
+	     since the shrink-wrap code sometimes uses an existing
+	     return.  This means there might be a path from
+	     pre-prologue code to this return, and dwarf2cfi code
+	     wants the eh_frame unwinder state to be the same on
+	     all paths to any point.  So we need to emit the
+	     cfa_restores before the return.  For -m64 we really
+	     don't need epilogue cfa_restores at all, except for
+	     this irritating dwarf2cfi with shrink-wrap
+	     requirement;  The stack red-zone means eh_frame info
+	     from the prologue telling the unwinder to restore
+	     from the stack is perfectly good right to the end of
+	     the function.  */
+	  emit_insn (gen_blockage ());
+	  emit_cfa_restores (cfa_restores);
+	  cfa_restores = NULL_RTX;
+	}
+
+      emit_jump_insn (targetm.gen_simple_return ());
+    }
+
+  if (!sibcall && !restoring_FPRs_inline)
     {
-      rtvec p;
       bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
-      if (! restoring_FPRs_inline)
-	{
-	  p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
-	  RTVEC_ELT (p, 0) = ret_rtx;
-	}
-      else
-	{
-	  if (cfa_restores)
-	    {
-	      /* We can't hang the cfa_restores off a simple return,
-		 since the shrink-wrap code sometimes uses an existing
-		 return.  This means there might be a path from
-		 pre-prologue code to this return, and dwarf2cfi code
-		 wants the eh_frame unwinder state to be the same on
-		 all paths to any point.  So we need to emit the
-		 cfa_restores before the return.  For -m64 we really
-		 don't need epilogue cfa_restores at all, except for
-		 this irritating dwarf2cfi with shrink-wrap
-		 requirement;  The stack red-zone means eh_frame info
-		 from the prologue telling the unwinder to restore
-		 from the stack is perfectly good right to the end of
-		 the function.  */
-	      emit_insn (gen_blockage ());
-	      emit_cfa_restores (cfa_restores);
-	      cfa_restores = NULL_RTX;
-	    }
-	  p = rtvec_alloc (2);
-	  RTVEC_ELT (p, 0) = simple_return_rtx;
-	}
+      rtvec p = rtvec_alloc (3 + !!lr + 64 - info->first_fp_reg_save);
+      int elt = 0;
+      RTVEC_ELT (p, elt++) = ret_rtx;
+      if (lr)
+	RTVEC_ELT (p, elt++)
+	  = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
 
-      RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
-			  ? gen_rtx_USE (VOIDmode,
-					 gen_rtx_REG (Pmode, LR_REGNO))
-			  : gen_rtx_CLOBBER (VOIDmode,
-					     gen_rtx_REG (Pmode, LR_REGNO)));
-
-      /* If we have to restore more than two FP registers, branch to the
+      /* We have to restore more than two FP registers, so branch to the
 	 restore function.  It will return to our caller.  */
-      if (! restoring_FPRs_inline)
+      int i;
+      int reg;
+      rtx sym;
+
+      if (flag_shrink_wrap)
+	cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
+
+      sym = rs6000_savres_routine_sym (info, SAVRES_FPR | (lr ? SAVRES_LR : 0));
+      RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, sym);
+      reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
+      RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
+
+      for (i = 0; i < 64 - info->first_fp_reg_save; i++)
 	{
-	  int i;
-	  int reg;
-	  rtx sym;
+	  rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
 
+	  RTVEC_ELT (p, elt++)
+	    = gen_frame_load (reg, sp_reg_rtx, info->fp_save_offset + 8 * i);
 	  if (flag_shrink_wrap)
-	    cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
-
-	  sym = rs6000_savres_routine_sym (info,
-					   SAVRES_FPR | (lr ? SAVRES_LR : 0));
-	  RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode, sym);
-	  reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
-	  RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
-
-	  for (i = 0; i < 64 - info->first_fp_reg_save; i++)
-	    {
-	      rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
-
-	      RTVEC_ELT (p, i + 4)
-		= gen_frame_load (reg, sp_reg_rtx, info->fp_save_offset + 8 * i);
-	      if (flag_shrink_wrap)
-		cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
-					       cfa_restores);
-	    }
+	    cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
 	}
 
       emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
@@ -29667,13 +29653,10 @@  rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
      generate sibcall RTL explicitly.  */
   insn = emit_call_insn (
 	   gen_rtx_PARALLEL (VOIDmode,
-	     gen_rtvec (4,
+	     gen_rtvec (3,
 			gen_rtx_CALL (VOIDmode,
 				      funexp, const0_rtx),
 			gen_rtx_USE (VOIDmode, const0_rtx),
-			gen_rtx_USE (VOIDmode,
-				     gen_rtx_REG (SImode,
-						  LR_REGNO)),
 			simple_return_rtx)));
   SIBLING_CALL_P (insn) = 1;
   emit_barrier ();
@@ -37578,9 +37561,6 @@  rs6000_sibcall_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
 
   /* Note use of the TOC register.  */
   use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, TOC_REGNUM));
-  /* We need to also mark a use of the link register since the function we
-     sibling-call to will use it to return to our caller.  */
-  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, LR_REGNO));
 }
 
 /* Return whether we need to always update the saved TOC pointer when we update
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index df75dc2..560cf1f 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10523,7 +10523,6 @@  (define_expand "sibcall"
   [(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
 		    (match_operand 1 "" ""))
 	      (use (match_operand 2 "" ""))
-	      (use (reg:SI LR_REGNO))
 	      (simple_return)])]
   ""
   "
@@ -10550,7 +10549,6 @@  (define_expand "sibcall_value"
 		(call (mem:SI (match_operand 1 "address_operand" ""))
 		      (match_operand 2 "" "")))
 	      (use (match_operand 3 "" ""))
-	      (use (reg:SI LR_REGNO))
 	      (simple_return)])]
   ""
   "
@@ -10572,15 +10570,10 @@  (define_expand "sibcall_value"
     }
 }")
 
-;; this and similar patterns must be marked as using LR, otherwise
-;; dataflow will try to delete the store into it.  This is true
-;; even when the actual reg to jump to is in CTR, when LR was
-;; saved and restored around the PIC-setting BCL.
 (define_insn "*sibcall_local32"
   [(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
 	 (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (use (reg:SI LR_REGNO))
    (simple_return)]
   "(INTVAL (operands[2]) & CALL_LONG) == 0"
   "*
@@ -10600,7 +10593,6 @@  (define_insn "*sibcall_local64"
   [(call (mem:SI (match_operand:DI 0 "current_file_function_operand" "s,s"))
 	 (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (use (reg:SI LR_REGNO))
    (simple_return)]
   "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
   "*
@@ -10621,7 +10613,6 @@  (define_insn "*sibcall_value_local32"
 	(call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
 	      (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (use (reg:SI LR_REGNO))
    (simple_return)]
   "(INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
@@ -10642,7 +10633,6 @@  (define_insn "*sibcall_value_local64"
 	(call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
 	      (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (use (reg:SI LR_REGNO))
    (simple_return)]
   "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
@@ -10662,7 +10652,6 @@  (define_insn "*sibcall_nonlocal_sysv<mode>"
   [(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c"))
 	 (match_operand 1 "" ""))
    (use (match_operand 2 "immediate_operand" "O,n,O,n"))
-   (use (reg:SI LR_REGNO))
    (simple_return)]
   "(DEFAULT_ABI == ABI_DARWIN
     || DEFAULT_ABI == ABI_V4)
@@ -10693,7 +10682,6 @@  (define_insn "*sibcall_value_nonlocal_sysv<mode>"
 	(call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c"))
 	      (match_operand 2 "" "")))
    (use (match_operand:SI 3 "immediate_operand" "O,n,O,n"))
-   (use (reg:SI LR_REGNO))
    (simple_return)]
   "(DEFAULT_ABI == ABI_DARWIN
     || DEFAULT_ABI == ABI_V4)
@@ -12612,13 +12600,6 @@  (define_insn "*lmw"
    (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")])
 
-(define_insn "*return_internal_<mode>"
-  [(simple_return)
-   (use (match_operand:P 0 "register_operand" "lc"))]
-  ""
-  "b%T0"
-  [(set_attr "type" "jmpreg")])
-
 ; FIXME: This would probably be somewhat simpler if the Cygnus sibcall
 ; stuff was in GCC.  Oh, and "any_parallel_operand" is a bit flexible...