[PATCH 4/6] Shrink-wrapping

Richard Sandiford richard.sandiford@linaro.org
Wed Aug 3 15:39:00 GMT 2011


Bernd Schmidt <bernds@codesourcery.com> writes:
> +@findex simple_return
> +@item (simple_return)
> +Like @code{(return)}, but truly represents only a function return, while
> +@code{(return)} may represent an insn that also performs other functions
> +of the function epilogue.  Like @code{(return)}, this may also occur in
> +conditional jumps.

Sorry, I've forgotton the outcome of the discussion about what happens
on targets whose return expands to the same code as their simple_return.
Do the targets still need both "return" and "simple_return" rtxes?
Do they need both md patterns (but potentially using the same rtx
underneath)?

I ask because the rtl.def comment implies that those targets still
need both expanders and both rtxes.  If that's so, I think it needs
to be mentioned here too.  E.g. something like:

  Like @code{(return)}, but truly represents only a function return, while
  @code{(return)} may represent an insn that also performs other functions
  of the function epilogue.  @code{(return)} only occurs on paths that
  pass through the function prologue, while @code{(simple_return)}
  only occurs on paths that do not pass through the prologue.

  Like @code{(return)}, @code{(simple_return)} may also occur in
  conditional jumps.

You need to document the simple_return pattern in md.texi too.

> @@ -231,6 +234,15 @@ first_active_target_insn (rtx insn)
>    return next_active_insn (insn);
>  }
>  
> +/* Return true iff INSN is a simplejump, or any kind of return insn.  */
> +
> +static bool
> +simplejump_or_return_p (rtx insn)
> +{
> +  return (JUMP_P (insn)
> +	  && (simplejump_p (insn) || ANY_RETURN_P (PATTERN (insn))));
> +}

Maybe better in jump.c?  I'll leave it up to you though.

> @@ -346,23 +358,29 @@ insn_sets_resource_p (rtx insn, struct r
>  
>     ??? There may be a problem with the current implementation.  Suppose
>     we start with a bare RETURN insn and call find_end_label.  It may set
> -   end_of_function_label just before the RETURN.  Suppose the machinery
> +   function_return_label just before the RETURN.  Suppose the machinery
>     is able to fill the delay slot of the RETURN insn afterwards.  Then
> -   end_of_function_label is no longer valid according to the property
> +   function_return_label is no longer valid according to the property
>     described above and find_end_label will still return it unmodified.
>     Note that this is probably mitigated by the following observation:
> -   once end_of_function_label is made, it is very likely the target of
> +   once function_return_label is made, it is very likely the target of
>     a jump, so filling the delay slot of the RETURN will be much more
>     difficult.  */
>  
>  static rtx
> -find_end_label (void)
> +find_end_label (rtx kind)

Need to document the new parameter.

>  {
>    rtx insn;
> +  rtx *plabel;
> +
> +  if (kind == ret_rtx)
> +    plabel = &function_return_label;
> +  else
> +    plabel = &function_simple_return_label;

I think it'd be worth a gcc_checking_assert that ret == simple_return_rtx
in the other case.

> -	  /* Put the label before an USE insns that may proceed the
> +	  /* Put the label before an USE insns that may precede the
>  	     RETURN insn.  */

Might as well fix s/an USE/any USE/ too while you're there

> @@ -3498,6 +3506,8 @@ relax_delay_slots (rtx first)
>  	continue;
>  
>        target_label = JUMP_LABEL (delay_insn);
> +      if (target_label && ANY_RETURN_P (target_label))
> +	continue;
>  
>        if (!ANY_RETURN_P (target_label))
>  	{

This doesn't look like a pure "handle return as well as simple return"
change.  Is the idea that every following test only makes sense for
labels, and that things like:

	  && prev_active_insn (target_label) == insn

(to pick just one example) are actively dangerous for returns?
If so, I think you should remove the immediately-following.
"if (!ANY_RETURN_P (target_label))" condition and reindent the body.

> @@ -3737,13 +3753,27 @@ make_return_insns (rtx first)
>    for (insn = first; insn; insn = NEXT_INSN (insn))
>      {
>        int flags;
> +      rtx kind, real_label;
>  
>        /* Only look at filled JUMP_INSNs that go to the end of function
>  	 label.  */
>        if (!NONJUMP_INSN_P (insn)
>  	  || GET_CODE (PATTERN (insn)) != SEQUENCE
> -	  || !JUMP_P (XVECEXP (PATTERN (insn), 0, 0))
> -	  || JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0)) != end_of_function_label)
> +	  || !JUMP_P (XVECEXP (PATTERN (insn), 0, 0)))
> +	continue;
> +
> +      if (JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0)) == function_return_label)
> +	{
> +	  kind = ret_rtx;
> +	  real_label = real_return_label;
> +	}
> +      else if (JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0))
> +	       == function_simple_return_label)
> +	{
> +	  kind = simple_return_rtx;
> +	  real_label = real_simple_return_label;
> +	}
> +      else
>  	continue;
>  
>        pat = PATTERN (insn);

Given what you said about JUMP_LABEL sometimes being null,
I think we need either (a) to check whether each *_return_label
is null before comparing it with JUMP_LABEL, or (b) to ensure that
we're dealing with a jump to a label.  (b) seems neater IMO
(as a call to jump_to_label_p).

> +#if defined HAVE_return || defined HAVE_simple_return
> +  if (
>  #ifdef HAVE_return
> -  if (HAVE_return && end_of_function_label != 0)
> +      (HAVE_return && function_return_label != 0)
> +#else
> +      0
> +#endif
> +#ifdef HAVE_simple_return
> +      || (HAVE_simple_return && function_simple_return_label != 0)
> +#endif
> +      )
>      make_return_insns (first);
>  #endif

Eww.  Given that make_return_insns clears the *return_labels,
it's probably more readable just to have two conditional calls:

#ifdef HAVE_return
  if (HAVE_return && function_return_label != 0)
    make_return_insns (first);
#endif
#ifdef HAVE_simple_return
  if (HAVE_simple_return && function_simple_return_label != 0)
    make_return_insns (first);
#endif

I'll leave it up to you though.

> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c	(revision 176881)
> +++ gcc/emit-rtl.c	(working copy)
> @@ -2518,6 +2518,7 @@ verify_rtx_sharing (rtx orig, rtx insn)
>      case PC:
>      case CC0:
>      case RETURN:
> +    case SIMPLE_RETURN:
>      case SCRATCH:
>        return;
>        /* SCRATCH must be shared because they represent distinct values.  */

Given Alan's patch, I suppose you also need cases for copy_rtx_if_shared_1,
copy_insn_1 and mark_used_flags.  (Sorry about being wise after the fact here.)

> Index: gcc/config/mips/mips.md
> ===================================================================
> --- gcc/config/mips/mips.md	(revision 176879)
> +++ gcc/config/mips/mips.md	(working copy)
> @@ -5724,6 +5724,18 @@ (define_insn "*return"
>    [(set_attr "type"	"jump")
>     (set_attr "mode"	"none")])
>  
> +(define_expand "simple_return"
> +  [(simple_return)]
> +  "!mips_can_use_return_insn ()"
> +  { mips_expand_before_return (); })
> +
> +(define_insn "*simple_return"
> +  [(simple_return)]
> +  "!mips_can_use_return_insn ()"
> +  "%*j\t$31%/"
> +  [(set_attr "type"	"jump")
> +   (set_attr "mode"	"none")])
> +
>  ;; Normal return.
>  
>  (define_insn "return_internal"
> @@ -5731,6 +5743,14 @@ (define_insn "return_internal"
>     (use (match_operand 0 "pmode_register_operand" ""))]
>    ""
>    "%*j\t%0%/"
> +  [(set_attr "type"	"jump")
> +   (set_attr "mode"	"none")])
> +
> +(define_insn "simple_return_internal"
> +  [(simple_return)
> +   (use (match_operand 0 "pmode_register_operand" ""))]
> +  ""
> +  "%*j\t%0%/"
>    [(set_attr "type"	"jump")
>     (set_attr "mode"	"none")])

Please add:

(define_code_iterator any_return [return simple_return])

and just change the appropriate returns to any_returns.

The rtl and MIPS bits look good to me otherwise.

Richard



More information about the Gcc-patches mailing list