From 40f683e88d5aeef52425f719a7197da4d1d524a7 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 24 Oct 2016 11:22:42 +0000 Subject: [PATCH] tree-vrp.c (evrp_dom_walker::before_dom_children): Ignore backedges when identifying the single predecessor to take conditional... 2016-10-24 Richard Biener * 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 --- gcc/ChangeLog | 8 ++++ gcc/lto-streamer-out.c | 5 ++- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c | 4 +- gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c | 19 ++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr21458.c | 2 +- gcc/tree-vrp.c | 50 +++++++++++++++++----- 7 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 291ef4507de..e8ddeb014f2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-10-24 Richard Biener + + * 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 PR target/78093 diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 22c4140cca8..22d8ac90724 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bc9bf676032..eb0f9761511 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-10-24 Richard Biener + + * 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 PR target/78093 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c index 6e4417a7520..f3fe8b51468 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c new file mode 100644 index 00000000000..2aee42f4c05 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c index 20ec9c9e9cf..97d17f21cfb 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c @@ -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); diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 9675ca239b4..fcdb3417bb3 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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; -- 2.30.2