public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* Re: c/3651: shifting unsigned long on 64 bit machine incorrectly does sign extension
@ 2002-04-23  2:09 rth
  0 siblings, 0 replies; 3+ messages in thread
From: rth @ 2002-04-23  2:09 UTC (permalink / raw)
  To: gcc-bugs, gcc-prs, mark.dewing, nobody

Synopsis: shifting unsigned long on 64 bit machine incorrectly does sign extension

State-Changed-From-To: open->closed
State-Changed-By: rth
State-Changed-When: Tue Apr 23 02:09:29 2002
State-Changed-Why:
    Fixed.

http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=3651


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: c/3651: shifting unsigned long on 64 bit machine incorrectly does sign extension
@ 2001-07-17  2:06 Richard Henderson
  0 siblings, 0 replies; 3+ messages in thread
From: Richard Henderson @ 2001-07-17  2:06 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR c/3651; it has been noted by GNATS.

From: Richard Henderson <rth@redhat.com>
To: mark.dewing@intel.com
Cc: gcc-gnats@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: Re: c/3651: shifting unsigned long on 64 bit machine incorrectly does sign extension
Date: Tue, 17 Jul 2001 02:01:55 -0700

 On Wed, Jul 11, 2001 at 07:09:17PM -0000, mark.dewing@intel.com wrote:
 > Right shifting an unsigned long should not do a sign
 > extension.  This shift on an unsigned long variable works
 > okay, but doing this shift on an expression that has
 > been cast to unsigned long does not.
 > This problem also occurs on Alpha Tru64 with gcc 2.7.2.1
 > and IRIX with gcc 2.8.1 in 64 bit mode.
 
 I'm currently testing the following patch on alphaev6-linux.
 Assuming no regressions, I'll check it in tomorrow.
 
 
 r~
 
 
 	* c-typeck.c (build_binary_op): Do not shorten unsigned
 	right shift after sign extension.
 
 Index: c-typeck.c
 ===================================================================
 RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
 retrieving revision 1.128
 diff -c -p -d -r1.128 c-typeck.c
 *** c-typeck.c	2001/07/07 01:07:17	1.128
 --- c-typeck.c	2001/07/17 08:56:46
 *************** build_binary_op (code, orig_op0, orig_op
 *** 2469,2490 ****
   	      /* We can shorten only if the shift count is less than the
   		 number of bits in the smaller type size.  */
   	      && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
 ! 	      /* If arg is sign-extended and then unsigned-shifted,
 ! 		 we can simulate this with a signed shift in arg's type
 ! 		 only if the extended result is at least twice as wide
 ! 		 as the arg.  Otherwise, the shift could use up all the
 ! 		 ones made by sign-extension and bring in zeros.
 ! 		 We can't optimize that case at all, but in most machines
 ! 		 it never happens because available widths are 2**N.  */
 ! 	      && (!TREE_UNSIGNED (final_type)
 ! 		  || unsigned_arg
 ! 		  || (2 * TYPE_PRECISION (TREE_TYPE (arg0))
 ! 		      <= TYPE_PRECISION (result_type))))
   	    {
   	      /* Do an unsigned shift if the operand was zero-extended.  */
   	      result_type
 ! 		= signed_or_unsigned_type (unsigned_arg,
 ! 					   TREE_TYPE (arg0));
   	      /* Convert value-to-be-shifted to that type.  */
   	      if (TREE_TYPE (op0) != result_type)
   		op0 = convert (result_type, op0);
 --- 2469,2480 ----
   	      /* We can shorten only if the shift count is less than the
   		 number of bits in the smaller type size.  */
   	      && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
 ! 	      /* We cannot drop an unsigned shift after sign-extension.  */
 ! 	      && (!TREE_UNSIGNED (final_type) || unsigned_arg))
   	    {
   	      /* Do an unsigned shift if the operand was zero-extended.  */
   	      result_type
 ! 		= signed_or_unsigned_type (unsigned_arg, TREE_TYPE (arg0));
   	      /* Convert value-to-be-shifted to that type.  */
   	      if (TREE_TYPE (op0) != result_type)
   		op0 = convert (result_type, op0);
 Index: testsuite/gcc.c-torture/execute/20010717-1.c
 ===================================================================
 RCS file: 20010717-1.c
 diff -N 20010717-1.c
 *** /dev/null	Tue May  5 13:32:27 1998
 --- 20010717-1.c	Tue Jul 17 01:56:46 2001
 ***************
 *** 0 ****
 --- 1,28 ----
 + static void test (unsigned long, unsigned long);
 + extern void abort (void);
 + 
 + int
 + main ()
 + {
 +   int i, j;
 +   unsigned long u, r1, r2;
 + 
 +   i = -16;
 +   j = 1;
 +   u = i + j;
 + 
 +   /* no sign extension upon shift */
 +   r1 = u >> 1;
 +   /* sign extension upon shift, but there shouldn't be */
 +   r2 = ((unsigned long) (i + j)) >> 1;
 +   test (r1, r2);
 + 
 +   return 0;
 + }
 + 
 + static void
 + test (unsigned long x, unsigned long y)
 + {
 +   if (x != y)
 +     abort ();
 + }


^ permalink raw reply	[flat|nested] 3+ messages in thread

* c/3651: shifting unsigned long on 64 bit machine incorrectly does sign extension
@ 2001-07-11 12:16 mark.dewing
  0 siblings, 0 replies; 3+ messages in thread
From: mark.dewing @ 2001-07-11 12:16 UTC (permalink / raw)
  To: gcc-gnats

>Number:         3651
>Category:       c
>Synopsis:       shifting unsigned long on 64 bit machine incorrectly does sign extension
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jul 11 12:16:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     mark.dewing@intel.com
>Release:        gcc version 3.0 20010526 (prerelease)
>Organization:
>Environment:
IA64 Turbolinux
>Description:
Right shifting an unsigned long should not do a sign
extension.  This shift on an unsigned long variable works
okay, but doing this shift on an expression that has
been cast to unsigned long does not.
This problem also occurs on Alpha Tru64 with gcc 2.7.2.1
and IRIX with gcc 2.8.1 in 64 bit mode.
>How-To-Repeat:

>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="shift-gcc.c"
Content-Disposition: inline; filename="shift-gcc.c"


#include <stdio.h>
main(){
int i,j;
unsigned long u,r1,r2;

 i = -16;
 j = 1;
 u = i+j;

 /* no sign extension upon shift */
 r1 = u >> 1;
 /* sign extension upon shift, but there shouldn't be */
 r2 = ( (unsigned long) (i+j) ) >> 1;
 printf(" r1 = %lx\n",r1);
 printf(" r2 = %lx\n",r2);
 
}


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2002-04-23  9:09 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-04-23  2:09 c/3651: shifting unsigned long on 64 bit machine incorrectly does sign extension rth
  -- strict thread matches above, loose matches on Subject: below --
2001-07-17  2:06 Richard Henderson
2001-07-11 12:16 mark.dewing

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).