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:
parent
6a5792b660
commit
40f683e88d
7 changed files with 78 additions and 16 deletions
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
19
gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c
Normal file
19
gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c
Normal 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" } } */
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue