===================================================================
@@ -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)
+ {
+ /* 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)
{
- edge e = single_pred_edge (bb);
- gimple *stmt = last_stmt (e->src);
+ 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 (ba
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 (ba
}
/* 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 (ba
{
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 (ba
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;
===================================================================
@@ -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,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" } } */
===================================================================
@@ -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);
===================================================================
@@ -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" } } */