2013-06-06 Teresa Johnson <tejohnson@google.com>
authortejohnson <tejohnson@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Jun 2013 16:30:07 +0000 (16:30 +0000)
committertejohnson <tejohnson@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Jun 2013 16:30:07 +0000 (16:30 +0000)
PR c++/53743
* ifcvt.c (find_if_case_1): Replace BB_COPY_PARTITION with assert
as this is now done by redirect_edge_and_branch_force.
* function.c (thread_prologue_and_epilogue_insns): Insert new bb after
barriers, and fix interaction with splitting.
* emit-rtl.c (try_split): Copy REG_CROSSING_JUMP notes.
* cfgcleanup.c (try_forward_edges): Fix early return value to properly
reflect changes made in the routine.
* bb-reorder.c (emit_barrier_after_bb): Move to cfgrtl.c.
(fix_up_fall_thru_edges): Remove incorrect check for bb layout order
since this is called in cfglayout mode, and replace partition fixup
with assert as that is now done by force_nonfallthru_and_redirect.
(add_reg_crossing_jump_notes): Handle the fact that some jumps may
already be marked with region crossing note.
(insert_section_boundary_note): Make non-static, gate on flag
has_bb_partition, rewrite to also check for multiple partitions.
(rest_of_handle_reorder_blocks): Remove call to
insert_section_boundary_note, now done later during free_cfg.
(duplicate_computed_gotos): Don't duplicate partition crossing edge.
* bb-reorder.h (insert_section_boundary_note): Declare.
* Makefile.in (cfgrtl.o): Depend on bb-reorder.h
* cfgrtl.c (rest_of_pass_free_cfg): If partitions exist
invoke insert_section_boundary_note.
(try_redirect_by_replacing_jump): Remove unnecessary
check for region crossing note.
(fixup_partition_crossing): New function.
(rtl_redirect_edge_and_branch): Fixup partition boundaries.
(emit_barrier_after_bb): Move here from bb-reorder.c, handle insertion
in non-cfglayout mode.
(force_nonfallthru_and_redirect): Fixup partition boundaries,
remove old code that tried to do this. Emit barrier correctly
when we are in cfglayout mode.
(last_bb_in_partition): New function.
(rtl_split_edge): Correctly fixup partition boundaries.
(commit_one_edge_insertion): Remove old code that tried to
fixup region crossing edge since this is now handled in
split_block, and set up insertion point correctly since
block may now end in a jump.
(verify_hot_cold_block_grouping): Guard against checking when not in
linearized RTL mode.
(rtl_verify_edges): Add checks for incorrect/missing REG_CROSSING_JUMP
notes.
(rtl_verify_flow_info_1): Move verify_hot_cold_block_grouping to
rtl_verify_flow_info, so not called in cfglayout mode.
(rtl_verify_flow_info): Move verify_hot_cold_block_grouping here.
(fixup_reorder_chain): Remove old code that attempted to fixup region
crossing note as this is now handled in force_nonfallthru_and_redirect.
(duplicate_insn_chain): Don't duplicate switch section notes.
(rtl_can_remove_branch_p): Remove unnecessary check for region crossing
note.
* basic-block.h (emit_barrier_after_bb): Declare.

* testsuite/gcc.dg/tree-prof/va-arg-pack-1.c: Cloned from c-torture, made
into -freorder-blocks-and-partition test.
* testsuite/gcc.dg/tree-prof/comp-goto-1.c: Ditto.
* testsuite/gcc.dg/tree-prof/20041218-1.c: Ditto.
* testsuite/gcc.dg/tree-prof/pr52027.c: Use -O2.
* testsuite/gcc.dg/tree-prof/pr50907.c: Ditto.
* testsuite/gcc.dg/tree-prof/pr45354.c: Ditto.
* testsuite/g++.dg/tree-prof/partition2.C: Ditto.
* testsuite/g++.dg/tree-prof/partition3.C: Ditto.

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

19 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/basic-block.h
gcc/bb-reorder.c
gcc/bb-reorder.h
gcc/cfgcleanup.c
gcc/cfgrtl.c
gcc/emit-rtl.c
gcc/function.c
gcc/ifcvt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-prof/partition2.C
gcc/testsuite/g++.dg/tree-prof/partition3.C
gcc/testsuite/gcc.dg/tree-prof/20041218-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-prof/comp-goto-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-prof/pr45354.c
gcc/testsuite/gcc.dg/tree-prof/pr50907.c
gcc/testsuite/gcc.dg/tree-prof/pr52027.c
gcc/testsuite/gcc.dg/tree-prof/va-arg-pack-1.c [new file with mode: 0644]

index 0febdb3..2d14419 100644 (file)
@@ -1,3 +1,57 @@
+2013-06-06  Teresa Johnson  <tejohnson@google.com>
+
+       PR c++/53743
+       * ifcvt.c (find_if_case_1): Replace BB_COPY_PARTITION with assert
+       as this is now done by redirect_edge_and_branch_force.
+       * function.c (thread_prologue_and_epilogue_insns): Insert new bb after
+       barriers, and fix interaction with splitting.
+       * emit-rtl.c (try_split): Copy REG_CROSSING_JUMP notes.
+       * cfgcleanup.c (try_forward_edges): Fix early return value to properly
+       reflect changes made in the routine.
+       * bb-reorder.c (emit_barrier_after_bb): Move to cfgrtl.c.
+       (fix_up_fall_thru_edges): Remove incorrect check for bb layout order
+       since this is called in cfglayout mode, and replace partition fixup
+       with assert as that is now done by force_nonfallthru_and_redirect.
+       (add_reg_crossing_jump_notes): Handle the fact that some jumps may
+       already be marked with region crossing note.
+       (insert_section_boundary_note): Make non-static, gate on flag
+       has_bb_partition, rewrite to also check for multiple partitions.
+       (rest_of_handle_reorder_blocks): Remove call to
+       insert_section_boundary_note, now done later during free_cfg.
+       (duplicate_computed_gotos): Don't duplicate partition crossing edge.
+       * bb-reorder.h (insert_section_boundary_note): Declare.
+       * Makefile.in (cfgrtl.o): Depend on bb-reorder.h
+       * cfgrtl.c (rest_of_pass_free_cfg): If partitions exist
+       invoke insert_section_boundary_note.
+       (try_redirect_by_replacing_jump): Remove unnecessary
+       check for region crossing note.
+       (fixup_partition_crossing): New function.
+       (rtl_redirect_edge_and_branch): Fixup partition boundaries.
+       (emit_barrier_after_bb): Move here from bb-reorder.c, handle insertion
+       in non-cfglayout mode.
+       (force_nonfallthru_and_redirect): Fixup partition boundaries,
+       remove old code that tried to do this. Emit barrier correctly
+       when we are in cfglayout mode.
+       (last_bb_in_partition): New function.
+       (rtl_split_edge): Correctly fixup partition boundaries.
+       (commit_one_edge_insertion): Remove old code that tried to
+       fixup region crossing edge since this is now handled in
+       split_block, and set up insertion point correctly since
+       block may now end in a jump.
+       (verify_hot_cold_block_grouping): Guard against checking when not in
+       linearized RTL mode.
+       (rtl_verify_edges): Add checks for incorrect/missing REG_CROSSING_JUMP
+       notes.
+       (rtl_verify_flow_info_1): Move verify_hot_cold_block_grouping to
+       rtl_verify_flow_info, so not called in cfglayout mode.
+       (rtl_verify_flow_info): Move verify_hot_cold_block_grouping here.
+       (fixup_reorder_chain): Remove old code that attempted to fixup region
+       crossing note as this is now handled in force_nonfallthru_and_redirect.
+       (duplicate_insn_chain): Don't duplicate switch section notes.
+       (rtl_can_remove_branch_p): Remove unnecessary check for region crossing
+       note.
+       * basic-block.h (emit_barrier_after_bb): Declare.
+
 2013-06-06  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/arm/arm-fixed.md (add<mode>3,usadd<mode>3,ssadd<mode>3,
index e95dd63..81f75ce 100644 (file)
@@ -3155,7 +3155,7 @@ cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
    $(FUNCTION_H) $(EXCEPT_H) $(TM_P_H) $(INSN_ATTR_H) \
    insn-config.h $(EXPR_H) \
    $(CFGLOOP_H) $(OBSTACK_H) $(TARGET_H) $(TREE_H) \
-   $(TREE_PASS_H) $(DF_H) $(GGC_H) $(COMMON_TARGET_H) gt-cfgrtl.h
+   $(TREE_PASS_H) $(DF_H) $(GGC_H) $(COMMON_TARGET_H) gt-cfgrtl.h bb-reorder.h
 cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(BASIC_BLOCK_H) \
    $(TIMEVAR_H) sbitmap.h $(BITMAP_H)
 cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
index eed320c..154dc7a 100644 (file)
@@ -796,6 +796,7 @@ extern basic_block force_nonfallthru_and_redirect (edge, basic_block, rtx);
 extern bool contains_no_active_insn_p (const_basic_block);
 extern bool forwarder_block_p (const_basic_block);
 extern bool can_fallthru (basic_block, basic_block);
+extern void emit_barrier_after_bb (basic_block bb);
 
 /* In cfgbuild.c.  */
 extern void find_many_sub_basic_blocks (sbitmap);
index 0a1f42a..d3bc4f9 100644 (file)
@@ -1380,15 +1380,6 @@ get_uncond_jump_length (void)
   return length;
 }
 
-/* Emit a barrier into the footer of BB.  */
-
-static void
-emit_barrier_after_bb (basic_block bb)
-{
-  rtx barrier = emit_barrier_after (BB_END (bb));
-  BB_FOOTER (bb) = unlink_insn_chain (barrier, barrier);
-}
-
 /* The landing pad OLD_LP, in block OLD_BB, has edges from both partitions.
    Duplicate the landing pad and split the edges so that no EH edge
    crosses partitions.  */
@@ -1720,8 +1711,7 @@ fix_up_fall_thru_edges (void)
                     (i.e. fix it so the fall through does not cross and
                     the cond jump does).  */
 
-                 if (!cond_jump_crosses
-                     && cur_bb->aux == cond_jump->dest)
+                 if (!cond_jump_crosses)
                    {
                      /* Find label in fall_thru block. We've already added
                         any missing labels, so there must be one.  */
@@ -1765,10 +1755,10 @@ fix_up_fall_thru_edges (void)
                      new_bb->aux = cur_bb->aux;
                      cur_bb->aux = new_bb;
 
-                     /* Make sure new fall-through bb is in same
-                        partition as bb it's falling through from.  */
+                      /* This is done by force_nonfallthru_and_redirect.  */
+                     gcc_assert (BB_PARTITION (new_bb)
+                                  == BB_PARTITION (cur_bb));
 
-                     BB_COPY_PARTITION (new_bb, cur_bb);
                      single_succ_edge (new_bb)->flags |= EDGE_CROSSING;
                    }
                  else
@@ -2064,7 +2054,10 @@ add_reg_crossing_jump_notes (void)
   FOR_EACH_BB (bb)
     FOR_EACH_EDGE (e, ei, bb->succs)
       if ((e->flags & EDGE_CROSSING)
-         && JUMP_P (BB_END (e->src)))
+         && JUMP_P (BB_END (e->src))
+          /* Some notes were added during fix_up_fall_thru_edges, via
+             force_nonfallthru_and_redirect.  */
+          && !find_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX))
        add_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX);
 }
 
@@ -2133,23 +2126,26 @@ reorder_basic_blocks (void)
    encountering this note will make the compiler switch between the
    hot and cold text sections.  */
 
-static void
+void
 insert_section_boundary_note (void)
 {
   basic_block bb;
-  int first_partition = 0;
+  bool switched_sections = false;
+  int current_partition = 0;
 
-  if (!flag_reorder_blocks_and_partition)
+  if (!crtl->has_bb_partition)
     return;
 
   FOR_EACH_BB (bb)
     {
-      if (!first_partition)
-       first_partition = BB_PARTITION (bb);
-      if (BB_PARTITION (bb) != first_partition)
+      if (!current_partition)
+       current_partition = BB_PARTITION (bb);
+      if (BB_PARTITION (bb) != current_partition)
        {
-         emit_note_before (NOTE_INSN_SWITCH_TEXT_SECTIONS, BB_HEAD (bb));
-         break;
+         gcc_assert (!switched_sections);
+          switched_sections = true;
+          emit_note_before (NOTE_INSN_SWITCH_TEXT_SECTIONS, BB_HEAD (bb));
+          current_partition = BB_PARTITION (bb);
        }
     }
 }
@@ -2180,8 +2176,6 @@ rest_of_handle_reorder_blocks (void)
       bb->aux = bb->next_bb;
   cfg_layout_finalize ();
 
-  /* Add NOTE_INSN_SWITCH_TEXT_SECTIONS notes.  */
-  insert_section_boundary_note ();
   return 0;
 }
 
@@ -2315,6 +2309,11 @@ duplicate_computed_gotos (void)
       if (!bitmap_bit_p (candidates, single_succ (bb)->index))
        continue;
 
+      /* Don't duplicate a partition crossing edge, which requires difficult
+         fixup.  */
+      if (find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX))
+       continue;
+
       new_bb = duplicate_block (single_succ (bb), single_succ_edge (bb), bb);
       new_bb->aux = bb->aux;
       bb->aux = new_bb;
index 5c68e3d..025300c 100644 (file)
@@ -35,4 +35,6 @@ extern struct target_bb_reorder *this_target_bb_reorder;
 
 extern int get_uncond_jump_length (void);
 
+extern void insert_section_boundary_note (void);
+
 #endif
index 1379cf7..99e0baa 100644 (file)
@@ -456,7 +456,7 @@ try_forward_edges (int mode, basic_block b)
 
       if (first != EXIT_BLOCK_PTR
          && find_reg_note (BB_END (first), REG_CROSSING_JUMP, NULL_RTX))
-       return false;
+       return changed;
 
       while (counter < n_basic_blocks)
        {
index 0ea297e..36438b8 100644 (file)
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
+#include "bb-reorder.h"
 #include "regs.h"
 #include "flags.h"
 #include "function.h"
@@ -451,6 +452,9 @@ rest_of_pass_free_cfg (void)
     }
 #endif
 
+  if (crtl->has_bb_partition)
+    insert_section_boundary_note ();
+
   free_bb_for_insn ();
   return 0;
 }
@@ -981,8 +985,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
      partition boundaries).  See  the comments at the top of
      bb-reorder.c:partition_hot_cold_basic_blocks for complete details.  */
 
-  if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)
-      || BB_PARTITION (src) != BB_PARTITION (target))
+  if (BB_PARTITION (src) != BB_PARTITION (target))
     return NULL;
 
   /* We can replace or remove a complex jump only when we have exactly
@@ -1291,6 +1294,53 @@ redirect_branch_edge (edge e, basic_block target)
   return e;
 }
 
+/* Called when edge E has been redirected to a new destination,
+   in order to update the region crossing flag on the edge and
+   jump.  */
+
+static void
+fixup_partition_crossing (edge e)
+{
+  rtx note;
+
+  if (e->src == ENTRY_BLOCK_PTR || e->dest == EXIT_BLOCK_PTR)
+    return;
+  /* If we redirected an existing edge, it may already be marked
+     crossing, even though the new src is missing a reg crossing note.
+     But make sure reg crossing note doesn't already exist before
+     inserting.  */
+  if (BB_PARTITION (e->src) != BB_PARTITION (e->dest))
+    {
+      e->flags |= EDGE_CROSSING;
+      note = find_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX);
+      if (JUMP_P (BB_END (e->src))
+          && !note)
+        add_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX);
+    }
+  else if (BB_PARTITION (e->src) == BB_PARTITION (e->dest))
+    {
+      e->flags &= ~EDGE_CROSSING;
+      /* Remove the section crossing note from jump at end of
+         src if it exists, and if no other successors are
+         still crossing.  */
+      note = find_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX);
+      if (note)
+        {
+          bool has_crossing_succ = false;
+          edge e2;
+          edge_iterator ei;
+          FOR_EACH_EDGE (e2, ei, e->src->succs)
+            {
+              has_crossing_succ |= (e2->flags & EDGE_CROSSING);
+              if (has_crossing_succ)
+                break;
+            }
+          if (!has_crossing_succ)
+            remove_note (BB_END (e->src), note);
+        }
+    }
+}
+
 /* Attempt to change code to redirect edge E to TARGET.  Don't do that on
    expense of adding new instructions or reordering basic blocks.
 
@@ -1307,16 +1357,18 @@ rtl_redirect_edge_and_branch (edge e, basic_block target)
 {
   edge ret;
   basic_block src = e->src;
+  basic_block dest = e->dest;
 
   if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
     return NULL;
 
-  if (e->dest == target)
+  if (dest == target)
     return e;
 
   if ((ret = try_redirect_by_replacing_jump (e, target, false)) != NULL)
     {
       df_set_bb_dirty (src);
+      fixup_partition_crossing (ret);
       return ret;
     }
 
@@ -1325,9 +1377,22 @@ rtl_redirect_edge_and_branch (edge e, basic_block target)
     return NULL;
 
   df_set_bb_dirty (src);
+  fixup_partition_crossing (ret);
   return ret;
 }
 
+/* Emit a barrier after BB, into the footer if we are in CFGLAYOUT mode.  */
+
+void
+emit_barrier_after_bb (basic_block bb)
+{
+  rtx barrier = emit_barrier_after (BB_END (bb));
+  gcc_assert (current_ir_type() == IR_RTL_CFGRTL
+              || current_ir_type () == IR_RTL_CFGLAYOUT);
+  if (current_ir_type () == IR_RTL_CFGLAYOUT)
+    BB_FOOTER (bb) = unlink_insn_chain (barrier, barrier);
+}
+
 /* Like force_nonfallthru below, but additionally performs redirection
    Used by redirect_edge_and_branch_force.  JUMP_LABEL is used only
    when redirecting to the EXIT_BLOCK, it is either ret_rtx or
@@ -1492,12 +1557,6 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
       /* Make sure new block ends up in correct hot/cold section.  */
 
       BB_COPY_PARTITION (jump_block, e->src);
-      if (flag_reorder_blocks_and_partition
-         && targetm_common.have_named_sections
-         && JUMP_P (BB_END (jump_block))
-         && !any_condjump_p (BB_END (jump_block))
-         && (EDGE_SUCC (jump_block, 0)->flags & EDGE_CROSSING))
-       add_reg_note (BB_END (jump_block), REG_CROSSING_JUMP, NULL_RTX);
 
       /* Wire edge in.  */
       new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
@@ -1508,6 +1567,10 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
       redirect_edge_pred (e, jump_block);
       e->probability = REG_BR_PROB_BASE;
 
+      /* If e->src was previously region crossing, it no longer is
+         and the reg crossing note should be removed.  */
+      fixup_partition_crossing (new_edge);
+
       /* If asm goto has any label refs to target's label,
         add also edge from asm goto bb to target.  */
       if (asm_goto_edge)
@@ -1559,13 +1622,16 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
       LABEL_NUSES (label)++;
     }
 
-  emit_barrier_after (BB_END (jump_block));
+  /* We might be in cfg layout mode, and if so, the following routine will
+     insert the barrier correctly.  */
+  emit_barrier_after_bb (jump_block);
   redirect_edge_succ_nodup (e, target);
 
   if (abnormal_edge_flags)
     make_edge (src, target, abnormal_edge_flags);
 
   df_mark_solutions_dirty ();
+  fixup_partition_crossing (e);
   return new_bb;
 }
 
@@ -1654,6 +1720,21 @@ rtl_move_block_after (basic_block bb ATTRIBUTE_UNUSED,
   return false;
 }
 
+/* Locate the last bb in the same partition as START_BB.  */
+
+static basic_block
+last_bb_in_partition (basic_block start_bb)
+{
+  basic_block bb;
+  FOR_BB_BETWEEN (bb, start_bb, EXIT_BLOCK_PTR, next_bb)
+    {
+      if (BB_PARTITION (start_bb) != BB_PARTITION (bb->next_bb))
+        return bb;
+    }
+  /* Return bb before EXIT_BLOCK_PTR.  */
+  return bb->prev_bb;
+}
+
 /* Split a (typically critical) edge.  Return the new block.
    The edge must not be abnormal.
 
@@ -1664,7 +1745,7 @@ rtl_move_block_after (basic_block bb ATTRIBUTE_UNUSED,
 static basic_block
 rtl_split_edge (edge edge_in)
 {
-  basic_block bb;
+  basic_block bb, new_bb;
   rtx before;
 
   /* Abnormal edges cannot be split.  */
@@ -1696,13 +1777,50 @@ rtl_split_edge (edge edge_in)
     }
   else
     {
-      bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
-      /* ??? Why not edge_in->dest->prev_bb here?  */
-      BB_COPY_PARTITION (bb, edge_in->dest);
+      if (edge_in->src == ENTRY_BLOCK_PTR)
+        {
+          bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
+          BB_COPY_PARTITION (bb, edge_in->dest);
+        }
+      else
+        {
+          basic_block after = edge_in->dest->prev_bb;
+          /* If this is post-bb reordering, and the edge crosses a partition
+             boundary, the new block needs to be inserted in the bb chain
+             at the end of the src partition (since we put the new bb into
+             that partition, see below). Otherwise we may end up creating
+             an extra partition crossing in the chain, which is illegal.
+             It can't go after the src, because src may have a fall-through
+             to a different block.  */
+          if (crtl->bb_reorder_complete
+              && (edge_in->flags & EDGE_CROSSING))
+            {
+              after = last_bb_in_partition (edge_in->src);
+              before = NEXT_INSN (BB_END (after));
+              /* The instruction following the last bb in partition should
+                 be a barrier, since it cannot end in a fall-through.  */
+              gcc_checking_assert (BARRIER_P (before));
+              before = NEXT_INSN (before);
+            }
+          bb = create_basic_block (before, NULL, after);
+          /* Put the split bb into the src partition, to avoid creating
+             a situation where a cold bb dominates a hot bb, in the case
+             where src is cold and dest is hot. The src will dominate
+             the new bb (whereas it might not have dominated dest).  */
+          BB_COPY_PARTITION (bb, edge_in->src);
+        }
     }
 
   make_single_succ_edge (bb, edge_in->dest, EDGE_FALLTHRU);
 
+  /* Can't allow a region crossing edge to be fallthrough.  */
+  if (BB_PARTITION (bb) != BB_PARTITION (edge_in->dest)
+      && edge_in->dest != EXIT_BLOCK_PTR)
+    {
+      new_bb = force_nonfallthru (single_succ_edge (bb));
+      gcc_assert (!new_bb);
+    }
+
   /* For non-fallthru edges, we must adjust the predecessor's
      jump instruction to target our new block.  */
   if ((edge_in->flags & EDGE_FALLTHRU) == 0)
@@ -1815,17 +1933,13 @@ commit_one_edge_insertion (edge e)
   else
     {
       bb = split_edge (e);
-      after = BB_END (bb);
-
-      if (flag_reorder_blocks_and_partition
-         && targetm_common.have_named_sections
-         && e->src != ENTRY_BLOCK_PTR
-         && BB_PARTITION (e->src) == BB_COLD_PARTITION
-         && !(e->flags & EDGE_CROSSING)
-         && JUMP_P (after)
-         && !any_condjump_p (after)
-         && (single_succ_edge (bb)->flags & EDGE_CROSSING))
-       add_reg_note (after, REG_CROSSING_JUMP, NULL_RTX);
+
+      /* If E crossed a partition boundary, we needed to make bb end in
+         a region-crossing jump, even though it was originally fallthru.  */
+      if (JUMP_P (BB_END (bb)))
+       before = BB_END (bb);
+      else
+        after = BB_END (bb);
     }
 
   /* Now that we've found the spot, do the insertion.  */
@@ -2071,7 +2185,11 @@ verify_hot_cold_block_grouping (void)
   bool switched_sections = false;
   int current_partition = BB_UNPARTITIONED;
 
-  if (!crtl->bb_reorder_complete)
+  /* Even after bb reordering is complete, we go into cfglayout mode
+     again (in compgoto). Ensure we don't call this before going back
+     into linearized RTL when any layout fixes would have been committed.  */
+  if (!crtl->bb_reorder_complete
+      || current_ir_type() != IR_RTL_CFGRTL)
     return err;
 
   FOR_EACH_BB (bb)
@@ -2116,6 +2234,7 @@ rtl_verify_edges (void)
       edge e, fallthru = NULL;
       edge_iterator ei;
       rtx note;
+      bool has_crossing_edge = false;
 
       if (JUMP_P (BB_END (bb))
          && (note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX))
@@ -2141,6 +2260,7 @@ rtl_verify_edges (void)
          is_crossing = (BB_PARTITION (e->src) != BB_PARTITION (e->dest)
                         && e->src != ENTRY_BLOCK_PTR
                         && e->dest != EXIT_BLOCK_PTR);
+          has_crossing_edge |= is_crossing;
          if (e->flags & EDGE_CROSSING)
            {
              if (!is_crossing)
@@ -2160,6 +2280,13 @@ rtl_verify_edges (void)
                         e->src->index);
                  err = 1;
                }
+              if (JUMP_P (BB_END (bb))
+                  && !find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX))
+               {
+                 error ("No region crossing jump at section boundary in bb %i",
+                        bb->index);
+                 err = 1;
+               }
            }
          else if (is_crossing)
            {
@@ -2188,6 +2315,15 @@ rtl_verify_edges (void)
            n_abnormal++;
        }
 
+        if (!has_crossing_edge
+            && find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX))
+          {
+            print_rtl_with_bb (stderr, get_insns (), TDF_RTL | TDF_BLOCKS | TDF_DETAILS);
+            error ("Region crossing jump across same section in bb %i",
+                   bb->index);
+            err = 1;
+          }
+
       if (n_eh && !find_reg_note (BB_END (bb), REG_EH_REGION, NULL_RTX))
        {
          error ("missing REG_EH_REGION note at the end of bb %i", bb->index);
@@ -2395,8 +2531,6 @@ rtl_verify_flow_info_1 (void)
 
   err |= rtl_verify_edges ();
 
-  err |= verify_hot_cold_block_grouping();
-
   return err;
 }
 
@@ -2642,6 +2776,8 @@ rtl_verify_flow_info (void)
 
   err |= rtl_verify_bb_layout ();
 
+  err |= verify_hot_cold_block_grouping ();
+
   return err;
 }
 \f
@@ -3343,7 +3479,7 @@ fixup_reorder_chain (void)
       edge e_fall, e_taken, e;
       rtx bb_end_insn;
       rtx ret_label = NULL_RTX;
-      basic_block nb, src_bb;
+      basic_block nb;
       edge_iterator ei;
 
       if (EDGE_COUNT (bb->succs) == 0)
@@ -3478,7 +3614,6 @@ fixup_reorder_chain (void)
       /* We got here if we need to add a new jump insn. 
         Note force_nonfallthru can delete E_FALL and thus we have to
         save E_FALL->src prior to the call to force_nonfallthru.  */
-      src_bb = e_fall->src;
       nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
       if (nb)
        {
@@ -3486,17 +3621,6 @@ fixup_reorder_chain (void)
          bb->aux = nb;
          /* Don't process this new block.  */
          bb = nb;
-
-         /* Make sure new bb is tagged for correct section (same as
-            fall-thru source, since you cannot fall-thru across
-            section boundaries).  */
-         BB_COPY_PARTITION (src_bb, single_pred (bb));
-         if (flag_reorder_blocks_and_partition
-             && targetm_common.have_named_sections
-             && JUMP_P (BB_END (bb))
-             && !any_condjump_p (BB_END (bb))
-             && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING))
-           add_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX);
        }
     }
 
@@ -3796,10 +3920,11 @@ duplicate_insn_chain (rtx from, rtx to)
            case NOTE_INSN_FUNCTION_BEG:
              /* There is always just single entry to function.  */
            case NOTE_INSN_BASIC_BLOCK:
+              /* We should only switch text sections once.  */
+           case NOTE_INSN_SWITCH_TEXT_SECTIONS:
              break;
 
            case NOTE_INSN_EPILOGUE_BEG:
-           case NOTE_INSN_SWITCH_TEXT_SECTIONS:
              emit_note_copy (insn);
              break;
 
@@ -4611,8 +4736,7 @@ rtl_can_remove_branch_p (const_edge e)
   if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
     return false;
 
-  if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)
-      || BB_PARTITION (src) != BB_PARTITION (target))
+  if (BB_PARTITION (src) != BB_PARTITION (target))
     return false;
 
   if (!onlyjump_p (insn)
index fc56776..8a7b8a5 100644 (file)
@@ -3574,6 +3574,7 @@ try_split (rtx pat, rtx trial, int last)
          break;
 
        case REG_NON_LOCAL_GOTO:
+       case REG_CROSSING_JUMP:
          for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn))
            {
              if (JUMP_P (insn))
index 36c874f..39fa22a 100644 (file)
@@ -6270,8 +6270,10 @@ thread_prologue_and_epilogue_insns (void)
                    break;
                if (e)
                  {
-                   copy_bb = create_basic_block (NEXT_INSN (BB_END (e->src)),
-                                                 NULL_RTX, e->src);
+                    /* Make sure we insert after any barriers.  */
+                    rtx end = get_last_bb_insn (e->src);
+                    copy_bb = create_basic_block (NEXT_INSN (end),
+                                                  NULL_RTX, e->src);
                    BB_COPY_PARTITION (copy_bb, e->src);
                  }
                else
@@ -6538,7 +6540,7 @@ epilogue_done:
       basic_block simple_return_block_cold = NULL;
       edge pending_edge_hot = NULL;
       edge pending_edge_cold = NULL;
-      basic_block exit_pred = EXIT_BLOCK_PTR->prev_bb;
+      basic_block exit_pred;
       int i;
 
       gcc_assert (entry_edge != orig_entry_edge);
@@ -6566,6 +6568,12 @@ epilogue_done:
            else
              pending_edge_cold = e;
          }
+      
+      /* Save a pointer to the exit's predecessor BB for use in
+         inserting new BBs at the end of the function. Do this
+         after the call to split_block above which may split
+         the original exit pred.  */
+      exit_pred = EXIT_BLOCK_PTR->prev_bb;
 
       FOR_EACH_VEC_ELT (unconverted_simple_returns, i, e)
        {
index 4057577..c6c2aeb 100644 (file)
@@ -3905,10 +3905,9 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
   if (new_bb)
     {
       df_bb_replace (then_bb_index, new_bb);
-      /* Since the fallthru edge was redirected from test_bb to new_bb,
-         we need to ensure that new_bb is in the same partition as
-         test bb (you can not fall through across section boundaries).  */
-      BB_COPY_PARTITION (new_bb, test_bb);
+      /* This should have been done above via force_nonfallthru_and_redirect
+         (possibly called from redirect_edge_and_branch_force).  */
+      gcc_checking_assert (BB_PARTITION (new_bb) == BB_PARTITION (test_bb));
     }
 
   num_true_changes++;
index 67b5d63..035781b 100644 (file)
@@ -1,3 +1,16 @@
+2013-06-06  Teresa Johnson  <tejohnson@google.com>
+
+       PR c++/53743
+       * gcc.dg/tree-prof/va-arg-pack-1.c: Cloned from c-torture, made
+       into -freorder-blocks-and-partition test.
+       * gcc.dg/tree-prof/comp-goto-1.c: Ditto.
+       * gcc.dg/tree-prof/20041218-1.c: Ditto.
+       * gcc.dg/tree-prof/pr52027.c: Use -O2.
+       * gcc.dg/tree-prof/pr50907.c: Ditto.
+       * gcc.dg/tree-prof/pr45354.c: Ditto.
+       * g++.dg/tree-prof/partition2.C: Ditto.
+       * g++.dg/tree-prof/partition3.C: Ditto.
+
 2013-06-06  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/57542
index ca5671f..0bc50fa 100644 (file)
@@ -1,6 +1,6 @@
 // PR middle-end/45458
 // { dg-require-effective-target freorder }
-// { dg-options "-fnon-call-exceptions -freorder-blocks-and-partition" }
+// { dg-options "-O2 -fnon-call-exceptions -freorder-blocks-and-partition" }
 
 int
 main ()
index 7846983..c62174a 100644 (file)
@@ -1,6 +1,6 @@
 // PR middle-end/45566
 // { dg-require-effective-target freorder }
-// { dg-options "-O -fnon-call-exceptions -freorder-blocks-and-partition" }
+// { dg-options "-O2 -fnon-call-exceptions -freorder-blocks-and-partition" }
 
 int k;
 
diff --git a/gcc/testsuite/gcc.dg/tree-prof/20041218-1.c b/gcc/testsuite/gcc.dg/tree-prof/20041218-1.c
new file mode 100644 (file)
index 0000000..cbd1c7c
--- /dev/null
@@ -0,0 +1,119 @@
+/* PR rtl-optimization/16968 */
+/* Testcase by Jakub Jelinek  <jakub@redhat.com> */
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -freorder-blocks-and-partition" } */
+
+struct T
+{
+  unsigned int b, c, *d;
+  unsigned char e;
+};
+struct S
+{
+  unsigned int a;
+  struct T f;
+};
+struct U
+{
+  struct S g, h;
+};
+struct V
+{
+  unsigned int i;
+  struct U j;
+};
+
+extern void exit (int);
+extern void abort (void);
+
+void *
+dummy1 (void *x)
+{
+  return "";
+}
+
+void *
+dummy2 (void *x, void *y)
+{
+  exit (0);
+}
+
+struct V *
+baz (unsigned int x)
+{
+  static struct V v;
+  __builtin_memset (&v, 0x55, sizeof (v));
+  return &v;
+}
+
+int
+check (void *x, struct S *y)
+{
+  if (y->a || y->f.b || y->f.c || y->f.d || y->f.e)
+    abort ();
+  return 1;
+}
+
+static struct V *
+bar (unsigned int x, void *y)
+{
+  const struct T t = { 0, 0, (void *) 0, 0 };
+  struct V *u;
+  void *v;
+  v = dummy1 (y);
+  if (!v)
+    return (void *) 0;
+
+  u = baz (sizeof (struct V));
+  u->i = x;
+  u->j.g.a = 0;
+  u->j.g.f = t;
+  u->j.h.a = 0;
+  u->j.h.f = t;
+
+  if (!check (v, &u->j.g) || !check (v, &u->j.h))
+    return (void *) 0;
+  return u;
+}
+
+int
+foo (unsigned int *x, unsigned int y, void **z)
+{
+  void *v;
+  unsigned int i, j;
+
+  *z = v = (void *) 0;
+
+  for (i = 0; i < y; i++)
+    {
+      struct V *c;
+
+      j = *x;
+
+      switch (j)
+       {
+       case 1:
+         c = bar (j, x);
+         break;
+       default:
+         c = 0;
+         break;
+       }
+      if (c)
+       v = dummy2 (v, c);
+      else
+        return 1;
+    }
+
+  *z = v;
+  return 0;
+}
+
+int
+main (void)
+{
+  unsigned int one = 1;
+  void *p;
+  foo (&one, 1, &p);
+  abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/tree-prof/comp-goto-1.c b/gcc/testsuite/gcc.dg/tree-prof/comp-goto-1.c
new file mode 100644 (file)
index 0000000..bbfe1f4
--- /dev/null
@@ -0,0 +1,166 @@
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -freorder-blocks-and-partition" } */
+#include <stdlib.h>
+
+#if !defined(NO_LABEL_VALUES) && (!defined(STACK_SIZE) || STACK_SIZE >= 4000) && __INT_MAX__ >= 2147483647
+typedef unsigned int uint32;
+typedef signed int sint32;
+
+typedef uint32 reg_t;
+
+typedef unsigned long int host_addr_t;
+typedef uint32 target_addr_t;
+typedef sint32 target_saddr_t;
+
+typedef union
+{
+  struct
+    {
+      unsigned int     offset:18;
+      unsigned int     ignore:4;
+      unsigned int     s1:8;
+      int              :2;
+      signed int       simm:14;
+      unsigned int     s3:8;
+      unsigned int     s2:8;
+      int              pad2:2;
+    } f1;
+  long long ll;
+  double d;
+} insn_t;
+
+typedef struct
+{
+  target_addr_t vaddr_tag;
+  unsigned long int rigged_paddr;
+} tlb_entry_t;
+
+typedef struct
+{
+  insn_t *pc;
+  reg_t registers[256];
+  insn_t *program;
+  tlb_entry_t tlb_tab[0x100];
+} environment_t;
+
+enum operations
+{
+  LOAD32_RR,
+  METAOP_DONE
+};
+
+host_addr_t
+f ()
+{
+  abort ();
+}
+
+reg_t
+simulator_kernel (int what, environment_t *env)
+{
+  register insn_t *pc = env->pc;
+  register reg_t *regs = env->registers;
+  register insn_t insn;
+  register int s1;
+  register reg_t r2;
+  register void *base_addr = &&sim_base_addr;
+  register tlb_entry_t *tlb = env->tlb_tab;
+
+  if (what != 0)
+    {
+      int i;
+      static void *op_map[] =
+       {
+         &&L_LOAD32_RR,
+         &&L_METAOP_DONE,
+       };
+      insn_t *program = env->program;
+      for (i = 0; i < what; i++)
+       program[i].f1.offset = op_map[program[i].f1.offset] - base_addr;
+    }
+
+ sim_base_addr:;
+
+  insn = *pc++;
+  r2 = (*(reg_t *) (((char *) regs) + (insn.f1.s2 << 2)));
+  s1 = (insn.f1.s1 << 2);
+  goto *(base_addr + insn.f1.offset);
+
+ L_LOAD32_RR:
+  {
+    target_addr_t vaddr_page = r2 / 4096;
+    unsigned int x = vaddr_page % 0x100;
+    insn = *pc++;
+
+    for (;;)
+      {
+       target_addr_t tag = tlb[x].vaddr_tag;
+       host_addr_t rigged_paddr = tlb[x].rigged_paddr;
+
+       if (tag == vaddr_page)
+         {
+           *(reg_t *) (((char *) regs) + s1) = *(uint32 *) (rigged_paddr + r2);
+           r2 = *(reg_t *) (((char *) regs) + (insn.f1.s2 << 2));
+           s1 = insn.f1.s1 << 2;
+           goto *(base_addr + insn.f1.offset);
+         }
+
+       if (((target_saddr_t) tag < 0))
+         {
+           *(reg_t *) (((char *) regs) + s1) = *(uint32 *) f ();
+           r2 = *(reg_t *) (((char *) regs) + (insn.f1.s2 << 2));
+           s1 = insn.f1.s1 << 2;
+           goto *(base_addr + insn.f1.offset);
+         }
+
+       x = (x - 1) % 0x100;
+      }
+
+    L_METAOP_DONE:
+      return (*(reg_t *) (((char *) regs) + s1));
+  }
+}
+
+insn_t program[2 + 1];
+
+void *malloc ();
+
+int
+main ()
+{
+  environment_t env;
+  insn_t insn;
+  int i, res;
+  host_addr_t a_page = (host_addr_t) malloc (2 * 4096);
+  target_addr_t a_vaddr = 0x123450;
+  target_addr_t vaddr_page = a_vaddr / 4096;
+  a_page = (a_page + 4096 - 1) & -4096;
+
+  env.tlb_tab[((vaddr_page) % 0x100)].vaddr_tag = vaddr_page;
+  env.tlb_tab[((vaddr_page) % 0x100)].rigged_paddr = a_page - vaddr_page * 4096;
+  insn.f1.offset = LOAD32_RR;
+  env.registers[0] = 0;
+  env.registers[2] = a_vaddr;
+  *(sint32 *) (a_page + a_vaddr % 4096) = 88;
+  insn.f1.s1 = 0;
+  insn.f1.s2 = 2;
+
+  for (i = 0; i < 2; i++)
+    program[i] = insn;
+
+  insn.f1.offset = METAOP_DONE;
+  insn.f1.s1 = 0;
+  program[2] = insn;
+
+  env.pc = program;
+  env.program = program;
+
+  res = simulator_kernel (2 + 1, &env);
+
+  if (res != 88)
+    abort ();
+  exit (0);
+}
+#else
+main(){ exit (0); }
+#endif
index b30ad77..849e786 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-require-effective-target freorder } */
-/* { dg-options "-O -freorder-blocks-and-partition -fschedule-insns -fselective-scheduling" { target powerpc*-*-* ia64-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -freorder-blocks-and-partition -fschedule-insns -fselective-scheduling" { target powerpc*-*-* ia64-*-* x86_64-*-* } } */
 
 extern void abort (void);
 
index 2ba26e3..b850513 100644 (file)
@@ -1,5 +1,5 @@
 /* PR middle-end/50907 */
 /* { dg-require-effective-target freorder } */
-/* { dg-options "-O -freorder-blocks-and-partition -fschedule-insns -fselective-scheduling -fpic" { target { { powerpc*-*-* ia64-*-* x86_64-*-* } && fpic } } } */
+/* { dg-options "-O2 -freorder-blocks-and-partition -fschedule-insns -fselective-scheduling -fpic" { target { { powerpc*-*-* ia64-*-* x86_64-*-* } && fpic } } } */
 
 #include "pr45354.c"
index c12f8b4..c46a14b 100644 (file)
@@ -1,6 +1,6 @@
 /* PR debug/52027 */
 /* { dg-require-effective-target freorder } */
-/* { dg-options "-O -freorder-blocks-and-partition -fno-reorder-functions" } */
+/* { dg-options "-O2 -freorder-blocks-and-partition -fno-reorder-functions" } */
 
 void
 foo (int len)
diff --git a/gcc/testsuite/gcc.dg/tree-prof/va-arg-pack-1.c b/gcc/testsuite/gcc.dg/tree-prof/va-arg-pack-1.c
new file mode 100644 (file)
index 0000000..8d17dbf
--- /dev/null
@@ -0,0 +1,145 @@
+/* __builtin_va_arg_pack () builtin tests.  */
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -freorder-blocks-and-partition" } */
+
+#include <stdarg.h>
+
+extern void abort (void);
+
+int v1 = 8;
+long int v2 = 3;
+void *v3 = (void *) &v2;
+struct A { char c[16]; } v4 = { "foo" };
+long double v5 = 40;
+char seen[20];
+int cnt;
+
+__attribute__ ((noinline)) int
+foo1 (int x, int y, ...)
+{
+  int i;
+  long int l;
+  void *v;
+  struct A a;
+  long double ld;
+  va_list ap;
+
+  va_start (ap, y);
+  if (x < 0 || x >= 20 || seen[x])
+    abort ();
+  seen[x] = ++cnt;
+  if (y != 6)
+    abort ();
+  i = va_arg (ap, int);
+  if (i != 5)
+    abort ();
+  switch (x)
+    {
+    case 0:
+      i = va_arg (ap, int);
+      if (i != 9 || v1 != 9)
+       abort ();
+      a = va_arg (ap, struct A);
+      if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0)
+       abort ();
+      v = (void *) va_arg (ap, struct A *);
+      if (v != (void *) &v4)
+       abort ();
+      l = va_arg (ap, long int);
+      if (l != 3 || v2 != 4)
+       abort ();
+      break;
+    case 1:
+      ld = va_arg (ap, long double);
+      if (ld != 41 || v5 != ld)
+       abort ();
+      i = va_arg (ap, int);
+      if (i != 8)
+       abort ();
+      v = va_arg (ap, void *);
+      if (v != &v2)
+       abort ();
+      break;
+    case 2:
+      break;
+    default:
+      abort ();
+    }
+  va_end (ap);
+  return x;
+}
+
+__attribute__ ((noinline)) int
+foo2 (int x, int y, ...)
+{
+  long long int ll;
+  void *v;
+  struct A a, b;
+  long double ld;
+  va_list ap;
+
+  va_start (ap, y);
+  if (x < 0 || x >= 20 || seen[x])
+    abort ();
+  seen[x] = ++cnt | 64;
+  if (y != 10)
+    abort ();
+  switch (x)
+    {
+    case 11:
+      break;
+    case 12:
+      ld = va_arg (ap, long double);
+      if (ld != 41 || v5 != 40)
+       abort ();
+      a = va_arg (ap, struct A);
+      if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0)
+       abort ();
+      b = va_arg (ap, struct A);
+      if (__builtin_memcmp (b.c, v4.c, sizeof (b.c)) != 0)
+       abort ();
+      v = va_arg (ap, void *);
+      if (v != &v2)
+       abort ();
+      ll = va_arg (ap, long long int);
+      if (ll != 16LL)
+       abort ();
+      break;
+    case 2:
+      break;
+    default:
+      abort ();
+    }
+  va_end (ap);
+  return x + 8;
+}
+
+__attribute__ ((noinline)) int
+foo3 (void)
+{
+  return 6;
+}
+
+extern inline __attribute__ ((always_inline, gnu_inline)) int
+bar (int x, ...)
+{
+  if (x < 10)
+    return foo1 (x, foo3 (), 5, __builtin_va_arg_pack ());
+  return foo2 (x, foo3 () + 4, __builtin_va_arg_pack ());
+}
+
+int
+main (void)
+{
+  if (bar (0, ++v1, v4, &v4, v2++) != 0)
+    abort ();
+  if (bar (1, ++v5, 8, v3) != 1)
+    abort ();
+  if (bar (2) != 2)
+    abort ();
+  if (bar (v1 + 2) != 19)
+    abort ();
+  if (bar (v1 + 3, v5--, v4, v4, v3, 16LL) != 20)
+    abort ();
+  return 0;
+}