This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Reduce complette unrolling & peeling limits
Hi,
here is updated patch. It should get the bounds safe enough to not have effect
on codegen of complette unrolling.
There is IMO no way to cut the walk of loop body w/o affecting codegen in
unrolling for size mode. The condition on unroling to happen is
unrolled_size * 2 / 3 < original_size
The patch makes the function walking body to stop after minimal number of
duplicated insns is large (PARAM_MAX_COMPLETELY_PEELED_INSNS). The formula
above allows unlimited duplication when loop body is large enough. This is
more a bug than feature, so I think it is safe to alter it.
Bootstrapped/regtested x86_64-linux, OK?
Honza
* tree-ssa-loop-ivcanon.c (tree_estimate_loop_size): Add UPPER_BOUND
parameter.
(try_unroll_loop_completely) Update.
Index: tree-ssa-loop-ivcanon.c
===================================================================
--- tree-ssa-loop-ivcanon.c (revision 193694)
+++ tree-ssa-loop-ivcanon.c (working copy)
@@ -1,5 +1,5 @@
-/* Induction variable canonicalization.
- Copyright (C) 2004, 2005, 2007, 2008, 2010
+/* Induction variable canonicalization and loop peeling.
+ Copyright (C) 2004, 2005, 2007, 2008, 2010, 2012
Free Software Foundation, Inc.
This file is part of GCC.
@@ -207,10 +210,12 @@ constant_after_peeling (tree op, gimple
iteration of the loop.
EDGE_TO_CANCEL (if non-NULL) is an non-exit edge eliminated in the last iteration
of loop.
- Return results in SIZE, estimate benefits for complete unrolling exiting by EXIT. */
+ Return results in SIZE, estimate benefits for complete unrolling exiting by EXIT.
+ Stop estimating after UPPER_BOUND is met. Return true in this case */
-static void
-tree_estimate_loop_size (struct loop *loop, edge exit, edge edge_to_cancel, struct loop_size *size)
+static bool
+tree_estimate_loop_size (struct loop *loop, edge exit, edge edge_to_cancel, struct loop_size *size,
+ int upper_bound)
{
basic_block *body = get_loop_body (loop);
gimple_stmt_iterator gsi;
@@ -316,6 +321,12 @@ tree_estimate_loop_size (struct loop *lo
if (likely_eliminated || likely_eliminated_last)
size->last_iteration_eliminated_by_peeling += num;
}
+ if ((size->overall * 3 / 2 - size->eliminated_by_peeling
+ - size->last_iteration_eliminated_by_peeling) > upper_bound)
+ {
+ free (body);
+ return true;
+ }
}
}
while (path.length ())
@@ -357,6 +368,7 @@ tree_estimate_loop_size (struct loop *lo
size->last_iteration_eliminated_by_peeling);
free (body);
+ return false;
}
/* Estimate number of insns of completely unrolled loop.
@@ -699,12 +711,22 @@ try_unroll_loop_completely (struct loop
sbitmap wont_exit;
edge e;
unsigned i;
- vec<edge> to_remove = vNULL;
+ bool large;
+ vec<edge> to_remove = vNULL;
if (ul == UL_SINGLE_ITER)
return false;
- tree_estimate_loop_size (loop, exit, edge_to_cancel, &size);
+ large = tree_estimate_loop_size
+ (loop, exit, edge_to_cancel, &size,
+ PARAM_VALUE (PARAM_MAX_COMPLETELY_PEELED_INSNS));
ninsns = size.overall;
+ if (large)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Not unrolling loop %d: it is too large.\n",
+ loop->num);
+ return false;
+ }
unr_insns = estimated_unrolled_size (&size, n_unroll);
if (dump_file && (dump_flags & TDF_DETAILS))