Commit e25a6711 by Teresa Johnson Committed by Teresa Johnson

dumpfile.c (dump_loc): Print filename with location.

2013-01-02  Teresa Johnson  <tejohnson@google.com>

	* dumpfile.c (dump_loc): Print filename with location.
	* tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Use
        new location_t parameter to emit complete unroll message with
        new dump framework.
	(canonicalize_loop_induction_variables): Compute loops location
        and pass to try_unroll_loop_completely.
	* loop-unroll.c (report_unroll_peel): New function.
	(peel_loops_completely): Use new dump format with location
        for main dumpfile message, and invoke report_unroll_peel on success.
	(decide_unrolling_and_peeling): Ditto.
	(decide_peel_once_rolling): Remove old dumpfile message subsumed
        by report_unroll_peel.
	(decide_peel_completely): Ditto.
	(decide_unroll_constant_iterations): Ditto.
	(decide_unroll_runtime_iterations): Ditto.
	(decide_peel_simple): Ditto.
	(decide_unroll_stupid): Ditto.
	* cfgloop.c (get_loop_location): New function.
	* cfgloop.h (get_loop_location): Declare.

        testsuite/
	* gcc.dg/tree-ssa/loop-1.c: Update expected dump message.
	* gcc.dg/tree-ssa/loop-23.c: Ditto.
	* gcc.dg/tree-ssa/cunroll-1.c: Ditto.
	* gcc.dg/tree-ssa/cunroll-2.c: Ditto.
	* gcc.dg/tree-ssa/cunroll-3.c: Ditto.
	* gcc.dg/tree-ssa/cunroll-4.c: Ditto.
	* gcc.dg/tree-ssa/cunroll-5.c: Ditto.
	* gcc.dg/unroll_1.c: Ditto.
	* gcc.dg/unroll_2.c: Ditto.
	* gcc.dg/unroll_3.c: Ditto.
	* gcc.dg/unroll_4.c: Ditto.

From-SVN: r194829
parent 77878621
2013-01-02 Teresa Johnson <tejohnson@google.com>
* dumpfile.c (dump_loc): Print filename with location.
* tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Use
new location_t parameter to emit complete unroll message with
new dump framework.
(canonicalize_loop_induction_variables): Compute loops location
and pass to try_unroll_loop_completely.
* loop-unroll.c (report_unroll_peel): New function.
(peel_loops_completely): Use new dump format with location
for main dumpfile message, and invoke report_unroll_peel on success.
(decide_unrolling_and_peeling): Ditto.
(decide_peel_once_rolling): Remove old dumpfile message subsumed
by report_unroll_peel.
(decide_peel_completely): Ditto.
(decide_unroll_constant_iterations): Ditto.
(decide_unroll_runtime_iterations): Ditto.
(decide_peel_simple): Ditto.
(decide_unroll_stupid): Ditto.
* cfgloop.c (get_loop_location): New function.
* cfgloop.h (get_loop_location): Declare.
testsuite/
* gcc.dg/tree-ssa/loop-1.c: Update expected dump message.
* gcc.dg/tree-ssa/loop-23.c: Ditto.
* gcc.dg/tree-ssa/cunroll-1.c: Ditto.
* gcc.dg/tree-ssa/cunroll-2.c: Ditto.
* gcc.dg/tree-ssa/cunroll-3.c: Ditto.
* gcc.dg/tree-ssa/cunroll-4.c: Ditto.
* gcc.dg/tree-ssa/cunroll-5.c: Ditto.
* gcc.dg/unroll_1.c: Ditto.
* gcc.dg/unroll_2.c: Ditto.
* gcc.dg/unroll_3.c: Ditto.
* gcc.dg/unroll_4.c: Ditto.
2013-01-02 Sriraman Tallam <tmsriram@google.com> 2013-01-02 Sriraman Tallam <tmsriram@google.com>
* config/i386/i386.c (fold_builtin_cpu): Remove unnecessary checks for * config/i386/i386.c (fold_builtin_cpu): Remove unnecessary checks for
...@@ -1666,3 +1666,55 @@ loop_exits_from_bb_p (struct loop *loop, basic_block bb) ...@@ -1666,3 +1666,55 @@ loop_exits_from_bb_p (struct loop *loop, basic_block bb)
return false; return false;
} }
/* Return location corresponding to the loop control condition if possible. */
location_t
get_loop_location (struct loop *loop)
{
rtx insn = NULL;
struct niter_desc *desc = NULL;
edge exit;
/* For a for or while loop, we would like to return the location
of the for or while statement, if possible. To do this, look
for the branch guarding the loop back-edge. */
/* If this is a simple loop with an in_edge, then the loop control
branch is typically at the end of its source. */
desc = get_simple_loop_desc (loop);
if (desc->in_edge)
{
FOR_BB_INSNS_REVERSE (desc->in_edge->src, insn)
{
if (INSN_P (insn) && INSN_HAS_LOCATION (insn))
return INSN_LOCATION (insn);
}
}
/* If loop has a single exit, then the loop control branch
must be at the end of its source. */
if ((exit = single_exit (loop)))
{
FOR_BB_INSNS_REVERSE (exit->src, insn)
{
if (INSN_P (insn) && INSN_HAS_LOCATION (insn))
return INSN_LOCATION (insn);
}
}
/* Next check the latch, to see if it is non-empty. */
FOR_BB_INSNS_REVERSE (loop->latch, insn)
{
if (INSN_P (insn) && INSN_HAS_LOCATION (insn))
return INSN_LOCATION (insn);
}
/* Finally, if none of the above identifies the loop control branch,
return the first location in the loop header. */
FOR_BB_INSNS (loop->header, insn)
{
if (INSN_P (insn) && INSN_HAS_LOCATION (insn))
return INSN_LOCATION (insn);
}
/* If all else fails, simply return the current function location. */
return DECL_SOURCE_LOCATION (current_function_decl);
}
...@@ -239,6 +239,7 @@ extern bool loop_exit_edge_p (const struct loop *, const_edge); ...@@ -239,6 +239,7 @@ extern bool loop_exit_edge_p (const struct loop *, const_edge);
extern bool loop_exits_to_bb_p (struct loop *, basic_block); extern bool loop_exits_to_bb_p (struct loop *, basic_block);
extern bool loop_exits_from_bb_p (struct loop *, basic_block); extern bool loop_exits_from_bb_p (struct loop *, basic_block);
extern void mark_loop_exit_edges (void); extern void mark_loop_exit_edges (void);
extern location_t get_loop_location (struct loop *loop);
/* Loops & cfg manipulation. */ /* Loops & cfg manipulation. */
extern basic_block *get_loop_body (const struct loop *); extern basic_block *get_loop_body (const struct loop *);
......
...@@ -265,7 +265,9 @@ dump_loc (int dump_kind, FILE *dfile, source_location loc) ...@@ -265,7 +265,9 @@ dump_loc (int dump_kind, FILE *dfile, source_location loc)
DECL_SOURCE_FILE (current_function_decl), DECL_SOURCE_FILE (current_function_decl),
DECL_SOURCE_LINE (current_function_decl)); DECL_SOURCE_LINE (current_function_decl));
else else
fprintf (dfile, "\n%d: ", LOCATION_LINE (loc)); fprintf (dfile, "\n%s:%d: note: ",
LOCATION_FILE (loc),
LOCATION_LINE (loc));
} }
} }
......
...@@ -148,6 +148,61 @@ static void combine_var_copies_in_loop_exit (struct var_to_expand *, ...@@ -148,6 +148,61 @@ static void combine_var_copies_in_loop_exit (struct var_to_expand *,
basic_block); basic_block);
static rtx get_expansion (struct var_to_expand *); static rtx get_expansion (struct var_to_expand *);
/* Emit a message summarizing the unroll or peel that will be
performed for LOOP, along with the loop's location LOCUS, if
appropriate given the dump or -fopt-info settings. */
static void
report_unroll_peel (struct loop *loop, location_t locus)
{
struct niter_desc *desc;
int niters = 0;
int report_flags = MSG_OPTIMIZED_LOCATIONS | TDF_RTL | TDF_DETAILS;
if (!dump_enabled_p ())
return;
/* In the special case where the loop never iterated, emit
a different message so that we don't report an unroll by 0.
This matches the equivalent message emitted during tree unrolling. */
if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY
&& !loop->lpt_decision.times)
{
dump_printf_loc (report_flags, locus,
"Turned loop into non-loop; it never loops.\n");
return;
}
desc = get_simple_loop_desc (loop);
if (desc->const_iter)
niters = desc->niter;
else if (loop->header->count)
niters = expected_loop_iterations (loop);
dump_printf_loc (report_flags, locus,
"%s loop %d times",
(loop->lpt_decision.decision == LPT_PEEL_COMPLETELY
? "Completely unroll"
: (loop->lpt_decision.decision == LPT_PEEL_SIMPLE
? "Peel" : "Unroll")),
loop->lpt_decision.times);
if (profile_info)
dump_printf (report_flags,
" (header execution count %d",
(int)loop->header->count);
if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY)
dump_printf (report_flags,
"%s%s iterations %d)",
profile_info ? ", " : " (",
desc->const_iter ? "const" : "average",
niters);
else if (profile_info)
dump_printf (report_flags, ")");
dump_printf (report_flags, "\n");
}
/* Unroll and/or peel (depending on FLAGS) LOOPS. */ /* Unroll and/or peel (depending on FLAGS) LOOPS. */
void void
unroll_and_peel_loops (int flags) unroll_and_peel_loops (int flags)
...@@ -234,11 +289,13 @@ peel_loops_completely (int flags) ...@@ -234,11 +289,13 @@ peel_loops_completely (int flags)
FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST) FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
{ {
loop->lpt_decision.decision = LPT_NONE; loop->lpt_decision.decision = LPT_NONE;
location_t locus = get_loop_location (loop);
if (dump_file) if (dump_enabled_p ())
fprintf (dump_file, dump_printf_loc (TDF_RTL, locus,
"\n;; *** Considering loop %d for complete peeling ***\n", ";; *** Considering loop %d at BB %d for "
loop->num); "complete peeling ***\n",
loop->num, loop->header->index);
loop->ninsns = num_loop_insns (loop); loop->ninsns = num_loop_insns (loop);
...@@ -248,6 +305,7 @@ peel_loops_completely (int flags) ...@@ -248,6 +305,7 @@ peel_loops_completely (int flags)
if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY) if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY)
{ {
report_unroll_peel (loop, locus);
peel_loop_completely (loop); peel_loop_completely (loop);
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
verify_loop_structure (); verify_loop_structure ();
...@@ -267,9 +325,13 @@ decide_unrolling_and_peeling (int flags) ...@@ -267,9 +325,13 @@ decide_unrolling_and_peeling (int flags)
FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST) FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
{ {
loop->lpt_decision.decision = LPT_NONE; loop->lpt_decision.decision = LPT_NONE;
location_t locus = get_loop_location (loop);
if (dump_file) if (dump_enabled_p ())
fprintf (dump_file, "\n;; *** Considering loop %d ***\n", loop->num); dump_printf_loc (TDF_RTL, locus,
";; *** Considering loop %d at BB %d for "
"unrolling and peeling ***\n",
loop->num, loop->header->index);
/* Do not peel cold areas. */ /* Do not peel cold areas. */
if (optimize_loop_for_size_p (loop)) if (optimize_loop_for_size_p (loop))
...@@ -309,6 +371,8 @@ decide_unrolling_and_peeling (int flags) ...@@ -309,6 +371,8 @@ decide_unrolling_and_peeling (int flags)
decide_unroll_stupid (loop, flags); decide_unroll_stupid (loop, flags);
if (loop->lpt_decision.decision == LPT_NONE) if (loop->lpt_decision.decision == LPT_NONE)
decide_peel_simple (loop, flags); decide_peel_simple (loop, flags);
report_unroll_peel (loop, locus);
} }
} }
...@@ -348,8 +412,6 @@ decide_peel_once_rolling (struct loop *loop, int flags ATTRIBUTE_UNUSED) ...@@ -348,8 +412,6 @@ decide_peel_once_rolling (struct loop *loop, int flags ATTRIBUTE_UNUSED)
} }
/* Success. */ /* Success. */
if (dump_file)
fprintf (dump_file, ";; Decided to peel exactly once rolling loop\n");
loop->lpt_decision.decision = LPT_PEEL_COMPLETELY; loop->lpt_decision.decision = LPT_PEEL_COMPLETELY;
} }
...@@ -429,8 +491,6 @@ decide_peel_completely (struct loop *loop, int flags ATTRIBUTE_UNUSED) ...@@ -429,8 +491,6 @@ decide_peel_completely (struct loop *loop, int flags ATTRIBUTE_UNUSED)
} }
/* Success. */ /* Success. */
if (dump_file)
fprintf (dump_file, ";; Decided to peel loop completely\n");
loop->lpt_decision.decision = LPT_PEEL_COMPLETELY; loop->lpt_decision.decision = LPT_PEEL_COMPLETELY;
} }
...@@ -608,10 +668,6 @@ decide_unroll_constant_iterations (struct loop *loop, int flags) ...@@ -608,10 +668,6 @@ decide_unroll_constant_iterations (struct loop *loop, int flags)
loop->lpt_decision.decision = LPT_UNROLL_CONSTANT; loop->lpt_decision.decision = LPT_UNROLL_CONSTANT;
loop->lpt_decision.times = best_unroll; loop->lpt_decision.times = best_unroll;
if (dump_file)
fprintf (dump_file, ";; Decided to unroll the loop %d times (%d copies).\n",
loop->lpt_decision.times, best_copies);
} }
/* Unroll LOOP with constant number of iterations LOOP->LPT_DECISION.TIMES times. /* Unroll LOOP with constant number of iterations LOOP->LPT_DECISION.TIMES times.
...@@ -893,10 +949,6 @@ decide_unroll_runtime_iterations (struct loop *loop, int flags) ...@@ -893,10 +949,6 @@ decide_unroll_runtime_iterations (struct loop *loop, int flags)
loop->lpt_decision.decision = LPT_UNROLL_RUNTIME; loop->lpt_decision.decision = LPT_UNROLL_RUNTIME;
loop->lpt_decision.times = i - 1; loop->lpt_decision.times = i - 1;
if (dump_file)
fprintf (dump_file, ";; Decided to unroll the loop %d times.\n",
loop->lpt_decision.times);
} }
/* Splits edge E and inserts the sequence of instructions INSNS on it, and /* Splits edge E and inserts the sequence of instructions INSNS on it, and
...@@ -1305,10 +1357,6 @@ decide_peel_simple (struct loop *loop, int flags) ...@@ -1305,10 +1357,6 @@ decide_peel_simple (struct loop *loop, int flags)
/* Success. */ /* Success. */
loop->lpt_decision.decision = LPT_PEEL_SIMPLE; loop->lpt_decision.decision = LPT_PEEL_SIMPLE;
loop->lpt_decision.times = npeel; loop->lpt_decision.times = npeel;
if (dump_file)
fprintf (dump_file, ";; Decided to simply peel the loop %d times.\n",
loop->lpt_decision.times);
} }
/* Peel a LOOP LOOP->LPT_DECISION.TIMES times. The transformation does this: /* Peel a LOOP LOOP->LPT_DECISION.TIMES times. The transformation does this:
...@@ -1460,10 +1508,6 @@ decide_unroll_stupid (struct loop *loop, int flags) ...@@ -1460,10 +1508,6 @@ decide_unroll_stupid (struct loop *loop, int flags)
loop->lpt_decision.decision = LPT_UNROLL_STUPID; loop->lpt_decision.decision = LPT_UNROLL_STUPID;
loop->lpt_decision.times = i - 1; loop->lpt_decision.times = i - 1;
if (dump_file)
fprintf (dump_file, ";; Decided to unroll the loop stupidly %d times.\n",
loop->lpt_decision.times);
} }
/* Unroll a LOOP LOOP->LPT_DECISION.TIMES times. The transformation does this: /* Unroll a LOOP LOOP->LPT_DECISION.TIMES times. The transformation does this:
......
...@@ -8,6 +8,6 @@ test(int c) ...@@ -8,6 +8,6 @@ test(int c)
a[i]=5; a[i]=5;
} }
/* 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 2 times.." "cunrolli"} } */ /* { dg-final { scan-tree-dump "Completely unroll loop 2 times" "cunrolli"} } */
/* { dg-final { scan-tree-dump "Last iteration exit edge was proved true." "cunrolli"} } */ /* { dg-final { scan-tree-dump "Last iteration exit edge was proved true." "cunrolli"} } */
/* { dg-final { cleanup-tree-dump "cunrolli" } } */ /* { dg-final { cleanup-tree-dump "cunrolli" } } */
...@@ -12,5 +12,5 @@ test(int c) ...@@ -12,5 +12,5 @@ test(int c)
} }
} }
/* We are not able to get rid of the final conditional because the loop has two exits. */ /* We are not able to get rid of the final conditional because the loop has two exits. */
/* { dg-final { scan-tree-dump "Unrolled loop 1 completely .duplicated 1 times.." "cunroll"} } */ /* { dg-final { scan-tree-dump "Completely unroll loop 1 times" "cunroll"} } */
/* { dg-final { cleanup-tree-dump "cunroll" } } */ /* { dg-final { cleanup-tree-dump "cunroll" } } */
...@@ -11,5 +11,5 @@ test(int c) ...@@ -11,5 +11,5 @@ test(int c)
} }
/* If we start duplicating headers prior curoll, this loop will have 0 iterations. */ /* If we start duplicating headers prior curoll, this loop will have 0 iterations. */
/* { dg-final { scan-tree-dump "Unrolled loop 1 completely .duplicated 1 times.." "cunrolli"} } */ /* { dg-final { scan-tree-dump "Completely unroll loop 1 times" "cunrolli"} } */
/* { dg-final { cleanup-tree-dump "cunrolli" } } */ /* { dg-final { cleanup-tree-dump "cunrolli" } } */
...@@ -16,6 +16,6 @@ test(int c) ...@@ -16,6 +16,6 @@ test(int c)
/* We should do this as part of cunrolli, but our cost model do not take into account early exit /* We should do this as part of cunrolli, but our cost model do not take into account early exit
from the last iteration. */ from the last iteration. */
/* { dg-final { scan-tree-dump "Turned loop 1 to non-loop; it never loops." "ivcanon"} } */ /* { dg-final { scan-tree-dump "Turned loop into non-loop; it never loops." "ivcanon"} } */
/* { dg-final { scan-tree-dump "Last iteration exit edge was proved true." "ivcanon"} } */ /* { dg-final { scan-tree-dump "Last iteration exit edge was proved true." "ivcanon"} } */
/* { dg-final { cleanup-tree-dump "ivcanon" } } */ /* { dg-final { cleanup-tree-dump "ivcanon" } } */
...@@ -8,7 +8,7 @@ test(int c) ...@@ -8,7 +8,7 @@ test(int c)
a[i]=5; a[i]=5;
} }
/* Basic testcase for complette unrolling. */ /* Basic testcase for complette unrolling. */
/* { dg-final { scan-tree-dump "Unrolled loop 1 completely .duplicated 5 times.." "cunroll"} } */ /* { dg-final { scan-tree-dump "Completely unroll loop 5 times" "cunroll"} } */
/* { dg-final { scan-tree-dump "Exit condition of peeled iterations was eliminated." "cunroll"} } */ /* { dg-final { scan-tree-dump "Exit condition of peeled iterations was eliminated." "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 "cunroll" } } */
...@@ -33,7 +33,7 @@ int xxx(void) ...@@ -33,7 +33,7 @@ int xxx(void)
/* { dg-final { scan-tree-dump-times "Added canonical iv to loop 1, 4 iterations" 1 "ivcanon"} } */ /* { dg-final { scan-tree-dump-times "Added canonical iv to loop 1, 4 iterations" 1 "ivcanon"} } */
/* { dg-final { cleanup-tree-dump "ivcanon" } } */ /* { dg-final { cleanup-tree-dump "ivcanon" } } */
/* { dg-final { scan-tree-dump-times "Unrolled loop 1 completely" 1 "cunroll"} } */ /* { dg-final { scan-tree-dump-times "Completely unroll loop 4 times" 1 "cunroll"} } */
/* { dg-final { cleanup-tree-dump "cunroll" } } */ /* { dg-final { cleanup-tree-dump "cunroll" } } */
/* { dg-final { scan-tree-dump-times "foo" 5 "optimized"} } */ /* { dg-final { scan-tree-dump-times "foo" 5 "optimized"} } */
/* { dg-final { cleanup-tree-dump "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */
......
...@@ -24,6 +24,6 @@ int foo(void) ...@@ -24,6 +24,6 @@ int foo(void)
return sum; return sum;
} }
/* { dg-final { scan-tree-dump-times "Unrolled loop 1 completely" 1 "cunroll" } } */ /* { dg-final { scan-tree-dump-times "Completely unroll loop 3 times" 1 "cunroll" } } */
/* { dg-final { cleanup-tree-dump "cunroll" } } */ /* { dg-final { cleanup-tree-dump "cunroll" } } */
...@@ -28,5 +28,5 @@ int foo2(void) ...@@ -28,5 +28,5 @@ int foo2(void)
return 1; return 1;
} }
/* { dg-final { scan-rtl-dump-times "Decided to peel loop completely" 2 "loop2_unroll" } } */ /* { dg-final { scan-rtl-dump-times "Turned loop into non-loop; it never loops" 2 "loop2_unroll" } } */
/* { dg-final { cleanup-rtl-dump "loop2_unroll" } } */ /* { dg-final { cleanup-rtl-dump "loop2_unroll" } } */
...@@ -28,6 +28,6 @@ int foo2(void) ...@@ -28,6 +28,6 @@ int foo2(void)
return 1; return 1;
} }
/* { dg-final { scan-rtl-dump-times "Decided to peel loop completely" 1 "loop2_unroll" } } */ /* { dg-final { scan-rtl-dump-times "Turned loop into non-loop; it never loops" 1 "loop2_unroll" } } */
/* { dg-final { cleanup-rtl-dump "loop2_unroll" } } */ /* { dg-final { cleanup-rtl-dump "loop2_unroll" } } */
/* { dg-excess-errors "extra notes" } */ /* { dg-excess-errors "extra notes" } */
...@@ -28,6 +28,6 @@ int foo2(void) ...@@ -28,6 +28,6 @@ int foo2(void)
return 1; return 1;
} }
/* { dg-final { scan-rtl-dump-times "Decided to peel loop completely" 1 "loop2_unroll" } } */ /* { dg-final { scan-rtl-dump-times "Turned loop into non-loop; it never loops" 1 "loop2_unroll" } } */
/* { dg-final { cleanup-rtl-dump "loop2_unroll" } } */ /* { dg-final { cleanup-rtl-dump "loop2_unroll" } } */
/* { dg-excess-errors "extra notes" } */ /* { dg-excess-errors "extra notes" } */
...@@ -28,6 +28,6 @@ int foo2(void) ...@@ -28,6 +28,6 @@ int foo2(void)
return 1; return 1;
} }
/* { dg-final { scan-rtl-dump-times "Decided to peel loop completely" 1 "loop2_unroll" } } */ /* { dg-final { scan-rtl-dump-times "Turned loop into non-loop; it never loops" 1 "loop2_unroll" } } */
/* { dg-final { cleanup-rtl-dump "loop2_unroll" } } */ /* { dg-final { cleanup-rtl-dump "loop2_unroll" } } */
/* { dg-excess-errors "extra notes" } */ /* { dg-excess-errors "extra notes" } */
...@@ -639,22 +639,24 @@ unloop_loops (bitmap loop_closed_ssa_invalidated, ...@@ -639,22 +639,24 @@ unloop_loops (bitmap loop_closed_ssa_invalidated,
/* Tries to unroll LOOP completely, i.e. NITER times. /* Tries to unroll LOOP completely, i.e. NITER times.
UL determines which loops we are allowed to unroll. UL determines which loops we are allowed to unroll.
EXIT is the exit of the loop that should be eliminated. EXIT is the exit of the loop that should be eliminated.
MAXITER specfy bound on number of iterations, -1 if it is MAXITER specfy bound on number of iterations, -1 if it is
not known or too large for HOST_WIDE_INT. */ not known or too large for HOST_WIDE_INT. The location
LOCUS corresponding to the loop is used when emitting
a summary of the unroll to the dump file. */
static bool static bool
try_unroll_loop_completely (struct loop *loop, try_unroll_loop_completely (struct loop *loop,
edge exit, tree niter, edge exit, tree niter,
enum unroll_level ul, enum unroll_level ul,
HOST_WIDE_INT maxiter) HOST_WIDE_INT maxiter,
location_t locus)
{ {
unsigned HOST_WIDE_INT n_unroll, ninsns, max_unroll, unr_insns; unsigned HOST_WIDE_INT n_unroll, ninsns, max_unroll, unr_insns;
gimple cond; gimple cond;
struct loop_size size; struct loop_size size;
bool n_unroll_found = false; bool n_unroll_found = false;
edge edge_to_cancel = NULL; edge edge_to_cancel = NULL;
int num = loop->num;
/* See if we proved number of iterations to be low constant. /* See if we proved number of iterations to be low constant.
...@@ -862,14 +864,25 @@ try_unroll_loop_completely (struct loop *loop, ...@@ -862,14 +864,25 @@ try_unroll_loop_completely (struct loop *loop,
loops_to_unloop.safe_push (loop); loops_to_unloop.safe_push (loop);
loops_to_unloop_nunroll.safe_push (n_unroll); loops_to_unloop_nunroll.safe_push (n_unroll);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_enabled_p ())
{ {
if (!n_unroll) if (!n_unroll)
fprintf (dump_file, "Turned loop %d to non-loop; it never loops.\n", dump_printf_loc (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS, locus,
num); "Turned loop into non-loop; it never loops.\n");
else else
fprintf (dump_file, "Unrolled loop %d completely " {
"(duplicated %i times).\n", num, (int)n_unroll); dump_printf_loc (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS, locus,
"Completely unroll loop %d times", (int)n_unroll);
if (profile_info)
dump_printf (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS,
" (header execution count %d)",
(int)loop->header->count);
dump_printf (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS, "\n");
}
}
if (dump_file && (dump_flags & TDF_DETAILS))
{
if (exit) if (exit)
fprintf (dump_file, "Exit condition of peeled iterations was " fprintf (dump_file, "Exit condition of peeled iterations was "
"eliminated.\n"); "eliminated.\n");
...@@ -898,15 +911,17 @@ canonicalize_loop_induction_variables (struct loop *loop, ...@@ -898,15 +911,17 @@ canonicalize_loop_induction_variables (struct loop *loop,
tree niter; tree niter;
HOST_WIDE_INT maxiter; HOST_WIDE_INT maxiter;
bool modified = false; bool modified = false;
location_t locus = UNKNOWN_LOCATION;
niter = number_of_latch_executions (loop); niter = number_of_latch_executions (loop);
exit = single_exit (loop);
if (TREE_CODE (niter) == INTEGER_CST) if (TREE_CODE (niter) == INTEGER_CST)
exit = single_exit (loop); locus = gimple_location (last_stmt (exit->src));
else else
{ {
/* If the loop has more than one exit, try checking all of them /* If the loop has more than one exit, try checking all of them
for # of iterations determinable through scev. */ for # of iterations determinable through scev. */
if (!single_exit (loop)) if (!exit)
niter = find_loop_niter (loop, &exit); niter = find_loop_niter (loop, &exit);
/* Finally if everything else fails, try brute force evaluation. */ /* Finally if everything else fails, try brute force evaluation. */
...@@ -915,6 +930,9 @@ canonicalize_loop_induction_variables (struct loop *loop, ...@@ -915,6 +930,9 @@ canonicalize_loop_induction_variables (struct loop *loop,
|| TREE_CODE (niter) != INTEGER_CST)) || TREE_CODE (niter) != INTEGER_CST))
niter = find_loop_niter_by_eval (loop, &exit); niter = find_loop_niter_by_eval (loop, &exit);
if (exit)
locus = gimple_location (last_stmt (exit->src));
if (TREE_CODE (niter) != INTEGER_CST) if (TREE_CODE (niter) != INTEGER_CST)
exit = NULL; exit = NULL;
} }
...@@ -949,7 +967,7 @@ canonicalize_loop_induction_variables (struct loop *loop, ...@@ -949,7 +967,7 @@ canonicalize_loop_induction_variables (struct loop *loop,
populates the loop bounds. */ populates the loop bounds. */
modified |= remove_redundant_iv_tests (loop); modified |= remove_redundant_iv_tests (loop);
if (try_unroll_loop_completely (loop, exit, niter, ul, maxiter)) if (try_unroll_loop_completely (loop, exit, niter, ul, maxiter, locus))
return true; return true;
if (create_iv if (create_iv
......
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