diff options
Diffstat (limited to 'gcc/tree-ssa-loop-niter.cc')
| -rw-r--r-- | gcc/tree-ssa-loop-niter.cc | 93 |
1 files changed, 90 insertions, 3 deletions
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc index 6e13086..cc76383 100644 --- a/gcc/tree-ssa-loop-niter.cc +++ b/gcc/tree-ssa-loop-niter.cc @@ -2321,6 +2321,48 @@ is_rshift_by_1 (gassign *stmt) return false; } +/* Helper for number_of_iterations_cltz that uses ranger to determine + if SRC's range, shifted left (when LEFT_SHIFT is true) or right + by NUM_IGNORED_BITS, is guaranteed to be != 0 on LOOP's preheader + edge. + Return true if so or false otherwise. */ + +static bool +shifted_range_nonzero_p (loop_p loop, tree src, + bool left_shift, int num_ignored_bits) +{ + int_range_max r (TREE_TYPE (src)); + gcc_assert (num_ignored_bits >= 0); + + if (get_range_query (cfun)->range_on_edge + (r, loop_preheader_edge (loop), src) + && !r.varying_p () + && !r.undefined_p ()) + { + if (num_ignored_bits) + { + range_op_handler op (left_shift ? LSHIFT_EXPR : RSHIFT_EXPR); + int_range_max shifted_range (TREE_TYPE (src)); + wide_int shift_count = wi::shwi (num_ignored_bits, + TYPE_PRECISION (TREE_TYPE + (src))); + int_range_max shift_amount + (TREE_TYPE (src), shift_count, shift_count); + + if (op.fold_range (shifted_range, TREE_TYPE (src), r, + shift_amount)) + r = shifted_range; + } + + /* If the range does not contain zero we are good. */ + if (!range_includes_zero_p (r)) + return true; + } + + return false; +} + + /* See comment below for number_of_iterations_bitcount. For c[lt]z, we have: @@ -2438,6 +2480,9 @@ number_of_iterations_cltz (loop_p loop, edge exit, tree src = gimple_phi_arg_def (phi, loop_preheader_edge (loop)->dest_idx); int src_precision = TYPE_PRECISION (TREE_TYPE (src)); + /* Save the original SSA name before preprocessing for ranger queries. */ + tree unshifted_src = src; + /* Apply any needed preprocessing to src. */ int num_ignored_bits; if (left_shift) @@ -2463,10 +2508,52 @@ number_of_iterations_cltz (loop_p loop, edge exit, expr = fold_convert (unsigned_type_node, expr); - tree assumptions = fold_build2 (NE_EXPR, boolean_type_node, src, - build_zero_cst (TREE_TYPE (src))); + /* If the copy-header (ch) pass peeled one iteration we're shifting + SRC by preprocessing it above. + + A loop like + if (bits) + { + while (!(bits & 1)) + { + bits >>= 1; + cnt += 1; + } + return cnt; + } + ch (roughly) transforms into: + if (bits) + { + if (!(bits & 1) + { + do + { + bits >>= 1; + cnt += 1; + } while (!(bits & 1)); + } + else + cnt = 1; + return cnt; + } + + Then, our preprocessed SRC (that is used for c[tl]z computation) + will be bits >> 1, and the assumption is bits >> 1 != 0. */ + + tree assumptions; + if (shifted_range_nonzero_p (loop, unshifted_src, + left_shift, num_ignored_bits)) + assumptions = boolean_true_node; + else + { + /* If ranger couldn't prove the assumption, try + simplify_using_initial_conditions. */ + assumptions = fold_build2 (NE_EXPR, boolean_type_node, src, + build_zero_cst (TREE_TYPE (src))); + assumptions = simplify_using_initial_conditions (loop, assumptions); + } - niter->assumptions = simplify_using_initial_conditions (loop, assumptions); + niter->assumptions = assumptions; niter->may_be_zero = boolean_false_node; niter->niter = simplify_using_initial_conditions (loop, expr); |
