Commit 09844a5f by Michael Matz Committed by Michael Matz

fix pr78060 pr78061 pr78088

	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
parent 0ef33d44
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> 2016-10-26 Georg-Johann Lay <avr@gjlay.de>
gen-pass-instances.awk is sensitive to the order in which gen-pass-instances.awk is sensitive to the order in which
......
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> 2016-10-26 Fritz Reese <fritzoreese@gmail.com>
* gfortran.dg/dec_io_1.f90: New test. * gfortran.dg/dec_io_1.f90: New test.
......
// 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;
}
// 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;
}
}
! { 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
...@@ -190,13 +190,40 @@ find_or_create_guard_phi (struct loop *loop, tree guard_iv, affine_iv * /*iv*/) ...@@ -190,13 +190,40 @@ find_or_create_guard_phi (struct loop *loop, tree guard_iv, affine_iv * /*iv*/)
return NULL; 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 /* This function updates the SSA form after connect_loops made a new
edge NEW_E leading from LOOP1 exit to LOOP2 (via in intermediate edge NEW_E leading from LOOP1 exit to LOOP2 (via in intermediate
conditional). I.e. the second loop can now be entered either 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 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 phi nodes are either the original ones or those at the exit
of LOOP1. Insert new phi nodes in LOOP2 pre-header reflecting of LOOP1. Insert new phi nodes in LOOP2 pre-header reflecting
this. */ this. The loops need to fulfill easy_exit_values(). */
static void static void
connect_loop_phis (struct loop *loop1, struct loop *loop2, edge new_e) 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, ...@@ -383,37 +410,37 @@ compute_new_first_bound (gimple_seq *stmts, struct tree_niter_desc *niter,
TREE_TYPE (controlbase), TREE_TYPE (controlbase),
controlbase, controlstep); 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))) 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); tem = gimple_build (stmts, NEGATE_EXPR, sizetype, tem);
enddiff = gimple_build (stmts, POINTER_PLUS_EXPR, enddiff = gimple_build (stmts, POINTER_PLUS_EXPR,
TREE_TYPE (enddiff), TREE_TYPE (enddiff),
enddiff, tem); end, tem);
} }
else else
enddiff = gimple_build (stmts, MINUS_EXPR, TREE_TYPE (enddiff), enddiff = gimple_build (stmts, MINUS_EXPR, TREE_TYPE (enddiff),
enddiff, guard_init); end, enddiff);
/* Compute end-(beg-guard_init). */ /* Compute guard_init + (end-beg). */
gimple_seq stmts2; tree newbound;
tree newbound = force_gimple_operand (niter->bound, &stmts2, enddiff = gimple_convert (stmts, TREE_TYPE (guard_init), enddiff);
true, NULL_TREE); if (POINTER_TYPE_P (TREE_TYPE (guard_init)))
gimple_seq_add_seq_without_update (stmts, stmts2);
if (POINTER_TYPE_P (TREE_TYPE (enddiff))
|| POINTER_TYPE_P (TREE_TYPE (newbound)))
{ {
enddiff = gimple_convert (stmts, sizetype, enddiff); enddiff = gimple_convert (stmts, sizetype, enddiff);
enddiff = gimple_build (stmts, NEGATE_EXPR, sizetype, enddiff); enddiff = gimple_build (stmts, NEGATE_EXPR, sizetype, enddiff);
newbound = gimple_build (stmts, POINTER_PLUS_EXPR, newbound = gimple_build (stmts, POINTER_PLUS_EXPR,
TREE_TYPE (newbound), TREE_TYPE (guard_init),
newbound, enddiff); guard_init, enddiff);
} }
else else
newbound = gimple_build (stmts, MINUS_EXPR, TREE_TYPE (enddiff), newbound = gimple_build (stmts, PLUS_EXPR, TREE_TYPE (guard_init),
newbound, enddiff); guard_init, enddiff);
/* Depending on the direction of the IVs the new bound for the first /* Depending on the direction of the IVs the new bound for the first
loop is the minimum or maximum of old bound and border. 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, ...@@ -449,7 +476,6 @@ compute_new_first_bound (gimple_seq *stmts, struct tree_niter_desc *niter,
build_int_cst (type2, addbound)); build_int_cst (type2, addbound));
} }
newbound = gimple_convert (stmts, TREE_TYPE (border), newbound);
tree newend = gimple_build (stmts, minmax, TREE_TYPE (border), tree newend = gimple_build (stmts, minmax, TREE_TYPE (border),
border, newbound); border, newbound);
return newend; return newend;
...@@ -615,6 +641,7 @@ tree_ssa_split_loops (void) ...@@ -615,6 +641,7 @@ tree_ssa_split_loops (void)
original exit before. */ original exit before. */
&& empty_block_p (loop->latch) && empty_block_p (loop->latch)
&& !optimize_loop_for_size_p (loop) && !optimize_loop_for_size_p (loop)
&& easy_exit_values (loop)
&& number_of_iterations_exit (loop, single_exit (loop), &niter, && number_of_iterations_exit (loop, single_exit (loop), &niter,
false, true) false, true)
&& niter.cmp != ERROR_MARK && niter.cmp != ERROR_MARK
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment