aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-loop-jam.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2017-12-08 17:41:58 +0000
committerMichael Matz <matz@gcc.gnu.org>2017-12-08 17:41:58 +0000
commitdc236397e4d96647c5d72fd9b6d503ca0b187bee (patch)
tree8625f7c609a77a4bd2a6ce6d24c8844af0a66513 /gcc/gimple-loop-jam.c
parent450aa0ee3d0f65be4288e8355d8923db5915baa6 (diff)
downloadgcc-dc236397e4d96647c5d72fd9b6d503ca0b187bee.zip
gcc-dc236397e4d96647c5d72fd9b6d503ca0b187bee.tar.gz
gcc-dc236397e4d96647c5d72fd9b6d503ca0b187bee.tar.bz2
re PR tree-optimization/83323 (186.crafty miscompares)
Fix PR83323 * gimple-loop-jam (unroll_jam_possible_p): Correct test for head-controlled loops and loop BBs. * common.opt (funroll-and-jam): Remove, instead ... (floop-unroll-and-jam): ... reuse this option. * opts.c (default_options_table): Use OPT_floop_unroll_and_jam. * doc/invoke.texi (-funroll-and-jam): Move docu to ... (-floop-unroll-and-jam): ... this option. testsuite/ * gcc.dg/pr83323.c: New test. * gcc.dg/unroll-and-jam.c: Use -floop-unroll-and-jam. From-SVN: r255514
Diffstat (limited to 'gcc/gimple-loop-jam.c')
-rw-r--r--gcc/gimple-loop-jam.c41
1 files changed, 20 insertions, 21 deletions
diff --git a/gcc/gimple-loop-jam.c b/gcc/gimple-loop-jam.c
index 32f813b..8ed1bef 100644
--- a/gcc/gimple-loop-jam.c
+++ b/gcc/gimple-loop-jam.c
@@ -152,7 +152,7 @@ merge_loop_tree (struct loop *loop, struct loop *old)
free (bbs);
}
-/* BB exits the outer loop of an unroll-and-jam situation.
+/* BB is part of the outer loop of an unroll-and-jam situation.
Check if any statements therein would prevent the transformation. */
static bool
@@ -160,9 +160,10 @@ bb_prevents_fusion_p (basic_block bb)
{
gimple_stmt_iterator gsi;
/* BB is duplicated by outer unrolling and then all N-1 first copies
- move into the body of the fused inner loop. The last copy remains
- the exit block of the outer loop and is still outside the inner loop
- also after fusion. We can't allow this for some effects of BB:
+ 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
+ by loop unrolling, so also after fusion it's the exit block.
+ But there might be other reasons that prevent fusion:
* stores or unknown side-effects prevent fusion
* loads don't
* computations into SSA names: these aren't problematic. Their
@@ -204,6 +205,19 @@ unroll_jam_possible_p (struct loop *outer, struct loop *loop)
if (outer->inner != loop || loop->next)
return false;
+ /* Prevent head-controlled inner loops, that we usually have.
+ The guard block would need to be accepted
+ (invariant condition either entering or skipping the loop),
+ without also accepting arbitrary control flow. When unswitching
+ ran before us (as with -O3) this won't be a problem because its
+ outer loop unswitching will have moved out the invariant condition.
+
+ If we do that we need to extend fuse_loops() to cope with this
+ by threading through the (still invariant) copied condition
+ between the two loop copies. */
+ if (!dominated_by_p (CDI_DOMINATORS, outer->latch, loop->header))
+ return false;
+
/* The number of iterations of the inner loop must be loop invariant
with respect to the outer loop. */
if (!number_of_iterations_exit (loop, single_exit (loop), &niter,
@@ -218,23 +232,8 @@ unroll_jam_possible_p (struct loop *outer, struct loop *loop)
n = get_loop_body_with_size (outer, bbs, n_basic_blocks_for_fn (cfun));
for (i = 0; i < n; i++)
- {
- if (bbs[i]->loop_father == outer
- && bbs[i] != outer->latch && bbs[i] != outer->header
- && (!loop_exits_from_bb_p (outer, bbs[i])
- || bb_prevents_fusion_p (bbs[i])))
- break;
- /* XXX Note that the above disallows head-controlled inner loops,
- that we usually have. The guard block would need to be accepted
- (invariant condition either entering or skipping the loop),
- without also accepting arbitrary control flow. When unswitching
- ran before us (as with -O3) this won't be a problem because its
- outer loop unswitching will have moved out the invariant condition.
-
- If we do that we need to extend fuse_loops() to cope with this
- by threading through the (still invariant) copied condition
- between the two loop copies. */
- }
+ if (bbs[i]->loop_father == outer && bb_prevents_fusion_p (bbs[i]))
+ break;
free (bbs);
if (i != n)
return false;