Skip to content

Commit 88ea7a1

Browse files
committed
Choose ppc compare_exchange constant path for more operand values.
The implementation uses smaller code when the "expected" operand is a small constant, but the implementation needlessly defined the set of acceptable constants more narrowly than the ABI does. Core PostgreSQL and PGXN don't use the constant path at all, so this is future-proofing. Back-patch to v13, where commit 30ee5d1 introduced this code. Reviewed by Tom Lane. Reported by Christoph Berg. Discussion: https://postgr.es/m/20201009092825.GD889580@msg.df7cb.de
1 parent f5c1167 commit 88ea7a1

File tree

2 files changed

+12
-10
lines changed

2 files changed

+12
-10
lines changed

src/include/port/atomics/arch-ppc.h

+4-10
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,6 @@ typedef struct pg_atomic_uint64
7272
* the __asm__. (That would remove the freedom to eliminate dead stores when
7373
* the caller ignores "expected", but few callers do.)
7474
*
75-
* The cmpwi variant may be dead code. In gcc 7.2.0,
76-
* __builtin_constant_p(*expected) always reports false.
77-
* __atomic_compare_exchange_n() does use cmpwi when its second argument
78-
* points to a constant. Hence, using this instead of
79-
* __atomic_compare_exchange_n() nominally penalizes the generic.h
80-
* pg_atomic_test_set_flag_impl(). Modern GCC will use the generic-gcc.h
81-
* version, making the penalty theoretical only.
82-
*
8375
* Recognizing constant "newval" would be superfluous, because there's no
8476
* immediate-operand version of stwcx.
8577
*/
@@ -94,7 +86,8 @@ pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
9486

9587
#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
9688
if (__builtin_constant_p(*expected) &&
97-
*expected <= PG_INT16_MAX && *expected >= PG_INT16_MIN)
89+
(int32) *expected <= PG_INT16_MAX &&
90+
(int32) *expected >= PG_INT16_MIN)
9891
__asm__ __volatile__(
9992
" sync \n"
10093
" lwarx %0,0,%5 \n"
@@ -183,7 +176,8 @@ pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
183176
/* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/; s/cmpw/cmpd/ */
184177
#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
185178
if (__builtin_constant_p(*expected) &&
186-
*expected <= PG_INT16_MAX && *expected >= PG_INT16_MIN)
179+
(int64) *expected <= PG_INT16_MAX &&
180+
(int64) *expected >= PG_INT16_MIN)
187181
__asm__ __volatile__(
188182
" sync \n"
189183
" ldarx %0,0,%5 \n"

src/test/regress/regress.c

+8
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,14 @@ test_atomic_uint32(void)
720720
EXPECT_EQ_U32(pg_atomic_read_u32(&var), (uint32) INT_MAX + 1);
721721
EXPECT_EQ_U32(pg_atomic_sub_fetch_u32(&var, INT_MAX), 1);
722722
pg_atomic_sub_fetch_u32(&var, 1);
723+
expected = PG_INT16_MAX;
724+
EXPECT_TRUE(!pg_atomic_compare_exchange_u32(&var, &expected, 1));
725+
expected = PG_INT16_MAX + 1;
726+
EXPECT_TRUE(!pg_atomic_compare_exchange_u32(&var, &expected, 1));
727+
expected = PG_INT16_MIN;
728+
EXPECT_TRUE(!pg_atomic_compare_exchange_u32(&var, &expected, 1));
729+
expected = PG_INT16_MIN - 1;
730+
EXPECT_TRUE(!pg_atomic_compare_exchange_u32(&var, &expected, 1));
723731

724732
/* fail exchange because of old expected */
725733
expected = 10;

0 commit comments

Comments
 (0)