Hi,
Loop split forces intermediate computation to gimple operands all the time when
computing bound information.  This is not good since folding opportunities are
missed.  This patch fixes the issue by feeding all computation to folder and 
only
forcing to gimple operand at last.

Bootstrap and test on x86_64 and AArch64.  Is it OK?

Thanks,
bin
2017-06-12  Bin Cheng  <bin.ch...@arm.com>

        * tree-ssa-loop-split.c (compute_new_first_bound): Feed bound
        computation to folder, rather than force to gimple operands too
        early.
From 372dc98aa91fd495c98c2326f854eb5f2c76500b Mon Sep 17 00:00:00 2001
From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com>
Date: Fri, 2 Jun 2017 18:05:03 +0100
Subject: [PATCH 1/2] feed-bound-computation-to-folder-20170601.txt

---
 gcc/tree-ssa-loop-split.c | 77 ++++++++++++++++++-----------------------------
 1 file changed, 30 insertions(+), 47 deletions(-)

diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c
index e77f2bf..f8fe8e6 100644
--- a/gcc/tree-ssa-loop-split.c
+++ b/gcc/tree-ssa-loop-split.c
@@ -396,53 +396,38 @@ compute_new_first_bound (gimple_seq *stmts, struct 
tree_niter_desc *niter,
 {
   /* The niter structure contains the after-increment IV, we need
      the loop-enter base, so subtract STEP once.  */
-  tree controlbase = force_gimple_operand (niter->control.base,
-                                          stmts, true, NULL_TREE);
+  tree controlbase = niter->control.base;
   tree controlstep = niter->control.step;
-  tree enddiff;
+  tree enddiff, end = niter->bound;
+  tree type;
+
+  /* Compute end-beg.  */
   if (POINTER_TYPE_P (TREE_TYPE (controlbase)))
     {
-      controlstep = gimple_build (stmts, NEGATE_EXPR,
-                                 TREE_TYPE (controlstep), controlstep);
-      enddiff = gimple_build (stmts, POINTER_PLUS_EXPR,
-                             TREE_TYPE (controlbase),
-                             controlbase, controlstep);
+      controlstep = fold_build1 (NEGATE_EXPR,
+                                TREE_TYPE (controlstep), controlstep);
+      enddiff = fold_build_pointer_plus (controlbase, controlstep);
+
+      type = unsigned_type_for (enddiff);
+      enddiff = fold_build1 (NEGATE_EXPR, type, fold_convert (type, enddiff));
+      end = fold_convert (type, end);
+      enddiff = fold_build2 (PLUS_EXPR, type, end, enddiff);
+      enddiff = fold_convert (sizetype, enddiff);
     }
   else
-    enddiff = gimple_build (stmts, MINUS_EXPR,
-                           TREE_TYPE (controlbase),
-                           controlbase, controlstep);
-
-  /* Compute end-beg.  */
-  gimple_seq stmts2;
-  tree end = force_gimple_operand (niter->bound, &stmts2,
-                                       true, NULL_TREE);
-  gimple_seq_add_seq_without_update (stmts, stmts2);
-  if (POINTER_TYPE_P (TREE_TYPE (enddiff)))
     {
-      tree tem = gimple_convert (stmts, sizetype, enddiff);
-      tem = gimple_build (stmts, NEGATE_EXPR, sizetype, tem);
-      enddiff = gimple_build (stmts, POINTER_PLUS_EXPR,
-                             TREE_TYPE (enddiff),
-                             end, tem);
+      enddiff = fold_build2 (MINUS_EXPR, TREE_TYPE (controlbase),
+                            controlbase, controlstep);
+      enddiff = fold_build2 (MINUS_EXPR, TREE_TYPE (enddiff), end, enddiff);
     }
-  else
-    enddiff = gimple_build (stmts, MINUS_EXPR, TREE_TYPE (enddiff),
-                           end, enddiff);
 
   /* Compute guard_init + (end-beg).  */
   tree newbound;
-  enddiff = gimple_convert (stmts, TREE_TYPE (guard_init), enddiff);
   if (POINTER_TYPE_P (TREE_TYPE (guard_init)))
-    {
-      enddiff = gimple_convert (stmts, sizetype, enddiff);
-      newbound = gimple_build (stmts, POINTER_PLUS_EXPR,
-                              TREE_TYPE (guard_init),
-                              guard_init, enddiff);
-    }
+    newbound = fold_build_pointer_plus (guard_init, enddiff);
   else
-    newbound = gimple_build (stmts, PLUS_EXPR, TREE_TYPE (guard_init),
-                            guard_init, enddiff);
+    newbound = fold_build2 (PLUS_EXPR, TREE_TYPE (guard_init), guard_init,
+                           fold_convert (TREE_TYPE (guard_init), enddiff));
 
   /* Depending on the direction of the IVs the new bound for the first
      loop is the minimum or maximum of old bound and border.
@@ -467,20 +452,18 @@ compute_new_first_bound (gimple_seq *stmts, struct 
tree_niter_desc *niter,
 
   if (addbound)
     {
-      tree type2 = TREE_TYPE (newbound);
-      if (POINTER_TYPE_P (type2))
-       type2 = sizetype;
-      newbound = gimple_build (stmts,
-                              POINTER_TYPE_P (TREE_TYPE (newbound))
-                              ? POINTER_PLUS_EXPR : PLUS_EXPR,
-                              TREE_TYPE (newbound),
-                              newbound,
-                              build_int_cst (type2, addbound));
+      type = TREE_TYPE (newbound);
+      if (POINTER_TYPE_P (type))
+       type = sizetype;
+      newbound = fold_build2 (POINTER_TYPE_P (TREE_TYPE (newbound))
+                               ? POINTER_PLUS_EXPR : PLUS_EXPR,
+                             TREE_TYPE (newbound),
+                             newbound,
+                             build_int_cst (type, addbound));
     }
 
-  tree newend = gimple_build (stmts, minmax, TREE_TYPE (border),
-                             border, newbound);
-  return newend;
+  newbound = fold_build2 (minmax, TREE_TYPE (border), border, newbound);
+  return force_gimple_operand (newbound, stmts, true, NULL_TREE);
 }
 
 /* Checks if LOOP contains an conditional block whose condition
-- 
1.9.1

Reply via email to