Commit 384d7a55 by Steven Bosscher

cprop.c (implicit_set_cond_p): Assume nothing about COND...

	* cprop.c (implicit_set_cond_p): Assume nothing about COND, move
	checks on form of COND from find_implicit_sets to here.
	(find_implicit_sets): Cleanup control flow. Split critical edges
	if it exposes implicit sets.  Allocate/resize implicit_sets as
	necessary.
	(one_cprop_pass): Only delete unreachable blocks if local_cprop_pass
	changed something.  Run df_analyze after find_implicit_sets if any
	edges were split.  Do not allocate implicit_sets here.

From-SVN: r171946
parent 3084ce69
2011-04-04 Steven Bosscher <steven@gcc.gnu.org>
* cprop.c (implicit_set_cond_p): Assume nothing about COND, move
checks on form of COND from find_implicit_sets to here.
(find_implicit_sets): Cleanup control flow. Split critical edges
if it exposes implicit sets. Allocate/resize implicit_sets as
necessary.
(one_cprop_pass): Only delete unreachable blocks if local_cprop_pass
changed something. Run df_analyze after find_implicit_sets if any
edges were split. Do not allocate implicit_sets here.
* cprop.c: s/gcse/cprop/ everywhere except for flag_gcse.
(gcse_obstack): Renamed to cprop_obstack.
(GNEW, GNEWVEC, GNEWVAR): Remove.
......
......@@ -1343,14 +1343,27 @@ fis_get_condition (rtx jump)
return get_condition (jump, NULL, false, true);
}
/* Check the comparison COND to see if we can safely form an implicit set from
it. COND is either an EQ or NE comparison. */
/* Check the comparison COND to see if we can safely form an implicit
set from it. */
static bool
implicit_set_cond_p (const_rtx cond)
{
const enum machine_mode mode = GET_MODE (XEXP (cond, 0));
const_rtx cst = XEXP (cond, 1);
enum machine_mode mode;
rtx cst;
/* COND must be either an EQ or NE comparison. */
if (GET_CODE (cond) != EQ && GET_CODE (cond) != NE)
return false;
/* The first operand of COND must be a pseudo-reg. */
if (! REG_P (XEXP (cond, 0))
|| HARD_REGISTER_P (XEXP (cond, 0)))
return false;
/* The second operand of COND must be a suitable constant. */
mode = GET_MODE (XEXP (cond, 0));
cst = XEXP (cond, 1);
/* We can't perform this optimization if either operand might be or might
contain a signed zero. */
......@@ -1382,55 +1395,78 @@ implicit_set_cond_p (const_rtx cond)
function records the set patterns that are implicit at the start of each
basic block.
FIXME: This would be more effective if critical edges are pre-split. As
it is now, we can't record implicit sets for blocks that have
critical successor edges. This results in missed optimizations
and in more (unnecessary) work in cfgcleanup.c:thread_jump(). */
If an implicit set is found but the set is implicit on a critical edge,
this critical edge is split.
static void
Return true if the CFG was modified, false otherwise. */
static bool
find_implicit_sets (void)
{
basic_block bb, dest;
unsigned int count;
rtx cond, new_rtx;
unsigned int count = 0;
bool edges_split = false;
size_t implicit_sets_size = last_basic_block + 10;
implicit_sets = XCNEWVEC (rtx, implicit_sets_size);
count = 0;
FOR_EACH_BB (bb)
/* Check for more than one successor. */
if (EDGE_COUNT (bb->succs) > 1)
{
cond = fis_get_condition (BB_END (bb));
{
/* Check for more than one successor. */
if (! EDGE_COUNT (bb->succs) > 1)
continue;
if (cond
&& (GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
&& REG_P (XEXP (cond, 0))
&& REGNO (XEXP (cond, 0)) >= FIRST_PSEUDO_REGISTER
&& implicit_set_cond_p (cond))
{
dest = GET_CODE (cond) == EQ ? BRANCH_EDGE (bb)->dest
: FALLTHRU_EDGE (bb)->dest;
cond = fis_get_condition (BB_END (bb));
if (dest
/* Record nothing for a critical edge. */
&& single_pred_p (dest)
&& dest != EXIT_BLOCK_PTR)
{
new_rtx = gen_rtx_SET (VOIDmode, XEXP (cond, 0),
XEXP (cond, 1));
implicit_sets[dest->index] = new_rtx;
if (dump_file)
{
fprintf(dump_file, "Implicit set of reg %d in ",
REGNO (XEXP (cond, 0)));
fprintf(dump_file, "basic block %d\n", dest->index);
}
count++;
}
}
/* If no condition is found or if it isn't of a suitable form,
ignore it. */
if (! cond || ! implicit_set_cond_p (cond))
continue;
dest = GET_CODE (cond) == EQ
? BRANCH_EDGE (bb)->dest : FALLTHRU_EDGE (bb)->dest;
/* If DEST doesn't go anywhere, ignore it. */
if (! dest || dest == EXIT_BLOCK_PTR)
continue;
/* We have found a suitable implicit set. Try to record it now as
a SET in DEST. If DEST has more than one predecessor, the edge
between BB and DEST is a critical edge and we must split it,
because we can only record one implicit set per DEST basic block. */
if (! single_pred_p (dest))
{
dest = split_edge (find_edge (bb, dest));
edges_split = true;
}
if (implicit_sets_size <= (size_t) dest->index)
{
size_t old_implicit_sets_size = implicit_sets_size;
implicit_sets_size *= 2;
implicit_sets = XRESIZEVEC (rtx, implicit_sets, implicit_sets_size);
memset (implicit_sets + old_implicit_sets_size, 0,
(implicit_sets_size - old_implicit_sets_size) * sizeof (rtx));
}
new_rtx = gen_rtx_SET (VOIDmode, XEXP (cond, 0),
XEXP (cond, 1));
implicit_sets[dest->index] = new_rtx;
if (dump_file)
{
fprintf(dump_file, "Implicit set of reg %d in ",
REGNO (XEXP (cond, 0)));
fprintf(dump_file, "basic block %d\n", dest->index);
}
count++;
}
if (dump_file)
fprintf (dump_file, "Found %d implicit sets\n", count);
/* Confess our sins. */
return edges_split;
}
/* Bypass conditional jumps. */
......@@ -1797,14 +1833,24 @@ one_cprop_pass (void)
the solver implemented in this file. */
changed |= local_cprop_pass ();
if (changed)
{
delete_unreachable_blocks ();
df_analyze ();
}
/* Determine implicit sets. */
implicit_sets = XCNEWVEC (rtx, last_basic_block);
find_implicit_sets ();
delete_unreachable_blocks ();
/* Determine implicit sets. This may change the CFG (split critical
edges if that exposes an implicit set).
Note that find_implicit_sets() does not rely on up-to-date DF caches
so that we do not have to re-run df_analyze() even if local CPROP
changed something.
??? This could run earlier so that any uncovered implicit sets
sets could be exploited in local_cprop_pass() also. Later. */
changed |= find_implicit_sets ();
/* If local_cprop_pass() or find_implicit_sets() changed something,
run df_analyze() to bring all insn caches up-to-date, and to take
new basic blocks from edge splitting on the DF radar.
NB: This also runs the fast DCE pass, because execute_rtl_cprop
sets DF_LR_RUN_DCE. */
if (changed)
df_analyze ();
alloc_hash_table (&set_hash_table);
compute_hash_table (&set_hash_table);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment