OSDN Git Service

* config/cris/arit.c (do_31div): Clarify what "31" refers to.
authorhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Dec 2005 03:02:30 +0000 (03:02 +0000)
committerhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Dec 2005 03:02:30 +0000 (03:02 +0000)
[L_divsi3] (__Udiv): Don't use as inline function.
[L_modsi3] (__Umod): Ditto.
(__Div): Rearrange to call do_31div directly instead of __Udiv.
(__Mod): Similarly regarding __Umod.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109007 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/cris/arit.c

index 0906088..1b64d26 100644 (file)
@@ -1,5 +1,11 @@
 2005-12-23  Hans-Peter Nilsson  <hp@axis.com>
 
+       * config/cris/arit.c (do_31div): Clarify what "31" refers to.
+       [L_divsi3] (__Udiv): Don't use as inline function.
+       [L_modsi3] (__Umod): Ditto.
+       (__Div): Rearrange to call do_31div directly instead of __Udiv.
+       (__Mod): Similarly regarding __Umod.
+
        PR target/24342
        * config/cris/cris.c (cris_split_movdx): Add REG_INC notes for
        emitted insns with post-increments.
index 32632ab..e094ea7 100644 (file)
@@ -2,7 +2,8 @@
    Contributed by Axis Communications.
    Written by Hans-Peter Nilsson <hp@axis.se>, c:a 1992.
 
-   Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002,
+   2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -62,7 +63,8 @@ struct quot_rem
  };
 
 /* This is the worker function for div and mod.  It is inlined into the
-   respective library function.  */
+   respective library function.  Parameter A must have bit 31 == 0.  */
+
 static __inline__ struct quot_rem
 do_31div (unsigned long a, unsigned long b)
      __attribute__ ((__const__, __always_inline__));
@@ -155,19 +157,10 @@ do_31div (unsigned long a, unsigned long b)
   }
 }
 
-/* Note that unsigned and signed division both build when L_divsi3, but
-   the unsigned variant is then inlined, as with do_31div above.  */
-#if defined (L_udivsi3) || defined (L_divsi3)
-#ifndef L_udivsi3
-static __inline__
-#endif
+#ifdef L_udivsi3
 unsigned long
-__Udiv (unsigned long a, unsigned long b)
-     __attribute__ ((__const__, __always_inline__));
+__Udiv (unsigned long a, unsigned long b) __attribute__ ((__const__));
 
-#ifndef L_udivsi3
-static __inline__
-#endif
 unsigned long
 __Udiv (unsigned long a, unsigned long b)
 {
@@ -208,7 +201,7 @@ __Udiv (unsigned long a, unsigned long b)
 
   return do_31div (a, b).quot+extra;
 }
-
+#endif /* L_udivsi3 */
 
 #ifdef L_divsi3
 long
@@ -217,35 +210,40 @@ __Div (long a, long b) __attribute__ ((__const__));
 long
 __Div (long a, long b)
 {
-  long sign;
-  long result;
-
-  /* Do *not* call do_31div since abs (-2147483648) == 2147483648
-     <=> abs (-0x80000000) == 0x80000000
-     which is still 32 bits.  */
+  long extra = 0;
+  long sign = (b < 0) ? -1 : 1;
+
+  /* We need to handle a == -2147483648 as expected and must while
+     doing that avoid producing a sequence like "abs (a) < 0" as GCC
+     may optimize out the test.  That sequence may not be obvious as
+     we call inline functions.  Testing for a being negative and
+     handling (presumably much rarer than positive) enables us to get
+     a bit of optimization for an (accumulated) reduction of the
+     penalty of the 0x80000000 special-case.  */
+  if (a < 0)
+    {
+      sign = -sign;
 
-  sign = a ^ b;
-  result = __Udiv (__builtin_labs (a), __builtin_labs (b));
+      if ((a & 0x7fffffff) == 0)
+       {
+         /* We're at 0x80000000.  Tread carefully.  */
+         a -= b * sign;
+         extra = sign;
+       }
+      a = -a;
+    }
 
-  return  (sign < 0) ? -result : result;
+  /* We knowingly penalize pre-v10 models by multiplication with the
+     sign.  */
+  return sign * do_31div (a, __builtin_labs (b)).quot + extra;
 }
 #endif /* L_divsi3 */
-#endif /* L_udivsi3 || L_divsi3 */
 
 
-/* Note that unsigned and signed modulus both build when L_modsi3, but
-   then the unsigned variant is inlined, as with do_31div above.  */
-#if defined (L_umodsi3) || defined (L_modsi3)
-#ifndef L_umodsi3
-static __inline__
-#endif
+#ifdef L_umodsi3
 unsigned long
-__Umod (unsigned long a, unsigned long b)
-     __attribute__ ((__const__, __always_inline__));
+__Umod (unsigned long a, unsigned long b) __attribute__ ((__const__));
 
-#ifndef L_umodsi3
-static __inline__
-#endif
 unsigned long
 __Umod (unsigned long a, unsigned long b)
 {
@@ -279,6 +277,7 @@ __Umod (unsigned long a, unsigned long b)
 
   return do_31div (a, b).rem;
 }
+#endif /* L_umodsi3 */
 
 #ifdef L_modsi3
 long
@@ -287,14 +286,27 @@ __Mod (long a, long b) __attribute__ ((__const__));
 long
 __Mod (long a, long b)
 {
-  long result;
-
-  result = __Umod (__builtin_labs (a), __builtin_labs (b));
+  long sign = 1;
+
+  /* We need to handle a == -2147483648 as expected and must while
+     doing that avoid producing a sequence like "abs (a) < 0" as GCC
+     may optimize out the test.  That sequence may not be obvious as
+     we call inline functions.  Testing for a being negative and
+     handling (presumably much rarer than positive) enables us to get
+     a bit of optimization for an (accumulated) reduction of the
+     penalty of the 0x80000000 special-case.  */
+  if (a < 0)
+    {
+      sign = -1;
+      if ((a & 0x7fffffff) == 0)
+       /* We're at 0x80000000.  Tread carefully.  */
+       a += __builtin_labs (b);
+      a = -a;
+    }
 
-  return (a < 0) ? -result : result;
+  return sign * do_31div (a, __builtin_labs (b)).rem;
 }
 #endif /* L_modsi3 */
-#endif /* L_umodsi3 || L_modsi3 */
 #endif /* L_udivsi3 || L_divsi3 || L_umodsi3 || L_modsi3 */
 
 /*