On Sat, Aug 02, 2025 at 05:14:21PM +0800, Yang Yujie wrote:
> In BEXTC, whether a _BitInt object is properly extended is examined
> by a value comparison against a copied object in a wider _BitInt
> type that utilizes all of the partial limb.
> 
> Since the (implicit) conversion to the wider type may be optimized
> away and cause the result of the comparison to always be true,
> we need to cast the copied object down to the original type to
> force a extension, so that it can serve as our reference.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.dg/bitintext.h (BEXTC): Convert the copied object back
>       to the original type before comparison.

The ChangeLog doesn't describe what the patch does, e.g. the introduction of
__BEXTC macro.

> @@ -25,22 +25,30 @@ do_copy (void *p, const void *q, __SIZE_TYPE__ 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, __x, __y) \
> +  do {                                           \
> +    typeof (x) __z;                      \
> +    do_copy (&(__x), &(x), sizeof (__x));   \
> +    __z = (typeof (x)) __x;              \
> +    do_copy (&(__y), &__z, sizeof (__y));   \
> +    if ((__x) != (__y))                          \
> +      __builtin_abort ();                \
> +  } while (0)

I'd suggest a change.  I'd just use a name of the macro
not reserved for implementation, and instead of adding __x and __y
arguments, let it take
#define BEXTC1(x, uns) \
  do {                                                  \
    uns _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x;  \
    do_copy (&__x, &(x), sizeof (__x));                 \
    if ((__x) != (typeof (x)) __x)                      \
      __builtin_abort ();                               \
  } while (0)

and then just use BEXTC1 (x, signed); for the signed case
and BEXTC1 (x, unsigned); for the unsigned one.
I think the above can't be optimized away, __x is the wider type and
after do_copy which is noipa the compiler can't know anything about
the state of the upper bits.  So, cast from __x to typeof (x) and
back to typeof (__x) for the comparison has to sign or zero extend
depending on whether typeof (x) is signed or unsigned.

        Jakub

Reply via email to