if (!abi_limb_prec)
abi_limb_prec
= GET_MODE_PRECISION (as_a <scalar_int_mode> (info.abi_limb_mode));
+ /* For bitint_ext_full with different limb_mode from abi_limb_mode we
+ currently only support only abi_limb_mode twice the precision of
+ limb_mode, and don't support big endian in that case either. */
+ gcc_assert (bitint_extended != bitint_ext_full
+ || (abi_limb_prec == 2 * limb_prec
+ && !bitint_big_endian));
if (!huge_min_prec)
{
if (4 * limb_prec >= MAX_FIXED_MODE_SIZE)
= (prec != (unsigned) TYPE_PRECISION (type)
&& (CEIL ((unsigned) TYPE_PRECISION (type), limb_prec)
> CEIL (prec, limb_prec)));
+ bool zero_ms_limb = false;
if (bitint_extended == bitint_ext_full
&& !eq_p
+ && !nlhs
&& abi_limb_prec > limb_prec
&& ((CEIL ((unsigned) TYPE_PRECISION (type), abi_limb_prec)
- * abi_limb_prec / limb_prec) > CEIL (prec, limb_prec)))
+ * abi_limb_prec / limb_prec)
+ > CEIL ((unsigned) TYPE_PRECISION (type), limb_prec)))
{
if (prec == (unsigned) TYPE_PRECISION (type))
- sext = !TYPE_UNSIGNED (type);
- separate_ext = true;
+ {
+ sext = !TYPE_UNSIGNED (type);
+ separate_ext = true;
+ }
+ else if (TYPE_UNSIGNED (type) && sext)
+ zero_ms_limb = true;
+ else
+ separate_ext = true;
}
unsigned dst_idx_off = 0;
if (separate_ext && bitint_big_endian)
kind = bitint_precision_kind (type);
unsigned start = CEIL (prec, limb_prec);
prec = TYPE_PRECISION (type);
- if (bitint_extended == bitint_ext_full && abi_limb_prec > limb_prec)
+ if (bitint_extended == bitint_ext_full
+ && !nlhs
+ && !zero_ms_limb
+ && abi_limb_prec > limb_prec)
{
prec = CEIL (prec, abi_limb_prec) * abi_limb_prec;
kind = bitint_precision_kind (prec);
}
}
}
+ if (zero_ms_limb)
+ {
+ tree p2 = build_int_cst (sizetype,
+ CEIL ((unsigned) TYPE_PRECISION (type),
+ abi_limb_prec)
+ * abi_limb_prec / limb_prec - 1);
+ tree l = limb_access (lhs_type, lhs, p2, true);
+ g = gimple_build_assign (l, build_zero_cst (m_limb_type));
+ insert_before (g);
+ if (eh)
+ {
+ maybe_duplicate_eh_stmt (g, stmt);
+ if (eh_pad)
+ {
+ edge e = split_block (gsi_bb (m_gsi), g);
+ m_gsi = gsi_after_labels (e->dest);
+ add_eh_edge (e->src, find_edge (gimple_bb (stmt), eh_pad));
+ }
+ }
+ }
if (gimple_store_p (stmt))
{
if (bitint_big_endian)
g = gimple_build_cond (NE_EXPR, idx, size_zero_node,
NULL_TREE, NULL_TREE);
+ else if (bitint_extended == bitint_ext_full
+ && abi_limb_prec > limb_prec)
+ {
+ tree p2 = build_int_cst (sizetype,
+ CEIL (prec, abi_limb_prec)
+ * abi_limb_prec / limb_prec - 1);
+ g = gimple_build_cond (LE_EXPR, idx_next, p2, NULL_TREE, NULL_TREE);
+ }
else
g = gimple_build_cond (LE_EXPR, idx_next, p, NULL_TREE, NULL_TREE);
insert_before (g);
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));
+ v = add_cast (m_limb_type, v);
+ g = gimple_build_assign (l, v);
+ insert_before (g);
+ if (bitint_extended == bitint_ext_full
+ && abi_limb_prec > limb_prec
+ && (CEIL (prec, abi_limb_prec) * abi_limb_prec
+ > CEIL (prec, limb_prec) * limb_prec))
+ {
+ tree p2 = build_int_cst (sizetype,
+ CEIL (prec, abi_limb_prec)
+ * abi_limb_prec / limb_prec - 1);
+ if (TYPE_UNSIGNED (TREE_TYPE (lhs)))
+ v = build_zero_cst (m_limb_type);
+ else
+ {
+ g = gimple_build_assign (make_ssa_name (m_limb_type),
+ RSHIFT_EXPR, v,
+ build_int_cst (unsigned_type_node,
+ limb_prec - 1));
+ v = gimple_assign_lhs (g);
+ insert_before (g);
+ }
+ l = limb_access (TREE_TYPE (lhs), obj, p2, true);
+ g = gimple_build_assign (l, v);
+ insert_before (g);
+ }
+ }
+ else if (bitint_extended == bitint_ext_full
+ && abi_limb_prec > limb_prec
+ && (CEIL (prec, abi_limb_prec) * abi_limb_prec
+ > CEIL (prec, limb_prec) * limb_prec))
+ {
+ m_gsi = gsi_after_labels (edge_false->dest);
+ tree p2 = build_int_cst (sizetype,
+ CEIL (prec, abi_limb_prec)
+ * abi_limb_prec / limb_prec - 1);
+ tree v;
+ if (TYPE_UNSIGNED (TREE_TYPE (lhs)))
+ v = build_zero_cst (m_limb_type);
+ else
+ {
+ tree l = limb_access (TREE_TYPE (lhs), obj, p, true);
+ v = make_ssa_name (m_limb_type);
+ g = gimple_build_assign (v, l);
+ insert_before (g);
+ g = gimple_build_assign (make_ssa_name (m_limb_type),
+ RSHIFT_EXPR, v,
+ build_int_cst (unsigned_type_node,
+ limb_prec - 1));
+ v = gimple_assign_lhs (g);
+ insert_before (g);
+ }
+ tree l = limb_access (TREE_TYPE (lhs), obj, p2, true);
+ g = gimple_build_assign (l, v);
insert_before (g);
}
}
#define CEIL(x,y) (((x) + (y) - 1) / (y))
/* Promote a _BitInt type to include its padding bits. */
-#if defined (__s390x__) || defined(__arm__) || defined(__riscv__)
+#if defined (__s390x__) || defined(__arm__) || defined(__riscv)
#define PROMOTED_SIZE(x) sizeof (x)
#elif defined(__loongarch__)
#define PROMOTED_SIZE(x) (sizeof (x) > 8 ? CEIL (S (x), 64) * 8 : sizeof (x))
/* 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__) \
- || defined(__riscv__)
+ || defined(__riscv)
#define BEXTC1(x, uns) \
do { \
uns _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \
/* PR middle-end/123635 */
/* { dg-do run { target bitint } } */
-/* { dg-require-effective-target sync_char_short } */
/* { dg-options "-std=c23 -pedantic-errors" } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
/* PR middle-end/123635 */
/* { dg-do run { target bitint } } */
-/* { dg-require-effective-target sync_char_short } */
/* { dg-options "-std=c23 -pedantic-errors" } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
--- /dev/null
+/* PR middle-end/123635 */
+/* { 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__ >= 1025
+unsigned _BitInt(513) a, b, c, d;
+_BitInt(513) e, f, g, h;
+unsigned _BitInt(1025) i, j, k, l;
+_BitInt(1025) m, n, o, p;
+#endif
+
+#include "../bitintext.h"
+
+#if __BITINT_MAXWIDTH__ >= 1025
+[[gnu::noipa]] void
+f1 (_BitInt(513) q, _BitInt(513) r, _BitInt(513) s,
+ unsigned _BitInt(513) t, unsigned _BitInt(513) u, unsigned _BitInt(513) v)
+{
+ a = q + r;
+ BEXTC (a);
+ b = r + s;
+ BEXTC (b);
+ c = q - r;
+ BEXTC (c);
+ d = q - s;
+ BEXTC (d);
+ e = t + u;
+ BEXTC (e);
+ f = u + v;
+ BEXTC (f);
+ g = t - u;
+ BEXTC (g);
+ h = t - v;
+ BEXTC (h);
+}
+
+[[gnu::noipa]] void
+f2 (_BitInt(513) q, _BitInt(513) r, _BitInt(513) s,
+ unsigned _BitInt(513) t, unsigned _BitInt(513) u, unsigned _BitInt(513) v)
+{
+ i = q + r;
+ BEXTC (i);
+ j = r + s;
+ BEXTC (j);
+ k = q - r;
+ BEXTC (k);
+ l = q - s;
+ BEXTC (l);
+ m = t + u;
+ BEXTC (m);
+ n = u + v;
+ BEXTC (n);
+ o = t - u;
+ BEXTC (o);
+ p = t - v;
+ BEXTC (p);
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 1025
+ __builtin_memset (&a, 0x55, sizeof (a));
+ __builtin_memset (&b, 0xaa, sizeof (b));
+ __builtin_memset (&c, 0x55, sizeof (c));
+ __builtin_memset (&d, 0xaa, sizeof (d));
+ __builtin_memset (&e, 0x55, sizeof (e));
+ __builtin_memset (&f, 0xaa, sizeof (f));
+ __builtin_memset (&g, 0x55, sizeof (g));
+ __builtin_memset (&h, 0xaa, sizeof (h));
+ f1 (-2639616085193412675089727272130019765984398127278861998378045997173219392866835944828454559654047247059773556852593471531433454810831298259785611283536204wb,
+ -7234121192495298112713936268702056205915537824658323839255206188456944966709752205781440683757949161649123152428620619997014209098183677328840647884700332wb,
+ 8654283549227219676537451326576929768614001427323560383705131223498505581982738964879437520020436012891649083646965651378407397436785749860023553778646861wb,
+ 15046745594550617619205422464231805109110883864578289024439083517871820578179553927615539526791313634437787081814763432804808038115388367331529035246240655uwb,
+ 20633637828717837096174917874088391607464281656818868213468970773994599068609617673436080725569780340050358299419252926775025136778754971701553110169281151uwb,
+ 513612209045189503622076474995216606086383139671427104179978688982034117764664711277072795083902951564358998498109412142322138933760173628255697435284781uwb);
+ __builtin_memset (&i, 0x55, sizeof (i));
+ __builtin_memset (&j, 0xaa, sizeof (j));
+ __builtin_memset (&k, 0x55, sizeof (k));
+ __builtin_memset (&l, 0xaa, sizeof (l));
+ __builtin_memset (&m, 0x55, sizeof (m));
+ __builtin_memset (&n, 0xaa, sizeof (n));
+ __builtin_memset (&o, 0x55, sizeof (o));
+ __builtin_memset (&p, 0xaa, sizeof (p));
+ f2 (-2639616085193412675089727272130019765984398127278861998378045997173219392866835944828454559654047247059773556852593471531433454810831298259785611283536204wb,
+ -7234121192495298112713936268702056205915537824658323839255206188456944966709752205781440683757949161649123152428620619997014209098183677328840647884700332wb,
+ 8654283549227219676537451326576929768614001427323560383705131223498505581982738964879437520020436012891649083646965651378407397436785749860023553778646861wb,
+ 15046745594550617619205422464231805109110883864578289024439083517871820578179553927615539526791313634437787081814763432804808038115388367331529035246240655uwb,
+ 20633637828717837096174917874088391607464281656818868213468970773994599068609617673436080725569780340050358299419252926775025136778754971701553110169281151uwb,
+ 513612209045189503622076474995216606086383139671427104179978688982034117764664711277072795083902951564358998498109412142322138933760173628255697435284781uwb);
+#endif
+}
--- /dev/null
+/* PR middle-end/123635 */
+/* { 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__ >= 1025
+_BitInt(513) a, b, c, d;
+unsigned _BitInt(513) e, f, g, h;
+_BitInt(513) i, j, k, l;
+unsigned _BitInt(513) m, n, o, p;
+#endif
+
+#include "../bitintext.h"
+
+#if __BITINT_MAXWIDTH__ >= 1025
+[[gnu::noipa]] void
+f1 (_BitInt(513) q, _BitInt(513) r, _BitInt(513) s,
+ unsigned _BitInt(513) t, unsigned _BitInt(513) u, unsigned _BitInt(513) v,
+ int z)
+{
+ a = q >> 23;
+ BEXTC (a);
+ b = r << 23;
+ BEXTC (b);
+ c = r >> z;
+ BEXTC (c);
+ d = s << z;
+ BEXTC (d);
+ e = t >> 23;
+ BEXTC (e);
+ f = u << 23;
+ BEXTC (f);
+ g = t >> z;
+ BEXTC (g);
+ h = v << z;
+ BEXTC (h);
+}
+
+[[gnu::noipa]] void
+f2 (_BitInt(513) q, _BitInt(513) r, _BitInt(513) s,
+ unsigned _BitInt(513) t, unsigned _BitInt(513) u, unsigned _BitInt(513) v,
+ int z)
+{
+ i = q >> 67;
+ BEXTC (i);
+ j = r << 67;
+ BEXTC (j);
+ k = q >> z;
+ BEXTC (k);
+ l = s << z;
+ BEXTC (l);
+ m = t >> 67;
+ BEXTC (m);
+ n = u << 67;
+ BEXTC (n);
+ o = t >> z;
+ BEXTC (o);
+ p = v << z;
+ BEXTC (p);
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 1025
+ __builtin_memset (&a, 0x55, sizeof (a));
+ __builtin_memset (&b, 0xaa, sizeof (b));
+ __builtin_memset (&c, 0x55, sizeof (c));
+ __builtin_memset (&d, 0xaa, sizeof (d));
+ __builtin_memset (&e, 0x55, sizeof (e));
+ __builtin_memset (&f, 0xaa, sizeof (f));
+ __builtin_memset (&g, 0x55, sizeof (g));
+ __builtin_memset (&h, 0xaa, sizeof (h));
+ f1 (-2639616085193412675089727272130019765984398127278861998378045997173219392866835944828454559654047247059773556852593471531433454810831298259785611283536204wb,
+ -7234121192495298112713936268702056205915537824658323839255206188456944966709752205781440683757949161649123152428620619997014209098183677328840647884700332wb,
+ 8654283549227219676537451326576929768614001427323560383705131223498505581982738964879437520020436012891649083646965651378407397436785749860023553778646861wb,
+ 15046745594550617619205422464231805109110883864578289024439083517871820578179553927615539526791313634437787081814763432804808038115388367331529035246240655uwb,
+ 20633637828717837096174917874088391607464281656818868213468970773994599068609617673436080725569780340050358299419252926775025136778754971701553110169281151uwb,
+ 513612209045189503622076474995216606086383139671427104179978688982034117764664711277072795083902951564358998498109412142322138933760173628255697435284781uwb,
+ 129);
+ __builtin_memset (&i, 0x55, sizeof (i));
+ __builtin_memset (&j, 0xaa, sizeof (j));
+ __builtin_memset (&k, 0x55, sizeof (k));
+ __builtin_memset (&l, 0xaa, sizeof (l));
+ __builtin_memset (&m, 0x55, sizeof (m));
+ __builtin_memset (&n, 0xaa, sizeof (n));
+ __builtin_memset (&o, 0x55, sizeof (o));
+ __builtin_memset (&p, 0xaa, sizeof (p));
+ f2 (2639616085193412675089727272130019765984398127278861998378045997173219392866835944828454559654047247059773556852593471531433454810831298259785611283536204wb,
+ -7234121192495298112713936268702056205915537824658323839255206188456944966709752205781440683757949161649123152428620619997014209098183677328840647884700332wb,
+ -8654283549227219676537451326576929768614001427323560383705131223498505581982738964879437520020436012891649083646965651378407397436785749860023553778646861wb,
+ 513612209045189503622076474995216606086383139671427104179978688982034117764664711277072795083902951564358998498109412142322138933760173628255697435284781uwb,
+ 20633637828717837096174917874088391607464281656818868213468970773994599068609617673436080725569780340050358299419252926775025136778754971701553110169281151uwb,
+ 15046745594550617619205422464231805109110883864578289024439083517871820578179553927615539526791313634437787081814763432804808038115388367331529035246240655uwb,
+ 211);
+#endif
+}