re PR tree-optimization/87074 (Unroll and jam bug: O3 result differ from O2)
Fix PR87074 PR tree-optimization/87074 * gimple-loop-jam.c (unroll_jam_possible_p): Check loop exit PHIs for outer-loop uses. testsuite/ * gcc.dg/pr87074.c: New test. From-SVN: r264029
This commit is contained in:
parent
c8a4f039fc
commit
395552b520
@ -1,3 +1,9 @@
|
|||||||
|
2018-09-01 Michael Matz <matz@suse.de>
|
||||||
|
|
||||||
|
PR tree-optimization/87074
|
||||||
|
* gimple-loop-jam.c (unroll_jam_possible_p): Check loop exit
|
||||||
|
PHIs for outer-loop uses.
|
||||||
|
|
||||||
2018-09-01 Gerald Pfeifer <gerald@pfeifer.com>
|
2018-09-01 Gerald Pfeifer <gerald@pfeifer.com>
|
||||||
|
|
||||||
* doc/install.texi (Prerequisites): Adjust link mpfr.org.
|
* doc/install.texi (Prerequisites): Adjust link mpfr.org.
|
||||||
|
@ -161,7 +161,7 @@ bb_prevents_fusion_p (basic_block bb)
|
|||||||
gimple_stmt_iterator gsi;
|
gimple_stmt_iterator gsi;
|
||||||
/* BB is duplicated by outer unrolling and then all N-1 first copies
|
/* BB is duplicated by outer unrolling and then all N-1 first copies
|
||||||
move into the body of the fused inner loop. If BB exits the outer loop
|
move into the body of the fused inner loop. If BB exits the outer loop
|
||||||
the last copy still doess so, and the first N-1 copies are cancelled
|
the last copy still does so, and the first N-1 copies are cancelled
|
||||||
by loop unrolling, so also after fusion it's the exit block.
|
by loop unrolling, so also after fusion it's the exit block.
|
||||||
But there might be other reasons that prevent fusion:
|
But there might be other reasons that prevent fusion:
|
||||||
* stores or unknown side-effects prevent fusion
|
* stores or unknown side-effects prevent fusion
|
||||||
@ -227,6 +227,33 @@ unroll_jam_possible_p (struct loop *outer, struct loop *loop)
|
|||||||
|| !expr_invariant_in_loop_p (outer, niter.niter))
|
|| !expr_invariant_in_loop_p (outer, niter.niter))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* If the inner loop produces any values that are used inside the
|
||||||
|
outer loop (except the virtual op) then it can flow
|
||||||
|
back (perhaps indirectly) into the inner loop. This prevents
|
||||||
|
fusion: without fusion the value at the last iteration is used,
|
||||||
|
with fusion the value after the initial iteration is used.
|
||||||
|
|
||||||
|
If all uses are outside the outer loop this doesn't prevent fusion;
|
||||||
|
the value of the last iteration is still used (and the values from
|
||||||
|
all intermediate iterations are dead). */
|
||||||
|
gphi_iterator psi;
|
||||||
|
for (psi = gsi_start_phis (single_exit (loop)->dest);
|
||||||
|
!gsi_end_p (psi); gsi_next (&psi))
|
||||||
|
{
|
||||||
|
imm_use_iterator imm_iter;
|
||||||
|
use_operand_p use_p;
|
||||||
|
tree op = gimple_phi_result (psi.phi ());
|
||||||
|
if (virtual_operand_p (op))
|
||||||
|
continue;
|
||||||
|
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
|
||||||
|
{
|
||||||
|
gimple *use_stmt = USE_STMT (use_p);
|
||||||
|
if (!is_gimple_debug (use_stmt)
|
||||||
|
&& flow_bb_inside_loop_p (outer, gimple_bb (use_stmt)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* And check blocks belonging to just outer loop. */
|
/* And check blocks belonging to just outer loop. */
|
||||||
bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
|
bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
|
||||||
n = get_loop_body_with_size (outer, bbs, n_basic_blocks_for_fn (cfun));
|
n = get_loop_body_with_size (outer, bbs, n_basic_blocks_for_fn (cfun));
|
||||||
@ -245,7 +272,6 @@ unroll_jam_possible_p (struct loop *outer, struct loop *loop)
|
|||||||
body would be the after-iter value of the first body) if it's over
|
body would be the after-iter value of the first body) if it's over
|
||||||
an associative and commutative operation. We wouldn't
|
an associative and commutative operation. We wouldn't
|
||||||
be able to handle unknown cycles. */
|
be able to handle unknown cycles. */
|
||||||
gphi_iterator psi;
|
|
||||||
for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
|
for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
|
||||||
{
|
{
|
||||||
affine_iv iv;
|
affine_iv iv;
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2018-09-01 Michael Matz <matz@suse.de>
|
||||||
|
|
||||||
|
PR tree-optimization/87074
|
||||||
|
* gcc.dg/pr87074.c: New test.
|
||||||
|
|
||||||
2018-08-31 Richard Biener <rguenther@suse.de>
|
2018-08-31 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
PR tree-optimization/87168
|
PR tree-optimization/87168
|
||||||
|
25
gcc/testsuite/gcc.dg/pr87074.c
Normal file
25
gcc/testsuite/gcc.dg/pr87074.c
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-options "-O3 -floop-unroll-and-jam --param unroll-jam-min-percent=0" } */
|
||||||
|
long b;
|
||||||
|
unsigned c[5];
|
||||||
|
unsigned long long d = 3;
|
||||||
|
int e, f, g;
|
||||||
|
|
||||||
|
void h() {
|
||||||
|
for (; f < 11; f++) {
|
||||||
|
b = g;
|
||||||
|
for (e = 0; e < 5; e++) {
|
||||||
|
c[e] = e - b - (c[e] >> 5);
|
||||||
|
g = c[e];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c[0])
|
||||||
|
d = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void abort(void);
|
||||||
|
int main() {
|
||||||
|
h();
|
||||||
|
if (d != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user