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