static int small_max_prec, mid_min_prec, large_min_prec, huge_min_prec;
static int limb_prec;
-static bool bitint_big_endian;
+static bool bitint_big_endian, bitint_extended;
/* Categorize _BitInt(PREC) as small, middle, large or huge. */
return bitint_prec_small;
}
bitint_big_endian = info.big_endian;
+ bitint_extended = info.extended;
if (!large_min_prec
&& GET_MODE_PRECISION (limb_mode) < MAX_FIXED_MODE_SIZE)
large_min_prec = MAX_FIXED_MODE_SIZE + 1;
g = gimple_build_cond (GE_EXPR, add_cast (ssizetype, idx_next),
ssize_int (0), NULL_TREE, NULL_TREE);
insert_before (g);
+ if (bitint_extended && prec % limb_prec != 0)
+ {
+ /* The most significant limb has been updated either in the
+ loop or in the if after it. To simplify the code, just
+ read it back from memory and extend. */
+ m_gsi = gsi_after_labels (edge_false->dest);
+ idx = bitint_big_endian ? size_zero_node : p;
+ tree l = limb_access (TREE_TYPE (lhs), obj, idx, true);
+ tree type = limb_access_type (TREE_TYPE (lhs), idx);
+ tree v = make_ssa_name (m_limb_type);
+ g = gimple_build_assign (v, l);
+ insert_before (g);
+ v = add_cast (type, v);
+ l = limb_access (TREE_TYPE (lhs), obj, idx, true);
+ g = gimple_build_assign (l, add_cast (m_limb_type, v));
+ insert_before (g);
+ }
}
}
--- /dev/null
+[[gnu::noipa]] void
+do_copy (void *p, const void *q, __SIZE_TYPE__ r)
+{
+ __builtin_memcpy (p, q, r);
+}
+
+/* Macro to test whether (on targets where psABI requires it) _BitInt
+ with padding bits have those filled with sign or zero extension. */
+#if defined(__s390x__) || defined(__arm__) || defined(__loongarch__)
+#define BEXTC(x) \
+ do { \
+ if ((typeof (x)) -1 < 0) \
+ { \
+ _BitInt(sizeof (x) * __CHAR_BIT__) __x; \
+ do_copy (&__x, &(x), sizeof (__x)); \
+ if (__x != (x)) \
+ __builtin_abort (); \
+ } \
+ else \
+ { \
+ unsigned _BitInt(sizeof (x) * __CHAR_BIT__) __x; \
+ do_copy (&__x, &(x), sizeof (__x)); \
+ if (__x != (x)) \
+ __builtin_abort (); \
+ } \
+ } while (0)
+#else
+#define BEXTC(x) do { (void) (x); } while (0)
+#endif
--- /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__ >= 532
+_BitInt(5) a = 2, b = -2;
+_BitInt(38) c = 12345, d = -12345;
+_BitInt(129) e = 147090211948845388976606115811401318743wb, f = -147090211948845388976606115811401318743wb;
+_BitInt(532) g = 34476769918317100226195145251004381172591594205376273814wb, h = -102116935649428556311918486808926113041433456371844211259677321wb;
+unsigned _BitInt(1) i = 1;
+unsigned _BitInt(17) j = 49127uwb;
+unsigned _BitInt(60) k = 588141367522129848uwb;
+unsigned _BitInt(205) l = 33991671979236490040668305838261113909013362173682935296620088uwb;
+unsigned _BitInt(475) z = 14834685124553929878903720794923785539321715423294864257448721201977655202426343038777008759878862591302200019811097993772912691139803983786083uwb;
+#endif
+
+#include "../bitintext.h"
+
+#if __BITINT_MAXWIDTH__ >= 532
+[[gnu::noipa]] _BitInt(217)
+f1 (_BitInt(9) a, unsigned _BitInt(12) b, _BitInt(36) c, unsigned _BitInt(105) d,
+ _BitInt(135) e, unsigned _BitInt(168) f, _BitInt(207) g, _BitInt(207) h,
+ unsigned _BitInt(531) i, _BitInt(36) j)
+{
+ BEXTC (a); BEXTC (b); BEXTC (c); BEXTC (d);
+ BEXTC (e); BEXTC (f); BEXTC (g); BEXTC (h);
+ BEXTC (i); BEXTC (j);
+ _BitInt(9) k = a + 1;
+ unsigned _BitInt(12) l = b - a;
+ _BitInt(36) m = c * j;
+ unsigned _BitInt(105) n = d >> (-2 * j);
+ _BitInt(135) o = e | -j;
+ unsigned _BitInt(168) p = f & 101010101010101010101010uwb;
+ _BitInt(207) q = g * j;
+ _BitInt(207) r = g + h;
+ unsigned _BitInt(531) s = i / j;
+ BEXTC (k); BEXTC (l); BEXTC (m); BEXTC (n);
+ BEXTC (o); BEXTC (p); BEXTC (q); BEXTC (r);
+ BEXTC (s);
+ unsigned _BitInt(105) t = d << (38 - j);
+ BEXTC (t);
+ _Atomic _BitInt(5) u = 15;
+ u += 8U;
+ BEXTC (u);
+ _BitInt(135) v = e << 28;
+ BEXTC (v);
+ unsigned _BitInt(475) w = z << (29 + j);
+ BEXTC (w);
+ return a + 4;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 532
+ BEXTC (a); BEXTC (b);
+ BEXTC (c); BEXTC (d);
+ BEXTC (e); BEXTC (f);
+ BEXTC (g); BEXTC (h);
+ BEXTC (i);
+ BEXTC (j);
+ BEXTC (k);
+ BEXTC (l);
+ BEXTC (z);
+ {
+ _BitInt(5) a = 2, b = -2;
+ _BitInt(38) c = 12345, d = -12345;
+ _BitInt(129) e = 147090211948845388976606115811401318743wb, f = -147090211948845388976606115811401318743wb;
+ _BitInt(532) g = 34476769918317100226195145251004381172591594205376273814wb, h = -102116935649428556311918486808926113041433456371844211259677321wb;
+ unsigned _BitInt(1) i = 1;
+ unsigned _BitInt(17) j = 49127uwb;
+ unsigned _BitInt(60) k = 588141367522129848uwb;
+ unsigned _BitInt(205) l = 33991671979236490040668305838261113909013362173682935296620088uwb;
+ BEXTC (a); BEXTC (b);
+ BEXTC (c); BEXTC (d);
+ BEXTC (e); BEXTC (f);
+ BEXTC (g); BEXTC (h);
+ BEXTC (i);
+ BEXTC (j);
+ BEXTC (k);
+ BEXTC (l);
+ }
+ _BitInt(217) m = f1 (57wb, 3927uwb, 10625699364wb, 23030359755638571619326514462579uwb,
+ 20797625176303404170317957140841712396356wb,
+ 111831871006433449872067089878311637796827405335256uwb,
+ 64853652491049541618437564623858346454131583900201311683495230wb,
+ 25108562626494976011700565632680191924545340440636663075662700wb,
+ 6366583146545926097709747296452085257498446783797668089081516596003270602920229800152065594152964557479773813310423759077951305431130758723519892452009351743676uwb,
+ -1);
+ BEXTC (m);
+#endif
+}