From 1d183080ed126bedbe0f3a8b15a09186b9ebbc27 Mon Sep 17 00:00:00 2001 From: rguenth Date: Thu, 14 Dec 2017 14:32:24 +0000 Subject: [PATCH] 2017-12-14 Richard Biener 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@255635 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 11 +++++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c | 2 +- gcc/tree-ssa-loop-ivcanon.c | 54 +++++++++++++++++++++++++++---- 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d18230841f4..4f97ca254ac 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2017-12-14 Richard Biener + 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 + 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 a7686ceb604..9bd5cbbe1bd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-12-14 Richard Biener + + PR tree-optimization/83326 + * gcc.dg/tree-ssa/pr81388-2.c: Adjust. + 2017-12-14 Eric Botcazou * 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 71fd2890f3d..aa40588f358 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 ae66ace3d7f..ce5a833de4d 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; } -- 2.11.4.GIT