fix pr78060 pr78061 pr78088
authorMichael Matz <matz@suse.de>
Wed, 26 Oct 2016 12:54:30 +0000 (12:54 +0000)
committerMichael Matz <matz@gcc.gnu.org>
Wed, 26 Oct 2016 12:54:30 +0000 (12:54 +0000)
PR tree-optimization/78060
PR tree-optimization/78061
PR tree-optimization/78088
* tree-ssa-loop-split.c (easy_exit_values): New function.
(tree_ssa_split_loops): Use it.
(compute_new_first_bound): Change order of operations,
fix invalid use of types.

testsuite/
* g++.dg/pr78060.C: New test.
* gfortran.dg/pr78061.f: New test.
* g++.dg/pr78088.C: New test.

From-SVN: r241551

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/pr78060.C [new file with mode: 0644]
gcc/testsuite/g++.dg/pr78088.C [new file with mode: 0644]
gcc/testsuite/gfortran.dg/pr78061.f [new file with mode: 0644]
gcc/tree-ssa-loop-split.c

index 5a93e88a97b6b61cfdc8121e5d3209402f5145a3..0b537acb64dc6ffef6ff44c5ec969c6da4333052 100644 (file)
@@ -1,3 +1,13 @@
+2016-10-26  Michael Matz  <matz@suse.de>
+
+       PR tree-optimization/78060
+       PR tree-optimization/78061
+       PR tree-optimization/78088
+       * tree-ssa-loop-split.c (easy_exit_values): New function.
+       (tree_ssa_split_loops): Use it.
+       (compute_new_first_bound): Change order of operations,
+       fix invalid use of types.
+
 2016-10-26  Georg-Johann Lay  <avr@gjlay.de>
 
        gen-pass-instances.awk is sensitive to the order in which
index d27d57addd5923e51acc7d88df2cc66f7b40daf0..a5049cf89cd2d645629aeade38238e3af39e16bb 100644 (file)
@@ -1,3 +1,9 @@
+2016-10-26  Michael Matz  <matz@suse.de>
+
+       * g++.dg/pr78060.C: New test.
+       * gfortran.dg/pr78061.f: New test.
+       * g++.dg/pr78088.C: New test.
+
 2016-10-26  Fritz Reese <fritzoreese@gmail.com>
 
        * gfortran.dg/dec_io_1.f90: New test.
diff --git a/gcc/testsuite/g++.dg/pr78060.C b/gcc/testsuite/g++.dg/pr78060.C
new file mode 100644 (file)
index 0000000..d6cc7b3
--- /dev/null
@@ -0,0 +1,14 @@
+// PR tree-optimization/78060
+// { dg-do compile }
+// { dg-options "-O3 -fsplit-loops" }
+class A {
+public:
+  template <typename T2> int &operator[](T2);
+};
+int a;
+A b;
+void fn1() {
+  long c;
+  for (int l; l < c; ++l)
+    b[l] = l < 2 ?: a;
+}
diff --git a/gcc/testsuite/g++.dg/pr78088.C b/gcc/testsuite/g++.dg/pr78088.C
new file mode 100644 (file)
index 0000000..1a5c063
--- /dev/null
@@ -0,0 +1,19 @@
+// PR tree-optimization/78088
+// { dg-do compile }
+// { dg-options "-O3 -fsplit-loops" }
+class A {
+public:
+  int m_fn1();
+};
+struct B : A {
+  void m_fn2();
+};
+void B::m_fn2() {
+  long a;
+  int b, c;
+  for (;;) {
+    c = 0;
+    for (; c < a; ++c, ++b)
+      b > 0 ? m_fn1() : 0;
+  }
+}
diff --git a/gcc/testsuite/gfortran.dg/pr78061.f b/gcc/testsuite/gfortran.dg/pr78061.f
new file mode 100644 (file)
index 0000000..7e4dd3d
--- /dev/null
@@ -0,0 +1,18 @@
+! { dg-do compile }
+! { dg-options "-O3 -fsplit-loops" }
+      SUBROUTINE SSYMM(C)
+      REAL C(LDC,*)
+      LOGICAL LSAME
+      LOGICAL UPPER
+      IF (LSAME) THEN
+          DO 170 J = 1,N
+              DO 140 K = 1,J  
+                  IF (UPPER) THEN
+                      END IF
+  140         CONTINUE
+              DO 160 K = J + 1,N
+                  C(I,J) = B(K)
+  160         CONTINUE
+  170     CONTINUE
+      END IF
+      END
index 53abb3616ca1839aa5e4ac10edeaaa72ac0842b7..dac68e6723a6be1146dfad526d953bba283c176a 100644 (file)
@@ -190,13 +190,40 @@ find_or_create_guard_phi (struct loop *loop, tree guard_iv, affine_iv * /*iv*/)
   return NULL;
 }
 
+/* Returns true if the exit values of all loop phi nodes can be
+   determined easily (i.e. that connect_loop_phis can determine them).  */
+
+static bool
+easy_exit_values (struct loop *loop)
+{
+  edge exit = single_exit (loop);
+  edge latch = loop_latch_edge (loop);
+  gphi_iterator psi;
+
+  /* Currently we regard the exit values as easy if they are the same
+     as the value over the backedge.  Which is the case if the definition
+     of the backedge value dominates the exit edge.  */
+  for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
+    {
+      gphi *phi = psi.phi ();
+      tree next = PHI_ARG_DEF_FROM_EDGE (phi, latch);
+      basic_block bb;
+      if (TREE_CODE (next) == SSA_NAME
+         && (bb = gimple_bb (SSA_NAME_DEF_STMT (next)))
+         && !dominated_by_p (CDI_DOMINATORS, exit->src, bb))
+       return false;
+    }
+
+  return true;
+}
+
 /* This function updates the SSA form after connect_loops made a new
    edge NEW_E leading from LOOP1 exit to LOOP2 (via in intermediate
    conditional).  I.e. the second loop can now be entered either
    via the original entry or via NEW_E, so the entry values of LOOP2
    phi nodes are either the original ones or those at the exit
    of LOOP1.  Insert new phi nodes in LOOP2 pre-header reflecting
-   this.  */
+   this.  The loops need to fulfill easy_exit_values().  */
 
 static void
 connect_loop_phis (struct loop *loop1, struct loop *loop2, edge new_e)
@@ -383,37 +410,37 @@ compute_new_first_bound (gimple_seq *stmts, struct tree_niter_desc *niter,
                            TREE_TYPE (controlbase),
                            controlbase, controlstep);
 
-  /* Compute beg-guard_init.  */
+  /* 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, guard_init);
+      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),
-                             enddiff, tem);
+                             end, tem);
     }
   else
     enddiff = gimple_build (stmts, MINUS_EXPR, TREE_TYPE (enddiff),
-                           enddiff, guard_init);
+                           end, enddiff);
 
-  /* Compute end-(beg-guard_init).  */
-  gimple_seq stmts2;
-  tree newbound = force_gimple_operand (niter->bound, &stmts2,
-                                       true, NULL_TREE);
-  gimple_seq_add_seq_without_update (stmts, stmts2);
-
-  if (POINTER_TYPE_P (TREE_TYPE (enddiff))
-      || POINTER_TYPE_P (TREE_TYPE (newbound)))
+  /* 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);
       enddiff = gimple_build (stmts, NEGATE_EXPR, sizetype, enddiff);
       newbound = gimple_build (stmts, POINTER_PLUS_EXPR,
-                              TREE_TYPE (newbound),
-                              newbound, enddiff);
+                              TREE_TYPE (guard_init),
+                              guard_init, enddiff);
     }
   else
-    newbound = gimple_build (stmts, MINUS_EXPR, TREE_TYPE (enddiff),
-                            newbound, enddiff);
+    newbound = gimple_build (stmts, PLUS_EXPR, TREE_TYPE (guard_init),
+                            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.
@@ -449,7 +476,6 @@ compute_new_first_bound (gimple_seq *stmts, struct tree_niter_desc *niter,
                               build_int_cst (type2, addbound));
     }
 
-  newbound = gimple_convert (stmts, TREE_TYPE (border), newbound);
   tree newend = gimple_build (stmts, minmax, TREE_TYPE (border),
                              border, newbound);
   return newend;
@@ -615,6 +641,7 @@ tree_ssa_split_loops (void)
             original exit before.  */
          && empty_block_p (loop->latch)
          && !optimize_loop_for_size_p (loop)
+         && easy_exit_values (loop)
          && number_of_iterations_exit (loop, single_exit (loop), &niter,
                                        false, true)
          && niter.cmp != ERROR_MARK