Bug 7120 - Run once loop should *always* be unrolled
Summary: Run once loop should *always* be unrolled
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 3.0.4
: P3 normal
Target Milestone: ---
Assignee: Alan Modra
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2002-06-25 09:16 UTC by rusty
Modified: 2003-07-25 17:33 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
foo.c.loop (709 bytes, application/octet-stream)
2003-05-21 15:17 UTC, rusty
Details

Note You need to log in before you can comment on or make changes to this bug.
Description rusty 2002-06-25 09:16:01 UTC
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.
Comment 1 rusty 2002-06-25 09:16:01 UTC
Fix:
Please 8)
Comment 2 David S. Miller 2002-06-25 09:21:31 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Verified on sparc-linux with 3.1 branch
    and mainline sources.
Comment 3 Richard Henderson 2002-06-26 10:54:53 UTC
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~

Comment 4 Alan Modra 2002-06-26 12:54:56 UTC
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

Comment 5 Alan Modra 2002-06-26 13:17:00 UTC
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

Comment 6 Alan Modra 2002-06-26 18:02:10 UTC
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

Comment 7 Alan Modra 2002-06-27 10:11:26 UTC
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

Comment 8 Alan Modra 2002-06-27 14:50:37 UTC
State-Changed-From-To: analyzed->closed
State-Changed-Why: Fixed in mainline by
    http://gcc.gnu.org/ml/gcc-patches/2002-06/msg02152.html
Comment 9 Richard Henderson 2002-06-28 17:48:24 UTC
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~

Comment 10 Alan Modra 2002-07-15 17:03:05 UTC
Responsible-Changed-From-To: unassigned->amodra
Responsible-Changed-Why: Fixed.
Comment 11 Alan Modra 2002-09-13 08:04:23 UTC
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