aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/pr78060.C14
-rw-r--r--gcc/testsuite/g++.dg/pr78088.C19
-rw-r--r--gcc/testsuite/gfortran.dg/pr78061.f18
-rw-r--r--gcc/tree-ssa-loop-split.c63
6 files changed, 112 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5a93e88..0b537ac 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d27d57a..a5049cf8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..d6cc7b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr78060.C
@@ -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
index 0000000..1a5c063
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr78088.C
@@ -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
index 0000000..7e4dd3d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr78061.f
@@ -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
diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c
index 53abb36..dac68e6 100644
--- a/gcc/tree-ssa-loop-split.c
+++ b/gcc/tree-ssa-loop-split.c
@@ -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