Run-once loop should *always* be unrolled, and isn't: /* gcc -S -dL -O2 */ #define NR_CPUS 1 extern void some_func(void); void func(void) { unsigned int cpu; for (cpu = 0; cpu < NR_CPUS; cpu++) some_func(); } foo.s: .file "foo.c" gcc2_compiled.: .section ".text" .align 2 .globl func .type func,@function func: stwu 1,-16(1) mflr 0 stw 31,12(1) stw 0,20(1) li 31,0 .L6: bl some_func addic. 31,31,1 bc 12,2,.L6 lwz 0,20(1) mtlr 0 lwz 31,12(1) la 1,16(1) blr .Lfe1: .size func,.Lfe1-func .ident "GCC: (GNU) 2.95.4 20011002 (Debian prerelease)" Release: gcc 3.0.4, gcc 2.95.4 Environment: ppc-linux, i386-linux How-To-Repeat: Compile, browse source & .loop file. RTH says the (< 1) test becomes (== 0), and breaks the unroll.
Fix: Please 8)
State-Changed-From-To: open->analyzed State-Changed-Why: Verified on sparc-linux with 3.1 branch and mainline sources.
From: Richard Henderson <rth@twiddle.net> To: davem@gcc.gnu.org, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org, rusty@rustcorp.com.au, gcc-gnats@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Subject: Re: optimization/7120: Run once loop should *always* be unrolled Date: Wed, 26 Jun 2002 10:54:53 -0700 On Wed, Jun 26, 2002 at 06:02:10PM +0930, Alan Modra wrote: > + if (((INTVAL (initial_value) + INTVAL (increment)) > + & (((unsigned HOST_WIDE_INT) 1 > + << (GET_MODE_BITSIZE (GET_MODE (iteration_var)) - 1) > + << 1) - 1)) == INTVAL (final_value)) Need to use gen_int_mode here and for the final_value calulation. Suggest something like rtx incone = gen_int_mode (INTVAL (initial_value) + INTVAL (increment), GET_MODE (iteration_var)); if (incone == final_value) { ... } else { loop_info->n_iterations = 1; loop_info->final_value = incone; loop_info->final_equiv_value = incone; return 1; } r~
From: Alan Modra <amodra@bigpond.net.au> To: davem@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org, nobody@gcc.gnu.org, rth@twiddle.net, rusty@rustcorp.com.au, gcc-gnats@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org Subject: Re: optimization/7120: Run once loop should *always* be unrolled Date: Wed, 26 Jun 2002 12:54:56 +0930 On Tue, Jun 25, 2002 at 04:21:32PM -0000, davem@gcc.gnu.org wrote: > Synopsis: Run once loop should *always* be unrolled This patch cures the problem. bootstrap i686-linux in progress. * unroll.c (loop_iterations): Handle EQ loops. Index: gcc/unroll.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/unroll.c,v retrieving revision 1.168 diff -u -p -r1.168 unroll.c --- gcc/unroll.c 15 Jun 2002 01:10:49 -0000 1.168 +++ gcc/unroll.c 26 Jun 2002 03:19:38 -0000 @@ -3941,12 +3941,6 @@ loop_iterations (loop) } return 0; } - else if (comparison_code == EQ) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n"); - return 0; - } else if (GET_CODE (final_value) != CONST_INT) { if (loop_dump_stream) @@ -3957,6 +3951,15 @@ loop_iterations (loop) fprintf (loop_dump_stream, ".\n"); } return 0; + } + else if (comparison_code == EQ) + { + if (loop_dump_stream) + fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n"); + if (INTVAL (increment) == 0) + return 0; + loop_info->n_iterations = 1; + return loop_info->n_iterations; } /* Final_larger is 1 if final larger, 0 if they are equal, otherwise -1. */ -- Alan Modra IBM OzLabs - Linux Technology Centre
From: Alan Modra <amodra@bigpond.net.au> To: davem@gcc.gnu.org, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org, rth@twiddle.net, rusty@rustcorp.com.au, gcc-gnats@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Subject: Re: optimization/7120: Run once loop should *always* be unrolled Date: Wed, 26 Jun 2002 13:17:00 +0930 On Wed, Jun 26, 2002 at 12:54:56PM +0930, Alan Modra wrote: > On Tue, Jun 25, 2002 at 04:21:32PM -0000, davem@gcc.gnu.org wrote: > > Synopsis: Run once loop should *always* be unrolled > > This patch cures the problem. bootstrap i686-linux in progress. > > * unroll.c (loop_iterations): Handle EQ loops. Bah, that's too simplistic. Patch withdrawn. -- Alan Modra IBM OzLabs - Linux Technology Centre
From: Alan Modra <amodra@bigpond.net.au> To: davem@gcc.gnu.org, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org, rth@twiddle.net, rusty@rustcorp.com.au, gcc-gnats@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Subject: Re: optimization/7120: Run once loop should *always* be unrolled Date: Wed, 26 Jun 2002 18:02:10 +0930 On Wed, Jun 26, 2002 at 01:17:00PM +0930, Alan Modra wrote: > Bah, that's too simplistic. Patch withdrawn. This one is better. Handles horrible loops like: extern int *arr; int i; i = 0; do { arr[i] = 0; i++; } while (i == 1); I'm also setting loop_info->final_value and loop_info->final_equiv_value as they were reset to zero earlier. bootstrapped and regression tested i686-linux. * unroll.c (loop_iterations): Handle EQ loops. Index: gcc/unroll.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/unroll.c,v retrieving revision 1.168 diff -u -p -r1.168 unroll.c --- gcc/unroll.c 15 Jun 2002 01:10:49 -0000 1.168 +++ gcc/unroll.c 26 Jun 2002 04:58:40 -0000 @@ -3941,12 +3941,6 @@ loop_iterations (loop) } return 0; } - else if (comparison_code == EQ) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n"); - return 0; - } else if (GET_CODE (final_value) != CONST_INT) { if (loop_dump_stream) @@ -3957,6 +3951,34 @@ loop_iterations (loop) fprintf (loop_dump_stream, ".\n"); } return 0; + } + else if (comparison_code == EQ) + { + if (loop_dump_stream) + fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n"); + + if (((INTVAL (initial_value) + INTVAL (increment)) + & (((unsigned HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (GET_MODE (iteration_var)) - 1) + << 1) - 1)) == INTVAL (final_value)) + { + /* The iterator value once through the loop is equal to the + comparision value. Either we have an infinite loop, or + we'll loop twice. */ + if (INTVAL (increment) == 0) + return 0; + loop_info->n_iterations = 2; + } + else + loop_info->n_iterations = 1; + + loop_info->final_value + = plus_constant (loop_info->initial_value, + loop_info->n_iterations * INTVAL (increment)); + loop_info->final_equiv_value + = GEN_INT (INTVAL (initial_value) + + loop_info->n_iterations * INTVAL (increment)); + return loop_info->n_iterations; } /* Final_larger is 1 if final larger, 0 if they are equal, otherwise -1. */ -- Alan Modra IBM OzLabs - Linux Technology Centre
From: Alan Modra <amodra@bigpond.net.au> To: Richard Henderson <rth@twiddle.net> Cc: davem@gcc.gnu.org, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org, rusty@rustcorp.com.au, gcc-gnats@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: Re: optimization/7120: Run once loop should *always* be unrolled Date: Thu, 27 Jun 2002 10:11:26 +0930 On Wed, Jun 26, 2002 at 10:54:53AM -0700, Richard Henderson wrote: > Need to use gen_int_mode here and for the final_value calulation. Yes, we need the mask when the final val is a const_int, but loop_info->initial_value may be an expression involving a reg. So in that case we still need plus_constant. I've also tweaked "INTVAL (increment) == 0" to "increment == const0_rtx". Were you suggesting to remove the n_iterations == 2 case? It's actually useful in weird loops like extern int *arr; int i = 0; do arr[i++] = 0; while (i == 1); and possibly other cases I haven't thought of. On powerpc, the array initialisation is unrolled. OK now? Index: gcc/unroll.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/unroll.c,v retrieving revision 1.168 diff -u -p -r1.168 unroll.c --- gcc/unroll.c 15 Jun 2002 01:10:49 -0000 1.168 +++ gcc/unroll.c 26 Jun 2002 23:44:55 -0000 @@ -3941,12 +3941,6 @@ loop_iterations (loop) } return 0; } - else if (comparison_code == EQ) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n"); - return 0; - } else if (GET_CODE (final_value) != CONST_INT) { if (loop_dump_stream) @@ -3957,6 +3951,43 @@ loop_iterations (loop) fprintf (loop_dump_stream, ".\n"); } return 0; + } + else if (comparison_code == EQ) + { + rtx inc_once; + + if (loop_dump_stream) + fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n"); + + inc_once = gen_int_mode (INTVAL (initial_value) + INTVAL (increment), + GET_MODE (iteration_var)); + + if (inc_once == final_value) + { + /* The iterator value once through the loop is equal to the + comparision value. Either we have an infinite loop, or + we'll loop twice. */ + if (increment == const0_rtx) + return 0; + loop_info->n_iterations = 2; + } + else + loop_info->n_iterations = 1; + + if (GET_CODE (loop_info->initial_value) == CONST_INT) + loop_info->final_value + = gen_int_mode ((INTVAL (loop_info->initial_value) + + loop_info->n_iterations * INTVAL (increment)), + GET_MODE (iteration_var)); + else + loop_info->final_value + = plus_constant (loop_info->initial_value, + loop_info->n_iterations * INTVAL (increment)); + loop_info->final_equiv_value + = gen_int_mode ((INTVAL (initial_value) + + loop_info->n_iterations * INTVAL (increment)), + GET_MODE (iteration_var)); + return loop_info->n_iterations; } /* Final_larger is 1 if final larger, 0 if they are equal, otherwise -1. */ -- Alan Modra IBM OzLabs - Linux Technology Centre
State-Changed-From-To: analyzed->closed State-Changed-Why: Fixed in mainline by http://gcc.gnu.org/ml/gcc-patches/2002-06/msg02152.html
From: Richard Henderson <rth@redhat.com> To: Richard Henderson <rth@twiddle.net>, davem@gcc.gnu.org, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org, rusty@rustcorp.com.au, gcc-gnats@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Subject: Re: optimization/7120: Run once loop should *always* be unrolled Date: Fri, 28 Jun 2002 17:48:24 -0700 On Thu, Jun 27, 2002 at 10:11:26AM +0930, Alan Modra wrote: > Were you suggesting to remove the n_iterations == 2 case? No, just didn't feel like typing it. Patch is ok. r~
Responsible-Changed-From-To: unassigned->amodra Responsible-Changed-Why: Fixed.
From: amodra@gcc.gnu.org To: gcc-gnats@gcc.gnu.org Cc: Subject: optimization/7120 Date: 13 Sep 2002 08:04:23 -0000 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_2-branch Changes by: amodra@gcc.gnu.org 2002-09-13 01:04:23 Modified files: gcc : ChangeLog unroll.c Log message: 2002-06-30 Alan Modra <amodra@bigpond.net.au> PR optimization/7120 * unroll.c (loop_iterations): Handle EQ loops. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.13152.2.657.2.43&r2=1.13152.2.657.2.44 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/unroll.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.160.2.4&r2=1.160.2.4.2.1