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
This commit is contained in:
parent
66071e103c
commit
3371a64f00
19 changed files with 713 additions and 82 deletions
|
@ -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,
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
210
gcc/cfgrtl.c
210
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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
119
gcc/testsuite/gcc.dg/tree-prof/20041218-1.c
Normal file
119
gcc/testsuite/gcc.dg/tree-prof/20041218-1.c
Normal file
|
@ -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 ();
|
||||
}
|
166
gcc/testsuite/gcc.dg/tree-prof/comp-goto-1.c
Normal file
166
gcc/testsuite/gcc.dg/tree-prof/comp-goto-1.c
Normal file
|
@ -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
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
145
gcc/testsuite/gcc.dg/tree-prof/va-arg-pack-1.c
Normal file
145
gcc/testsuite/gcc.dg/tree-prof/va-arg-pack-1.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue