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
This commit is contained in:
Richard Biener 2016-10-24 11:22:42 +00:00 committed by Richard Biener
parent 6a5792b660
commit 40f683e88d
7 changed files with 78 additions and 16 deletions

View file

@ -1,3 +1,11 @@
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

View file

@ -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. */

View file

@ -1,3 +1,9 @@
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

View file

@ -1,5 +1,5 @@
/* { 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" } } */

View file

@ -0,0 +1,19 @@
/* { 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" } } */

View file

@ -1,5 +1,5 @@
/* { 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);

View file

@ -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;