cfgrtl.c (verify_hot_cold_block_grouping): Return err.

2013-05-16  Teresa Johnson  <tejohnson@google.com>

	* cfgrtl.c (verify_hot_cold_block_grouping): Return err.
	(rtl_verify_edges): New function.
	(rtl_verify_bb_insns): Ditto.
	(rtl_verify_bb_pointers): Ditto.
	(rtl_verify_bb_insn_chain): Ditto.
	(rtl_verify_fallthru): Ditto.
	(rtl_verify_bb_layout): Ditto.
	(rtl_verify_flow_info_1): Outline checks into new functions.
	(rtl_verify_flow_info): Ditto.

From-SVN: r198982
This commit is contained in:
Teresa Johnson 2013-05-16 17:45:35 +00:00 committed by Teresa Johnson
parent 1e5b06335f
commit 251a41b978
2 changed files with 209 additions and 113 deletions

View File

@ -1,3 +1,15 @@
2013-05-16 Teresa Johnson <tejohnson@google.com>
* cfgrtl.c (verify_hot_cold_block_grouping): Return err.
(rtl_verify_edges): New function.
(rtl_verify_bb_insns): Ditto.
(rtl_verify_bb_pointers): Ditto.
(rtl_verify_bb_insn_chain): Ditto.
(rtl_verify_fallthru): Ditto.
(rtl_verify_bb_layout): Ditto.
(rtl_verify_flow_info_1): Outline checks into new functions.
(rtl_verify_flow_info): Ditto.
2013-05-16 Steve Ellcey <sellcey@imgtec.com>
* cfghooks.c (copy_bbs): Add update_dominance argument.

View File

@ -2063,7 +2063,7 @@ get_last_bb_insn (basic_block bb)
between hot/cold partitions. This condition will not be true until
after reorder_basic_blocks is called. */
static void
static int
verify_hot_cold_block_grouping (void)
{
basic_block bb;
@ -2072,7 +2072,7 @@ verify_hot_cold_block_grouping (void)
int current_partition = BB_UNPARTITIONED;
if (!crtl->bb_reorder_complete)
return;
return err;
FOR_EACH_BB (bb)
{
@ -2094,81 +2094,28 @@ verify_hot_cold_block_grouping (void)
current_partition = BB_PARTITION (bb);
}
gcc_assert(!err);
return err;
}
/* Verify the CFG and RTL consistency common for both underlying RTL and
cfglayout RTL.
Currently it does following checks:
- overlapping of basic blocks
- insns with wrong BLOCK_FOR_INSN pointers
- headers of basic blocks (the NOTE_INSN_BASIC_BLOCK note)
- tails of basic blocks (ensure that boundary is necessary)
- scans body of the basic block for JUMP_INSN, CODE_LABEL
and NOTE_INSN_BASIC_BLOCK
- verify that no fall_thru edge crosses hot/cold partition boundaries
- verify that there are no pending RTL branch predictions
- verify that there is a single hot/cold partition boundary after bbro
In future it can be extended check a lot of other stuff as well
(reachability of basic blocks, life information, etc. etc.). */
/* Perform several checks on the edges out of each block, such as
the consistency of the branch probabilities, the correctness
of hot/cold partition crossing edges, and the number of expected
successor edges. */
static int
rtl_verify_flow_info_1 (void)
rtl_verify_edges (void)
{
rtx x;
int err = 0;
basic_block bb;
/* Check the general integrity of the basic blocks. */
FOR_EACH_BB_REVERSE (bb)
{
rtx insn;
if (!(bb->flags & BB_RTL))
{
error ("BB_RTL flag not set for block %d", bb->index);
err = 1;
}
FOR_BB_INSNS (bb, insn)
if (BLOCK_FOR_INSN (insn) != bb)
{
error ("insn %d basic block pointer is %d, should be %d",
INSN_UID (insn),
BLOCK_FOR_INSN (insn) ? BLOCK_FOR_INSN (insn)->index : 0,
bb->index);
err = 1;
}
for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn))
if (!BARRIER_P (insn)
&& BLOCK_FOR_INSN (insn) != NULL)
{
error ("insn %d in header of bb %d has non-NULL basic block",
INSN_UID (insn), bb->index);
err = 1;
}
for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn))
if (!BARRIER_P (insn)
&& BLOCK_FOR_INSN (insn) != NULL)
{
error ("insn %d in footer of bb %d has non-NULL basic block",
INSN_UID (insn), bb->index);
err = 1;
}
}
/* Now check the basic blocks (boundaries etc.) */
FOR_EACH_BB_REVERSE (bb)
{
int n_fallthru = 0, n_branch = 0, n_abnormal_call = 0, n_sibcall = 0;
int n_eh = 0, n_abnormal = 0;
edge e, fallthru = NULL;
rtx note;
edge_iterator ei;
rtx note;
if (JUMP_P (BB_END (bb))
&& (note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX))
@ -2183,6 +2130,7 @@ rtl_verify_flow_info_1 (void)
err = 1;
}
}
FOR_EACH_EDGE (e, ei, bb->succs)
{
bool is_crossing;
@ -2296,26 +2244,26 @@ rtl_verify_flow_info_1 (void)
error ("abnormal edges for no purpose in bb %i", bb->index);
err = 1;
}
}
for (x = BB_HEAD (bb); x != NEXT_INSN (BB_END (bb)); x = NEXT_INSN (x))
/* We may have a barrier inside a basic block before dead code
elimination. There is no BLOCK_FOR_INSN field in a barrier. */
if (!BARRIER_P (x) && BLOCK_FOR_INSN (x) != bb)
{
debug_rtx (x);
if (! BLOCK_FOR_INSN (x))
error
("insn %d inside basic block %d but block_for_insn is NULL",
INSN_UID (x), bb->index);
else
error
("insn %d inside basic block %d but block_for_insn is %i",
INSN_UID (x), bb->index, BLOCK_FOR_INSN (x)->index);
/* Clean up. */
return err;
}
err = 1;
}
/* Checks on the instructions within blocks. Currently checks that each
block starts with a basic block note, and that basic block notes and
control flow jumps are not found in the middle of the block. */
/* OK pointers are correct. Now check the header of basic
static int
rtl_verify_bb_insns (void)
{
rtx x;
int err = 0;
basic_block bb;
FOR_EACH_BB_REVERSE (bb)
{
/* Now check the header of basic
block. It ought to contain optional CODE_LABEL followed
by NOTE_BASIC_BLOCK. */
x = BB_HEAD (bb);
@ -2362,7 +2310,57 @@ rtl_verify_flow_info_1 (void)
}
}
verify_hot_cold_block_grouping();
/* Clean up. */
return err;
}
/* Verify that block pointers for instructions in basic blocks, headers and
footers are set appropriately. */
static int
rtl_verify_bb_pointers (void)
{
int err = 0;
basic_block bb;
/* Check the general integrity of the basic blocks. */
FOR_EACH_BB_REVERSE (bb)
{
rtx insn;
if (!(bb->flags & BB_RTL))
{
error ("BB_RTL flag not set for block %d", bb->index);
err = 1;
}
FOR_BB_INSNS (bb, insn)
if (BLOCK_FOR_INSN (insn) != bb)
{
error ("insn %d basic block pointer is %d, should be %d",
INSN_UID (insn),
BLOCK_FOR_INSN (insn) ? BLOCK_FOR_INSN (insn)->index : 0,
bb->index);
err = 1;
}
for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn))
if (!BARRIER_P (insn)
&& BLOCK_FOR_INSN (insn) != NULL)
{
error ("insn %d in header of bb %d has non-NULL basic block",
INSN_UID (insn), bb->index);
err = 1;
}
for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn))
if (!BARRIER_P (insn)
&& BLOCK_FOR_INSN (insn) != NULL)
{
error ("insn %d in footer of bb %d has non-NULL basic block",
INSN_UID (insn), bb->index);
err = 1;
}
}
/* Clean up. */
return err;
@ -2372,31 +2370,54 @@ rtl_verify_flow_info_1 (void)
cfglayout RTL.
Currently it does following checks:
- all checks of rtl_verify_flow_info_1
- test head/end pointers
- check that all insns are in the basic blocks
(except the switch handling code, barriers and notes)
- check that all returns are followed by barriers
- check that all fallthru edge points to the adjacent blocks. */
- overlapping of basic blocks
- insns with wrong BLOCK_FOR_INSN pointers
- headers of basic blocks (the NOTE_INSN_BASIC_BLOCK note)
- tails of basic blocks (ensure that boundary is necessary)
- scans body of the basic block for JUMP_INSN, CODE_LABEL
and NOTE_INSN_BASIC_BLOCK
- verify that no fall_thru edge crosses hot/cold partition boundaries
- verify that there are no pending RTL branch predictions
- verify that there is a single hot/cold partition boundary after bbro
In future it can be extended check a lot of other stuff as well
(reachability of basic blocks, life information, etc. etc.). */
static int
rtl_verify_flow_info (void)
rtl_verify_flow_info_1 (void)
{
int err = 0;
err |= rtl_verify_bb_pointers ();
err |= rtl_verify_bb_insns ();
err |= rtl_verify_edges ();
err |= verify_hot_cold_block_grouping();
return err;
}
/* Walk the instruction chain and verify that bb head/end pointers
are correct, and that instructions are in exactly one bb and have
correct block pointers. */
static int
rtl_verify_bb_insn_chain (void)
{
basic_block bb;
int err = rtl_verify_flow_info_1 ();
int err = 0;
rtx x;
rtx last_head = get_last_insn ();
basic_block *bb_info;
int num_bb_notes;
const rtx rtx_first = get_insns ();
basic_block last_bb_seen = ENTRY_BLOCK_PTR, curr_bb = NULL;
const int max_uid = get_max_uid ();
bb_info = XCNEWVEC (basic_block, max_uid);
FOR_EACH_BB_REVERSE (bb)
{
edge e;
rtx head = BB_HEAD (bb);
rtx end = BB_END (bb);
@ -2406,14 +2427,14 @@ rtl_verify_flow_info (void)
if (x == end)
break;
/* And that the code outside of basic blocks has NULL bb field. */
if (!BARRIER_P (x)
&& BLOCK_FOR_INSN (x) != NULL)
{
error ("insn %d outside of basic blocks has non-NULL bb field",
INSN_UID (x));
err = 1;
}
/* And that the code outside of basic blocks has NULL bb field. */
if (!BARRIER_P (x)
&& BLOCK_FOR_INSN (x) != NULL)
{
error ("insn %d outside of basic blocks has non-NULL bb field",
INSN_UID (x));
err = 1;
}
}
if (!x)
@ -2449,6 +2470,37 @@ rtl_verify_flow_info (void)
}
last_head = PREV_INSN (x);
}
for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
{
/* Check that the code before the first basic block has NULL
bb field. */
if (!BARRIER_P (x)
&& BLOCK_FOR_INSN (x) != NULL)
{
error ("insn %d outside of basic blocks has non-NULL bb field",
INSN_UID (x));
err = 1;
}
}
free (bb_info);
return err;
}
/* Verify that fallthru edges point to adjacent blocks in layout order and
that barriers exist after non-fallthru blocks. */
static int
rtl_verify_fallthru (void)
{
basic_block bb;
int err = 0;
FOR_EACH_BB_REVERSE (bb)
{
edge e;
e = find_fallthru_edge (bb->succs);
if (!e)
@ -2493,19 +2545,22 @@ rtl_verify_flow_info (void)
}
}
for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
{
/* Check that the code before the first basic block has NULL
bb field. */
if (!BARRIER_P (x)
&& BLOCK_FOR_INSN (x) != NULL)
{
error ("insn %d outside of basic blocks has non-NULL bb field",
INSN_UID (x));
err = 1;
}
}
free (bb_info);
return err;
}
/* Verify that blocks are laid out in consecutive order. While walking the
instructions, verify that all expected instructions are inside the basic
blocks, and that all returns are followed by barriers. */
static int
rtl_verify_bb_layout (void)
{
basic_block bb;
int err = 0;
rtx x;
int num_bb_notes;
const rtx rtx_first = get_insns ();
basic_block last_bb_seen = ENTRY_BLOCK_PTR, curr_bb = NULL;
num_bb_notes = 0;
last_bb_seen = ENTRY_BLOCK_PTR;
@ -2549,6 +2604,7 @@ rtl_verify_flow_info (void)
&& returnjump_p (x) && ! condjump_p (x)
&& ! (next_nonnote_insn (x) && BARRIER_P (next_nonnote_insn (x))))
fatal_insn ("return not followed by barrier", x);
if (curr_bb && x == BB_END (curr_bb))
curr_bb = NULL;
}
@ -2560,6 +2616,34 @@ rtl_verify_flow_info (void)
return err;
}
/* Verify the CFG and RTL consistency common for both underlying RTL and
cfglayout RTL, plus consistency checks specific to linearized RTL mode.
Currently it does following checks:
- all checks of rtl_verify_flow_info_1
- test head/end pointers
- check that blocks are laid out in consecutive order
- check that all insns are in the basic blocks
(except the switch handling code, barriers and notes)
- check that all returns are followed by barriers
- check that all fallthru edge points to the adjacent blocks. */
static int
rtl_verify_flow_info (void)
{
int err = 0;
err |= rtl_verify_flow_info_1 ();
err |= rtl_verify_bb_insn_chain ();
err |= rtl_verify_fallthru ();
err |= rtl_verify_bb_layout ();
return err;
}
/* Assume that the preceding pass has possibly eliminated jump instructions
or converted the unconditional jumps. Eliminate the edges from CFG.