This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR middle-end/6578: -ftrapv fixes to libgcc2.c


The following is a copy of Bruno Haible's fixes to subvsi3, subvdi3,
mulvsi3, absvdi2 and mulvdi3 in libgcc2.c as posted in PR 6578.  It
looks like the copy in bugzilla has become slightly corrupted by a
mailer at some point, whilst the patch below applies cleanly to GCC
mainline.  These functions are used to implement arithmetic operations
when -ftrapv is specified.  Most of the bug-fixes are obvious, but
__mulvdi3 is a significant rewrite of the currently broken routine.

This patch has been tested on i686-pc-linux-gnu with a complete
"make bootstrap", all languages except treelang, and regression
tested with a top-level "make -k check" with no new failures.

If someone can show me how to test for an "abort" at run-time to
indicate success, I'll happily add a new testcase.  I've also
confirmed with Bruno that he has the appropriate FSF assignments
in place.

Ok for mainline?


2003-06-30  Bruno Haible  <bruno@clisp.org>

	PR middle-end/6578
	* libgcc2.c (__subvsi3): Remove simplification that would not work
	when subtracting -0x80000000.
	(__subvdi3): Remove simplification that would return a wrong result.
	(__mulvsi3): Fix overflow check.
	(__absvdi2): Fix simplification that would return a wrong result.
	(__mulvdi3): Fix overflow check.


Index: libgcc2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc2.c,v
retrieving revision 1.167
diff -c -3 -p -r1.167 libgcc2.c
*** libgcc2.c	15 Jun 2003 05:47:38 -0000	1.167
--- libgcc2.c	29 Jun 2003 18:40:12 -0000
*************** __addvdi3 (DWtype a, DWtype b)
*** 109,117 ****
  Wtype
  __subvsi3 (Wtype a, Wtype b)
  {
- #ifdef L_addvsi3
-   return __addvsi3 (a, (-b));
- #else
    DWtype w;

    w = a - b;
--- 109,114 ----
*************** __subvsi3 (Wtype a, Wtype b)
*** 120,126 ****
      abort ();

    return w;
- #endif
  }
  #endif

--- 117,122 ----
*************** __subvsi3 (Wtype a, Wtype b)
*** 128,136 ****
  DWtype
  __subvdi3 (DWtype a, DWtype b)
  {
- #ifdef L_addvdi3
-   return __addvdi3 (a, (-b));
- #else
    DWtype w;

    w = a - b;
--- 124,129 ----
*************** __subvdi3 (DWtype a, DWtype b)
*** 139,157 ****
      abort ();

    return w;
- #endif
  }
  #endif

  #ifdef L_mulvsi3
  Wtype
  __mulvsi3 (Wtype a, Wtype b)
  {
    DWtype w;

!   w = a * b;

!   if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
      abort ();

    return w;
--- 132,152 ----
      abort ();

    return w;
  }
  #endif

  #ifdef L_mulvsi3
+ #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
  Wtype
  __mulvsi3 (Wtype a, Wtype b)
  {
    DWtype w;

!   w = (DWtype) a * (DWtype) b;

!   if (((a >= 0) == (b >= 0))
!       ? (UDWtype) w > (UDWtype) (((DWtype) 1 << (WORD_SIZE - 1)) - 1)
!       : (UDWtype) w < (UDWtype) ((DWtype) -1 << (WORD_SIZE - 1)))
      abort ();

    return w;
*************** __absvdi2 (DWtype a)
*** 215,222 ****
    DWtype w = a;

    if (a < 0)
! #ifdef L_negvsi2
!     w = __negvsi2 (a);
  #else
      w = -a;

--- 210,217 ----
    DWtype w = a;

    if (a < 0)
! #ifdef L_negvdi2
!     w = __negvdi2 (a);
  #else
      w = -a;

*************** __absvdi2 (DWtype a)
*** 229,245 ****
  #endif

  #ifdef L_mulvdi3
  DWtype
  __mulvdi3 (DWtype u, DWtype v)
  {
!   DWtype w;
!
!   w = u * v;

!   if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
!     abort ();
!
!   return w;
  }
  #endif

--- 224,355 ----
  #endif

  #ifdef L_mulvdi3
+ #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
  DWtype
  __mulvdi3 (DWtype u, DWtype v)
  {
!   /* The unchecked multiplication needs 3 Wtype x Wtype multiplications,
!      but the checked multiplication needs only two.  */
!   DWunion uu, vv;
!
!   uu.ll = u;
!   vv.ll = v;
!
!   if (__builtin_expect (uu.s.high == uu.s.low >> (WORD_SIZE - 1), 1))
!     {
!       /* u fits in a single Wtype.  */
!       if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
! 	{
! 	  /* v fits in a single Wtype as well.  */
! 	  /* A single multiplication.  No overflow risk.  */
! 	  return (DWtype) uu.s.low * (DWtype) vv.s.low;
! 	}
!       else
! 	{
! 	  /* Two multiplications.  */
! 	  DWunion w0, w1;
!
! 	  w0.ll = (UDWtype) (UWtype) uu.s.low * (UDWtype) (UWtype) vv.s.low;
! 	  w1.ll = (UDWtype) (UWtype) uu.s.low * (UDWtype) (UWtype) vv.s.high;
! 	  if (vv.s.high < 0)
! 	    w1.s.high -= uu.s.low;
! 	  if (uu.s.low < 0)
! 	    w1.ll -= vv.ll;
! 	  w1.ll += (UWtype) w0.s.high;
! 	  if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1))
! 	    {
! 	      w0.s.high = w1.s.low;
! 	      return w0.ll;
! 	    }
! 	}
!     }
!   else
!     {
!       if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
! 	{
! 	  /* v fits into a single Wtype.  */
! 	  /* Two multiplications.  */
! 	  DWunion w0, w1;
!
! 	  w0.ll = (UDWtype) (UWtype) uu.s.low * (UDWtype) (UWtype) vv.s.low;
! 	  w1.ll = (UDWtype) (UWtype) uu.s.high * (UDWtype) (UWtype) vv.s.low;
! 	  if (uu.s.high < 0)
! 	    w1.s.high -= vv.s.low;
! 	  if (vv.s.low < 0)
! 	    w1.ll -= uu.ll;
! 	  w1.ll += (UWtype) w0.s.high;
! 	  if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1))
! 	    {
! 	      w0.s.high = w1.s.low;
! 	      return w0.ll;
! 	    }
! 	}
!       else
! 	{
! 	  /* A few sign checks and a single multiplication.  */
! 	  if (uu.s.high >= 0)
! 	    {
! 	      if (vv.s.high >= 0)
! 		{
! 		  if (uu.s.high == 0 && vv.s.high == 0)
! 		    {
! 		      DWtype w;
!
! 		      w = (UDWtype) (UWtype) uu.s.low
! 			  * (UDWtype) (UWtype) vv.s.low;
! 		      if (__builtin_expect (w >= 0, 1))
! 			return w;
! 		    }
! 		}
! 	      else
! 		{
! 		  if (uu.s.high == 0 && vv.s.high == (Wtype) -1)
! 		    {
! 		      DWunion ww;
!
! 		      ww.ll = (UDWtype) (UWtype) uu.s.low
! 			      * (UDWtype) (UWtype) vv.s.low;
! 		      ww.s.high -= uu.s.low;
! 		      if (__builtin_expect (ww.s.high < 0, 1))
! 			return ww.ll;
! 		    }
! 		}
! 	    }
! 	  else
! 	    {
! 	      if (vv.s.high >= 0)
! 		{
! 		  if (uu.s.high == (Wtype) -1 && vv.s.high == 0)
! 		    {
! 		      DWunion ww;
!
! 		      ww.ll = (UDWtype) (UWtype) uu.s.low
! 			      * (UDWtype) (UWtype) vv.s.low;
! 		      ww.s.high -= vv.s.low;
! 		      if (__builtin_expect (ww.s.high < 0, 1))
! 			return ww.ll;
! 		    }
! 		}
! 	      else
! 		{
! 		  if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1)
! 		    {
! 		      DWunion ww;
!
! 		      ww.ll = (UDWtype) (UWtype) uu.s.low
! 			      * (UDWtype) (UWtype) vv.s.low;
! 		      ww.s.high -= uu.s.low;
! 		      ww.s.high -= vv.s.low;
! 		      if (__builtin_expect (ww.s.high >= 0, 1))
! 			return ww.ll;
! 		    }
! 		}
! 	    }
! 	}
!     }

!   /* Overflow.  */
!   abort ();
  }
  #endif


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]