Bernd Schmidt <ber...@codesourcery.com> writes:
> On 07/07/11 16:34, Richard Sandiford wrote:
>> Is JUMP_LABEL ever null after this change?  (In fully-complete rtl
>> sequences, I mean.)  It looked like some of the null checks in the
>> patch might not be necessary any more.
>
> It turns out that computed jumps can have a NULL JUMP_LABEL, and so can
> JUMP_INSNs holding ADDR_VECs.

Bleh.  Thanks for checking.

> +/* A wrapper around next_active_insn which takes care to return ret_rtx
> +   unchanged.  */
> +
> +static rtx
> +active_insn_after (rtx insn)
> +{
> +  if (ANY_RETURN_P (insn))
> +    return insn;
> +  return next_active_insn (insn);
> +}

The name "active_insn_after" seems a bit too similar to "next_active_insn"
for the difference to be obvious.  How about something like
"first_active_target_insn" instead?

It wasn't clear to me whether this should return null instead of "insn"
for the ANY_RETURN_P code.  In things like:

     insn_at_target = active_insn_after (target_label);

it introduces a new "INSN_P or RETURN" rtx choice, rather than the
"label or RETURN" choice seen in JUMP_LABELs.  So it might seem at a
glance that PATTERN could be directly applied to a nonnull insn_at_target,
whereas you actually need to test ANY_RETURN_P first.

But the existing code seems inconsistent.  Sometimes it passes
JUMP_LABELs directly to functions like own_thread_p, whereas sometimes
it passes the first active insn instead.  So if you returned null here,
you'd probably have three-way "null or RETURN or LABEL" checks where you
otherwise wouldn't.

All in all, I agree it's probably better this way.

> @@ -921,7 +933,7 @@ rare_destination (rtx insn)
>    int jump_count = 0;
>    rtx next;
>  
> -  for (; insn; insn = next)
> +  for (; insn && !ANY_RETURN_P (insn); insn = next)
>      {
>        if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
>       insn = XVECEXP (PATTERN (insn), 0, 0);

Since ANY_RETURN looks for patterns, while this loop iterates over insns,
I think it'd be more obvious to have:

  if (insn && ANY_RETURN_P (insn))
    return 1;

above the loop instead, as you did in follow_jumps and
skip_consecutive_labels.

> Index: gcc/jump.c
> ===================================================================
> --- gcc/jump.c        (revision 176230)
> +++ gcc/jump.c        (working copy)
> @@ -1217,7 +1217,7 @@ delete_related_insns (rtx insn)
>    /* If deleting a jump, decrement the count of the label,
>       and delete the label if it is now unused.  */
>  
> -  if (JUMP_P (insn) && JUMP_LABEL (insn))
> +  if (JUMP_P (insn) && !ANY_RETURN_P (JUMP_LABEL (insn)))
>      {
>        rtx lab = JUMP_LABEL (insn), lab_next;
>  

Given what you said above, and given that this is a public function,
I think we should keep the null check.

This pattern came up in reorg.c too, so maybe it would be worth having
a jump_to_label_p inline function somewhere, such as:

static bool
jump_to_label_p (rtx insn)
{
  return JUMP_P (insn) && JUMP_LABEL (insn) && LABEL_P (JUMP_LABEL (insn));
}

And maybe also:

static rtx
jump_target_insn (rtx insn)
{
  return jump_to_label_p (insn) ? JUMP_LABEL (insn) : NULL_RTX;
}

It might help avoid the sprinkling of ANY_RETURN_Ps.  Just a suggestion
though, not going to insist.

>  /* Throughout LOC, redirect OLABEL to NLABEL.  Treat null OLABEL or
>     NLABEL as a return.  Accrue modifications into the change group.  */
>  
> @@ -1359,37 +1371,19 @@ redirect_exp_1 (rtx *loc, rtx olabel, rt
>    int i;
>    const char *fmt;
>  
> -  if (code == LABEL_REF)
> -    {
> -      if (XEXP (x, 0) == olabel)
> -     {
> -       rtx n;
> -       if (nlabel)
> -         n = gen_rtx_LABEL_REF (Pmode, nlabel);
> -       else
> -         n = ret_rtx;
> -
> -       validate_change (insn, loc, n, 1);
> -       return;
> -     }
> -    }
> -  else if (code == RETURN && olabel == 0)
> +  if ((code == LABEL_REF && XEXP (x, 0) == olabel)
> +      || x == olabel)
>      {
> -      if (nlabel)
> -     x = gen_rtx_LABEL_REF (Pmode, nlabel);
> -      else
> -     x = ret_rtx;
> -      if (loc == &PATTERN (insn))
> -     x = gen_rtx_SET (VOIDmode, pc_rtx, x);
> -      validate_change (insn, loc, x, 1);
> +      validate_change (insn, loc, redirect_target (nlabel), 1);
>        return;

It looks like the old code tried to allow returns to be redirected
to a label -- (return) to (set (pc) (label_ref)) -- whereas the new
code doesn't.  (Then again, it looks like the old code would create
(set (pc) (return)) when "redirecting" a return to a return.
That doesn't seem like a good idea, and it ought to be dead
anyway with the olabel == nlabel shortcuts.)

How about:

      x = redirect_target (nlabel);
      if (GET_CODE (x) == LABEL_REF && loc == &PATTERN (insn))
        x = gen_rtx_SET (VOIDmode, pc_rtx, x);
      validate_change (insn, loc, x, 1);

I realise this doesn't help for PARALLELs though (just as it didn't
for the old code).

> @@ -4126,6 +4129,18 @@ dead_or_predicable (basic_block test_bb,
>      }
>  
>   no_body:
> +  if (JUMP_P (BB_END (dest_edge->src)))
> +    new_dest_label = JUMP_LABEL (BB_END (dest_edge->src));
> +  else if (other_bb != new_dest)
> +    {
> +      if (new_dest == EXIT_BLOCK_PTR)
> +     new_dest_label = ret_rtx;
> +      else
> +     new_dest_label = block_label (new_dest);
> +    }
> +  else
> +    new_dest_label = NULL_RTX;
> +

I found the placement of this code a bit confusing as things stand.
new_dest_label is only meaningful if other_bb != new_dest, so it seemed
like something that should directly replace the existing new_label
assignment.  It's OK if it makes the shrink-wrap stuff easier though.

> @@ -1195,6 +1195,9 @@ duplicate_insn_chain (rtx from, rtx to)
>             break;
>           }
>         copy = emit_copy_of_insn_after (insn, get_last_insn ());
> +       if (JUMP_P (insn) && JUMP_LABEL (insn) != NULL_RTX
> +           && ANY_RETURN_P (JUMP_LABEL (insn)))
> +         JUMP_LABEL (copy) = JUMP_LABEL (insn);

I think this should go in emit_copy_of_insn_after instead.

> @@ -2294,6 +2294,8 @@ create_cfi_notes (void)
>         dwarf2out_frame_debug (insn, false);
>         continue;
>       }
> +      if (GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC)
> +     continue;
>  
>        if (GET_CODE (pat) == SEQUENCE)
>       {

rth better approve this bit...

Looks good to me otherwise.

Richard

Reply via email to