Subject: bin/7066: GCC code generator bug with -O
To: None <gnats-bugs@gnats.netbsd.org, bug-gcc@prep.ai.mit.edu, harte@xs4all.nl,>
From: Felix A. Croes <felix@dworkin.nl>
List: netbsd-bugs
Date: 03/01/1999 01:47:32
>Number:         7066
>Category:       bin
>Synopsis:       GCC code generator bug with -O
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Feb 28 18:20:01 1999
>Last-Modified:
>Originator:     Felix A. Croes
>Organization:
	Dworkin B.V.
>Release:        1.3.3
>Environment:
	
System: NetBSD pattern 1.3.3 NetBSD 1.3.3 (PATTERN) #1: Sun Jan 31 13:19:17 CET 1999 felix@pattern:/usr/src/sys/arch/i386/compile/PATTERN i386


>Description:
fold_truthop() forgets to apply previously computed bitmasks when
merging two successive fields into one wider field.  As a result,
wrong code is generated for the following:

    if (x.a == (y.a & mask) && x.b == y.b) { ...

Code is generated instead for the following:

    if (x.a == y.a && x.b == y.b) { ...

I verified that this bug exists in gcc 2.7.2.2, 2.7.2.3 and 2.8.1.
It may also exist in egcs.

>How-To-Repeat:
Compile the following code with gcc -O:

    struct foo {
	char a, b;
	short c;
    };

    int main()
    {
	static struct foo x = { 1, 2 }, y = { 65, 2 };

	return !(x.a == (y.a & ~64) && x.b == y.b);
    }

If the bug is present, the program will exit with status 1.

>Fix:
*** fold-const.c.old	Tue May  5 08:33:36 1998
--- fold-const.c	Mon Mar  1 02:34:26 1999
***************
*** 2978,2993 ****
  	   && lr_bitsize + lr_bitpos == rr_bitpos)
  	  || (ll_bitpos == rl_bitpos + rl_bitsize
  	      && lr_bitpos == rr_bitpos + rr_bitsize))
! 	return build (wanted_code, truth_type,
! 		      make_bit_field_ref (ll_inner, type,
! 					  ll_bitsize + rl_bitsize,
! 					  MIN (ll_bitpos, rl_bitpos),
! 					  ll_unsignedp),
! 		      make_bit_field_ref (lr_inner, type,
! 					  lr_bitsize + rr_bitsize,
! 					  MIN (lr_bitpos, rr_bitpos),
! 					  lr_unsignedp));
  
        return 0;
      }
  
--- 2978,2995 ----
  	   && lr_bitsize + lr_bitpos == rr_bitpos)
  	  || (ll_bitpos == rl_bitpos + rl_bitsize
  	      && lr_bitpos == rr_bitpos + rr_bitsize))
! 	{
! 	  lhs = make_bit_field_ref (ll_inner, type, ll_bitsize + rl_bitsize,
! 				    MIN (ll_bitpos, rl_bitpos), ll_unsignedp);
! 	  rhs = make_bit_field_ref (lr_inner, type, lr_bitsize + rr_bitsize,
! 				    MIN (lr_bitpos, rr_bitpos), lr_unsignedp);
! 	  if (! all_ones_mask_p (ll_mask, ll_bitsize + rl_bitsize))
! 	    lhs = build (BIT_AND_EXPR, type, lhs, ll_mask);
! 	  if (! all_ones_mask_p (lr_mask, lr_bitsize + rr_bitsize))
! 	    rhs = build (BIT_AND_EXPR, type, rhs, lr_mask);
! 	return build (wanted_code, truth_type, lhs, rhs);
  
+ 	}
        return 0;
      }
  
>Audit-Trail:
>Unformatted: