OSDN Git Service

Divide REG_LABEL notes into REG_LABEL_OPERAND and REG_LABEL_TARGET.
authorhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Sep 2007 04:41:58 +0000 (04:41 +0000)
committerhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Sep 2007 04:41:58 +0000 (04:41 +0000)
* doc/rtl.texi (Insns): Specify when a label_ref makes a jump_insn.
Similar for what label_refs can go in the JUMP_TARGET field.  Split
REG_LABEL documentation into REG_LABEL_TARGET and REG_LABEL_OPERAND.
* reload.c (find_reloads): Generate REG_LABEL_OPERAND, not
REG_LABEL when replacing an operand with a LABEL_REF for a
non-jump insn.
(subst_reloads): When replacing a LABEL_REG with a register,
instead of generating a REG_LABEL note, assert that there already
is one or that the label is a known target for the insn.
* rtlanal.c (computed_jump_p): Instead of looking for a REG_LABEL
note, check the JUMP_LABEL field.  Remove "else" after return.
* reorg.c (emit_delay_sequence): Replace case for REG_LABEL with
cases for REG_LABEL_OPERAND and REG_LABEL_TARGET.
(fill_slots_from_thread): Handle both REG_LABEL_OPERAND and
REG_LABEL_TARGET notes, including the JUMP_TARGET field on JUMP_P
insns.  Iterate over all notes; don't assume there's only one.
* cse.c (recorded_label_ref): Adjust comment to refer to
REG_LABEL_OPERAND.
(cse_extended_basic_block): Do LABEL_REF check for all INSN_P
insns, not just NONJUMP_INSN_P.
(check_for_label_ref): For JUMP_P insns, check that the LABEL_REF
isn't a jump target.
* jump.c (rebuild_jump_labels): Adjust head comment.
(init_label_info): Ditto.  Remove REG_LABEL_OPERAND notes only;
don't reset REG_LABEL_TARGET notes, including the JUMP_LABEL field.
(mark_all_labels): For JUMP_P insns without a target, check if the
the target is noted on the previous nonjump insn.
(mark_jump_label_1): New function, guts from mark_jump_label.
<case IF_THEN_ELSE>: Handle first operand as a non-target when
marking jump target labels.
<case LABEL_REF>: Adjust for whether to generate a
REG_LABEL_TARGET or a REG_LABEL_OPERAND note.
For 'E' format rtl, iterate in descending element order.
(delete_related_insns): Handle both REG_LABEL_TARGET and
REG_LABEL_OPERAND notes.  For JUMP_P insns with labels with zero
reference count, delete and fallthrough.  Move finding-next-
non-deleted insn last in the function.  Look at all INSN_P insns
for REG_LABEL_OPERAND notes.
(redirect_jump_2): Assert that OLABEL equals the old JUMP_LABEL of
JUMP.
* print-rtl.c (print_rtx): For JUMP_P insns and a non-NULL
JUMP_LABEL, output the INSN_UID of it.
* gcse.c: Adjust comments as appropriate to say REG_LABEL_OPERAND
and/or REG_LABEL_TARGET.
(add_label_notes): Only add REG_LABEL_OPERAND notes.  Put in line
with jump.c copy by only adding notes for labels actually
referenced in the insn.
* emit-rtl.c (try_split): Don't assume only NONJUMP_INSN_P need
usage count increment; handle all INSN_P trial insns.
(emit_copy_of_insn_after): Change to not copy REG_LABEL_OPERAND
notes.
* rtl.h (struct rtx_def) <volatil>: Adjust to mention
REG_LABEL_TARGET and REG_LABEL_OPERAND.
(LABEL_REF_NONLOCAL_P): Allow REG_LABEL_TARGET and
REG_LABEL_OPERAND.
* combine.c (distribute_notes): Adjust for REG_LABEL_TARGET on
JUMP_P insns and REG_LABEL_OPERAND everywhere.
* sched-rgn.c (is_cfg_nonregular): Check for REG_LABEL_OPERANDS
on all INSN_P insns.
* reg-notes.def (LABEL_TARGET, LABEL_OPERAND): Split from LABEL.
* cfgrtl.c (delete_insn): Adjust to handle REG_LABEL_TARGET and
REG_LABEL_OPERAND notes.
* reload1.c (calculate_needs_all_insns): Adjust comments.
(set_label_offsets): Adjust to look for REG_LABEL_OPERAND notes.
* config/alpha/alpha.md (split for load of an address into a
four-insn sequence on Unicos/Mk): Adjust to use
REG_LABEL_OPERAND.
* config/sh/sh.md (sh_reorg, final_prescan_insn): Ditto.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128287 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
gcc/ChangeLog
gcc/cfgrtl.c
gcc/combine.c
gcc/config/alpha/alpha.md
gcc/config/sh/sh.c
gcc/cse.c
gcc/doc/rtl.texi
gcc/emit-rtl.c
gcc/gcse.c
gcc/jump.c
gcc/print-rtl.c
gcc/reg-notes.def
gcc/reload.c
gcc/reload1.c
gcc/reorg.c
gcc/rtl.h
gcc/rtlanal.c
gcc/sched-rgn.c

index 212a56d..6f30563 100644 (file)
@@ -1,3 +1,75 @@
+2007-09-09  Hans-Peter Nilsson  <hp@axis.com>
+
+       Divide REG_LABEL notes into REG_LABEL_OPERAND and REG_LABEL_TARGET.
+       * doc/rtl.texi (Insns): Specify when a label_ref makes a jump_insn.
+       Similar for what label_refs can go in the JUMP_TARGET field.  Split
+       REG_LABEL documentation into REG_LABEL_TARGET and REG_LABEL_OPERAND.
+       * reload.c (find_reloads): Generate REG_LABEL_OPERAND, not
+       REG_LABEL when replacing an operand with a LABEL_REF for a
+       non-jump insn.
+       (subst_reloads): When replacing a LABEL_REG with a register,
+       instead of generating a REG_LABEL note, assert that there already
+       is one or that the label is a known target for the insn.
+       * rtlanal.c (computed_jump_p): Instead of looking for a REG_LABEL
+       note, check the JUMP_LABEL field.  Remove "else" after return.
+       * reorg.c (emit_delay_sequence): Replace case for REG_LABEL with
+       cases for REG_LABEL_OPERAND and REG_LABEL_TARGET.
+       (fill_slots_from_thread): Handle both REG_LABEL_OPERAND and
+       REG_LABEL_TARGET notes, including the JUMP_TARGET field on JUMP_P
+       insns.  Iterate over all notes; don't assume there's only one.
+       * cse.c (recorded_label_ref): Adjust comment to refer to
+       REG_LABEL_OPERAND.
+       (cse_extended_basic_block): Do LABEL_REF check for all INSN_P
+       insns, not just NONJUMP_INSN_P.
+       (check_for_label_ref): For JUMP_P insns, check that the LABEL_REF
+       isn't a jump target.
+       * jump.c (rebuild_jump_labels): Adjust head comment.
+       (init_label_info): Ditto.  Remove REG_LABEL_OPERAND notes only;
+       don't reset REG_LABEL_TARGET notes, including the JUMP_LABEL field.
+       (mark_all_labels): For JUMP_P insns without a target, check if the
+       the target is noted on the previous nonjump insn.
+       (mark_jump_label_1): New function, guts from mark_jump_label.
+       <case IF_THEN_ELSE>: Handle first operand as a non-target when
+       marking jump target labels.
+       <case LABEL_REF>: Adjust for whether to generate a
+       REG_LABEL_TARGET or a REG_LABEL_OPERAND note.
+       For 'E' format rtl, iterate in descending element order.
+       (delete_related_insns): Handle both REG_LABEL_TARGET and
+       REG_LABEL_OPERAND notes.  For JUMP_P insns with labels with zero
+       reference count, delete and fallthrough.  Move finding-next-
+       non-deleted insn last in the function.  Look at all INSN_P insns
+       for REG_LABEL_OPERAND notes.
+       (redirect_jump_2): Assert that OLABEL equals the old JUMP_LABEL of
+       JUMP.
+       * print-rtl.c (print_rtx): For JUMP_P insns and a non-NULL
+       JUMP_LABEL, output the INSN_UID of it.
+       * gcse.c: Adjust comments as appropriate to say REG_LABEL_OPERAND
+       and/or REG_LABEL_TARGET.
+       (add_label_notes): Only add REG_LABEL_OPERAND notes.  Put in line
+       with jump.c copy by only adding notes for labels actually
+       referenced in the insn.
+       * emit-rtl.c (try_split): Don't assume only NONJUMP_INSN_P need
+       usage count increment; handle all INSN_P trial insns.
+       (emit_copy_of_insn_after): Change to not copy REG_LABEL_OPERAND
+       notes.
+       * rtl.h (struct rtx_def) <volatil>: Adjust to mention
+       REG_LABEL_TARGET and REG_LABEL_OPERAND.
+       (LABEL_REF_NONLOCAL_P): Allow REG_LABEL_TARGET and
+       REG_LABEL_OPERAND.
+       * combine.c (distribute_notes): Adjust for REG_LABEL_TARGET on
+       JUMP_P insns and REG_LABEL_OPERAND everywhere.
+       * sched-rgn.c (is_cfg_nonregular): Check for REG_LABEL_OPERANDS
+       on all INSN_P insns.
+       * reg-notes.def (LABEL_TARGET, LABEL_OPERAND): Split from LABEL.
+       * cfgrtl.c (delete_insn): Adjust to handle REG_LABEL_TARGET and
+       REG_LABEL_OPERAND notes.
+       * reload1.c (calculate_needs_all_insns): Adjust comments.
+       (set_label_offsets): Adjust to look for REG_LABEL_OPERAND notes.
+       * config/alpha/alpha.md (split for load of an address into a
+       four-insn sequence on Unicos/Mk): Adjust to use
+       REG_LABEL_OPERAND.
+       * config/sh/sh.md (sh_reorg, final_prescan_insn): Ditto.
+
 2007-09-09  Laurynas Biveinis  <laurynas.biveinis@gmail.com>
 
        Revert:
index 33ba86c..2893c83 100644 (file)
@@ -138,15 +138,15 @@ delete_insn (rtx insn)
 
   /* If deleting a jump, decrement the use count of the label.  Deleting
      the label itself should happen in the normal course of block merging.  */
-  if (JUMP_P (insn)
-      && JUMP_LABEL (insn)
-      && LABEL_P (JUMP_LABEL (insn)))
-    LABEL_NUSES (JUMP_LABEL (insn))--;
-
-  /* Also if deleting an insn that references a label.  */
-  else
+  if (JUMP_P (insn))
     {
-      while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX
+      if (JUMP_LABEL (insn)
+         && LABEL_P (JUMP_LABEL (insn)))
+       LABEL_NUSES (JUMP_LABEL (insn))--;
+
+      /* If there are more targets, remove them too.  */
+      while ((note
+             = find_reg_note (insn, REG_LABEL_TARGET, NULL_RTX)) != NULL_RTX
             && LABEL_P (XEXP (note, 0)))
        {
          LABEL_NUSES (XEXP (note, 0))--;
@@ -154,6 +154,14 @@ delete_insn (rtx insn)
        }
     }
 
+  /* Also if deleting any insn that references a label as an operand.  */
+  while ((note = find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX)) != NULL_RTX
+        && LABEL_P (XEXP (note, 0)))
+    {
+      LABEL_NUSES (XEXP (note, 0))--;
+      remove_note (insn, note);
+    }
+
   if (JUMP_P (insn)
       && (GET_CODE (PATTERN (insn)) == ADDR_VEC
          || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
index 133dfbe..319c532 100644 (file)
@@ -12408,7 +12408,8 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
            }
          break;
 
-       case REG_LABEL:
+       case REG_LABEL_TARGET:
+       case REG_LABEL_OPERAND:
          /* This can show up in several ways -- either directly in the
             pattern, or hidden off in the constant pool with (or without?)
             a REG_EQUAL note.  */
@@ -12431,34 +12432,33 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                place = i2;
            }
 
-         /* Don't attach REG_LABEL note to a JUMP_INSN.  Add
-            a JUMP_LABEL instead or decrement LABEL_NUSES.  */
-         if (place && JUMP_P (place))
+         /* For REG_LABEL_TARGET on a JUMP_P, we prefer to put the note
+            as a JUMP_LABEL or decrement LABEL_NUSES if it's already
+            there.  */
+         if (place && JUMP_P (place)
+             && REG_NOTE_KIND (note) == REG_LABEL_TARGET
+             && (JUMP_LABEL (place) == NULL
+                 || JUMP_LABEL (place) == XEXP (note, 0)))
            {
              rtx label = JUMP_LABEL (place);
 
              if (!label)
                JUMP_LABEL (place) = XEXP (note, 0);
-             else
-               {
-                 gcc_assert (label == XEXP (note, 0));
-                 if (LABEL_P (label))
-                   LABEL_NUSES (label)--;
-               }
-             place = 0;
+             else if (LABEL_P (label))
+               LABEL_NUSES (label)--;
            }
-         if (place2 && JUMP_P (place2))
+
+         if (place2 && JUMP_P (place2)
+             && REG_NOTE_KIND (note) == REG_LABEL_TARGET
+             && (JUMP_LABEL (place2) == NULL
+                 || JUMP_LABEL (place2) == XEXP (note, 0)))
            {
              rtx label = JUMP_LABEL (place2);
 
              if (!label)
                JUMP_LABEL (place2) = XEXP (note, 0);
-             else
-               {
-                 gcc_assert (label == XEXP (note, 0));
-                 if (LABEL_P (label))
-                   LABEL_NUSES (label)--;
-               }
+             else if (LABEL_P (label))
+               LABEL_NUSES (label)--;
              place2 = 0;
            }
          break;
index f381dde..f4f3eb3 100644 (file)
 
 ;; Split the load of an address into a four-insn sequence on Unicos/Mk.
 ;; Always generate a REG_EQUAL note for the last instruction to facilitate
-;; optimizations. If the symbolic operand is a label_ref, generate REG_LABEL
-;; notes and update LABEL_NUSES because this is not done automatically.
-;; Labels may be incorrectly deleted if we don't do this.
+;; optimizations. If the symbolic operand is a label_ref, generate
+;; REG_LABEL_OPERAND notes and update LABEL_NUSES because this is not done
+;; automatically.  Labels may be incorrectly deleted if we don't do this.
 ;;
 ;; Describing what the individual instructions do correctly is too complicated
 ;; so use UNSPECs for each of the three parts of an address.
       rtx label;
 
       label = XEXP (operands[1], 0);
-      REG_NOTES (insn1) = gen_rtx_EXPR_LIST (REG_LABEL, label,
+      REG_NOTES (insn1) = gen_rtx_EXPR_LIST (REG_LABEL_OPERAND, label,
                                             REG_NOTES (insn1));
-      REG_NOTES (insn2) = gen_rtx_EXPR_LIST (REG_LABEL, label,
+      REG_NOTES (insn2) = gen_rtx_EXPR_LIST (REG_LABEL_OPERAND, label,
                                             REG_NOTES (insn2));
-      REG_NOTES (insn3) = gen_rtx_EXPR_LIST (REG_LABEL, label,
+      REG_NOTES (insn3) = gen_rtx_EXPR_LIST (REG_LABEL_OPERAND, label,
                                             REG_NOTES (insn3));
       LABEL_NUSES (label) += 3;
     }
index 927355f..ad9dd22 100644 (file)
@@ -4716,8 +4716,8 @@ sh_reorg (void)
   mdep_reorg_phase = SH_INSERT_USES_LABELS;
   if (TARGET_RELAX)
     {
-      /* Remove all REG_LABEL notes.  We want to use them for our own
-        purposes.  This works because none of the remaining passes
+      /* Remove all REG_LABEL_OPERAND notes.  We want to use them for our
+        own purposes.  This works because none of the remaining passes
         need to look at them.
 
         ??? But it may break in the future.  We should use a machine
@@ -4728,7 +4728,8 @@ sh_reorg (void)
            {
              rtx note;
 
-             while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != 0)
+             while ((note = find_reg_note (insn, REG_LABEL_OPERAND,
+                                           NULL_RTX)) != 0)
                remove_note (insn, note);
            }
        }
@@ -4879,16 +4880,16 @@ sh_reorg (void)
              continue;
            }
 
-         /* Create a code label, and put it in a REG_LABEL note on
-             the insn which sets the register, and on each call insn
-             which uses the register.  In final_prescan_insn we look
-             for the REG_LABEL notes, and output the appropriate label
+         /* Create a code label, and put it in a REG_LABEL_OPERAND note
+             on the insn which sets the register, and on each call insn
+             which uses the register.  In final_prescan_insn we look for
+             the REG_LABEL_OPERAND notes, and output the appropriate label
              or pseudo-op.  */
 
          label = gen_label_rtx ();
-         REG_NOTES (link) = gen_rtx_INSN_LIST (REG_LABEL, label,
+         REG_NOTES (link) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, label,
                                                REG_NOTES (link));
-         REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
+         REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, label,
                                                REG_NOTES (insn));
          if (rescan)
            {
@@ -4904,7 +4905,8 @@ sh_reorg (void)
                          || ((reg2 = sfunc_uses_reg (scan))
                              && REGNO (reg2) == REGNO (reg))))
                    REG_NOTES (scan)
-                     = gen_rtx_INSN_LIST (REG_LABEL, label, REG_NOTES (scan));
+                     = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, label,
+                                          REG_NOTES (scan));
                }
              while (scan != dies);
            }
@@ -5405,7 +5407,7 @@ final_prescan_insn (rtx insn, rtx *opvec ATTRIBUTE_UNUSED,
     {
       rtx note;
 
-      note = find_reg_note (insn, REG_LABEL, NULL_RTX);
+      note = find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX);
       if (note)
        {
          rtx pattern;
index c26c6e7..7e76661 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -353,8 +353,9 @@ static HARD_REG_SET hard_regs_in_table;
 
 static int cse_jumps_altered;
 
-/* Nonzero if we put a LABEL_REF into the hash table for an INSN without a
-   REG_LABEL, we have to rerun jump after CSE to put in the note.  */
+/* Nonzero if we put a LABEL_REF into the hash table for an INSN
+   without a REG_LABEL_OPERAND, we have to rerun jump after CSE to put
+   in the note.  */
 static int recorded_label_ref;
 
 /* canon_hash stores 1 in do_not_record
@@ -6091,7 +6092,7 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
            
              /* If we haven't already found an insn where we added a LABEL_REF,
                 check this one.  */
-             if (NONJUMP_INSN_P (insn) && ! recorded_label_ref
+             if (INSN_P (insn) && ! recorded_label_ref
                  && for_each_rtx (&PATTERN (insn), check_for_label_ref,
                                   (void *) insn))
                recorded_label_ref = 1;
@@ -6277,23 +6278,26 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nregs)
   return cse_jumps_altered || recorded_label_ref;
 }
 \f
-/* Called via for_each_rtx to see if an insn is using a LABEL_REF for which
-   there isn't a REG_LABEL note.  Return one if so.  DATA is the insn.  */
+/* Called via for_each_rtx to see if an insn is using a LABEL_REF for
+   which there isn't a REG_LABEL_OPERAND note.
+   Return one if so.  DATA is the insn.  */
 
 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)));
 }
 \f
 /* Count the number of times registers are used (not set) in X.
index 83fa089..639aabe 100644 (file)
@@ -3201,9 +3201,10 @@ mandatory ones listed above.  These four are described in a table below.
 @findex jump_insn
 @item jump_insn
 The expression code @code{jump_insn} is used for instructions that may
-jump (or, more generally, may contain @code{label_ref} expressions).  If
-there is an instruction to return from the current function, it is
-recorded as a @code{jump_insn}.
+jump (or, more generally, may contain @code{label_ref} expressions to
+which @code{pc} can be set in that instruction).  If there is an
+instruction to return from the current function, it is recorded as a
+@code{jump_insn}.
 
 @findex JUMP_LABEL
 @code{jump_insn} insns have the same extra fields as @code{insn} insns,
@@ -3213,9 +3214,11 @@ accessed in the same way and in addition contain a field
 For simple conditional and unconditional jumps, this field contains
 the @code{code_label} to which this insn will (possibly conditionally)
 branch.  In a more complex jump, @code{JUMP_LABEL} records one of the
-labels that the insn refers to; the only way to find the others is to
-scan the entire body of the insn.  In an @code{addr_vec},
-@code{JUMP_LABEL} is @code{NULL_RTX}.
+labels that the insn refers to; other jump target labels are recorded
+as @code{REG_LABEL_TARGET} notes.  The exception is @code{addr_vec}
+and @code{addr_diff_vec}, where @code{JUMP_LABEL} is @code{NULL_RTX}
+and the only way to find the labels is to scan the entire body of the
+insn.
 
 Return insns count as jumps, but since they do not refer to any
 labels, their @code{JUMP_LABEL} is @code{NULL_RTX}.
@@ -3531,14 +3534,25 @@ note giving the expression being computed.  This block is encapsulated
 with @code{REG_LIBCALL} and @code{REG_RETVAL} notes on the first and
 last insns, respectively.
 
-@findex REG_LABEL
-@item REG_LABEL
+@findex REG_LABEL_OPERAND
+@item REG_LABEL_OPERAND
 This insn uses @var{op}, a @code{code_label} or a @code{note} of type
-@code{NOTE_INSN_DELETED_LABEL}, but is not a
-@code{jump_insn}, or it is a @code{jump_insn} that required the label to
-be held in a register.  The presence of this note allows jump
-optimization to be aware that @var{op} is, in fact, being used, and flow
-optimization to build an accurate flow graph.
+@code{NOTE_INSN_DELETED_LABEL}, but is not a @code{jump_insn}, or it
+is a @code{jump_insn} that refers to the operand as an ordinary
+operand.  The label may still eventually be a jump target, but if so
+in an indirect jump in a subsequent insn.  The presence of this note
+allows jump optimization to be aware that @var{op} is, in fact, being
+used, and flow optimization to build an accurate flow graph.
+
+@findex REG_LABEL_TARGET
+@item REG_LABEL_TARGET
+This insn is a @code{jump_insn} but not a @code{addr_vec} or
+@code{addr_diff_vec}.  It uses @var{op}, a @code{code_label} as a
+direct or indirect jump target.  Its purpose is similar to that of
+@code{REG_LABEL_OPERAND}.  This note is only present if the insn has
+multiple targets; the last label in the insn (in the highest numbered
+insn-field) goes into the @code{JUMP_LABEL} field and does not have a
+@code{REG_LABEL_TARGET} note.  @xref{Insns, JUMP_LABEL}.
 
 @findex REG_CROSSING_JUMP
 @item REG_CROSSING_JUMP
index b3f2101..8d1b1c7 100644 (file)
@@ -3355,11 +3355,12 @@ try_split (rtx pat, rtx trial, int last)
 
   /* If there are LABELS inside the split insns increment the
      usage count so we don't delete the label.  */
-  if (NONJUMP_INSN_P (trial))
+  if (INSN_P (trial))
     {
       insn = insn_last;
       while (insn != NULL_RTX)
        {
+         /* JUMP_P insns have already been "marked" above.  */
          if (NONJUMP_INSN_P (insn))
            mark_label_nuses (PATTERN (insn));
 
@@ -5529,10 +5530,11 @@ emit_copy_of_insn_after (rtx insn, rtx after)
      which may be duplicated by the basic block reordering code.  */
   RTX_FRAME_RELATED_P (new) = RTX_FRAME_RELATED_P (insn);
 
-  /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
-     make them.  */
+  /* Copy all REG_NOTES except REG_LABEL_OPERAND since mark_jump_label
+     will make them.  REG_LABEL_TARGETs are created there too, but are
+     supposed to be sticky, so we copy them.  */
   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
-    if (REG_NOTE_KIND (link) != REG_LABEL)
+    if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
       {
        if (GET_CODE (link) == EXPR_LIST)
          REG_NOTES (new)
index b6b7c5e..e3ffae0 100644 (file)
@@ -4584,14 +4584,15 @@ one_pre_gcse_pass (int pass)
   return changed;
 }
 \f
-/* If X contains any LABEL_REF's, add REG_LABEL notes for them to INSN.
-   If notes are added to an insn which references a CODE_LABEL, the
-   LABEL_NUSES count is incremented.  We have to add REG_LABEL notes,
-   because the following loop optimization pass requires them.  */
+/* If X contains any LABEL_REF's, add REG_LABEL_OPERAND notes for them
+   to INSN.  If such notes are added to an insn which references a
+   CODE_LABEL, the LABEL_NUSES count is incremented.  We have to add
+   that note, because the following loop optimization pass requires
+   them.  */
 
 /* ??? If there was a jump optimization pass after gcse and before loop,
    then we would not need to do this here, because jump would add the
-   necessary REG_LABEL notes.  */
+   necessary REG_LABEL_OPERAND and REG_LABEL_TARGET notes.  */
 
 static void
 add_label_notes (rtx x, rtx insn)
@@ -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;
     }
 
index cd51764..e62024f 100644 (file)
@@ -67,13 +67,15 @@ along with GCC; see the file COPYING3.  If not see
 
 static void init_label_info (rtx);
 static void mark_all_labels (rtx);
+static void mark_jump_label_1 (rtx, rtx, bool, bool);
 static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
 static int invert_exp_1 (rtx, rtx);
 static int returnjump_p_1 (rtx *, void *);
 \f
-/* Alternate entry into the jump optimizer.  This entry point only rebuilds
-   the JUMP_LABEL field in jumping insns and REG_LABEL notes in non-jumping
-   instructions.  */
+/* This function rebuilds the JUMP_LABEL field and REG_LABEL_TARGET
+   notes in jumping insns and REG_LABEL_OPERAND notes in non-jumping
+   instructions and jumping insns that have labels as operands
+   (e.g. cbranchsi4).  */
 void
 rebuild_jump_labels (rtx f)
 {
@@ -138,31 +140,43 @@ struct tree_opt_pass pass_cleanup_barriers =
 };
 
 \f
-/* Initialize LABEL_NUSES and JUMP_LABEL fields.  Delete any REG_LABEL
-   notes whose labels don't occur in the insn any more.  Returns the
-   largest INSN_UID found.  */
+/* Initialize LABEL_NUSES and JUMP_LABEL fields, add REG_LABEL_TARGET
+   for remaining targets for JUMP_P.  Delete any REG_LABEL_OPERAND
+   notes whose labels don't occur in the insn any more.  */
+
 static void
 init_label_info (rtx f)
 {
   rtx insn;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
-    if (LABEL_P (insn))
-      LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
-    else if (JUMP_P (insn))
-      JUMP_LABEL (insn) = 0;
-    else if (NONJUMP_INSN_P (insn) || CALL_P (insn))
-      {
-       rtx note, next;
+    {
+      if (LABEL_P (insn))
+       LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
+
+      /* REG_LABEL_TARGET notes (including the JUMP_LABEL field) are
+        sticky and not reset here; that way we won't lose association
+        with a label when e.g. the source for a target register
+        disappears out of reach for targets that may use jump-target
+        registers.  Jump transformations are supposed to transform
+        any REG_LABEL_TARGET notes.  The target label reference in a
+        branch may disappear from the branch (and from the
+        instruction before it) for other reasons, like register
+        allocation.  */
+
+      if (INSN_P (insn))
+       {
+         rtx note, next;
 
-       for (note = REG_NOTES (insn); note; note = next)
-         {
-           next = XEXP (note, 1);
-           if (REG_NOTE_KIND (note) == REG_LABEL
-               && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
-             remove_note (insn, note);
-         }
-      }
+         for (note = REG_NOTES (insn); note; note = next)
+           {
+             next = XEXP (note, 1);
+             if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
+                 && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
+               remove_note (insn, note);
+           }
+       }
+    }
 }
 
 /* Mark the label each jump jumps to.
@@ -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)
          {
-           /* When we know the LABEL_REF contained in a REG used in
-              an indirect jump, we'll have a REG_LABEL note so that
-              flow can tell where it's going.  */
-           if (JUMP_LABEL (insn) == 0)
+           rtx label_note = NULL;
+           rtx pc = pc_set (insn);
+           rtx pc_src = pc != NULL ? SET_SRC (pc) : NULL;
+
+           if (prev_nonjump_insn != NULL)
+             label_note
+               = find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);
+
+           if (label_note != NULL && pc_src != NULL)
              {
-               rtx label_note = find_reg_note (insn, REG_LABEL, NULL_RTX);
-               if (label_note)
+               rtx label_set = single_set (prev_nonjump_insn);
+               rtx label_dest
+                 = label_set != NULL ? SET_DEST (label_set) : NULL;
+
+               if (label_set != NULL
+                   /* The source must be the direct LABEL_REF, not a
+                      PLUS, UNSPEC, IF_THEN_ELSE etc.  */
+                   && GET_CODE (SET_SRC (label_set)) == LABEL_REF
+                   && (rtx_equal_p (label_dest, pc_src)
+                       || (GET_CODE (pc_src) == IF_THEN_ELSE
+                           && (rtx_equal_p (label_dest, XEXP (pc_src, 1))
+                               || rtx_equal_p (label_dest,
+                                               XEXP (pc_src, 2))))))
+                               
                  {
-                   /* But a LABEL_REF around the REG_LABEL note, so
-                      that we can canonicalize it.  */
-                   rtx label_ref = gen_rtx_LABEL_REF (Pmode,
-                                                      XEXP (label_note, 0));
-
-                   mark_jump_label (label_ref, insn, 0);
-                   XEXP (label_note, 0) = XEXP (label_ref, 0);
-                   JUMP_LABEL (insn) = XEXP (label_note, 0);
+                   /* The CODE_LABEL referred to in the note must be the
+                      CODE_LABEL in the LABEL_REF of the "set".  We can
+                      conveniently use it for the marker function, which
+                      requires a LABEL_REF wrapping.  */
+                   gcc_assert (XEXP (label_note, 0)
+                               == XEXP (SET_SRC (label_set), 0));
+
+                   mark_jump_label_1 (label_set, insn, false, true);
+                   gcc_assert (JUMP_LABEL (insn)
+                               == XEXP (SET_SRC (label_set), 0));
                  }
              }
          }
+       else if (! INSN_DELETED_P (insn))
+         prev_nonjump_insn = insn;
       }
-  
+    else if (LABEL_P (insn))
+      prev_nonjump_insn = NULL;
+
   /* If we are in cfglayout mode, there may be non-insns between the
      basic blocks.  If those non-insns represent tablejump data, they
      contain label references that we must record.  */
@@ -904,12 +953,14 @@ sets_cc0_p (const_rtx x)
 }
 #endif
 \f
-/* Find all CODE_LABELs referred to in X, and increment their use counts.
-   If INSN is a JUMP_INSN and there is at least one CODE_LABEL referenced
-   in INSN, then store one of them in JUMP_LABEL (INSN).
-   If INSN is an INSN or a CALL_INSN and there is at least one CODE_LABEL
-   referenced in INSN, add a REG_LABEL note containing that label to INSN.
-   Also, when there are consecutive labels, canonicalize on the last of them.
+/* Find all CODE_LABELs referred to in X, and increment their use
+   counts.  If INSN is a JUMP_INSN and there is at least one
+   CODE_LABEL referenced in INSN as a jump target, then store the last
+   one in JUMP_LABEL (INSN).  For a tablejump, this must be the label
+   for the ADDR_VEC.  Store any other jump targets as REG_LABEL_TARGET
+   notes.  If INSN is an INSN or a CALL_INSN or non-target operands of
+   a JUMP_INSN, and there is at least one CODE_LABEL referenced in
+   INSN, add a REG_LABEL_OPERAND note containing that label to INSN.
 
    Note that two labels separated by a loop-beginning note
    must be kept distinct if we have not yet done loop-optimization,
@@ -920,6 +971,19 @@ sets_cc0_p (const_rtx x)
 void
 mark_jump_label (rtx x, rtx insn, int in_mem)
 {
+  mark_jump_label_1 (x, insn, in_mem != 0,
+                    (insn != NULL && x == PATTERN (insn) && JUMP_P (insn)));
+}
+
+/* Worker function for mark_jump_label.  IN_MEM is TRUE when X occurrs
+   within a (MEM ...).  IS_TARGET is TRUE when X is to be treated as a
+   jump-target; when the JUMP_LABEL field of INSN should be set or a
+   REG_LABEL_TARGET note should be added, not a REG_LABEL_OPERAND
+   note.  */
+
+static void
+mark_jump_label_1 (rtx x, rtx insn, bool in_mem, bool is_target)
+{
   RTX_CODE code = GET_CODE (x);
   int i;
   const char *fmt;
@@ -936,7 +1000,7 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
       return;
 
     case MEM:
-      in_mem = 1;
+      in_mem = true;
       break;
 
     case SEQUENCE:
@@ -951,9 +1015,19 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
 
       /* If this is a constant-pool reference, see if it is a label.  */
       if (CONSTANT_POOL_ADDRESS_P (x))
-       mark_jump_label (get_pool_constant (x), insn, in_mem);
+       mark_jump_label_1 (get_pool_constant (x), insn, in_mem, is_target);
       break;
 
+      /* Handle operands in the condition of an if-then-else as for a
+        non-jump insn.  */
+    case IF_THEN_ELSE:
+      if (!is_target)
+       break;
+      mark_jump_label_1 (XEXP (x, 0), insn, in_mem, false);
+      mark_jump_label_1 (XEXP (x, 1), insn, in_mem, true);
+      mark_jump_label_1 (XEXP (x, 2), insn, in_mem, true);
+      return;
+
     case LABEL_REF:
       {
        rtx label = XEXP (x, 0);
@@ -976,17 +1050,21 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
 
        if (insn)
          {
-           if (JUMP_P (insn))
+           if (is_target
+               && (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == label))
              JUMP_LABEL (insn) = label;
            else
              {
-               /* Add a REG_LABEL note for LABEL unless there already
-                  is one.  All uses of a label, except for labels
-                  that are the targets of jumps, must have a
-                  REG_LABEL note.  */
-               if (! find_reg_note (insn, REG_LABEL, label))
-                 REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
-                                                       REG_NOTES (insn));
+               enum reg_note kind
+                 = is_target ? REG_LABEL_TARGET : REG_LABEL_OPERAND;
+
+               /* Add a REG_LABEL_OPERAND or REG_LABEL_TARGET note
+                  for LABEL unless there already is one.  All uses of
+                  a label, except for the primary target of a jump,
+                  must have such a note.  */
+               if (! find_reg_note (insn, kind, label))
+                 REG_NOTES (insn)
+                   = gen_rtx_INSN_LIST (kind, label, REG_NOTES (insn));
              }
          }
        return;
@@ -1001,7 +1079,8 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
          int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
 
          for (i = 0; i < XVECLEN (x, eltnum); i++)
-           mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX, in_mem);
+           mark_jump_label_1 (XVECEXP (x, eltnum, i), NULL_RTX, in_mem,
+                              is_target);
        }
       return;
 
@@ -1010,15 +1089,21 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
     }
 
   fmt = GET_RTX_FORMAT (code);
+
+  /* The primary target of a tablejump is the label of the ADDR_VEC,
+     which is canonically mentioned *last* in the insn.  To get it
+     marked as JUMP_LABEL, we iterate over items in reverse order.  */
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-       mark_jump_label (XEXP (x, i), insn, in_mem);
+       mark_jump_label_1 (XEXP (x, i), insn, in_mem, is_target);
       else if (fmt[i] == 'E')
        {
          int j;
-         for (j = 0; j < XVECLEN (x, i); j++)
-           mark_jump_label (XVECEXP (x, i, j), insn, in_mem);
+
+         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+           mark_jump_label_1 (XVECEXP (x, i, j), insn, in_mem,
+                              is_target);
        }
     }
 }
@@ -1062,20 +1147,10 @@ delete_related_insns (rtx insn)
       rtx lab = JUMP_LABEL (insn), lab_next;
 
       if (LABEL_NUSES (lab) == 0)
-       {
-         /* This can delete NEXT or PREV,
-            either directly if NEXT is JUMP_LABEL (INSN),
-            or indirectly through more levels of jumps.  */
-         delete_related_insns (lab);
-
-         /* I feel a little doubtful about this loop,
-            but I see no clean and sure alternative way
-            to find the first insn after INSN that is not now deleted.
-            I hope this works.  */
-         while (next && INSN_DELETED_P (next))
-           next = NEXT_INSN (next);
-         return next;
-       }
+       /* This can delete NEXT or PREV,
+          either directly if NEXT is JUMP_LABEL (INSN),
+          or indirectly through more levels of jumps.  */
+       delete_related_insns (lab);
       else if (tablejump_p (insn, NULL, &lab_next))
        {
          /* If we're deleting the tablejump, delete the dispatch table.
@@ -1104,10 +1179,12 @@ delete_related_insns (rtx insn)
       return next;
     }
 
-  /* Likewise for an ordinary INSN / CALL_INSN with a REG_LABEL note.  */
-  if (NONJUMP_INSN_P (insn) || CALL_P (insn))
+  /* Likewise for any JUMP_P / INSN / CALL_INSN with a
+     REG_LABEL_OPERAND or REG_LABEL_TARGET note.  */
+  if (INSN_P (insn))
     for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-      if (REG_NOTE_KIND (note) == REG_LABEL
+      if ((REG_NOTE_KIND (note) == REG_LABEL_OPERAND
+          || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
          /* This could also be a NOTE_INSN_DELETED_LABEL note.  */
          && LABEL_P (XEXP (note, 0)))
        if (LABEL_NUSES (XEXP (note, 0)) == 0)
@@ -1151,6 +1228,12 @@ delete_related_insns (rtx insn)
        }
     }
 
+  /* I feel a little doubtful about this loop,
+     but I see no clean and sure alternative way
+     to find the first insn after INSN that is not now deleted.
+     I hope this works.  */
+  while (next && INSN_DELETED_P (next))
+    next = NEXT_INSN (next);
   return next;
 }
 \f
@@ -1307,6 +1390,8 @@ redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
 {
   rtx note;
 
+  gcc_assert (JUMP_LABEL (jump) == olabel);
+
   /* Negative DELETE_UNUSED used to be used to signalize behavior on
      moving FUNCTION_END note.  Just sanity check that no user still worry
      about this.  */
index 3dc8762..d776455 100644 (file)
@@ -335,6 +335,9 @@ print_rtx (const_rtx in_rtx)
                break;
              }
          }
+       else if (i == 9 && JUMP_P (in_rtx) && XEXP (in_rtx, i) != NULL)
+         /* Output the JUMP_LABEL reference.  */
+         fprintf (outfile, "\n -> %d", INSN_UID (XEXP (in_rtx, i)));
        break;
 
       case 'e':
index a01d888..713bc28 100644 (file)
@@ -91,10 +91,16 @@ REG_NOTE (UNUSED)
 REG_NOTE (CC_SETTER)
 REG_NOTE (CC_USER)
 
-/* Points to a CODE_LABEL.  Used by non-JUMP_INSNs to say that the
-   CODE_LABEL contained in the REG_LABEL note is used by the insn.
-   This note is an INSN_LIST.  */
-REG_NOTE (LABEL)
+/* Points to a CODE_LABEL.  Used by JUMP_INSNs to say that the CODE_LABEL
+   contained in the REG_LABEL_TARGET note is a possible jump target of
+   this insn.  This note is an INSN_LIST.  */
+REG_NOTE (LABEL_TARGET)
+
+/* Points to a CODE_LABEL.  Used by any insn to say that the CODE_LABEL
+   contained in the REG_LABEL_OPERAND note is used by the insn, but as an
+   operand, not as a jump target (though it may indirectly be a jump
+   target for a later jump insn).  This note is an INSN_LIST.  */
+REG_NOTE (LABEL_OPERAND)
 
 /* REG_DEP_OUTPUT and REG_DEP_ANTI are used in scheduler dependencies lists
    to represent write-after-write and write-after-read dependencies
index 6eb3802..e88a82d 100644 (file)
@@ -4103,13 +4103,18 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
          *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));
        }
@@ -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
index 31626f5..9021050 100644 (file)
@@ -1539,8 +1539,8 @@ calculate_needs_all_insns (int global)
       chain->need_operand_change = 0;
 
       /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
-        include REG_LABEL), we need to see what effects this has on the
-        known offsets at labels.  */
+        include REG_LABEL_OPERAND and REG_LABEL_TARGET), we need to see
+        what effects this has on the known offsets at labels.  */
 
       if (LABEL_P (insn) || JUMP_P (insn)
          || (INSN_P (insn) && REG_NOTES (insn) != 0))
@@ -2295,10 +2295,11 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
 
     case INSN:
     case CALL_INSN:
-      /* Any labels mentioned in REG_LABEL notes can be branched to indirectly
-        and hence must have all eliminations at their initial offsets.  */
+      /* Any labels mentioned in REG_LABEL_OPERAND notes can be branched
+        to indirectly and hence must have all eliminations at their
+        initial offsets.  */
       for (tem = REG_NOTES (x); tem; tem = XEXP (tem, 1))
-       if (REG_NOTE_KIND (tem) == REG_LABEL)
+       if (REG_NOTE_KIND (tem) == REG_LABEL_OPERAND)
          set_label_offsets (XEXP (tem, 0), insn, 1);
       return;
 
@@ -8049,7 +8050,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
   else if (OBJECT_P (in) || GET_CODE (in) == SUBREG)
     {
       tem = emit_insn (gen_move_insn (out, in));
-      /* IN may contain a LABEL_REF, if so add a REG_LABEL note.  */
+      /* IN may contain a LABEL_REF, if so add a REG_LABEL_OPERAND note.  */
       mark_jump_label (in, tem, 0);
     }
 
index 8083c88..291e1aa 100644 (file)
@@ -541,7 +541,8 @@ emit_delay_sequence (rtx insn, rtx list, int length)
              remove_note (tem, note);
              break;
 
-           case REG_LABEL:
+           case REG_LABEL_OPERAND:
+           case REG_LABEL_TARGET:
              /* Keep the label reference count up to date.  */
              if (LABEL_P (XEXP (note, 0)))
                LABEL_NUSES (XEXP (note, 0)) ++;
@@ -2736,14 +2737,40 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
                      /* 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))++;
 
                      delete_related_insns (trial);
 
-                     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))--;
                    }
                  else
index 0a114c3..3473fb3 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -265,7 +265,8 @@ struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
      1 in a REG expression if corresponds to a variable declared by the user,
      0 for an internally generated temporary.
      1 in a SUBREG with a negative value.
-     1 in a LABEL_REF or in a REG_LABEL note for a non-local label.
+     1 in a LABEL_REF, REG_LABEL_TARGET or REG_LABEL_OPERAND note for a
+     non-local label.
      In a SYMBOL_REF, this flag is used for machine-specific purposes.  */
   unsigned int volatil : 1;
   /* 1 in a MEM referring to a field of an aggregate.
@@ -1224,10 +1225,11 @@ do {                                            \
    MEM_ATTRS (LHS) = MEM_ATTRS (RHS))
 
 /* 1 if RTX is a label_ref for a nonlocal label.  */
-/* Likewise in an expr_list for a reg_label note.  */
+/* Likewise in an expr_list for a REG_LABEL_OPERAND or
+   REG_LABEL_TARGET note.  */
 #define LABEL_REF_NONLOCAL_P(RTX)                                      \
-  (RTL_FLAG_CHECK2("LABEL_REF_NONLOCAL_P", (RTX), LABEL_REF,           \
-                  REG_LABEL)->volatil)
+  (RTL_FLAG_CHECK3("LABEL_REF_NONLOCAL_P", (RTX), LABEL_REF,           \
+                  REG_LABEL_OPERAND, REG_LABEL_TARGET)->volatil)
 
 /* 1 if RTX is a code_label that should always be considered to be needed.  */
 #define LABEL_PRESERVE_P(RTX)                                          \
index 3c4331e..a47c36f 100644 (file)
@@ -2703,9 +2703,11 @@ computed_jump_p (const_rtx insn)
     {
       rtx pat = PATTERN (insn);
 
-      if (find_reg_note (insn, REG_LABEL, NULL_RTX))
+      /* If we have a JUMP_LABEL set, we're not a computed jump.  */
+      if (JUMP_LABEL (insn) != NULL)
        return 0;
-      else if (GET_CODE (pat) == PARALLEL)
+
+      if (GET_CODE (pat) == PARALLEL)
        {
          int len = XVECLEN (pat, 0);
          int has_use_labelref = 0;
index 6df5c33..0ca1a47 100644 (file)
@@ -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;
       }