Bug 6909 - [3.2 regression] problem w/ -Os on modified loop-2c.c test case.
Summary: [3.2 regression] problem w/ -Os on modified loop-2c.c test case.
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 3.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-06-02 13:36 UTC by glen
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
loop-2c-new.c (181 bytes, application/octet-stream)
2003-05-21 15:17 UTC, glen
Details

Note You need to log in before you can comment on or make changes to this bug.
Description glen 2002-06-02 13:36:01 UTC
Modified gcc.c-torture/execute/loop-2c.c test case fails on i586-pc-linux-gnu when compiling w/ -Os.  I actually noticed this problem on the 3.1 branch, but I think the mainline is also affected...  I'll verify this and post a patch.

Release:
3.1.1 20020526 (prerelease), 3.2? (experimental)

Environment:
i586-pc-linux-gnu

How-To-Repeat:
gcc -Os loop-2c-new.c
./a.out
Comment 1 glen 2002-06-02 13:36:01 UTC
Fix:
patch pending...
Comment 2 glen 2002-06-02 15:51:32 UTC
From: Glen Nakamura <glen@imodulo.com>
To: gcc-gnats@gcc.gnu.org, gcc-bugs@gcc.gnu.org
Cc:  
Subject: Re: optimization/6909: problem w/ -Os on modified loop-2c.c test case.
Date: Sun, 2 Jun 2002 15:51:32 -1000

 --IS0zKkzwUGydFO0o
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=6909
 
 2002-06-02  Glen Nakamura  <glen@imodulo.com>
 
 	* fold-const.c (fold): Move transformation of X >= CST to X > (CST - 1)
 	and X < CST to X <= (CST - 1) to expose the following simplifications:
 	  1. unsigned int < 0x80000000 to signed int >= 0.
 	  2. unsigned int >= 0x80000000 to signed int < 0.
 	  3. unsigned int > 0xfffffffe to unsigned int == 0xffffffff.
 	  4. unsigned int <= 0xfffffffe to unsigned int != 0xffffffff.
 
 Notes: This patch is a variation of a similar one posted in regard to PR6822.
 I added "code = ??_EXPR;" in a number of places to keep "code" and
 "TREE_CODE (t)" in sync.  I couldn't think of a specific test case to expose
 the problem, but I think it's correct and other places that use TREE_SET_CODE
 do the same thing.
 
 - Glen Nakamura
 
 
 --IS0zKkzwUGydFO0o
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="fold.diff"
 
 Index: fold-const.c
 ===================================================================
 RCS file: /cvsroot/gcc/gcc/gcc/fold-const.c,v
 retrieving revision 1.207
 diff -c -3 -p -u -r1.207 fold-const.c
 --- fold-const.c	1 Jun 2002 16:56:07 -0000	1.207
 +++ fold-const.c	2 Jun 2002 21:32:28 -0000
 @@ -5994,6 +5994,70 @@ fold (expr)
  	  }
        }
  
 +      /* Change X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
 +	 if CST is positive.  This transformation affects the cases which are
 +	 handled in later optimizations involving comparisons with non-negative
 +	 constants.  Remember to handle the equivalent > and <= cases instead
 +	 of the >= and < cases.  Refer to the optimizations involving unsigned
 +	 comparisons with 0 and comparisons with the highest possible integer
 +	 of a specified type below for details of how this transformation
 +	 affects them.  */
 +      if (TREE_CODE (arg1) == INTEGER_CST
 +	  && TREE_CODE (arg0) != INTEGER_CST
 +	  && tree_int_cst_sgn (arg1) > 0)
 +	{
 +	  switch (TREE_CODE (t))
 +	    {
 +	    case GE_EXPR:
 +	      code = GT_EXPR;
 +	      arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
 +	      t = build (code, type, TREE_OPERAND (t, 0), arg1);
 +	      break;
 +
 +	    case LT_EXPR:
 +	      code = LE_EXPR;
 +	      arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
 +	      t = build (code, type, TREE_OPERAND (t, 0), arg1);
 +	      break;
 +
 +	    default:
 +	      break;
 +	    }
 +	}
 +
 +      /* An unsigned comparison against 0 can be simplified.
 +	 This optimization also applies to X >= 1 and X < 1 since those cases
 +	 are converted to X > 0 and X <= 0 by a previous transformation
 +	 which changes X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
 +	 if CST is positive.  */
 +      if (integer_zerop (arg1)
 +	  && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
 +	      || POINTER_TYPE_P (TREE_TYPE (arg1)))
 +	  && TREE_UNSIGNED (TREE_TYPE (arg1)))
 +	{
 +	  switch (TREE_CODE (t))
 +	    {
 +	    case GT_EXPR:
 +	      code = NE_EXPR;
 +	      TREE_SET_CODE (t, NE_EXPR);
 +	      break;
 +	    case LE_EXPR:
 +	      code = EQ_EXPR;
 +	      TREE_SET_CODE (t, EQ_EXPR);
 +	      break;
 +	    case GE_EXPR:
 +	      return omit_one_operand (type,
 +				       convert (type, integer_one_node),
 +				       arg0);
 +	    case LT_EXPR:
 +	      return omit_one_operand (type,
 +				       convert (type, integer_zero_node),
 +				       arg0);
 +	    default:
 +	      break;
 +	    }
 +	}
 +
        /* Comparisons with the highest or lowest possible integer of
  	 the specified size will have known values and an unsigned
  	 <= 0x7fffffff can be simplified.  */
 @@ -6017,6 +6081,7 @@ fold (expr)
  					   convert (type, integer_zero_node),
  					   arg0);
  		case GE_EXPR:
 +		  code = EQ_EXPR;
  		  TREE_SET_CODE (t, EQ_EXPR);
  		  break;
  
 @@ -6025,9 +6090,38 @@ fold (expr)
  					   convert (type, integer_one_node),
  					   arg0);
  		case LT_EXPR:
 +		  code = NE_EXPR;
  		  TREE_SET_CODE (t, NE_EXPR);
  		  break;
  
 +		/* The GE_EXPR and LT_EXPR cases above are not normally
 +		   reached because a previous transformation changes
 +		   X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
 +		   if CST is positive.  The two new cases are handled
 +		   in the next switch statement.  */
 +
 +		default:
 +		  break;
 +		}
 +
 +	    else if (TREE_INT_CST_HIGH (arg1) == 0
 +		&& (TREE_INT_CST_LOW (arg1)
 +		    == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 2)
 +		&& ! TREE_UNSIGNED (TREE_TYPE (arg1)))
 +	      switch (TREE_CODE (t))
 +		{
 +		case GT_EXPR:
 +		  code = EQ_EXPR;
 +		  arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
 +		  t = build (code, type, TREE_OPERAND (t, 0), arg1);
 +		  break;
 +
 +		case LE_EXPR:
 +		  code = NE_EXPR;
 +		  arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
 +		  t = build (code, type, TREE_OPERAND (t, 0), arg1);
 +		  break;
 +
  		default:
  		  break;
  		}
 @@ -6043,6 +6137,7 @@ fold (expr)
  					   convert (type, integer_zero_node),
  					   arg0);
  		case LE_EXPR:
 +		  code = EQ_EXPR;
  		  TREE_SET_CODE (t, EQ_EXPR);
  		  break;
  
 @@ -6051,6 +6146,7 @@ fold (expr)
  					   convert (type, integer_one_node),
  					   arg0);
  		case GT_EXPR:
 +		  code = NE_EXPR;
  		  TREE_SET_CODE (t, NE_EXPR);
  		  break;
  
 @@ -6065,6 +6161,10 @@ fold (expr)
  		     /* signed_type does not work on pointer types.  */
  		     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
  	      {
 +		/* The following case also applies to X < (1 << (width - 1))
 +		   and X >= (1 << (width - 1)) because a previous
 +		   transformation changes X < CST to X <= (CST - 1)
 +		   and X >= CST to X > (CST - 1) if CST is positive.  */
  		if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR)
  		  {
  		    tree st0, st1;
 @@ -6076,6 +6176,7 @@ fold (expr)
  			      convert (st1, integer_zero_node)));
  		  }
  	      }
 +
  	    else if (TREE_INT_CST_HIGH (arg1) == 0
  		     && (TREE_INT_CST_LOW (arg1)
  			 == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1)
 @@ -6087,6 +6188,7 @@ fold (expr)
  					   convert (type, integer_zero_node),
  					   arg0);
  		case GE_EXPR:
 +		  code = EQ_EXPR;
  		  TREE_SET_CODE (t, EQ_EXPR);
  		  break;
  
 @@ -6095,67 +6197,43 @@ fold (expr)
  					   convert (type, integer_one_node),
  					   arg0);
  		case LT_EXPR:
 +		  code = NE_EXPR;
  		  TREE_SET_CODE (t, NE_EXPR);
  		  break;
  
 +		/* The GE_EXPR and LT_EXPR cases above are not normally
 +		   reached because a previous transformation changes
 +		   X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
 +		   if CST is positive.  The two new cases are handled
 +		   in the next switch statement.  */
 +
  		default:
  		  break;
  		}
 -	  }
 -      }
 -
 -      /* Change X >= C to X > C-1 and X < C to X <= C-1 if C is positive.  */
 -      if (TREE_CODE (arg1) == INTEGER_CST
 -	  && TREE_CODE (arg0) != INTEGER_CST
 -	  && tree_int_cst_sgn (arg1) > 0)
 -	{
 -	  switch (TREE_CODE (t))
 -	    {
 -	    case GE_EXPR:
 -	      code = GT_EXPR;
 -	      arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
 -	      t = build (code, type, TREE_OPERAND (t, 0), arg1);
 -	      break;
 -
 -	    case LT_EXPR:
 -	      code = LE_EXPR;
 -	      arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
 -	      t = build (code, type, TREE_OPERAND (t, 0), arg1);
 -	      break;
  
 -	    default:
 -	      break;
 -	    }
 -	}
 +	    else if (TREE_INT_CST_HIGH (arg1) == 0
 +		     && (TREE_INT_CST_LOW (arg1)
 +			 == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 2)
 +		     && TREE_UNSIGNED (TREE_TYPE (arg1)))
 +	      switch (TREE_CODE (t))
 +		{
 +		case GT_EXPR:
 +		  code = EQ_EXPR;
 +		  arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
 +		  t = build (code, type, TREE_OPERAND (t, 0), arg1);
 +		  break;
 +  
 +		case LE_EXPR:
 +		  code = NE_EXPR;
 +		  arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
 +		  t = build (code, type, TREE_OPERAND (t, 0), arg1);
 +		  break;
  
 -      /* An unsigned comparison against 0 can be simplified.  */
 -      if (integer_zerop (arg1)
 -	  && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
 -	      || POINTER_TYPE_P (TREE_TYPE (arg1)))
 -	  && TREE_UNSIGNED (TREE_TYPE (arg1)))
 -	{
 -	  switch (TREE_CODE (t))
 -	    {
 -	    case GT_EXPR:
 -	      code = NE_EXPR;
 -	      TREE_SET_CODE (t, NE_EXPR);
 -	      break;
 -	    case LE_EXPR:
 -	      code = EQ_EXPR;
 -	      TREE_SET_CODE (t, EQ_EXPR);
 -	      break;
 -	    case GE_EXPR:
 -	      return omit_one_operand (type,
 -				       convert (type, integer_one_node),
 -				       arg0);
 -	    case LT_EXPR:
 -	      return omit_one_operand (type,
 -				       convert (type, integer_zero_node),
 -				       arg0);
 -	    default:
 -	      break;
 -	    }
 -	}
 +		default:
 +		  break;
 +		}
 +	  }
 +      }
  
        /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
  	 a MINUS_EXPR of a constant, we can convert it into a comparison with
 
 --IS0zKkzwUGydFO0o--
Comment 3 Eric Botcazou 2003-02-19 09:54:08 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Confirmed on 3.2 branch. 3.3 and mainline are not affected.
Comment 4 Joe Buck 2003-04-25 19:48:35 UTC
State-Changed-From-To: analyzed->closed
State-Changed-Why: Fixed for the next release (3.3).