Skip to content

Commit 31635bc

Browse files
committed
Extend configure's __int128 test to check for a known gcc bug.
On Sparc64, use of __attribute__(aligned(8)) with __int128 causes faulty code generation in gcc versions at least through 5.5.0. We can work around that by disabling use of __int128, so teach configure to test for the bug. This solution doesn't fix things for the case of cross-compiling with a buggy compiler; to support that nicely, we'd need to add a manual disable switch. Unless more such cases turn up, it doesn't seem worth the work. Affected users could always edit pg_config.h manually. In passing, fix some typos in the existing configure test for __int128. They're harmless because we only compile that code not run it, but they're still confusing for anyone looking at it closely. This is needed in support of commit 7518049, so back-patch to 9.5 as that was. Marina Polyakova, Victor Wagner, Tom Lane Discussion: https://postgr.es/m/0d3a9fa264cebe1cb9966f37b7c06e86@postgrespro.ru
1 parent 4eae1e6 commit 31635bc

File tree

2 files changed

+105
-15
lines changed

2 files changed

+105
-15
lines changed

config/c-compiler.m4

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,29 +140,61 @@ AC_DEFUN([PGAC_TYPE_128BIT_INT],
140140
[AC_CACHE_CHECK([for __int128], [pgac_cv__128bit_int],
141141
[AC_LINK_IFELSE([AC_LANG_PROGRAM([
142142
/*
143+
* We don't actually run this test, just link it to verify that any support
144+
* functions needed for __int128 are present.
145+
*
143146
* These are globals to discourage the compiler from folding all the
144147
* arithmetic tests down to compile-time constants. We do not have
145-
* convenient support for 64bit literals at this point...
148+
* convenient support for 128bit literals at this point...
146149
*/
147150
__int128 a = 48828125;
148-
__int128 b = 97656255;
151+
__int128 b = 97656250;
149152
],[
150153
__int128 c,d;
151154
a = (a << 12) + 1; /* 200000000001 */
152155
b = (b << 12) + 5; /* 400000000005 */
153-
/* use the most relevant arithmetic ops */
156+
/* try the most relevant arithmetic ops */
154157
c = a * b;
155158
d = (c + b) / b;
156-
/* return different values, to prevent optimizations */
159+
/* must use the results, else compiler may optimize arithmetic away */
157160
if (d != a+1)
158-
return 0;
159-
return 1;
161+
return 1;
160162
])],
161163
[pgac_cv__128bit_int=yes],
162164
[pgac_cv__128bit_int=no])])
163165
if test x"$pgac_cv__128bit_int" = xyes ; then
164-
AC_DEFINE(PG_INT128_TYPE, __int128, [Define to the name of a signed 128-bit integer type.])
165-
AC_CHECK_ALIGNOF(PG_INT128_TYPE)
166+
# Use of non-default alignment with __int128 tickles bugs in some compilers.
167+
# If not cross-compiling, we can test for bugs and disable use of __int128
168+
# with buggy compilers. If cross-compiling, hope for the best.
169+
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
170+
AC_CACHE_CHECK([for __int128 alignment bug], [pgac_cv__128bit_int_bug],
171+
[AC_RUN_IFELSE([AC_LANG_PROGRAM([
172+
/* This must match the corresponding code in c.h: */
173+
#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
174+
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
175+
#endif
176+
typedef __int128 int128a
177+
#if defined(pg_attribute_aligned)
178+
pg_attribute_aligned(8)
179+
#endif
180+
;
181+
int128a holder;
182+
void pass_by_val(void *buffer, int128a par) { holder = par; }
183+
],[
184+
long int i64 = 97656225L << 12;
185+
int128a q;
186+
pass_by_val(main, (int128a) i64);
187+
q = (int128a) i64;
188+
if (q != holder)
189+
return 1;
190+
])],
191+
[pgac_cv__128bit_int_bug=ok],
192+
[pgac_cv__128bit_int_bug=broken],
193+
[pgac_cv__128bit_int_bug="assuming ok"])])
194+
if test x"$pgac_cv__128bit_int_bug" != xbroken ; then
195+
AC_DEFINE(PG_INT128_TYPE, __int128, [Define to the name of a signed 128-bit integer type.])
196+
AC_CHECK_ALIGNOF(PG_INT128_TYPE)
197+
fi
166198
fi])# PGAC_TYPE_128BIT_INT
167199

168200

configure

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14055,12 +14055,15 @@ else
1405514055
/* end confdefs.h. */
1405614056
1405714057
/*
14058+
* We don't actually run this test, just link it to verify that any support
14059+
* functions needed for __int128 are present.
14060+
*
1405814061
* These are globals to discourage the compiler from folding all the
1405914062
* arithmetic tests down to compile-time constants. We do not have
14060-
* convenient support for 64bit literals at this point...
14063+
* convenient support for 128bit literals at this point...
1406114064
*/
1406214065
__int128 a = 48828125;
14063-
__int128 b = 97656255;
14066+
__int128 b = 97656250;
1406414067
1406514068
int
1406614069
main ()
@@ -14069,13 +14072,12 @@ main ()
1406914072
__int128 c,d;
1407014073
a = (a << 12) + 1; /* 200000000001 */
1407114074
b = (b << 12) + 5; /* 400000000005 */
14072-
/* use the most relevant arithmetic ops */
14075+
/* try the most relevant arithmetic ops */
1407314076
c = a * b;
1407414077
d = (c + b) / b;
14075-
/* return different values, to prevent optimizations */
14078+
/* must use the results, else compiler may optimize arithmetic away */
1407614079
if (d != a+1)
14077-
return 0;
14078-
return 1;
14080+
return 1;
1407914081
1408014082
;
1408114083
return 0;
@@ -14092,10 +14094,65 @@ fi
1409214094
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__128bit_int" >&5
1409314095
$as_echo "$pgac_cv__128bit_int" >&6; }
1409414096
if test x"$pgac_cv__128bit_int" = xyes ; then
14097+
# Use of non-default alignment with __int128 tickles bugs in some compilers.
14098+
# If not cross-compiling, we can test for bugs and disable use of __int128
14099+
# with buggy compilers. If cross-compiling, hope for the best.
14100+
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
14101+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128 alignment bug" >&5
14102+
$as_echo_n "checking for __int128 alignment bug... " >&6; }
14103+
if ${pgac_cv__128bit_int_bug+:} false; then :
14104+
$as_echo_n "(cached) " >&6
14105+
else
14106+
if test "$cross_compiling" = yes; then :
14107+
pgac_cv__128bit_int_bug="assuming ok"
14108+
else
14109+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
14110+
/* end confdefs.h. */
14111+
14112+
/* This must match the corresponding code in c.h: */
14113+
#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
14114+
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
14115+
#endif
14116+
typedef __int128 int128a
14117+
#if defined(pg_attribute_aligned)
14118+
pg_attribute_aligned(8)
14119+
#endif
14120+
;
14121+
int128a holder;
14122+
void pass_by_val(void *buffer, int128a par) { holder = par; }
14123+
14124+
int
14125+
main ()
14126+
{
14127+
14128+
long int i64 = 97656225L << 12;
14129+
int128a q;
14130+
pass_by_val(main, (int128a) i64);
14131+
q = (int128a) i64;
14132+
if (q != holder)
14133+
return 1;
14134+
14135+
;
14136+
return 0;
14137+
}
14138+
_ACEOF
14139+
if ac_fn_c_try_run "$LINENO"; then :
14140+
pgac_cv__128bit_int_bug=ok
14141+
else
14142+
pgac_cv__128bit_int_bug=broken
14143+
fi
14144+
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
14145+
conftest.$ac_objext conftest.beam conftest.$ac_ext
14146+
fi
14147+
14148+
fi
14149+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__128bit_int_bug" >&5
14150+
$as_echo "$pgac_cv__128bit_int_bug" >&6; }
14151+
if test x"$pgac_cv__128bit_int_bug" != xbroken ; then
1409514152

1409614153
$as_echo "#define PG_INT128_TYPE __int128" >>confdefs.h
1409714154

14098-
# The cast to long int works around a bug in the HP C Compiler,
14155+
# The cast to long int works around a bug in the HP C Compiler,
1409914156
# see AC_CHECK_SIZEOF for more information.
1410014157
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of PG_INT128_TYPE" >&5
1410114158
$as_echo_n "checking alignment of PG_INT128_TYPE... " >&6; }
@@ -14130,6 +14187,7 @@ cat >>confdefs.h <<_ACEOF
1413014187
_ACEOF
1413114188

1413214189

14190+
fi
1413314191
fi
1413414192

1413514193
# Check for various atomic operations now that we have checked how to declare

0 commit comments

Comments
 (0)