diff options
author | Teresa Johnson <tejohnson@google.com> | 2013-06-06 16:30:07 +0000 |
---|---|---|
committer | Teresa Johnson <tejohnson@gcc.gnu.org> | 2013-06-06 16:30:07 +0000 |
commit | 3371a64f00ea4bbcb9752c952cd9b2fafc9c9d27 (patch) | |
tree | 16bf9573b52b0a038e49fde2d0f5bda9f0f70dd8 /gcc | |
parent | 66071e103cdaf8535c63a096aab414db51e06c99 (diff) | |
download | gcc-3371a64f00ea4bbcb9752c952cd9b2fafc9c9d27.zip gcc-3371a64f00ea4bbcb9752c952cd9b2fafc9c9d27.tar.gz gcc-3371a64f00ea4bbcb9752c952cd9b2fafc9c9d27.tar.bz2 |
re PR c++/53743 (ICE when compiling firefox with PGO and LTO)
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.
* 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.
From-SVN: r199744
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 54 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/basic-block.h | 1 | ||||
-rw-r--r-- | gcc/bb-reorder.c | 49 | ||||
-rw-r--r-- | gcc/bb-reorder.h | 2 | ||||
-rw-r--r-- | gcc/cfgcleanup.c | 2 | ||||
-rw-r--r-- | gcc/cfgrtl.c | 212 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 1 | ||||
-rw-r--r-- | gcc/function.c | 14 | ||||
-rw-r--r-- | gcc/ifcvt.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-prof/partition2.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-prof/partition3.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-prof/20041218-1.c | 119 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-prof/comp-goto-1.c | 166 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-prof/pr45354.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-prof/pr50907.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-prof/pr52027.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-prof/va-arg-pack-1.c | 145 |
19 files changed, 714 insertions, 83 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0febdb3..2d14419 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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, diff --git a/gcc/Makefile.in b/gcc/Makefile.in index e95dd63..81f75ce 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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) \ diff --git a/gcc/basic-block.h b/gcc/basic-block.h index eed320c..154dc7a 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -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); diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index 0a1f42a..d3bc4f9 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -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; diff --git a/gcc/bb-reorder.h b/gcc/bb-reorder.h index 5c68e3d..025300c 100644 --- a/gcc/bb-reorder.h +++ b/gcc/bb-reorder.h @@ -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 diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 1379cf7..99e0baa 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -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) { diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 0ea297e..36438b8 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -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; } @@ -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) diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index fc56776..8a7b8a5 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -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)) diff --git a/gcc/function.c b/gcc/function.c index 36c874f..39fa22a 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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) { diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 4057577..c6c2aeb 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -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++; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 67b5d63..035781b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/tree-prof/partition2.C b/gcc/testsuite/g++.dg/tree-prof/partition2.C index ca5671f..0bc50fa 100644 --- a/gcc/testsuite/g++.dg/tree-prof/partition2.C +++ b/gcc/testsuite/g++.dg/tree-prof/partition2.C @@ -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 () diff --git a/gcc/testsuite/g++.dg/tree-prof/partition3.C b/gcc/testsuite/g++.dg/tree-prof/partition3.C index 7846983..c62174a 100644 --- a/gcc/testsuite/g++.dg/tree-prof/partition3.C +++ b/gcc/testsuite/g++.dg/tree-prof/partition3.C @@ -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 index 0000000..cbd1c7c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-prof/20041218-1.c @@ -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 index 0000000..bbfe1f4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-prof/comp-goto-1.c @@ -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 diff --git a/gcc/testsuite/gcc.dg/tree-prof/pr45354.c b/gcc/testsuite/gcc.dg/tree-prof/pr45354.c index b30ad77..849e786 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/pr45354.c +++ b/gcc/testsuite/gcc.dg/tree-prof/pr45354.c @@ -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); diff --git a/gcc/testsuite/gcc.dg/tree-prof/pr50907.c b/gcc/testsuite/gcc.dg/tree-prof/pr50907.c index 2ba26e3..b850513 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/pr50907.c +++ b/gcc/testsuite/gcc.dg/tree-prof/pr50907.c @@ -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" diff --git a/gcc/testsuite/gcc.dg/tree-prof/pr52027.c b/gcc/testsuite/gcc.dg/tree-prof/pr52027.c index c12f8b4..c46a14b 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/pr52027.c +++ b/gcc/testsuite/gcc.dg/tree-prof/pr52027.c @@ -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 index 0000000..8d17dbf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-prof/va-arg-pack-1.c @@ -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; +} |