On 14 June 2017 at 15:08, Bin Cheng <bin.ch...@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; + } + } +