* the __asm__. (That would remove the freedom to eliminate dead stores when
* the caller ignores "expected", but few callers do.)
*
- * The cmpwi variant may be dead code. In gcc 7.2.0,
- * __builtin_constant_p(*expected) always reports false.
- * __atomic_compare_exchange_n() does use cmpwi when its second argument
- * points to a constant. Hence, using this instead of
- * __atomic_compare_exchange_n() nominally penalizes the generic.h
- * pg_atomic_test_set_flag_impl(). Modern GCC will use the generic-gcc.h
- * version, making the penalty theoretical only.
- *
* Recognizing constant "newval" would be superfluous, because there's no
* immediate-operand version of stwcx.
*/
#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
if (__builtin_constant_p(*expected) &&
- *expected <= PG_INT16_MAX && *expected >= PG_INT16_MIN)
+ (int32) *expected <= PG_INT16_MAX &&
+ (int32) *expected >= PG_INT16_MIN)
__asm__ __volatile__(
" sync \n"
" lwarx %0,0,%5 \n"
/* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/; s/cmpw/cmpd/ */
#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
if (__builtin_constant_p(*expected) &&
- *expected <= PG_INT16_MAX && *expected >= PG_INT16_MIN)
+ (int64) *expected <= PG_INT16_MAX &&
+ (int64) *expected >= PG_INT16_MIN)
__asm__ __volatile__(
" sync \n"
" ldarx %0,0,%5 \n"
EXPECT_EQ_U32(pg_atomic_read_u32(&var), (uint32) INT_MAX + 1);
EXPECT_EQ_U32(pg_atomic_sub_fetch_u32(&var, INT_MAX), 1);
pg_atomic_sub_fetch_u32(&var, 1);
+ expected = PG_INT16_MAX;
+ EXPECT_TRUE(!pg_atomic_compare_exchange_u32(&var, &expected, 1));
+ expected = PG_INT16_MAX + 1;
+ EXPECT_TRUE(!pg_atomic_compare_exchange_u32(&var, &expected, 1));
+ expected = PG_INT16_MIN;
+ EXPECT_TRUE(!pg_atomic_compare_exchange_u32(&var, &expected, 1));
+ expected = PG_INT16_MIN - 1;
+ EXPECT_TRUE(!pg_atomic_compare_exchange_u32(&var, &expected, 1));
/* fail exchange because of old expected */
expected = 10;