diff mbox

Use new dump scheme to emit loop unroll/peel summary info (issue6941070)

Message ID CAAe5K+UWv0Pd0jjtocUOQ9UzJqJuMnKj-ZCuRTY91XM6sJV4vw@mail.gmail.com
State New
Headers show

Commit Message

Teresa Johnson Dec. 20, 2012, 5:20 p.m. UTC
On Thu, Dec 20, 2012 at 1:21 AM, Bernhard Reutner-Fischer
<rep.dot.nop@gmail.com> wrote:

Thanks for your comments. Responses inlined below, and new patch include below.

> On Mon, Dec 17, 2012 at 10:44:59PM -0800, Teresa Johnson wrote:
>>Index: tree-ssa-loop-ivcanon.c
>>===================================================================
>>--- tree-ssa-loop-ivcanon.c    (revision 194516)
>>+++ tree-ssa-loop-ivcanon.c    (working copy)
>>@@ -639,22 +639,24 @@ unloop_loops (bitmap loop_closed_ssa_invalidated,
>>
>> /* Tries to unroll LOOP completely, i.e. NITER times.
>>    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
>>-   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
>> try_unroll_loop_completely (struct loop *loop,
>>                           edge exit, tree niter,
>>                           enum unroll_level ul,
>>-                          HOST_WIDE_INT maxiter)
>>+                          HOST_WIDE_INT maxiter,
>>+                            location_t locus)
>
> whitespace damage?

This and the other location you pointed out below as possible
whitespace damage are because the surrounding lines use tab characters
whereas mine uses spaces. Is there a guideline on which one is correct
for gcc? I looked in the style guide but didn't find anything. The
existing code uses a mix of indentation via tabs and spaces. I have
fixed this location and the one you point out below to use a tab
character so that the diff goes away, but I haven't searched the patch
exhaustively for similar issues.

>
>>Index: loop-unroll.c
>>===================================================================
>>--- loop-unroll.c      (revision 194516)
>>+++ loop-unroll.c      (working copy)
>>@@ -148,6 +148,61 @@ static void combine_var_copies_in_loop_exit (struc
>>                                            basic_block);
>> 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)
>
> missing space before (
>
> contrib/check_GNU_style.sh generally says:
> Dot, space, space, new sentence.
> loop-dump.01.patch:223:+   not known or too large for HOST_WIDE_INT. The location
> loop-dump.01.patch:514:+   * of the for or while statement, if possible. To do this, look
>
> Dot, space, space, end of comment.
> loop-dump.01.patch:504:+/* Return location corresponding to the loop control condition if possible. */
> loop-dump.01.patch:541:+  /* Next check the latch, to see if it is non-empty. *
> loop-dump.01.patch:555:+  /* If all else fails, simply return the current function location. */
>
> There should be exactly one space between function name and parentheses.
> loop-dump.01.patch:329:+report_unroll_peel(struct loop *loop, location_t locus)
> loop-dump.01.patch:386:+      location_t locus = get_loop_location(loop);
> loop-dump.01.patch:404:+          report_unroll_peel(loop, locus);
> loop-dump.01.patch:412:+      location_t locus = get_loop_location(loop);
> loop-dump.01.patch:429:+      report_unroll_peel(loop, locus);
> loop-dump.01.patch:533:+  if ((exit = single_exit(loop)))

I fixed all these and verified that check_GNU_style.sh no longer reports these.

>
>>@@ -248,6 +305,7 @@ peel_loops_completely (int flags)
>>
>>       if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY)
>>       {
>>+          report_unroll_peel(loop, locus);
>>         peel_loop_completely (loop);
>
> whitespace damage? You seem to have this kind of whitespace error
> throughout the patch. I take it you are aware of
> http://gcc.gnu.org/wiki/FormattingCodeForGCC
> and just forgot to have it on the machine you edited?

This was the same issue described above (tab vs space). As noted
above, I fixed this instance too, but there may be others and I'm not
sure what is required or correct.

>
> I seemingly have
> $ cat ~/.vim/gcc_style.vim
> " put this plugin into ~/.vim/gcc_style.vim and source it into your ~/.vimrc via
> " source ~/.vim/gcc_style.vim
> if exists("g:loaded_gcc_style") || &cp
>   finish
> endif
> let g:loaded_gcc_style = 1
>
> augroup gcc_style
>   autocmd BufReadPost,FileReadPost * call s:maybe_gcc_style()
> augroup END
> if exists("*s:maybe_gcc_style")
>   finish
> endif
> let s:cpo_save = &cpo
> set cpo&vim
>
> function! s:maybe_gcc_style()
>   let s:i = 1 + 0
>   while s:i <= line("$") && s:i <= 25
>     let s:line = getline(s:i)
>     if s:line =~ '^\s*This\sfile\sis\spart\sof\sGCC.*'
>       " gcc-mode
>       set cino=:s,{s,n-s,>2s,^-s
>       set sw=2
>       set sts=2
>       set cindent
>       set smartindent
>       set autoindent
>       break
>     else
>       let s:i = s:i + 1
>     endif
>   endwhile
> endfunction
>
> "command! NoGCCstyle unlet! g:loaded_gcc_style | au! gcc_style
> "command! DoGCCstyle runtime gcc_style.vim
> let &cpo = s:cpo_save

Thanks! I will see if I can use something like this too -
unfortunately I have multiple coding styles I need to code for, but I
will see if I can get myself to use this when editing gcc.

>
>>Index: cfgloop.c
>>===================================================================
>>--- cfgloop.c  (revision 194516)
>>+++ cfgloop.c  (working copy)
>>@@ -1666,3 +1666,59 @@ loop_exits_from_bb_p (struct loop *loop, basic_blo
>>
>>   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.
>>+   */
>
> IIRC there is not supposed to be a * in comments.

Fixed.

>
> Other than these nits i like it (but cannot approve it).

Thanks!
Teresa

>
> thanks,

New patch:

2012-12-20  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.
	* testsuite/gcc.dg/unroll_1.c: Ditto.
	* testsuite/gcc.dg/unroll_2.c: Ditto.
	* testsuite/gcc.dg/unroll_3.c: Ditto.
	* testsuite/gcc.dg/unroll_4.c: Ditto.


--
Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413

Comments

Teresa Johnson Jan. 2, 2013, 3:55 p.m. UTC | #1
On Thu, Dec 20, 2012 at 9:20 AM, Teresa Johnson <tejohnson@google.com> wrote:
> On Thu, Dec 20, 2012 at 1:21 AM, Bernhard Reutner-Fischer
> <rep.dot.nop@gmail.com> wrote:
>
> Thanks for your comments. Responses inlined below, and new patch include below.
>
>> On Mon, Dec 17, 2012 at 10:44:59PM -0800, Teresa Johnson wrote:
>>>Index: tree-ssa-loop-ivcanon.c
>>>===================================================================
>>>--- tree-ssa-loop-ivcanon.c    (revision 194516)
>>>+++ tree-ssa-loop-ivcanon.c    (working copy)
>>>@@ -639,22 +639,24 @@ unloop_loops (bitmap loop_closed_ssa_invalidated,
>>>
>>> /* Tries to unroll LOOP completely, i.e. NITER times.
>>>    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
>>>-   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
>>> try_unroll_loop_completely (struct loop *loop,
>>>                           edge exit, tree niter,
>>>                           enum unroll_level ul,
>>>-                          HOST_WIDE_INT maxiter)
>>>+                          HOST_WIDE_INT maxiter,
>>>+                            location_t locus)
>>
>> whitespace damage?
>
> This and the other location you pointed out below as possible
> whitespace damage are because the surrounding lines use tab characters
> whereas mine uses spaces. Is there a guideline on which one is correct
> for gcc? I looked in the style guide but didn't find anything. The
> existing code uses a mix of indentation via tabs and spaces. I have
> fixed this location and the one you point out below to use a tab
> character so that the diff goes away, but I haven't searched the patch
> exhaustively for similar issues.
>
>>
>>>Index: loop-unroll.c
>>>===================================================================
>>>--- loop-unroll.c      (revision 194516)
>>>+++ loop-unroll.c      (working copy)
>>>@@ -148,6 +148,61 @@ static void combine_var_copies_in_loop_exit (struc
>>>                                            basic_block);
>>> 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)
>>
>> missing space before (
>>
>> contrib/check_GNU_style.sh generally says:
>> Dot, space, space, new sentence.
>> loop-dump.01.patch:223:+   not known or too large for HOST_WIDE_INT. The location
>> loop-dump.01.patch:514:+   * of the for or while statement, if possible. To do this, look
>>
>> Dot, space, space, end of comment.
>> loop-dump.01.patch:504:+/* Return location corresponding to the loop control condition if possible. */
>> loop-dump.01.patch:541:+  /* Next check the latch, to see if it is non-empty. *
>> loop-dump.01.patch:555:+  /* If all else fails, simply return the current function location. */
>>
>> There should be exactly one space between function name and parentheses.
>> loop-dump.01.patch:329:+report_unroll_peel(struct loop *loop, location_t locus)
>> loop-dump.01.patch:386:+      location_t locus = get_loop_location(loop);
>> loop-dump.01.patch:404:+          report_unroll_peel(loop, locus);
>> loop-dump.01.patch:412:+      location_t locus = get_loop_location(loop);
>> loop-dump.01.patch:429:+      report_unroll_peel(loop, locus);
>> loop-dump.01.patch:533:+  if ((exit = single_exit(loop)))
>
> I fixed all these and verified that check_GNU_style.sh no longer reports these.
>
>>
>>>@@ -248,6 +305,7 @@ peel_loops_completely (int flags)
>>>
>>>       if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY)
>>>       {
>>>+          report_unroll_peel(loop, locus);
>>>         peel_loop_completely (loop);
>>
>> whitespace damage? You seem to have this kind of whitespace error
>> throughout the patch. I take it you are aware of
>> http://gcc.gnu.org/wiki/FormattingCodeForGCC
>> and just forgot to have it on the machine you edited?
>
> This was the same issue described above (tab vs space). As noted
> above, I fixed this instance too, but there may be others and I'm not
> sure what is required or correct.
>
>>
>> I seemingly have
>> $ cat ~/.vim/gcc_style.vim
>> " put this plugin into ~/.vim/gcc_style.vim and source it into your ~/.vimrc via
>> " source ~/.vim/gcc_style.vim
>> if exists("g:loaded_gcc_style") || &cp
>>   finish
>> endif
>> let g:loaded_gcc_style = 1
>>
>> augroup gcc_style
>>   autocmd BufReadPost,FileReadPost * call s:maybe_gcc_style()
>> augroup END
>> if exists("*s:maybe_gcc_style")
>>   finish
>> endif
>> let s:cpo_save = &cpo
>> set cpo&vim
>>
>> function! s:maybe_gcc_style()
>>   let s:i = 1 + 0
>>   while s:i <= line("$") && s:i <= 25
>>     let s:line = getline(s:i)
>>     if s:line =~ '^\s*This\sfile\sis\spart\sof\sGCC.*'
>>       " gcc-mode
>>       set cino=:s,{s,n-s,>2s,^-s
>>       set sw=2
>>       set sts=2
>>       set cindent
>>       set smartindent
>>       set autoindent
>>       break
>>     else
>>       let s:i = s:i + 1
>>     endif
>>   endwhile
>> endfunction
>>
>> "command! NoGCCstyle unlet! g:loaded_gcc_style | au! gcc_style
>> "command! DoGCCstyle runtime gcc_style.vim
>> let &cpo = s:cpo_save
>
> Thanks! I will see if I can use something like this too -
> unfortunately I have multiple coding styles I need to code for, but I
> will see if I can get myself to use this when editing gcc.
>
>>
>>>Index: cfgloop.c
>>>===================================================================
>>>--- cfgloop.c  (revision 194516)
>>>+++ cfgloop.c  (working copy)
>>>@@ -1666,3 +1666,59 @@ loop_exits_from_bb_p (struct loop *loop, basic_blo
>>>
>>>   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.
>>>+   */
>>
>> IIRC there is not supposed to be a * in comments.
>
> Fixed.
>
>>
>> Other than these nits i like it (but cannot approve it).
>
> Thanks!
> Teresa
>
>>
>> thanks,
>
> New patch:
>

Ping.

Thanks,
Teresa

> 2012-12-20  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.
>         * testsuite/gcc.dg/unroll_1.c: Ditto.
>         * testsuite/gcc.dg/unroll_2.c: Ditto.
>         * testsuite/gcc.dg/unroll_3.c: Ditto.
>         * testsuite/gcc.dg/unroll_4.c: Ditto.
>
> Index: dumpfile.c
> ===================================================================
> --- dumpfile.c  (revision 194516)
> +++ dumpfile.c  (working copy)
> @@ -265,7 +265,9 @@ dump_loc (int dump_kind, FILE *dfile, source_locat
>                   DECL_SOURCE_FILE (current_function_decl),
>                   DECL_SOURCE_LINE (current_function_decl));
>       else
> -        fprintf (dfile, "\n%d: ", LOCATION_LINE (loc));
> +        fprintf (dfile, "\n%s:%d: note: ",
> +                 LOCATION_FILE (loc),
> +                 LOCATION_LINE (loc));
>      }
>  }
>
> Index: testsuite/gcc.dg/unroll_2.c
> ===================================================================
> --- testsuite/gcc.dg/unroll_2.c (revision 194516)
> +++ testsuite/gcc.dg/unroll_2.c (working copy)
> @@ -28,6 +28,6 @@ int foo2(void)
>    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-excess-errors "extra notes" } */
> Index: testsuite/gcc.dg/unroll_3.c
> ===================================================================
> --- testsuite/gcc.dg/unroll_3.c (revision 194516)
> +++ testsuite/gcc.dg/unroll_3.c (working copy)
> @@ -28,6 +28,6 @@ int foo2(void)
>    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-excess-errors "extra notes" } */
> Index: testsuite/gcc.dg/tree-ssa/loop-1.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/loop-1.c  (revision 194516)
> +++ testsuite/gcc.dg/tree-ssa/loop-1.c  (working copy)
> @@ -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 { 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 { scan-tree-dump-times "foo" 5 "optimized"} } */
>  /* { dg-final { cleanup-tree-dump "optimized" } } */
> Index: testsuite/gcc.dg/tree-ssa/cunroll-1.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/cunroll-1.c       (revision 194516)
> +++ testsuite/gcc.dg/tree-ssa/cunroll-1.c       (working copy)
> @@ -8,6 +8,6 @@ test(int c)
>      a[i]=5;
>  }
>  /* 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 { cleanup-tree-dump "cunrolli" } } */
> Index: testsuite/gcc.dg/tree-ssa/cunroll-2.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/cunroll-2.c       (revision 194516)
> +++ testsuite/gcc.dg/tree-ssa/cunroll-2.c       (working copy)
> @@ -12,5 +12,5 @@ test(int c)
>      }
>  }
>  /* 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" } } */
> Index: testsuite/gcc.dg/tree-ssa/loop-23.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/loop-23.c (revision 194516)
> +++ testsuite/gcc.dg/tree-ssa/loop-23.c (working copy)
> @@ -24,6 +24,6 @@ int foo(void)
>    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" } } */
> Index: testsuite/gcc.dg/tree-ssa/cunroll-3.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/cunroll-3.c       (revision 194516)
> +++ testsuite/gcc.dg/tree-ssa/cunroll-3.c       (working copy)
> @@ -11,5 +11,5 @@ test(int c)
>  }
>  /* 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" } } */
> Index: testsuite/gcc.dg/tree-ssa/cunroll-4.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/cunroll-4.c       (revision 194516)
> +++ testsuite/gcc.dg/tree-ssa/cunroll-4.c       (working copy)
> @@ -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
>     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 { cleanup-tree-dump "ivcanon" } } */
> Index: testsuite/gcc.dg/tree-ssa/cunroll-5.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/cunroll-5.c       (revision 194516)
> +++ testsuite/gcc.dg/tree-ssa/cunroll-5.c       (working copy)
> @@ -8,7 +8,7 @@ test(int c)
>      a[i]=5;
>  }
>  /* 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 "Last iteration exit edge was proved
> true." "cunroll"} } */
>  /* { dg-final { cleanup-tree-dump "cunroll" } } */
> Index: testsuite/gcc.dg/unroll_4.c
> ===================================================================
> --- testsuite/gcc.dg/unroll_4.c (revision 194516)
> +++ testsuite/gcc.dg/unroll_4.c (working copy)
> @@ -28,6 +28,6 @@ int foo2(void)
>    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-excess-errors "extra notes" } */
> Index: testsuite/gcc.dg/unroll_1.c
> ===================================================================
> --- testsuite/gcc.dg/unroll_1.c (revision 194516)
> +++ testsuite/gcc.dg/unroll_1.c (working copy)
> @@ -28,5 +28,5 @@ int foo2(void)
>    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" } } */
> Index: tree-ssa-loop-ivcanon.c
> ===================================================================
> --- tree-ssa-loop-ivcanon.c     (revision 194516)
> +++ tree-ssa-loop-ivcanon.c     (working copy)
> @@ -639,22 +639,24 @@ unloop_loops (bitmap loop_closed_ssa_invalidated,
>
>  /* Tries to unroll LOOP completely, i.e. NITER times.
>     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
> -   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
>  try_unroll_loop_completely (struct loop *loop,
>                             edge exit, tree niter,
>                             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;
>    gimple cond;
>    struct loop_size size;
>    bool n_unroll_found = false;
>    edge edge_to_cancel = NULL;
> -  int num = loop->num;
>
>    /* See if we proved number of iterations to be low constant.
>
> @@ -862,14 +864,25 @@ try_unroll_loop_completely (struct loop *loop,
>    loops_to_unloop.safe_push (loop);
>    loops_to_unloop_nunroll.safe_push (n_unroll);
>
> -  if (dump_file && (dump_flags & TDF_DETAILS))
> +  if (dump_enabled_p ())
>      {
>        if (!n_unroll)
> -        fprintf (dump_file, "Turned loop %d to non-loop; it never loops.\n",
> -                num);
> +        dump_printf_loc (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS, locus,
> +                         "Turned loop into non-loop; it never loops.\n");
>        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)
>          fprintf (dump_file, "Exit condition of peeled iterations was "
>                  "eliminated.\n");
> @@ -898,15 +911,19 @@ canonicalize_loop_induction_variables (struct loop
>    tree niter;
>    HOST_WIDE_INT maxiter;
>    bool modified = false;
> +  location_t locus = UNKNOWN_LOCATION;
>
>    niter = number_of_latch_executions (loop);
>    if (TREE_CODE (niter) == INTEGER_CST)
> -    exit = single_exit (loop);
> +    {
> +      exit = single_exit (loop);
> +      locus = gimple_location (last_stmt (exit->src));
> +    }
>    else
>      {
>        /* If the loop has more than one exit, try checking all of them
>          for # of iterations determinable through scev.  */
> -      if (!single_exit (loop))
> +      if (!(exit = single_exit (loop)))
>         niter = find_loop_niter (loop, &exit);
>
>        /* Finally if everything else fails, try brute force evaluation.  */
> @@ -915,6 +932,9 @@ canonicalize_loop_induction_variables (struct loop
>               || TREE_CODE (niter) != INTEGER_CST))
>         niter = find_loop_niter_by_eval (loop, &exit);
>
> +      if (exit)
> +        locus = gimple_location (last_stmt (exit->src));
> +
>        if (TREE_CODE (niter) != INTEGER_CST)
>         exit = NULL;
>      }
> @@ -949,7 +969,7 @@ canonicalize_loop_induction_variables (struct loop
>       populates the loop bounds.  */
>    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;
>
>    if (create_iv
> Index: loop-unroll.c
> ===================================================================
> --- loop-unroll.c       (revision 194516)
> +++ loop-unroll.c       (working copy)
> @@ -148,6 +148,61 @@ static void combine_var_copies_in_loop_exit (struc
>                                              basic_block);
>  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.  */
>  void
>  unroll_and_peel_loops (int flags)
> @@ -234,11 +289,13 @@ peel_loops_completely (int flags)
>    FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
>      {
>        loop->lpt_decision.decision = LPT_NONE;
> +      location_t locus = get_loop_location (loop);
>
> -      if (dump_file)
> -       fprintf (dump_file,
> -                "\n;; *** Considering loop %d for complete peeling ***\n",
> -                loop->num);
> +      if (dump_enabled_p ())
> +       dump_printf_loc (TDF_RTL, locus,
> +                         ";; *** Considering loop %d at BB %d for "
> +                         "complete peeling ***\n",
> +                         loop->num, loop->header->index);
>
>        loop->ninsns = num_loop_insns (loop);
>
> @@ -248,6 +305,7 @@ peel_loops_completely (int flags)
>
>        if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY)
>         {
> +         report_unroll_peel (loop, locus);
>           peel_loop_completely (loop);
>  #ifdef ENABLE_CHECKING
>           verify_loop_structure ();
> @@ -267,9 +325,13 @@ decide_unrolling_and_peeling (int flags)
>    FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
>      {
>        loop->lpt_decision.decision = LPT_NONE;
> +      location_t locus = get_loop_location (loop);
>
> -      if (dump_file)
> -       fprintf (dump_file, "\n;; *** Considering loop %d ***\n", loop->num);
> +      if (dump_enabled_p ())
> +       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.  */
>        if (optimize_loop_for_size_p (loop))
> @@ -309,6 +371,8 @@ decide_unrolling_and_peeling (int flags)
>         decide_unroll_stupid (loop, flags);
>        if (loop->lpt_decision.decision == LPT_NONE)
>         decide_peel_simple (loop, flags);
> +
> +      report_unroll_peel (loop, locus);
>      }
>  }
>
> @@ -348,8 +412,6 @@ decide_peel_once_rolling (struct loop *loop, int f
>      }
>
>    /* Success.  */
> -  if (dump_file)
> -    fprintf (dump_file, ";; Decided to peel exactly once rolling loop\n");
>    loop->lpt_decision.decision = LPT_PEEL_COMPLETELY;
>  }
>
> @@ -429,8 +491,6 @@ decide_peel_completely (struct loop *loop, int fla
>      }
>
>    /* Success.  */
> -  if (dump_file)
> -    fprintf (dump_file, ";; Decided to peel loop completely\n");
>    loop->lpt_decision.decision = LPT_PEEL_COMPLETELY;
>  }
>
> @@ -608,10 +668,6 @@ decide_unroll_constant_iterations (struct loop *lo
>
>    loop->lpt_decision.decision = LPT_UNROLL_CONSTANT;
>    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.
> @@ -893,10 +949,6 @@ decide_unroll_runtime_iterations (struct loop *loo
>
>    loop->lpt_decision.decision = LPT_UNROLL_RUNTIME;
>    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
> @@ -1305,10 +1357,6 @@ decide_peel_simple (struct loop *loop, int flags)
>    /* Success.  */
>    loop->lpt_decision.decision = LPT_PEEL_SIMPLE;
>    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:
> @@ -1460,10 +1508,6 @@ decide_unroll_stupid (struct loop *loop, int flags
>
>    loop->lpt_decision.decision = LPT_UNROLL_STUPID;
>    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:
> Index: cfgloop.c
> ===================================================================
> --- cfgloop.c   (revision 194516)
> +++ cfgloop.c   (working copy)
> @@ -1666,3 +1666,55 @@ loop_exits_from_bb_p (struct loop *loop, basic_blo
>
>    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);
> +}
> +
> Index: cfgloop.h
> ===================================================================
> --- cfgloop.h   (revision 194516)
> +++ cfgloop.h   (working copy)
> @@ -239,6 +239,7 @@ extern bool loop_exit_edge_p (const struct loop *,
>  extern bool loop_exits_to_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 location_t get_loop_location (struct loop *loop);
>
>  /* Loops & cfg manipulation.  */
>  extern basic_block *get_loop_body (const struct loop *);
>
> --
> Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
diff mbox

Patch

Index: dumpfile.c
===================================================================
--- dumpfile.c	(revision 194516)
+++ dumpfile.c	(working copy)
@@ -265,7 +265,9 @@  dump_loc (int dump_kind, FILE *dfile, source_locat
                  DECL_SOURCE_FILE (current_function_decl),
                  DECL_SOURCE_LINE (current_function_decl));
      else
-        fprintf (dfile, "\n%d: ", LOCATION_LINE (loc));
+        fprintf (dfile, "\n%s:%d: note: ",
+                 LOCATION_FILE (loc),
+                 LOCATION_LINE (loc));
     }
 }

Index: testsuite/gcc.dg/unroll_2.c
===================================================================
--- testsuite/gcc.dg/unroll_2.c	(revision 194516)
+++ testsuite/gcc.dg/unroll_2.c	(working copy)
@@ -28,6 +28,6 @@  int foo2(void)
   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-excess-errors "extra notes" } */
Index: testsuite/gcc.dg/unroll_3.c
===================================================================
--- testsuite/gcc.dg/unroll_3.c	(revision 194516)
+++ testsuite/gcc.dg/unroll_3.c	(working copy)
@@ -28,6 +28,6 @@  int foo2(void)
   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-excess-errors "extra notes" } */
Index: testsuite/gcc.dg/tree-ssa/loop-1.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/loop-1.c	(revision 194516)
+++ testsuite/gcc.dg/tree-ssa/loop-1.c	(working copy)
@@ -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 { 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 { scan-tree-dump-times "foo" 5 "optimized"} } */
 /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/cunroll-1.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/cunroll-1.c	(revision 194516)
+++ testsuite/gcc.dg/tree-ssa/cunroll-1.c	(working copy)
@@ -8,6 +8,6 @@  test(int c)
     a[i]=5;
 }
 /* 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 { cleanup-tree-dump "cunrolli" } } */
Index: testsuite/gcc.dg/tree-ssa/cunroll-2.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/cunroll-2.c	(revision 194516)
+++ testsuite/gcc.dg/tree-ssa/cunroll-2.c	(working copy)
@@ -12,5 +12,5 @@  test(int c)
     }
 }
 /* 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" } } */
Index: testsuite/gcc.dg/tree-ssa/loop-23.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/loop-23.c	(revision 194516)
+++ testsuite/gcc.dg/tree-ssa/loop-23.c	(working copy)
@@ -24,6 +24,6 @@  int foo(void)
   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" } } */
Index: testsuite/gcc.dg/tree-ssa/cunroll-3.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/cunroll-3.c	(revision 194516)
+++ testsuite/gcc.dg/tree-ssa/cunroll-3.c	(working copy)
@@ -11,5 +11,5 @@  test(int c)
 }
 /* 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" } } */
Index: testsuite/gcc.dg/tree-ssa/cunroll-4.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/cunroll-4.c	(revision 194516)
+++ testsuite/gcc.dg/tree-ssa/cunroll-4.c	(working copy)
@@ -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
    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 { cleanup-tree-dump "ivcanon" } } */
Index: testsuite/gcc.dg/tree-ssa/cunroll-5.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/cunroll-5.c	(revision 194516)
+++ testsuite/gcc.dg/tree-ssa/cunroll-5.c	(working copy)
@@ -8,7 +8,7 @@  test(int c)
     a[i]=5;
 }
 /* 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 "Last iteration exit edge was proved
true." "cunroll"} } */
 /* { dg-final { cleanup-tree-dump "cunroll" } } */
Index: testsuite/gcc.dg/unroll_4.c
===================================================================
--- testsuite/gcc.dg/unroll_4.c	(revision 194516)
+++ testsuite/gcc.dg/unroll_4.c	(working copy)
@@ -28,6 +28,6 @@  int foo2(void)
   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-excess-errors "extra notes" } */
Index: testsuite/gcc.dg/unroll_1.c
===================================================================
--- testsuite/gcc.dg/unroll_1.c	(revision 194516)
+++ testsuite/gcc.dg/unroll_1.c	(working copy)
@@ -28,5 +28,5 @@  int foo2(void)
   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" } } */
Index: tree-ssa-loop-ivcanon.c
===================================================================
--- tree-ssa-loop-ivcanon.c	(revision 194516)
+++ tree-ssa-loop-ivcanon.c	(working copy)
@@ -639,22 +639,24 @@  unloop_loops (bitmap loop_closed_ssa_invalidated,

 /* Tries to unroll LOOP completely, i.e. NITER times.
    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
-   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
 try_unroll_loop_completely (struct loop *loop,
 			    edge exit, tree niter,
 			    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;
   gimple cond;
   struct loop_size size;
   bool n_unroll_found = false;
   edge edge_to_cancel = NULL;
-  int num = loop->num;

   /* See if we proved number of iterations to be low constant.

@@ -862,14 +864,25 @@  try_unroll_loop_completely (struct loop *loop,
   loops_to_unloop.safe_push (loop);
   loops_to_unloop_nunroll.safe_push (n_unroll);

-  if (dump_file && (dump_flags & TDF_DETAILS))
+  if (dump_enabled_p ())
     {
       if (!n_unroll)
-        fprintf (dump_file, "Turned loop %d to non-loop; it never loops.\n",
-		 num);
+        dump_printf_loc (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS, locus,
+                         "Turned loop into non-loop; it never loops.\n");
       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)
         fprintf (dump_file, "Exit condition of peeled iterations was "
 		 "eliminated.\n");
@@ -898,15 +911,19 @@  canonicalize_loop_induction_variables (struct loop
   tree niter;
   HOST_WIDE_INT maxiter;
   bool modified = false;
+  location_t locus = UNKNOWN_LOCATION;

   niter = number_of_latch_executions (loop);
   if (TREE_CODE (niter) == INTEGER_CST)
-    exit = single_exit (loop);
+    {
+      exit = single_exit (loop);
+      locus = gimple_location (last_stmt (exit->src));
+    }
   else
     {
       /* If the loop has more than one exit, try checking all of them
 	 for # of iterations determinable through scev.  */
-      if (!single_exit (loop))
+      if (!(exit = single_exit (loop)))
 	niter = find_loop_niter (loop, &exit);

       /* Finally if everything else fails, try brute force evaluation.  */
@@ -915,6 +932,9 @@  canonicalize_loop_induction_variables (struct loop
 	      || TREE_CODE (niter) != INTEGER_CST))
 	niter = find_loop_niter_by_eval (loop, &exit);

+      if (exit)
+        locus = gimple_location (last_stmt (exit->src));
+
       if (TREE_CODE (niter) != INTEGER_CST)
 	exit = NULL;
     }
@@ -949,7 +969,7 @@  canonicalize_loop_induction_variables (struct loop
      populates the loop bounds.  */
   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;

   if (create_iv
Index: loop-unroll.c
===================================================================
--- loop-unroll.c	(revision 194516)
+++ loop-unroll.c	(working copy)
@@ -148,6 +148,61 @@  static void combine_var_copies_in_loop_exit (struc
 					     basic_block);
 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.  */
 void
 unroll_and_peel_loops (int flags)
@@ -234,11 +289,13 @@  peel_loops_completely (int flags)
   FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
     {
       loop->lpt_decision.decision = LPT_NONE;
+      location_t locus = get_loop_location (loop);

-      if (dump_file)
-	fprintf (dump_file,
-		 "\n;; *** Considering loop %d for complete peeling ***\n",
-		 loop->num);
+      if (dump_enabled_p ())
+	dump_printf_loc (TDF_RTL, locus,
+                         ";; *** Considering loop %d at BB %d for "
+                         "complete peeling ***\n",
+                         loop->num, loop->header->index);

       loop->ninsns = num_loop_insns (loop);

@@ -248,6 +305,7 @@  peel_loops_completely (int flags)

       if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY)
 	{
+	  report_unroll_peel (loop, locus);
 	  peel_loop_completely (loop);
 #ifdef ENABLE_CHECKING
 	  verify_loop_structure ();
@@ -267,9 +325,13 @@  decide_unrolling_and_peeling (int flags)
   FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
     {
       loop->lpt_decision.decision = LPT_NONE;
+      location_t locus = get_loop_location (loop);

-      if (dump_file)
-	fprintf (dump_file, "\n;; *** Considering loop %d ***\n", loop->num);
+      if (dump_enabled_p ())
+	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.  */
       if (optimize_loop_for_size_p (loop))
@@ -309,6 +371,8 @@  decide_unrolling_and_peeling (int flags)
 	decide_unroll_stupid (loop, flags);
       if (loop->lpt_decision.decision == LPT_NONE)
 	decide_peel_simple (loop, flags);
+
+      report_unroll_peel (loop, locus);
     }
 }

@@ -348,8 +412,6 @@  decide_peel_once_rolling (struct loop *loop, int f
     }

   /* Success.  */
-  if (dump_file)
-    fprintf (dump_file, ";; Decided to peel exactly once rolling loop\n");
   loop->lpt_decision.decision = LPT_PEEL_COMPLETELY;
 }

@@ -429,8 +491,6 @@  decide_peel_completely (struct loop *loop, int fla
     }

   /* Success.  */
-  if (dump_file)
-    fprintf (dump_file, ";; Decided to peel loop completely\n");
   loop->lpt_decision.decision = LPT_PEEL_COMPLETELY;
 }

@@ -608,10 +668,6 @@  decide_unroll_constant_iterations (struct loop *lo

   loop->lpt_decision.decision = LPT_UNROLL_CONSTANT;
   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.
@@ -893,10 +949,6 @@  decide_unroll_runtime_iterations (struct loop *loo

   loop->lpt_decision.decision = LPT_UNROLL_RUNTIME;
   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
@@ -1305,10 +1357,6 @@  decide_peel_simple (struct loop *loop, int flags)
   /* Success.  */
   loop->lpt_decision.decision = LPT_PEEL_SIMPLE;
   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:
@@ -1460,10 +1508,6 @@  decide_unroll_stupid (struct loop *loop, int flags

   loop->lpt_decision.decision = LPT_UNROLL_STUPID;
   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:
Index: cfgloop.c
===================================================================
--- cfgloop.c	(revision 194516)
+++ cfgloop.c	(working copy)
@@ -1666,3 +1666,55 @@  loop_exits_from_bb_p (struct loop *loop, basic_blo

   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);
+}
+
Index: cfgloop.h
===================================================================
--- cfgloop.h	(revision 194516)
+++ cfgloop.h	(working copy)
@@ -239,6 +239,7 @@  extern bool loop_exit_edge_p (const struct loop *,
 extern bool loop_exits_to_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 location_t get_loop_location (struct loop *loop);

 /* Loops & cfg manipulation.  */
 extern basic_block *get_loop_body (const struct loop *);