In LoongArch psABI, large _BitInt(N) (N > 64) objects are only
extended to fill the highest 8-byte chunk that contains any used bit,
but the size of such a large _BitInt type is a multiple of their
16-byte alignment.  So there may be an entire unused 8-byte
chunk that is not filled by extension, and this chunk shouldn't be
checked when testing if the object is properly extended.

The original bitintext.h assumed that all bits within
sizeof(_BitInt(N)) beyond used bits are filled by extension.
This patch changes that for LoongArch and possibly
any future ports with a similar behavior.

P.S. For encoding this test as well as type-generic programming,
it would be nice to have a builtin function to obtain "N" at
compile time from _BitInt(N)-typed expressions.  But here
we stick to existing ones (__builtin_clrsbg / __builtin_clzg).

gcc/testsuite/ChangeLog:

        * gcc.dg/bitintext.h: Generalize BEXTC to only check extension
        within PROMOTED_SIZE bits.
---
 gcc/testsuite/gcc.dg/bitintext.h | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/bitintext.h b/gcc/testsuite/gcc.dg/bitintext.h
index 99fedb32a9a..522b96ed715 100644
--- a/gcc/testsuite/gcc.dg/bitintext.h
+++ b/gcc/testsuite/gcc.dg/bitintext.h
@@ -4,6 +4,24 @@ do_copy (void *p, const void *q, __SIZE_TYPE__ r)
   __builtin_memcpy (p, q, r);
 }
 
+/* Obtain the value of N from a _BitInt(N)-typed expression X
+   at compile time.  */
+#define S(x) \
+  ((typeof (x)) -1 < 0                                                   \
+   ? __builtin_clrsbg (__builtin_choose_expr ((typeof (x)) -1 < 0,       \
+                                             (typeof (x)) -1, -1)) + 1  \
+   : __builtin_popcountg (__builtin_choose_expr ((typeof (x)) -1 < 0,    \
+                                                0U, (typeof (x)) -1)))
+                                             
+#define CEIL(x,y) (((x) + (y) - 1) / (y))
+
+/* Promote a _BitInt type to include its padding bits.  */
+#if defined (__s390x__) || defined(__arm__)
+#define PROMOTED_SIZE(x) sizeof (x)
+#elif defined(__loongarch__)
+#define PROMOTED_SIZE(x) (sizeof (x) > 8 ? CEIL (S (x), 64) * 8 : sizeof (x))
+#endif
+
 /* 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__)
@@ -11,14 +29,14 @@ do_copy (void *p, const void *q, __SIZE_TYPE__ r)
   do {                                                         \
     if ((typeof (x)) -1 < 0)                                   \
       {                                                                \
-       _BitInt(sizeof (x) * __CHAR_BIT__) __x;                 \
+       _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x;          \
        do_copy (&__x, &(x), sizeof (__x));                     \
        if (__x != (x))                                         \
          __builtin_abort ();                                   \
       }                                                                \
     else                                                       \
       {                                                                \
-       unsigned _BitInt(sizeof (x) * __CHAR_BIT__) __x;        \
+       unsigned _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \
        do_copy (&__x, &(x), sizeof (__x));                     \
        if (__x != (x))                                         \
          __builtin_abort ();                                   \
-- 
2.46.0

Reply via email to