Fix mark_all_labels vs cfglayout mode.
authorRichard Henderson <rth@redhat.com>
Fri, 22 Jul 2011 23:19:25 +0000 (16:19 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 22 Jul 2011 23:19:25 +0000 (16:19 -0700)
        * jump.c (maybe_propagate_label_ref): Split out of...
        (mark_all_labels): ... here.  Do not attempt label_ref
        propagation while in cfglayout mode.

From-SVN: r176663

gcc/ChangeLog
gcc/jump.c

index ea9b48bfe4f829178bfc5b8efc3e53cb2b7fa7f3..905dc1c54edc6abd7a86193fe8001ae7d8380b72 100644 (file)
@@ -1,3 +1,9 @@
+2011-07-22  Richard Henderson  <rth@redhat.com>
+
+       * jump.c (maybe_propagate_label_ref): Split out of...
+       (mark_all_labels): ... here.  Do not attempt label_ref
+       propagation while in cfglayout mode.
+
 2011-07-22  Jakub Jelinek  <jakub@redhat.com>
 
        * dwarf2out.c (struct macinfo_struct): Change code to unsigned char.
index f337eb3add0aa03d11962c22ee18e8c249297e48..0d29f0fcb18c47219eba6f07087eabc63bca84bd 100644 (file)
@@ -200,6 +200,54 @@ init_label_info (rtx f)
     }
 }
 
+/* A subroutine of mark_all_labels.  Trivially propagate a simple label
+   load into a jump_insn that uses it.  */
+
+static void
+maybe_propagate_label_ref (rtx jump_insn, rtx prev_nonjump_insn)
+{
+  rtx label_note, pc, pc_src;
+
+  pc = pc_set (jump_insn);
+  pc_src = pc != NULL ? SET_SRC (pc) : NULL;
+  label_note = find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);
+
+  /* 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 (label_note != NULL && pc_src != NULL)
+    {
+      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))))))
+       {
+         /* 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, jump_insn, false, true);
+
+         gcc_assert (JUMP_LABEL (jump_insn) == XEXP (label_note, 0));
+       }
+    }
+}
+
 /* Mark the label each jump jumps to.
    Combine consecutive labels, and count uses of labels.  */
 
@@ -207,85 +255,31 @@ static void
 mark_all_labels (rtx f)
 {
   rtx insn;
-  rtx prev_nonjump_insn = NULL;
-
-  for (insn = f; insn; insn = NEXT_INSN (insn))
-    if (NONDEBUG_INSN_P (insn))
-      {
-       mark_jump_label (PATTERN (insn), insn, 0);
-
-       /* 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)
-         {
-           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_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))))))
-
-                 {
-                   /* 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.  */
   if (current_ir_type () == IR_RTL_CFGLAYOUT)
     {
       basic_block bb;
-      rtx insn;
       FOR_EACH_BB (bb)
        {
+         /* In cfglayout mode, we don't bother with trivial next-insn
+            propagation of LABEL_REFs into JUMP_LABEL.  This will be
+            handled by other optimizers using better algorithms.  */
+         FOR_BB_INSNS (bb, insn)
+           {
+             gcc_assert (! INSN_DELETED_P (insn));
+             if (NONDEBUG_INSN_P (insn))
+               mark_jump_label (PATTERN (insn), insn, 0);
+           }
+
+         /* 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.  */
          for (insn = bb->il.rtl->header; insn; insn = NEXT_INSN (insn))
            if (INSN_P (insn))
              {
                gcc_assert (JUMP_TABLE_DATA_P (insn));
                mark_jump_label (PATTERN (insn), insn, 0);
              }
-
          for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn))
            if (INSN_P (insn))
              {
@@ -294,6 +288,28 @@ mark_all_labels (rtx f)
              }
        }
     }
+  else
+    {
+      rtx prev_nonjump_insn = NULL;
+      for (insn = f; insn; insn = NEXT_INSN (insn))
+       {
+         if (INSN_DELETED_P (insn))
+           ;
+         else if (LABEL_P (insn))
+           prev_nonjump_insn = NULL;
+         else if (NONDEBUG_INSN_P (insn))
+           {
+             mark_jump_label (PATTERN (insn), insn, 0);
+             if (JUMP_P (insn))
+               {
+                 if (JUMP_LABEL (insn) == NULL && prev_nonjump_insn != NULL)
+                   maybe_propagate_label_ref (insn, prev_nonjump_insn);
+               }
+             else
+               prev_nonjump_insn = insn;
+           }
+       }
+    }
 }
 \f
 /* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code