Commit 519cac4a by Jan Hubicka Committed by Jan Hubicka

cfgloopanal.c (get_loop_hot_path): New function.

	* cfgloopanal.c (get_loop_hot_path): New function.
	* tree-ssa-lop-ivcanon.c (struct loop_size): Add CONSTANT_IV,
	NUM_NON_PURE_CALLS_ON_HOT_PATH, NUM_PURE_CALLS_ON_HOT_PATH,
	NUM_BRANCHES_ON_HOT_PATH.
	(tree_estimate_loop_size): Compute the new values.
	(try_unroll_loop_completely): Disable unrolling of loops with only
	calls or too many branches.
	(tree_unroll_loops_completely): Deal also with outer loops of hot loops.
	* cfgloop.h (get_loop_hot_path): Declare.
	* params.def (PARAM_MAX_PEEL_BRANCHES): New parameters.
	* invoke.texi (max-peel-branches): Document.

	* gcc.dg/tree-ssa/loop-1.c: Make to look like a good unroling candidate still.
	* gcc.dg/tree-ssa/loop-23.c: Likewise.
	* gcc.dg/tree-ssa/cunroll-1.c: Unrolling now happens early.
	* gcc.dg/tree-prof/unroll-1.c: Remove confused dg-options.

From-SVN: r193246
parent 425b784f
...@@ -714,6 +714,7 @@ extern void doloop_optimize_loops (void); ...@@ -714,6 +714,7 @@ extern void doloop_optimize_loops (void);
extern void move_loop_invariants (void); extern void move_loop_invariants (void);
extern bool finite_loop_p (struct loop *); extern bool finite_loop_p (struct loop *);
extern void scale_loop_profile (struct loop *loop, int scale, int iteration_bound); extern void scale_loop_profile (struct loop *loop, int scale, int iteration_bound);
extern VEC (basic_block, heap) * get_loop_hot_path (const struct loop *loop);
/* Returns the outermost loop of the loop nest that contains LOOP.*/ /* Returns the outermost loop of the loop nest that contains LOOP.*/
static inline struct loop * static inline struct loop *
......
...@@ -483,3 +483,36 @@ single_likely_exit (struct loop *loop) ...@@ -483,3 +483,36 @@ single_likely_exit (struct loop *loop)
VEC_free (edge, heap, exits); VEC_free (edge, heap, exits);
return found; return found;
} }
/* Gets basic blocks of a LOOP. Header is the 0-th block, rest is in dfs
order against direction of edges from latch. Specially, if
header != latch, latch is the 1-st block. */
VEC (basic_block, heap) *
get_loop_hot_path (const struct loop *loop)
{
basic_block bb = loop->header;
VEC (basic_block, heap) *path = NULL;
bitmap visited = BITMAP_ALLOC (NULL);
while (true)
{
edge_iterator ei;
edge e;
edge best = NULL;
VEC_safe_push (basic_block, heap, path, bb);
bitmap_set_bit (visited, bb->index);
FOR_EACH_EDGE (e, ei, bb->succs)
if ((!best || e->probability > best->probability)
&& !loop_exit_edge_p (loop, e)
&& !bitmap_bit_p (visited, e->dest->index))
best = e;
if (!best || best->dest == loop->header)
break;
bb = best->dest;
}
BITMAP_FREE (visited);
return path;
}
...@@ -9085,6 +9085,9 @@ the loop code is peeled. ...@@ -9085,6 +9085,9 @@ the loop code is peeled.
@item max-peel-times @item max-peel-times
The maximum number of peelings of a single loop. The maximum number of peelings of a single loop.
@item max-peel-branches
The maximum number of branches on the hot path through the peeled sequence.
@item max-completely-peeled-insns @item max-completely-peeled-insns
The maximum number of insns of a completely peeled loop. The maximum number of insns of a completely peeled loop.
......
...@@ -291,6 +291,11 @@ DEFPARAM(PARAM_MAX_PEEL_TIMES, ...@@ -291,6 +291,11 @@ DEFPARAM(PARAM_MAX_PEEL_TIMES,
"max-peel-times", "max-peel-times",
"The maximum number of peelings of a single loop", "The maximum number of peelings of a single loop",
16, 0, 0) 16, 0, 0)
/* The maximum number of peelings of a single loop that is peeled completely. */
DEFPARAM(PARAM_MAX_PEEL_BRANCHES,
"max-peel-branches",
"The maximum number of branches on the path through the peeled sequence",
32, 0, 0)
/* The maximum number of insns of a peeled loop. */ /* The maximum number of insns of a peeled loop. */
DEFPARAM(PARAM_MAX_COMPLETELY_PEELED_INSNS, DEFPARAM(PARAM_MAX_COMPLETELY_PEELED_INSNS,
"max-completely-peeled-insns", "max-completely-peeled-insns",
......
2012-11-06 Jan Hubicka <jh@suse.cz>
* gcc.dg/tree-ssa/loop-1.c: Make to look like a good unroling candidate still.
* gcc.dg/tree-ssa/loop-23.c: Likewise.
* gcc.dg/tree-ssa/cunroll-1.c: Unrolling now happens early.
* gcc.dg/tree-prof/unroll-1.c: Remove confused dg-options.
2012-11-06 David Edelsohn <dje.gcc@gmail.com> 2012-11-06 David Edelsohn <dje.gcc@gmail.com>
* const-uniq-1.c: Expand regex to match AIX XCOFF labels. * const-uniq-1.c: Expand regex to match AIX XCOFF labels.
......
...@@ -21,4 +21,3 @@ main() ...@@ -21,4 +21,3 @@ main()
} }
/* { dg-final-use { scan-rtl-dump "Considering unrolling loop with constant number of iterations" "loop2_unroll" } } */ /* { dg-final-use { scan-rtl-dump "Considering unrolling loop with constant number of iterations" "loop2_unroll" } } */
/* { dg-final-use { cleanup-rtl-dump "Not unrolling loop, doesn't roll" } } */ /* { dg-final-use { cleanup-rtl-dump "Not unrolling loop, doesn't roll" } } */
/* { dg-options "-O3 -fdump-rtl-loop2_unroll -funroll-loops -fno-peel-loops" } */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O3 -fdump-tree-cunroll-details" } */ /* { dg-options "-O3 -fdump-tree-cunrolli-details" } */
int a[2]; int a[2];
test(int c) test(int c)
{ {
...@@ -10,4 +10,4 @@ test(int c) ...@@ -10,4 +10,4 @@ test(int c)
/* Array bounds says the loop will not roll much. */ /* Array bounds says the loop will not roll much. */
/* { dg-final { scan-tree-dump "Unrolled loop 1 completely .duplicated 1 times.." "cunroll"} } */ /* { dg-final { scan-tree-dump "Unrolled loop 1 completely .duplicated 1 times.." "cunroll"} } */
/* { dg-final { scan-tree-dump "Last iteration exit edge was proved true." "cunroll"} } */ /* { dg-final { scan-tree-dump "Last iteration exit edge was proved true." "cunroll"} } */
/* { dg-final { cleanup-tree-dump "cunroll" } } */ /* { dg-final { cleanup-tree-dump "cunrolli" } } */
...@@ -17,13 +17,16 @@ ...@@ -17,13 +17,16 @@
to the load from the GOT this also contains the name of the funtion so for to the load from the GOT this also contains the name of the funtion so for
each call the function name would appear twice. */ each call the function name would appear twice. */
/* { dg-options "-O1 -ftree-loop-ivcanon -funroll-loops -fdump-tree-ivcanon-details -fdump-tree-cunroll-details -fdump-tree-optimized -mno-relax-pic-calls" { target mips*-*-* } } */ /* { dg-options "-O1 -ftree-loop-ivcanon -funroll-loops -fdump-tree-ivcanon-details -fdump-tree-cunroll-details -fdump-tree-optimized -mno-relax-pic-calls" { target mips*-*-* } } */
__attribute__ ((pure))
void xxx(void) int foo (int x);
int xxx(void)
{ {
int x = 45; int x = 45;
int sum;
while (x >>= 1) while (x >>= 1)
foo (); sum += foo (x) * 2;
return sum;
} }
/* We should be able to find out that the loop iterates four times and unroll it completely. */ /* We should be able to find out that the loop iterates four times and unroll it completely. */
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -funroll-loops -fdump-tree-cunroll-details" } */ /* { dg-options "-O2 -funroll-loops -fdump-tree-cunroll-details" } */
void bla(int); __attribute__ ((pure))
int bla(int);
void foo(void) int foo(void)
{ {
int i; int i;
int sum;
/* This loop used to appear to be too large for unrolling. */ /* This loop used to appear to be too large for unrolling. */
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
bla (i); sum += bla (i);
bla (2*i); sum += bla (2*i);
bla (3*i); sum += bla (3*i);
bla (4*i); sum += bla (4*i);
bla (5*i); sum += bla (5*i);
bla (6*i); sum += bla (6*i);
bla (7*i); sum += bla (7*i);
bla (8*i); sum += bla (8*i);
} }
return sum;
} }
/* { dg-final { scan-tree-dump-times "Unrolled loop 1 completely" 1 "cunroll" } } */ /* { dg-final { scan-tree-dump-times "Unrolled loop 1 completely" 1 "cunroll" } } */
......
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