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;
+ }
+    }
+

Reply via email to