Commit 40f683e8 by Richard Biener Committed by Richard Biener

tree-vrp.c (evrp_dom_walker::before_dom_children): Ignore backedges when…

tree-vrp.c (evrp_dom_walker::before_dom_children): Ignore backedges when identifying the single predecessor to take conditional...

2016-10-24  Richard Biener  <rguenther@suse.de>

	* tree-vrp.c (evrp_dom_walker::before_dom_children): Ignore
	backedges when identifying the single predecessor to take
	conditional info from.  Use SCEV to get at ranges for loop IVs.
	* lto-streamer-out.c (lto_write_mode_table): CSE inner mode to
	avoid false warning.

	* gcc.dg/tree-ssa/cunroll-13.c: Disable EVRP.
	* gcc.dg/tree-ssa/pr21458.c: Likewise.
	* gcc.dg/tree-ssa/pr21458-2.c: New testcase for EVRP.

From-SVN: r241470
parent 6a5792b6
2016-10-24 Richard Biener <rguenther@suse.de>
* tree-vrp.c (evrp_dom_walker::before_dom_children): Ignore
backedges when identifying the single predecessor to take
conditional info from. Use SCEV to get at ranges for loop IVs.
* lto-streamer-out.c (lto_write_mode_table): CSE inner mode to
avoid false warning.
2016-10-24 Georg-Johann Lay <avr@gjlay.de>
PR target/78093
......
......@@ -2720,8 +2720,9 @@ lto_write_mode_table (void)
if (streamer_mode_table[i])
{
machine_mode m = (machine_mode) i;
if (GET_MODE_INNER (m) != m)
streamer_mode_table[(int) GET_MODE_INNER (m)] = 1;
machine_mode inner_m = GET_MODE_INNER (m);
if (inner_m != m)
streamer_mode_table[(int) inner_m] = 1;
}
/* First stream modes that have GET_MODE_INNER (m) == m,
so that we can refer to them afterwards. */
......
2016-10-24 Richard Biener <rguenther@suse.de>
* gcc.dg/tree-ssa/cunroll-13.c: Disable EVRP.
* gcc.dg/tree-ssa/pr21458.c: Likewise.
* gcc.dg/tree-ssa/pr21458-2.c: New testcase for EVRP.
2016-10-24 Georg-Johann Lay <avr@gjlay.de>
PR target/78093
......
/* { dg-do compile } */
/* { dg-options "-O3 -fdisable-tree-cunrolli -fdisable-tree-vrp1 -fdump-tree-cunroll-blocks-details" } */
/* { dg-options "-O3 -fdisable-tree-evrp -fdisable-tree-cunrolli -fdisable-tree-vrp1 -fdump-tree-cunroll-blocks-details" } */
struct a {int a[8];int b;};
void
t(struct a *a)
......@@ -8,7 +8,7 @@ t(struct a *a)
a->a[i]++;
}
/* This pass relies on the fact that we do not eliminate the redundant test for i early.
It is necessary to disable all passes that do so. At the moment it is vrp1 and cunrolli. */
It is necessary to disable all passes that do so. At the moment it is evrp, vrp1 and cunrolli. */
/* { dg-final { scan-tree-dump-times "Loop 1 iterates 123454 times" 1 "cunroll" } } */
/* { dg-final { scan-tree-dump-times "Last iteration exit edge was proved true" 1 "cunroll" } } */
/* { dg-final { scan-tree-dump-times "Exit condition of peeled iterations was eliminated" 1 "cunroll" } } */
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-evrp-details" } */
extern void g (void);
extern void bar (int);
int
foo (int a)
{
int i;
for (i = 1; i < 100; i++)
{
if (i)
g ();
}
}
/* { dg-final { scan-tree-dump-times "Predicate evaluates to: 1" 1 "evrp" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1" } */
/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1" } */
extern void g (void);
extern void bar (int);
......
......@@ -10693,12 +10693,29 @@ edge
evrp_dom_walker::before_dom_children (basic_block bb)
{
tree op0 = NULL_TREE;
edge_iterator ei;
edge e;
push_value_range (NULL_TREE, NULL);
if (single_pred_p (bb))
edge pred_e = NULL;
FOR_EACH_EDGE (e, ei, bb->preds)
{
edge e = single_pred_edge (bb);
gimple *stmt = last_stmt (e->src);
/* Ignore simple backedges from this to allow recording conditions
in loop headers. */
if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
continue;
if (! pred_e)
pred_e = e;
else
{
pred_e = NULL;
break;
}
}
if (pred_e)
{
gimple *stmt = last_stmt (pred_e->src);
if (stmt
&& gimple_code (stmt) == GIMPLE_COND
&& (op0 = gimple_cond_lhs (stmt))
......@@ -10715,7 +10732,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
op1 = drop_tree_overflow (op1);
/* If condition is false, invert the cond. */
if (e->flags & EDGE_FALSE_VALUE)
if (pred_e->flags & EDGE_FALSE_VALUE)
code = invert_tree_comparison (gimple_cond_code (stmt),
HONOR_NANS (op0));
/* Add VR when (OP0 CODE OP1) condition is true. */
......@@ -10743,11 +10760,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
}
/* Visit PHI stmts and discover any new VRs possible. */
gimple_stmt_iterator gsi;
edge e;
edge_iterator ei;
bool has_unvisited_preds = false;
FOR_EACH_EDGE (e, ei, bb->preds)
if (e->flags & EDGE_EXECUTABLE
&& !(e->src->flags & BB_VISITED))
......@@ -10761,12 +10774,26 @@ evrp_dom_walker::before_dom_children (basic_block bb)
{
gphi *phi = gpi.phi ();
tree lhs = PHI_RESULT (phi);
if (virtual_operand_p (lhs))
continue;
value_range vr_result = VR_INITIALIZER;
bool interesting = stmt_interesting_for_vrp (phi);
if (!has_unvisited_preds
&& stmt_interesting_for_vrp (phi))
&& interesting)
extract_range_from_phi_node (phi, &vr_result);
else
set_value_range_to_varying (&vr_result);
{
set_value_range_to_varying (&vr_result);
/* When we have an unvisited executable predecessor we can't
use PHI arg ranges which may be still UNDEFINED but have
to use VARYING for them. But we can still resort to
SCEV for loop header PHIs. */
struct loop *l;
if (interesting
&& (l = loop_containing_stmt (phi))
&& l->header == gimple_bb (phi))
adjust_range_with_scev (&vr_result, l, phi, lhs);
}
update_value_range (lhs, &vr_result);
/* Mark PHIs whose lhs we fully propagate for removal. */
......@@ -10778,7 +10805,8 @@ evrp_dom_walker::before_dom_children (basic_block bb)
edge taken_edge = NULL;
/* Visit all other stmts and discover any new VRs possible. */
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
!gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
tree output = NULL_TREE;
......
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