public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Hans-Peter Nilsson <hans-peter.nilsson@axis.com>
To: ebotcazou@libertysurf.fr
Cc: hans-peter.nilsson@axis.com, gcc-patches@gcc.gnu.org
Subject: Re: [RFA:] Split REG_LABEL into REG_LABEL_TARGET and REG_LABEL_OPERAND
Date: Thu, 13 Sep 2007 03:17:00 -0000	[thread overview]
Message-ID: <200709130203.l8D236jg010538@ignucius.se.axis.com> (raw)
In-Reply-To: <200709091100.37734.ebotcazou@libertysurf.fr> (message from Eric 	Botcazou on Sun, 9 Sep 2007 11:00:37 +0200)

> From: Eric Botcazou <ebotcazou@libertysurf.fr>
> Date: Sun, 9 Sep 2007 11:00:37 +0200

Sorry for not replying sooner.  Some of your questions warrant a
bit of an investigation (details no longer in the head-cache and
then there's the df impact) but here's a partial reply:

> > Index: gcc/reload.c
> > ===================================================================
> > --- gcc/reload.c	(revision 128285)
> > +++ gcc/reload.c	(working copy)
> > @@ -4103,13 +4103,18 @@ find_reloads (rtx insn, int replace, int
> >
> >  	  *recog_data.operand_loc[i] = substitution;
> >
> > -	  /* If we're replacing an operand with a LABEL_REF, we need
> > -	     to make sure that there's a REG_LABEL note attached to
> > +	  /* If we're replacing an operand with a LABEL_REF, we need to
> > +	     make sure that there's a REG_LABEL_OPERAND note attached to
> >  	     this instruction.  */
> > -	  if (!JUMP_P (insn)
> > -	      && GET_CODE (substitution) == LABEL_REF
> > -	      && !find_reg_note (insn, REG_LABEL, XEXP (substitution, 0)))
> > -	    REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
> > +	  if (GET_CODE (substitution) == LABEL_REF
> > +	      && !find_reg_note (insn, REG_LABEL_OPERAND,
> > +				 XEXP (substitution, 0))
> > +	      /* For a JUMP_P, if it was a branch target it must have
> > +		 already been recorded as such.  */
> > +	      && (!JUMP_P (insn)
> > +		  || !label_is_jump_target_p (XEXP (substitution, 0),
> > +					      insn)))
> > +	    REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND,
> >  						  XEXP (substitution, 0),
> >  						  REG_NOTES (insn));
> >  	}
> 
> You're not updating label_is_jump_target_p to take into account the operands 
> of REG_LABEL_TARGET notes, so can't you be creating REG_LABEL_OPERAND notes
> for them?

(I assume you mean s/can't/shouldn't/ and "REG_LABEL_TARGET
notes for them".  If not, please rephrase the question.)

To trig that case, a target is needed that can jump to more than
one location in the same insn (e.g. a conditional branch that
doesn't fall through) but which isn't a *simple* tablejump,
because otherwise label_is_jump_target_p fits as-is.  (Hm, the
CRIS "*casesi_adds_w" insn seems to match that somewhat; the
label for the jump-table is possibly dangling unless tablejumps
are explicitly handled... need to investigate.)

If there's a problem, the remedy would be to update
label_is_jump_target_p to be less simplified than its heading
says; to handle REG_LABEL_TARGET notes.  (I *think* code
elsewhere will fail for non-tablejump insns with more than one
branch target, but anyway consistency is a reason to update it.)

The code here just needs to cope with updating REG_LABEL_OPERAND
notes; labels that aren't trivially jumped to (see original,
"-"-marked code).  All REG_LABEL_TARGET notes are added long
before reload.

> > @@ -6123,17 +6128,15 @@ subst_reloads (rtx insn)
> >  	    }
> >  #endif /* DEBUG_RELOAD */
> >
> > -	  /* If we're replacing a LABEL_REF with a register, add a
> > -	     REG_LABEL note to indicate to flow which label this
> > +	  /* If we're replacing a LABEL_REF with a register, there must
> > +	     already be an indication (to e.g. flow) which label this
> >  	     register refers to.  */
> > -	  if (GET_CODE (*r->where) == LABEL_REF
> > -	      && JUMP_P (insn))
> > -	    {
> > -	      REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
> > -						    XEXP (*r->where, 0),
> > -						    REG_NOTES (insn));
> > -	      JUMP_LABEL (insn) = XEXP (*r->where, 0);
> > -	   }
> > +	  gcc_assert (GET_CODE (*r->where) != LABEL_REF
> > +		      || !JUMP_P (insn)
> > +		      || find_reg_note (insn,
> > +					REG_LABEL_OPERAND,
> > +					XEXP (*r->where, 0))
> > +		      || label_is_jump_target_p (XEXP (*r->where, 0), insn));
> >
> >  	  /* Encapsulate RELOADREG so its machine mode matches what
> >  	     used to be there.  Note that gen_lowpart_common will
> 
> Same question: what about operands of REG_LABEL_TARGET notes?

They've already been generated when we come to reload; for a
simple un/conditional jump the label sticks to the JUMP_LABEL
field.  The semantics are changed to be sticky, so they don't
need to be added again.  Note the old code adding them to both
the JUMP_LABEL field and as a REG_LABEL note!

(For this code and the one above; since you have to ask, this
code needs a comment to the effect of my reply.)

> > @@ -2736,14 +2737,40 @@ fill_slots_from_thread (rtx insn, rtx co
> >  		      /* We are moving this insn, not deleting it.  We must
> >  			 temporarily increment the use count on any referenced
> >  			 label lest it be deleted by delete_related_insns.  */
> > -		      note = find_reg_note (trial, REG_LABEL, 0);
> > -		      /* REG_LABEL could be NOTE_INSN_DELETED_LABEL too.  */
> > -		      if (note && LABEL_P (XEXP (note, 0)))
> > +		      for (note = REG_NOTES (trial);
> > +			   note != NULL;
> > +			   note = XEXP (note, 1))
> > +			if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
> > +			    || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
> > +			  {
> > +			    /* REG_LABEL_OPERAND could be
> > +			       NOTE_INSN_DELETED_LABEL too.  */
> > +			    if (LABEL_P (XEXP (note, 0)))
> > +			      LABEL_NUSES (XEXP (note, 0))++;
> > +			    else
> > +			      gcc_assert (REG_NOTE_KIND (note)
> > +					  == REG_LABEL_OPERAND);
> > +			  }
> > +		      if (JUMP_P (trial) && JUMP_LABEL (trial))
> >  			LABEL_NUSES (XEXP (note, 0))++;
> 
> AFAICS note == NULL at this point (and it should be NULL_RTX instead of NULL).
> ...
> Likewise.

Yes... typo: they should just move inside the closing bracket on
the previous line.  I'm curious this didn't trig a SEGV in my
testing.  Investigating.

> >  static int
> >  check_for_label_ref (rtx *rtl, void *data)
> >  {
> >    rtx insn = (rtx) data;
> >
> > -  /* If this insn uses a LABEL_REF and there isn't a REG_LABEL note for
> > it, -     we must rerun jump since it needs to place the note.  If this is
> > a -     LABEL_REF for a CODE_LABEL that isn't in the insn chain, don't do
> > this -     since no REG_LABEL will be added.  */
> > +  /* If this insn uses a LABEL_REF and there isn't a REG_LABEL_OPERAND
> > +     note for it, we must rerun jump since it needs to place the note.  If
> > +     this is a LABEL_REF for a CODE_LABEL that isn't in the insn chain,
> > +     don't do this since no REG_LABEL_OPERAND will be added.  */
> >    return (GET_CODE (*rtl) == LABEL_REF
> >  	  && ! LABEL_REF_NONLOCAL_P (*rtl)
> > +	  && (!JUMP_P (insn)
> > +	      || !label_is_jump_target_p (XEXP (*rtl, 0), insn))
> >  	  && LABEL_P (XEXP (*rtl, 0))
> >  	  && INSN_UID (XEXP (*rtl, 0)) != 0
> > -	  && ! find_reg_note (insn, REG_LABEL, XEXP (*rtl, 0)));
> > +	  && ! find_reg_note (insn, REG_LABEL_OPERAND, XEXP (*rtl, 0)));
> 
> What about operands of REG_LABEL_TARGET notes?

They aren't supposed to (must not) be handled here.  This code
is only for REG_LABEL_OPERAND notes needing to be updated;
non-jump-insns moved around without notes being updated.  Same
comment about label_is_jump_target_p maybe being too simple
applies.  (Since you have to ask, this function needs a comment
to this effect.)

> > @@ -172,34 +186,69 @@ static void
> >  mark_all_labels (rtx f)
> >  {
> >    rtx insn;
> > +  rtx prev_nonjump_insn = NULL;
> >
> >    for (insn = f; insn; insn = NEXT_INSN (insn))
> >      if (INSN_P (insn))
> >        {
> >  	mark_jump_label (PATTERN (insn), insn, 0);
> > -	if (! INSN_DELETED_P (insn) && JUMP_P (insn))
> > +
> > +	/* If the previous non-jump insn sets something to a label,
> > +	   something that this jump insn uses, make that label the primary
> > +	   target of this insn if we don't yet have any.  That previous
> > +	   insn must be a single_set and not refer to more than one label.
> > +	   The jump insn must not refer to other labels as jump targets
> > +	   and must be a plain (set (pc) ...), maybe in a parallel, and
> > +	   may refer to the item being set only directly or as one of the
> > +	   arms in an IF_THEN_ELSE.  */
> > +	if (! INSN_DELETED_P (insn)
> > +	    && JUMP_P (insn)
> > +	    && JUMP_LABEL (insn) == NULL)
> 
> Why do you need to do this?  Is it an optimization?

It's the core machinery for targets with branch-target
registers, to have the label recorded as a branch target before
further optimizations moves the set and use of that register
apart.  Otherwise, those branches will all be treated as
computed jumps.  Hm, we'll still have the REG_LABEL_OPERAND note
on the register load, but then again, so we did before too.
I'll check that this still happens and add a comment actually
mentioning "branch-target register"!

> 
> > @@ -976,17 +1050,21 @@ mark_jump_label (rtx x, rtx insn, int in
> >
> >  	if (insn)
> >  	  {
> > -	    if (JUMP_P (insn))
> > +	    if (is_target
> > +		&& (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == label))
> >  	      JUMP_LABEL (insn) = label;
> 
> Please add a small comment, one can easily think there is a typo in the second 
> part of the disjunction: JUMP_LABEL (insn) != label.

Will do.

> > @@ -4608,10 +4609,18 @@ add_label_notes (rtx x, rtx insn)
> >  	 We no longer ignore such label references (see LABEL_REF handling in
> >  	 mark_jump_label for additional information).  */
> >
> > -      REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0),
> > -					    REG_NOTES (insn));
> > -      if (LABEL_P (XEXP (x, 0)))
> > -	LABEL_NUSES (XEXP (x, 0))++;
> > +	if (reg_mentioned_p (XEXP (x, 0), insn))
> > +	  {
> > +	    /* There's no reason for current users to emit jump-insns
> > +	       with such a LABEL_REF, so we don't have to handle
> > +	       REG_LABEL_TARGET notes.  */
> > +	    gcc_assert (!JUMP_P (insn));
> > +	    REG_NOTES (insn)
> > +	      = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, XEXP (x, 0),
> > +				   REG_NOTES (insn));
> > +	    if (LABEL_P (XEXP (x, 0)))
> > +	      LABEL_NUSES (XEXP (x, 0))++;
> > +	  }
> >        return;
> >      }
> 
> "Put in line with jump.c copy by only adding notes for labels actually 
> referenced in the insn" but AFAICS mark_jump_label doesn't do that.

Uhm, it does; it iterates on the insn, and when it finds
LABEL_REFs, it adds unique REG_LABEL_OPERAND notes (and sets the
JUMP_LABEL field and emits REG_LABEL_TARGET notes, but they
weren't the issue here).  It no longer emit duplicates.
Rephrase suggested?  Perhaps just "Make sure not to add
duplicate REG_LABEL_OPERAND notes" and referring to consistency
by adding a comment in the add_label_notes code?

> > Index: gcc/sched-rgn.c
> > ===================================================================
> > --- gcc/sched-rgn.c	(revision 128285)
> > +++ gcc/sched-rgn.c	(working copy)
> > @@ -315,24 +315,20 @@ is_cfg_nonregular (void)
> >    if (current_function_has_exception_handlers ())
> >      return 1;
> >
> > -  /* If we have non-jumping insns which refer to labels, then we consider
> > -     the cfg not well structured.  */
> > +  /* If we have insns which refer to labels as non-jumped-to operands,
> > +     then we consider the cfg not well structured.  */
> >    FOR_EACH_BB (b)
> >      FOR_BB_INSNS (b, insn)
> >        {
> > -	/* Check for labels referred by non-jump insns.  */
> > -	if (NONJUMP_INSN_P (insn) || CALL_P (insn))
> > -	  {
> > -	    rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
> > -	    if (note
> > -		&& ! (JUMP_P (NEXT_INSN (insn))
> > -		      && find_reg_note (NEXT_INSN (insn), REG_LABEL,
> > -					XEXP (note, 0))))
> > -	      return 1;
> > -	  }
> > +	/* Check for labels referred to but (at least not directly) as
> > +	   jump targets.  */
> > +	if (INSN_P (insn)
> > +	    && find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX))
> > +	  return 1;
> > +
> >  	/* If this function has a computed jump, then we consider the cfg
> >  	   not well structured.  */
> > -	else if (JUMP_P (insn) && computed_jump_p (insn))
> > +	if (JUMP_P (insn) && computed_jump_p (insn))
> >  	  return 1;
> >        }
> 
> Why did you drop the check on NEXT_INSN altogether?

Because that old code was sloppily only trying to deal with the
immediately consecutive (no notes or anything in-between!) insn
pair (set branch-target-reg label) (set pc branch-target-reg) as
a non-computed jump (the whole REG_LABEL ambiguity).  Hm, the
new code will still have a REG_LABEL_OPERAND on the (set
branch-target-reg label) so that'll always be seen as
is_cfg_nonregular.  Will investigate the impact and how to merge
identifiable set/jump pairs as non-computed.  I hope REG_DEAD
notes are present here...

brgds, H-P

  reply	other threads:[~2007-09-13  2:03 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-01-30 20:54 Hans-Peter Nilsson
2006-01-30 21:31 ` Hans-Peter Nilsson
2006-01-30 22:18 ` Hans-Peter Nilsson
2006-02-25  0:05 ` Geoffrey Keating
2007-09-04  5:12 ` [RFA:] " Hans-Peter Nilsson
2007-09-09  7:13   ` Hans-Peter Nilsson
2007-09-09 10:47     ` Eric Botcazou
2007-09-13  3:17       ` Hans-Peter Nilsson [this message]
2007-09-13 13:15         ` Eric Botcazou
2007-11-14  0:24       ` Hans-Peter Nilsson
2007-11-24 21:12         ` Eric Botcazou
2007-11-15 12:14       ` Hans-Peter Nilsson
2007-11-24 21:16         ` Eric Botcazou

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200709130203.l8D236jg010538@ignucius.se.axis.com \
    --to=hans-peter.nilsson@axis.com \
    --cc=ebotcazou@libertysurf.fr \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).