/* Caches to speed up bitint_precision_kind. */
static int small_max_prec, mid_min_prec, large_min_prec, huge_min_prec;
-static int limb_prec;
+static int limb_prec, abi_limb_prec;
static bool bitint_big_endian, bitint_extended;
/* Categorize _BitInt(PREC) as small, middle, large or huge. */
large_min_prec = MAX_FIXED_MODE_SIZE + 1;
if (!limb_prec)
limb_prec = GET_MODE_PRECISION (limb_mode);
+ if (!abi_limb_prec)
+ abi_limb_prec
+ = GET_MODE_PRECISION (as_a <scalar_int_mode> (info.abi_limb_mode));
if (!huge_min_prec)
{
if (4 * limb_prec >= MAX_FIXED_MODE_SIZE)
gimple_lower_bitint (void)
{
small_max_prec = mid_min_prec = large_min_prec = huge_min_prec = 0;
- limb_prec = 0;
+ limb_prec = abi_limb_prec = 0;
bitint_big_endian = false;
unsigned int i;
from smaller number. */
min_prec = prec;
else
- min_prec = CEIL (min_prec, limb_prec) * limb_prec;
+ {
+ min_prec = CEIL (min_prec, limb_prec) * limb_prec;
+ if (min_prec > limb_prec && abi_limb_prec > limb_prec)
+ {
+ /* For targets with ABI limb precision higher than
+ limb precision round to ABI limb precision,
+ otherwise c can contain padding bits. */
+ min_prec
+ = CEIL (min_prec, abi_limb_prec) * abi_limb_prec;
+ if (min_prec > prec - rem - 2 * limb_prec)
+ min_prec = prec;
+ }
+ }
if (min_prec == 0)
c = NULL_TREE;
else if (min_prec == prec)
--- /dev/null
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c23 -pedantic-errors" } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __BITINT_MAXWIDTH__ >= 1024
+constexpr _BitInt(1024) d = -541140097068598424394740839221562143161511518875518765552323978870598341733206554363735813878577506997168480201818027232521wb;
+int c;
+
+static inline void
+foo (_BitInt(1024) b, _BitInt(1024) *r)
+{
+ if (c)
+ b = 0;
+ *r = b;
+}
+
+[[gnu::noipa]] void
+bar (_BitInt(1024) y)
+{
+ if (y != d)
+ __builtin_abort ();
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 1024
+ _BitInt(1024) x;
+ foo (d, &x);
+ bar (x);
+#endif
+}