--- -/libgcc/libgcc2.c
+++ +/libgcc/libgcc2.c
@@ -75,9 +75,9 @@
 Wtype
 __addvSI3 (Wtype a, Wtype b)
 {
-  const Wtype w = (UWtype) a + (UWtype) b;
+  Wtype w;
 
-  if (b >= 0 ? w < a : w > a)
+  if (__builtin_add_overflow(a, b, &w))
     abort ();
 
   return w;
@@ -86,9 +86,9 @@
 SItype
 __addvsi3 (SItype a, SItype b)
 {
-  const SItype w = (USItype) a + (USItype) b;
+  SItype w;
 
-  if (b >= 0 ? w < a : w > a)
+  if (__builtin_add_overflow(a, b, &w))
     abort ();
 
   return w;
@@ -100,9 +100,9 @@
 DWtype
 __addvDI3 (DWtype a, DWtype b)
 {
-  const DWtype w = (UDWtype) a + (UDWtype) b;
+  DWtype w;
 
-  if (b >= 0 ? w < a : w > a)
+  if (__builtin_add_overflow(a, b, &w))
     abort ();
 
   return w;
@@ -113,9 +113,9 @@
 Wtype
 __subvSI3 (Wtype a, Wtype b)
 {
-  const Wtype w = (UWtype) a - (UWtype) b;
+  Wtype w;
 
-  if (b >= 0 ? w > a : w < a)
+  if (__builtin_sub_overflow(a, b, &w))
     abort ();
 
   return w;
@@ -124,9 +124,9 @@
 SItype
 __subvsi3 (SItype a, SItype b)
 {
-  const SItype w = (USItype) a - (USItype) b;
+  SItype w;
 
-  if (b >= 0 ? w > a : w < a)
+  if (__builtin_sub_overflow(a, b, &w))
     abort ();
 
   return w;
@@ -138,9 +138,9 @@
 DWtype
 __subvDI3 (DWtype a, DWtype b)
 {
-  const DWtype w = (UDWtype) a - (UDWtype) b;
+  DWtype w;
 
-  if (b >= 0 ? w > a : w < a)
+  if (__builtin_sub_overflow(a, b, &w))
     abort ();
 
   return w;
@@ -151,22 +151,20 @@
 Wtype
 __mulvSI3 (Wtype a, Wtype b)
 {
-  const DWtype w = (DWtype) a * (DWtype) b;
+  Wtype w;
 
-  if ((Wtype) (w >> W_TYPE_SIZE) != (Wtype) w >> (W_TYPE_SIZE - 1))
+  if (__builtin_mul_overflow(a, b, &w))
     abort ();
 
   return w;
 }
 #ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
-#undef WORD_SIZE
-#define WORD_SIZE (sizeof (SItype) * __CHAR_BIT__)
 SItype
 __mulvsi3 (SItype a, SItype b)
 {
-  const DItype w = (DItype) a * (DItype) b;
+  DItype w;
 
-  if ((SItype) (w >> WORD_SIZE) != (SItype) w >> (WORD_SIZE-1))
+  if (__builtin_mul_overflow(a, b, &w))
     abort ();
 
   return w;
@@ -178,23 +176,23 @@
 Wtype
 __negvSI2 (Wtype a)
 {
-  const Wtype w = -(UWtype) a;
+  Wtype w;
 
-  if (a >= 0 ? w > 0 : w < 0)
+  if (__builtin_sub_overflow(0, a, &w))
     abort ();
 
-   return w;
+  return w;
 }
 #ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
 SItype
 __negvsi2 (SItype a)
 {
-  const SItype w = -(USItype) a;
+  SItype w;
 
-  if (a >= 0 ? w > 0 : w < 0)
+  if (__builtin_sub_overflow(0, a, &w))
     abort ();
 
-   return w;
+  return w;
 }
 #endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
 #endif
@@ -203,9 +201,9 @@
 DWtype
 __negvDI2 (DWtype a)
 {
-  const DWtype w = -(UDWtype) a;
+  DWtype w;
 
-  if (a >= 0 ? w > 0 : w < 0)
+  if (__builtin_sub_overflow(0, a, &w))
     abort ();
 
   return w;
@@ -216,37 +214,43 @@
 Wtype
 __absvSI2 (Wtype a)
 {
-  Wtype w = a;
+  const Wtype v = 0 - (a < 0);
+#ifdef LIBGCC2_BAD_CODE
+  Wtype w = a ^ v;
 
-  if (a < 0)
-#ifdef L_negvsi2
-    w = __negvSI2 (a);
+  if (__builtin_sub_overflow(v, w, &w))
+    abort ();
+
+  return w;
 #else
-    w = -(UWtype) a;
+  Wtype w;
 
-  if (w < 0)
+  if (__builtin_add_overflow(a, v, &w))
     abort ();
-#endif
 
-   return w;
+  return v ^ w;
+#endif
 }
 #ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
 SItype
 __absvsi2 (SItype a)
 {
-  SItype w = a;
+  const SItype v = 0 - (a < 0);
+#ifdef LIBGCC2_BAD_CODE
+  SItype w = a ^ v;
 
-  if (a < 0)
-#ifdef L_negvsi2
-    w = __negvsi2 (a);
+  if (__builtin_sub_overflow(v, w, &w))
+    abort ();
+
+  return w;
 #else
-    w = -(USItype) a;
+  SItype w;
 
-  if (w < 0)
+  if (__builtin_add_overflow(a, v, &w))
     abort ();
-#endif
 
-   return w;
+  return v ^ w;
+#endif
 }
 #endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
 #endif
@@ -255,144 +259,50 @@
 DWtype
 __absvDI2 (DWtype a)
 {
-  DWtype w = a;
+  const DWtype v = 0 - (a < 0);
+#ifdef LIBGCC2_BAD_CODE
+  DWtype w = a ^ v;
 
-  if (a < 0)
-#ifdef L_negvdi2
-    w = __negvDI2 (a);
+  if (__builtin_sub_overflow(v, w, &w))
+    abort ();
+
+  return w;
 #else
-    w = -(UDWtype) a;
+  DWtype w;
 
-  if (w < 0)
+  if (__builtin_add_overflow(a, v, &w))
     abort ();
-#endif
 
-  return w;
+  return v ^ w;
+#endif
 }
 #endif
 
 #ifdef L_mulvdi3
 DWtype
-__mulvDI3 (DWtype u, DWtype v)
+__mulvDI3 (DWtype a, DWtype b)
 {
-  /* The unchecked multiplication needs 3 Wtype x Wtype multiplications,
-     but the checked multiplication needs only two.  */
-  const DWunion uu = {.ll = u};
-  const DWunion vv = {.ll = v};
+#ifdef LIBGCC2_BAD_CODE
+  DWtype w;
 
-  if (__builtin_expect (uu.s.high == uu.s.low >> (W_TYPE_SIZE - 1), 1))
-    {
-      /* u fits in a single Wtype.  */
-      if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_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 = {.ll = (UDWtype) (UWtype) uu.s.low
-			* (UDWtype) (UWtype) vv.s.low};
-	  DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.low
-			* (UDWtype) (UWtype) vv.s.high};
+  if (__builtin_mul_overflow(a, b, &w))
+    abort ();
 
-	  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 >> (W_TYPE_SIZE - 1), 1))
-	    {
-	      w0.s.high = w1.s.low;
-	      return w0.ll;
-	    }
-	}
-    }
-  else
-    {
-      if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
-	{
-	  /* v fits into a single Wtype.  */
-	  /* Two multiplications.  */
-	  DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
-			* (UDWtype) (UWtype) vv.s.low};
-	  DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.high
-			* (UDWtype) (UWtype) vv.s.low};
+  return w;
+#else
+  DWtype t;
+  const DWunion u = {.ll = a};
+  const DWunion v = {.ll = b};
+  DWunion w = {.ll = __umulsidi3 (u.s.low, v.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 >> (W_TYPE_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)
-		    {
-		      const DWtype 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 = {.ll = (UDWtype) (UWtype) uu.s.low
-				    * (UDWtype) (UWtype) vv.s.low};
+  if (__builtin_mul_overflow(u.s.low, v.s.high, &t)
+   || __builtin_add_overflow(t, w.s.high, &w.s.high)
+   || __builtin_mul_overflow(u.s.high, v.s.low, &t)
+   || __builtin_add_overflow(t, w.s.high, &w.s.high))
+    abort ();
 
-		      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 = {.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 & vv.s.high) == (Wtype) -1
-		      && (uu.s.low | vv.s.low) != 0)
-		    {
-		      DWunion 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 ();
+  return w.ll;
+#endif
 }
 #endif
 
@@ -953,7 +863,7 @@
      aligns the divisor under the dividend and then perform number of
      test-subtract iterations which shift the dividend left. Number of
      iterations is k + 1 where k is the number of bit positions the
-     divisor must be shifted left  to align it under the dividend.
+     divisor must be shifted left to align it under the dividend.
      quotient bits can be saved in the rightmost positions of the dividend
      as it shifts left on each test-subtract iteration. */
 
@@ -965,7 +875,7 @@
       k = lz1 - lz2;
       y = (y << k);
 
-      /* Dividend can exceed 2 ^ (width − 1) − 1 but still be less than the
+      /* Dividend can exceed 2 ^ (width - 1) - 1 but still be less than the
 	 aligned divisor. Normal iteration can drops the high order bit
 	 of the dividend. Therefore, first test-subtract iteration is a
 	 special case, saving its quotient bit in a separate location and
@@ -1325,37 +1235,15 @@
 cmp_return_type
 __cmpdi2 (DWtype a, DWtype b)
 {
-  const DWunion au = {.ll = a};
-  const DWunion bu = {.ll = b};
-
-  if (au.s.high < bu.s.high)
-    return 0;
-  else if (au.s.high > bu.s.high)
-    return 2;
-  if ((UWtype) au.s.low < (UWtype) bu.s.low)
-    return 0;
-  else if ((UWtype) au.s.low > (UWtype) bu.s.low)
-    return 2;
-  return 1;
+  return (a > b) - (a < b) + 1;
 }
 #endif
 
 #ifdef L_ucmpdi2
 cmp_return_type
-__ucmpdi2 (DWtype a, DWtype b)
+__ucmpdi2 (UDWtype a, UDWtype b)
 {
-  const DWunion au = {.ll = a};
-  const DWunion bu = {.ll = b};
-
-  if ((UWtype) au.s.high < (UWtype) bu.s.high)
-    return 0;
-  else if ((UWtype) au.s.high > (UWtype) bu.s.high)
-    return 2;
-  if ((UWtype) au.s.low < (UWtype) bu.s.low)
-    return 0;
-  else if ((UWtype) au.s.low > (UWtype) bu.s.low)
-    return 2;
-  return 1;
+  return (a > b) - (a < b) + 1;
 }
 #endif
 