]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
bitint: Allow unused bits when testing extended _BitInt ABIs
authorYang Yujie <yangyujie@loongson.cn>
Tue, 5 Aug 2025 10:59:30 +0000 (12:59 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 5 Aug 2025 10:59:30 +0000 (12:59 +0200)
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.dg/bitintext.h (S, CEIL, PROMOTED_SIZE): Define.
(BEXTC): Generalize to only check extension within PROMOTED_SIZE bits.

gcc/testsuite/gcc.dg/bitintext.h

index 99fedb32a9a59df0dfb701d40f03567ded48a7d1..d5f2689daec4f05a9a0a769d9a31c10f4f074c70 100644 (file)
@@ -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 ();                                   \