--- /dev/null
+/* PR libgcc/114397 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c23" } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __BITINT_MAXWIDTH__ >= 129
+int
+foo (unsigned _BitInt (128) a, _BitInt (129) b)
+{
+ return a / b;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 192
+int
+bar (unsigned _BitInt (128) a, _BitInt (192) b)
+{
+ return a / b;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 129
+ if (foo (336225022742818342628768636932743029911uwb,
+ -336225022742818342628768636932743029911wb) != -1
+ || foo (336225022742818342628768636932743029912uwb,
+ -336225022742818342628768636932743029911wb) != -1
+ || foo (336225022742818342628768636932743029911uwb,
+ -336225022742818342628768636932743029912wb) != 0)
+ __builtin_abort ();
+#endif
+#if __BITINT_MAXWIDTH__ >= 192
+ if (bar (336225022742818342628768636932743029911uwb,
+ -336225022742818342628768636932743029911wb) != -1
+ || bar (336225022742818342628768636932743029912uwb,
+ -336225022742818342628768636932743029911wb) != -1
+ || bar (336225022742818342628768636932743029911uwb,
+ -336225022742818342628768636932743029912wb) != 0)
+ __builtin_abort ();
+#endif
+}
USItype vp = avprec % W_TYPE_SIZE;
if (__builtin_expect (un < vn, 0))
{
- /* If abs(v) > abs(u), then q is 0 and r is u. */
- if (q)
- __builtin_memset (q, 0, qn * sizeof (UWtype));
- if (r == NULL)
- return;
-#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
- r += rn - 1;
- u += un - 1;
-#endif
- if (up)
- --un;
- if (rn < un)
- un = rn;
- for (rn -= un; un; --un)
+ /* If abs(v) > abs(u), then q is 0 and r is u.
+ Unfortunately un < vn doesn't always mean abs(v) > abs(u).
+ If uprec > 0 and vprec < 0 and vn == un + 1, if the
+ top limb of v is all ones and the second most significant
+ limb has most significant bit clear, then just decrease
+ vn/avprec/vp and continue, after negation both numbers
+ will have the same number of limbs. */
+ if (un + 1 == vn
+ && uprec >= 0
+ && vprec < 0
+ && ((v[BITINT_END (0, vn - 1)] | (vp ? ((UWtype) -1 << vp) : 0))
+ == (UWtype) -1)
+ && (Wtype) v[BITINT_END (1, vn - 2)] >= 0)
{
- *r = *u;
- r += BITINT_INC;
- u += BITINT_INC;
+ vp = 0;
+ --vn;
+#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
+ ++v;
+#endif
}
- if (!rn)
- return;
- if (up)
+ else
{
- if (uprec > 0)
- *r = *u & (((UWtype) 1 << up) - 1);
- else
- *r = *u | ((UWtype) -1 << up);
- r += BITINT_INC;
- if (!--rn)
+ /* q is 0 and r is u. */
+ if (q)
+ __builtin_memset (q, 0, qn * sizeof (UWtype));
+ if (r == NULL)
return;
+#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
+ r += rn - 1;
+ u += un - 1;
+#endif
+ if (up)
+ --un;
+ if (rn < un)
+ un = rn;
+ for (rn -= un; un; --un)
+ {
+ *r = *u;
+ r += BITINT_INC;
+ u += BITINT_INC;
+ }
+ if (!rn)
+ return;
+ if (up)
+ {
+ if (uprec > 0)
+ *r = *u & (((UWtype) 1 << up) - 1);
+ else
+ *r = *u | ((UWtype) -1 << up);
+ r += BITINT_INC;
+ if (!--rn)
+ return;
+ }
+ UWtype c = uprec < 0 ? (UWtype) -1 : (UWtype) 0;
+ for (; rn; --rn)
+ {
+ *r = c;
+ r += BITINT_INC;
+ }
+ return;
}
- UWtype c = uprec < 0 ? (UWtype) -1 : (UWtype) 0;
- for (; rn; --rn)
- {
- *r = c;
- r += BITINT_INC;
- }
- return;
}
USItype qn2 = un - vn + 1;
if (qn >= qn2)