This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH GCC][2/2]Refine CFG and bound information for split loops
- From: Bernhard Reutner-Fischer <rep dot dot dot nop at gmail dot com>
- To: Bin Cheng <Bin dot Cheng at arm dot com>
- Cc: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>, nd <nd at arm dot com>
- Date: Wed, 14 Jun 2017 18:05:28 +0200
- Subject: Re: [PATCH GCC][2/2]Refine CFG and bound information for split loops
- Authentication-results: sourceware.org; auth=none
- References: <VI1PR0802MB21764A3511EE944657C64543E7C30@VI1PR0802MB2176.eurprd08.prod.outlook.com>
On 14 June 2017 at 15:08, Bin Cheng <Bin.Cheng@arm.com> wrote:
> Hi,
> Loop split currently generates below control flow graph for split loops:
> +
> + .------ guard1 ------.
> + v v
> + pre1(loop1) .---------->pre2(loop2)
> + | | |
> + .--->h1 | h2<----.
> + | | | | |
> + | ex1---. | .---ex2 |
> + | / v | | \ |
> + '---l1 guard2---' | l2---'
> + | |
> + | |
> + '--->join<---'
> +
> In which,
> + LOOP2 is the second loop after split, GUARD1 and GUARD2 are the two bbs
> + controling if loop2 should be executed.
>
> Take added test case as an example, the second loop only iterates for 1 time,
> as a result, the CFG and loop niter bound information can be refined. In general,
> guard1/guard2 can be folded to true/false if loop2's niters is known at compilation
> time. This patch does such improvement by analyzing and refining niters of
> loop2; as well as using that information to simplify CFG. With this patch,
> the second split loop as in test can be completely unrolled by later passes.
@@ -462,8 +476,148 @@ compute_new_first_bound (gimple_seq *stmts,
struct tree_niter_desc *niter,
build_int_cst (type, addbound));
}
- newbound = fold_build2 (minmax, TREE_TYPE (border), border, newbound);
- return force_gimple_operand (newbound, stmts, true, NULL_TREE);
+ tree cmp_rslt = fold_build2 (cmp_code, boolean_type_node, border, newbound);
+ /* Only handle simple case with unit step. */
+ if (wi::eq_p (wi::abs (step), 1)
+ && cmp_rslt != NULL_TREE && integer_nonzerop (cmp_rslt))
Did you mean to drop the above integer_nonzerop() in favour of
distinguishing -1 and -2 below or did you disable -2 on purpose?
If so then i'd swap the order of the NULL check and the wi:: as
supposedly faster and easier to read..
thanks,
+ {
+ if (integer_nonzerop (cmp_rslt))
+ {
+ tree niter_type, diff;
+
+ niter_type = unsigned_type_for (TREE_TYPE (newbound));
+ /* The split condition indicates smaller iteration space than the
+ original loop, so the second loop must be executed. */
+ if (cmp_code == LT_EXPR)
+ diff = fold_build2 (MINUS_EXPR, niter_type,
+ fold_convert (niter_type, newbound),
+ fold_convert (niter_type, border));
+ else
+ diff = fold_build2 (MINUS_EXPR, niter_type,
+ fold_convert (niter_type, border),
+ fold_convert (niter_type, newbound));
+
+ /* Check if niter can be computed. */
+ if (tree_fits_shwi_p (diff) && !tree_int_cst_sign_bit (diff))
+ *second_loop_niter_bound = tree_to_shwi (diff) - 1;
+ else
+ *second_loop_niter_bound = -1;
+
+ return border;
+ }
+ else if (integer_zerop (cmp_rslt))
+ {
+ /* The split condition indicates larger iteration space than the
+ oiginal loop, so the second loop must not be executed. */
+ *second_loop_niter_bound = -2;
+ return newbound;
+ }
+ }
+