Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit30ee5d1

Browse files
committed
For all ppc compilers, implement compare_exchange and fetch_add with asm.
This is more like how we handle s_lock.h and arch-x86.h.Reviewed by Tom Lane.Discussion:https://postgr.es/m/20191005173400.GA3979129@rfd.leadboat.com
1 parent89b4d77 commit30ee5d1

File tree

8 files changed

+298
-151
lines changed

8 files changed

+298
-151
lines changed

‎configure

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14517,6 +14517,46 @@ $as_echo "$pgac_cv_have_ppc_mutex_hint" >&6; }
1451714517

1451814518
$as_echo "#define HAVE_PPC_LWARX_MUTEX_HINT 1" >>confdefs.h
1451914519

14520+
fi
14521+
# Check if compiler accepts "i"(x) when __builtin_constant_p(x).
14522+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __builtin_constant_p(x) implies \"i\"(x) acceptance" >&5
14523+
$as_echo_n "checking whether __builtin_constant_p(x) implies \"i\"(x) acceptance... " >&6; }
14524+
if ${pgac_cv_have_i_constraint__builtin_constant_p+:} false; then :
14525+
$as_echo_n "(cached) " >&6
14526+
else
14527+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
14528+
/* end confdefs.h. */
14529+
static inline int
14530+
addi(int ra, int si)
14531+
{
14532+
int res = 0;
14533+
if (__builtin_constant_p(si))
14534+
__asm__ __volatile__(
14535+
" addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
14536+
return res;
14537+
}
14538+
int test_adds(int x) { return addi(3, x) + addi(x, 5); }
14539+
int
14540+
main ()
14541+
{
14542+
14543+
;
14544+
return 0;
14545+
}
14546+
_ACEOF
14547+
if ac_fn_c_try_compile "$LINENO"; then :
14548+
pgac_cv_have_i_constraint__builtin_constant_p=yes
14549+
else
14550+
pgac_cv_have_i_constraint__builtin_constant_p=no
14551+
fi
14552+
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
14553+
fi
14554+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_have_i_constraint__builtin_constant_p" >&5
14555+
$as_echo "$pgac_cv_have_i_constraint__builtin_constant_p" >&6; }
14556+
if test x"$pgac_cv_have_i_constraint__builtin_constant_p" = xyes ; then
14557+
14558+
$as_echo "#define HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P 1" >>confdefs.h
14559+
1452014560
fi
1452114561
;;
1452214562
esac

‎configure.in

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,6 +1539,26 @@ case $host_cpu in
15391539
if test x"$pgac_cv_have_ppc_mutex_hint" = xyes ; then
15401540
AC_DEFINE(HAVE_PPC_LWARX_MUTEX_HINT, 1, [Define to 1 if the assembler supports PPC's LWARX mutex hint bit.])
15411541
fi
1542+
# Check if compiler accepts "i"(x) when __builtin_constant_p(x).
1543+
AC_CACHE_CHECK([whether __builtin_constant_p(x) implies "i"(x) acceptance],
1544+
[pgac_cv_have_i_constraint__builtin_constant_p],
1545+
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
1546+
[static inline int
1547+
addi(int ra, int si)
1548+
{
1549+
int res = 0;
1550+
if (__builtin_constant_p(si))
1551+
__asm__ __volatile__(
1552+
" addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
1553+
return res;
1554+
}
1555+
int test_adds(int x) { return addi(3, x) + addi(x, 5); }], [])],
1556+
[pgac_cv_have_i_constraint__builtin_constant_p=yes],
1557+
[pgac_cv_have_i_constraint__builtin_constant_p=no])])
1558+
if test x"$pgac_cv_have_i_constraint__builtin_constant_p" = xyes ; then
1559+
AC_DEFINE(HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P, 1,
1560+
[Define to 1 if __builtin_constant_p(x) implies "i"(x) acceptance.])
1561+
fi
15421562
;;
15431563
esac
15441564

‎src/include/pg_config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@
329329
/* Define to 1 if you have isinf(). */
330330
#undef HAVE_ISINF
331331

332+
/* Define to 1 if __builtin_constant_p(x) implies "i"(x) acceptance. */
333+
#undef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
334+
332335
/* Define to 1 if you have the <langinfo.h> header file. */
333336
#undef HAVE_LANGINFO_H
334337

‎src/include/port/atomics.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,11 @@
8787
* using compiler intrinsics are a good idea.
8888
*/
8989
/*
90-
*Given a gcc-compatible xlc compiler, prefer the xlc implementation. The
91-
*ppc64le "IBMXL C/C++ for Linux, V13.1.2"implements both interfaces, but
92-
*__sync_lock_test_and_set()of one-byte types elicits SIGSEGV.
90+
*gcc orcompatible, including clang and icc. Exclude xlc. The ppc64le "IBM
91+
* XL C/C++ for Linux, V13.1.2"emulates gcc, but __sync_lock_test_and_set()
92+
* of one-byte types elicits SIGSEGV.
9393
*/
94-
#if defined(__IBMC__)|| defined(__IBMCPP__)
95-
#include"port/atomics/generic-xlc.h"
96-
/* gcc or compatible, including clang and icc */
97-
#elif defined(__GNUC__)|| defined(__INTEL_COMPILER)
94+
#if (defined(__GNUC__)|| defined(__INTEL_COMPILER))&& !(defined(__IBMC__)|| defined(__IBMCPP__))
9895
#include"port/atomics/generic-gcc.h"
9996
#elif defined(_MSC_VER)
10097
#include"port/atomics/generic-msvc.h"

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

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,236 @@
2525
#definepg_write_barrier_impl()__asm__ __volatile__ ("lwsync" : : : "memory")
2626
#endif
2727

28+
#definePG_HAVE_ATOMIC_U32_SUPPORT
29+
typedefstructpg_atomic_uint32
30+
{
31+
volatileuint32value;
32+
}pg_atomic_uint32;
33+
34+
/* 64bit atomics are only supported in 64bit mode */
35+
#ifdef__64BIT__
36+
#definePG_HAVE_ATOMIC_U64_SUPPORT
37+
typedefstructpg_atomic_uint64
38+
{
39+
volatileuint64valuepg_attribute_aligned(8);
40+
}pg_atomic_uint64;
41+
42+
#endif/* __64BIT__ */
43+
44+
/*
45+
* This mimics gcc __atomic_compare_exchange_n(..., __ATOMIC_SEQ_CST), but
46+
* code generation differs at the end. __atomic_compare_exchange_n():
47+
* 100:isync
48+
* 104:mfcr r3
49+
* 108:rlwinm r3,r3,3,31,31
50+
* 10c:bne 120 <.eb+0x10>
51+
* 110:clrldi r3,r3,63
52+
* 114:addi r1,r1,112
53+
* 118:blr
54+
* 11c:nop
55+
* 120:clrldi r3,r3,63
56+
* 124:stw r9,0(r4)
57+
* 128:addi r1,r1,112
58+
* 12c:blr
59+
*
60+
* This:
61+
* f0:isync
62+
* f4:mfcr r9
63+
* f8:rldicl. r3,r9,35,63
64+
* fc:bne 104 <.eb>
65+
* 100:stw r10,0(r4)
66+
* 104:addi r1,r1,112
67+
* 108:blr
68+
*
69+
* This implementation may or may not have materially different performance.
70+
* It's not exploiting the fact that cr0 still holds the relevant comparison
71+
* bits, set during the __asm__. One could fix that by moving more code into
72+
* the __asm__. (That would remove the freedom to eliminate dead stores when
73+
* the caller ignores "expected", but few callers do.)
74+
*
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+
*
83+
* Recognizing constant "newval" would be superfluous, because there's no
84+
* immediate-operand version of stwcx.
85+
*/
86+
#definePG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
87+
staticinlinebool
88+
pg_atomic_compare_exchange_u32_impl(volatilepg_atomic_uint32*ptr,
89+
uint32*expected,uint32newval)
90+
{
91+
uint32found;
92+
uint32condition_register;
93+
boolret;
94+
95+
#ifdefHAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
96+
if (__builtin_constant_p(*expected)&&
97+
*expected <=PG_INT16_MAX&&*expected >=PG_INT16_MIN)
98+
__asm__ __volatile__(
99+
"sync\n"
100+
"lwarx %0,0,%5\n"
101+
"cmpwi %0,%3\n"
102+
"bne $+12\n"/* branch to isync */
103+
"stwcx. %4,0,%5\n"
104+
"bne $-16\n"/* branch to lwarx */
105+
"isync\n"
106+
"mfcr %1 \n"
107+
:"=&r"(found),"=r"(condition_register),"+m"(ptr->value)
108+
:"i"(*expected),"r"(newval),"r"(&ptr->value)
109+
:"memory","cc");
110+
else
111+
#endif
112+
__asm__ __volatile__(
113+
"sync\n"
114+
"lwarx %0,0,%5\n"
115+
"cmpw %0,%3\n"
116+
"bne $+12\n"/* branch to isync */
117+
"stwcx. %4,0,%5\n"
118+
"bne $-16\n"/* branch to lwarx */
119+
"isync\n"
120+
"mfcr %1 \n"
121+
:"=&r"(found),"=r"(condition_register),"+m"(ptr->value)
122+
:"r"(*expected),"r"(newval),"r"(&ptr->value)
123+
:"memory","cc");
124+
125+
ret= (condition_register >>29)&1;/* test eq bit of cr0 */
126+
if (!ret)
127+
*expected=found;
128+
returnret;
129+
}
130+
131+
/*
132+
* This mirrors gcc __sync_fetch_and_add().
133+
*
134+
* Like tas(), use constraint "=&b" to avoid allocating r0.
135+
*/
136+
#definePG_HAVE_ATOMIC_FETCH_ADD_U32
137+
staticinlineuint32
138+
pg_atomic_fetch_add_u32_impl(volatilepg_atomic_uint32*ptr,int32add_)
139+
{
140+
uint32_t;
141+
uint32res;
142+
143+
#ifdefHAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
144+
if (__builtin_constant_p(add_)&&
145+
add_ <=PG_INT16_MAX&&add_ >=PG_INT16_MIN)
146+
__asm__ __volatile__(
147+
"sync\n"
148+
"lwarx %1,0,%4\n"
149+
"addi %0,%1,%3\n"
150+
"stwcx. %0,0,%4\n"
151+
"bne $-12\n"/* branch to lwarx */
152+
"isync\n"
153+
:"=&r"(_t),"=&b"(res),"+m"(ptr->value)
154+
:"i"(add_),"r"(&ptr->value)
155+
:"memory","cc");
156+
else
157+
#endif
158+
__asm__ __volatile__(
159+
"sync\n"
160+
"lwarx %1,0,%4\n"
161+
"add %0,%1,%3\n"
162+
"stwcx. %0,0,%4\n"
163+
"bne $-12\n"/* branch to lwarx */
164+
"isync\n"
165+
:"=&r"(_t),"=&r"(res),"+m"(ptr->value)
166+
:"r"(add_),"r"(&ptr->value)
167+
:"memory","cc");
168+
169+
returnres;
170+
}
171+
172+
#ifdefPG_HAVE_ATOMIC_U64_SUPPORT
173+
174+
#definePG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
175+
staticinlinebool
176+
pg_atomic_compare_exchange_u64_impl(volatilepg_atomic_uint64*ptr,
177+
uint64*expected,uint64newval)
178+
{
179+
uint64found;
180+
uint32condition_register;
181+
boolret;
182+
183+
/* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/; s/cmpw/cmpd/ */
184+
#ifdefHAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
185+
if (__builtin_constant_p(*expected)&&
186+
*expected <=PG_INT16_MAX&&*expected >=PG_INT16_MIN)
187+
__asm__ __volatile__(
188+
"sync\n"
189+
"ldarx %0,0,%5\n"
190+
"cmpdi %0,%3\n"
191+
"bne $+12\n"/* branch to isync */
192+
"stdcx. %4,0,%5\n"
193+
"bne $-16\n"/* branch to ldarx */
194+
"isync\n"
195+
"mfcr %1 \n"
196+
:"=&r"(found),"=r"(condition_register),"+m"(ptr->value)
197+
:"i"(*expected),"r"(newval),"r"(&ptr->value)
198+
:"memory","cc");
199+
else
200+
#endif
201+
__asm__ __volatile__(
202+
"sync\n"
203+
"ldarx %0,0,%5\n"
204+
"cmpd %0,%3\n"
205+
"bne $+12\n"/* branch to isync */
206+
"stdcx. %4,0,%5\n"
207+
"bne $-16\n"/* branch to ldarx */
208+
"isync\n"
209+
"mfcr %1 \n"
210+
:"=&r"(found),"=r"(condition_register),"+m"(ptr->value)
211+
:"r"(*expected),"r"(newval),"r"(&ptr->value)
212+
:"memory","cc");
213+
214+
ret= (condition_register >>29)&1;/* test eq bit of cr0 */
215+
if (!ret)
216+
*expected=found;
217+
returnret;
218+
}
219+
220+
#definePG_HAVE_ATOMIC_FETCH_ADD_U64
221+
staticinlineuint64
222+
pg_atomic_fetch_add_u64_impl(volatilepg_atomic_uint64*ptr,int64add_)
223+
{
224+
uint64_t;
225+
uint64res;
226+
227+
/* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/ */
228+
#ifdefHAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
229+
if (__builtin_constant_p(add_)&&
230+
add_ <=PG_INT16_MAX&&add_ >=PG_INT16_MIN)
231+
__asm__ __volatile__(
232+
"sync\n"
233+
"ldarx %1,0,%4\n"
234+
"addi %0,%1,%3\n"
235+
"stdcx. %0,0,%4\n"
236+
"bne $-12\n"/* branch to ldarx */
237+
"isync\n"
238+
:"=&r"(_t),"=&b"(res),"+m"(ptr->value)
239+
:"i"(add_),"r"(&ptr->value)
240+
:"memory","cc");
241+
else
242+
#endif
243+
__asm__ __volatile__(
244+
"sync\n"
245+
"ldarx %1,0,%4\n"
246+
"add %0,%1,%3\n"
247+
"stdcx. %0,0,%4\n"
248+
"bne $-12\n"/* branch to ldarx */
249+
"isync\n"
250+
:"=&r"(_t),"=&r"(res),"+m"(ptr->value)
251+
:"r"(add_),"r"(&ptr->value)
252+
:"memory","cc");
253+
254+
returnres;
255+
}
256+
257+
#endif/* PG_HAVE_ATOMIC_U64_SUPPORT */
258+
28259
/* per architecture manual doubleword accesses have single copy atomicity */
29260
#definePG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp