diff options
author | Richard Biener <rguenther@suse.de> | 2017-12-14 14:32:24 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2017-12-14 14:32:24 +0000 |
commit | 8fa06648cde628f49ac69587d31841fc338ec841 (patch) | |
tree | 4ed9aa324a460c80fca144994aeda6284b57d5b2 | |
parent | f297ebafdcdf5d5a8c3ef74c9906de67998e5aa7 (diff) | |
download | gcc-8fa06648cde628f49ac69587d31841fc338ec841.zip gcc-8fa06648cde628f49ac69587d31841fc338ec841.tar.gz gcc-8fa06648cde628f49ac69587d31841fc338ec841.tar.bz2 |
re PR tree-optimization/83326 (SPEC CPU2017 648.exchange2_s ~6% performance regression with r255267 (reproducer attached))
2017-12-14 Richard Biener <rguenther@suse.de>
PR tree-optimization/83326
* tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Add
may_be_zero parameter and handle it by not marking the first
peeled copy as not exiting the loop.
(try_peel_loop): Likewise.
(canonicalize_loop_induction_variables): Use number_of_iterations_exit
to handle the case of constant or zero iterations and perform
loop header copying on-the-fly.
* gcc.dg/tree-ssa/pr81388-2.c: Adjust.
From-SVN: r255635
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivcanon.c | 54 |
4 files changed, 64 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d182308..4f97ca2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2017-12-14 Richard Biener <rguenther@suse.de> + PR tree-optimization/83326 + * tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Add + may_be_zero parameter and handle it by not marking the first + peeled copy as not exiting the loop. + (try_peel_loop): Likewise. + (canonicalize_loop_induction_variables): Use number_of_iterations_exit + to handle the case of constant or zero iterations and perform + loop header copying on-the-fly. + +2017-12-14 Richard Biener <rguenther@suse.de> + PR tree-optimization/83418 * vr-values.c (vr_values::extract_range_for_var_from_comparison_expr): Instead of asserting we don't get unfolded comparisons deal with diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a7686ce..9bd5cbb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-12-14 Richard Biener <rguenther@suse.de> + + PR tree-optimization/83326 + * gcc.dg/tree-ssa/pr81388-2.c: Adjust. + 2017-12-14 Eric Botcazou <ebotcazou@adacore.com> * gnat.dg/alignment11.adb: New test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c index 71fd289..aa40588 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c @@ -11,4 +11,4 @@ void foo(unsigned dst) } while (dst < end); } -/* { dg-final { scan-tree-dump-times " zero if " 1 "ivcanon" } } */ +/* { dg-final { scan-tree-dump " zero if " "ivcanon" } } */ diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index ae66ace..ce5a833 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -681,7 +681,7 @@ unloop_loops (bitmap loop_closed_ssa_invalidated, static bool try_unroll_loop_completely (struct loop *loop, - edge exit, tree niter, + edge exit, tree niter, bool may_be_zero, enum unroll_level ul, HOST_WIDE_INT maxiter, location_t locus, bool allow_peel) @@ -893,6 +893,8 @@ try_unroll_loop_completely (struct loop *loop, exit = NULL; bitmap_clear (wont_exit); } + if (may_be_zero) + bitmap_clear_bit (wont_exit, 1); if (!gimple_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop), n_unroll, wont_exit, @@ -977,7 +979,7 @@ estimated_peeled_sequence_size (struct loop_size *size, static bool try_peel_loop (struct loop *loop, - edge exit, tree niter, + edge exit, tree niter, bool may_be_zero, HOST_WIDE_INT maxiter) { HOST_WIDE_INT npeel; @@ -1080,6 +1082,8 @@ try_peel_loop (struct loop *loop, exit = NULL; bitmap_clear (wont_exit); } + if (may_be_zero) + bitmap_clear_bit (wont_exit, 1); if (!gimple_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop), npeel, wont_exit, exit, &edges_to_remove, @@ -1152,13 +1156,35 @@ canonicalize_loop_induction_variables (struct loop *loop, HOST_WIDE_INT maxiter; bool modified = false; location_t locus = UNKNOWN_LOCATION; + struct tree_niter_desc niter_desc; + bool may_be_zero = false; - niter = number_of_latch_executions (loop); + /* For unrolling allow conditional constant or zero iterations, thus + perform loop-header copying on-the-fly. */ exit = single_exit (loop); + niter = chrec_dont_know; + if (exit && number_of_iterations_exit (loop, exit, &niter_desc, false)) + { + niter = niter_desc.niter; + may_be_zero + = niter_desc.may_be_zero && !integer_zerop (niter_desc.may_be_zero); + } if (TREE_CODE (niter) == INTEGER_CST) locus = gimple_location (last_stmt (exit->src)); else { + /* For non-constant niter fold may_be_zero into niter again. */ + if (may_be_zero) + { + if (COMPARISON_CLASS_P (niter_desc.may_be_zero)) + niter = fold_build3 (COND_EXPR, TREE_TYPE (niter), + niter_desc.may_be_zero, + build_int_cst (TREE_TYPE (niter), 0), niter); + else + niter = chrec_dont_know; + may_be_zero = false; + } + /* If the loop has more than one exit, try checking all of them for # of iterations determinable through scev. */ if (!exit) @@ -1213,17 +1239,31 @@ canonicalize_loop_induction_variables (struct loop *loop, populates the loop bounds. */ modified |= remove_redundant_iv_tests (loop); - if (try_unroll_loop_completely (loop, exit, niter, ul, maxiter, locus, - allow_peel)) + if (try_unroll_loop_completely (loop, exit, niter, may_be_zero, ul, + maxiter, locus, allow_peel)) return true; if (create_iv && niter && !chrec_contains_undetermined (niter) && exit && just_once_each_iteration_p (loop, exit->src)) - create_canonical_iv (loop, exit, niter); + { + tree iv_niter = niter; + if (may_be_zero) + { + if (COMPARISON_CLASS_P (niter_desc.may_be_zero)) + iv_niter = fold_build3 (COND_EXPR, TREE_TYPE (iv_niter), + niter_desc.may_be_zero, + build_int_cst (TREE_TYPE (iv_niter), 0), + iv_niter); + else + iv_niter = NULL_TREE; + } + if (iv_niter) + create_canonical_iv (loop, exit, iv_niter); + } if (ul == UL_ALL) - modified |= try_peel_loop (loop, exit, niter, maxiter); + modified |= try_peel_loop (loop, exit, niter, may_be_zero, maxiter); return modified; } |