mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
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 751804998, so back-patch to 9.5 as that was. Marina Polyakova, Victor Wagner, Tom Lane Discussion: https://postgr.es/m/0d3a9fa264cebe1cb9966f37b7c06e86@postgrespro.ru
This commit is contained in:
parent
4a81c02297
commit
456cab29df
@ -106,29 +106,61 @@ AC_DEFUN([PGAC_TYPE_128BIT_INT],
|
|||||||
[AC_CACHE_CHECK([for __int128], [pgac_cv__128bit_int],
|
[AC_CACHE_CHECK([for __int128], [pgac_cv__128bit_int],
|
||||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
[AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||||
/*
|
/*
|
||||||
|
* We don't actually run this test, just link it to verify that any support
|
||||||
|
* functions needed for __int128 are present.
|
||||||
|
*
|
||||||
* These are globals to discourage the compiler from folding all the
|
* These are globals to discourage the compiler from folding all the
|
||||||
* arithmetic tests down to compile-time constants. We do not have
|
* arithmetic tests down to compile-time constants. We do not have
|
||||||
* convenient support for 64bit literals at this point...
|
* convenient support for 128bit literals at this point...
|
||||||
*/
|
*/
|
||||||
__int128 a = 48828125;
|
__int128 a = 48828125;
|
||||||
__int128 b = 97656255;
|
__int128 b = 97656250;
|
||||||
],[
|
],[
|
||||||
__int128 c,d;
|
__int128 c,d;
|
||||||
a = (a << 12) + 1; /* 200000000001 */
|
a = (a << 12) + 1; /* 200000000001 */
|
||||||
b = (b << 12) + 5; /* 400000000005 */
|
b = (b << 12) + 5; /* 400000000005 */
|
||||||
/* use the most relevant arithmetic ops */
|
/* try the most relevant arithmetic ops */
|
||||||
c = a * b;
|
c = a * b;
|
||||||
d = (c + b) / b;
|
d = (c + b) / b;
|
||||||
/* return different values, to prevent optimizations */
|
/* must use the results, else compiler may optimize arithmetic away */
|
||||||
if (d != a+1)
|
if (d != a+1)
|
||||||
return 0;
|
return 1;
|
||||||
return 1;
|
|
||||||
])],
|
])],
|
||||||
[pgac_cv__128bit_int=yes],
|
[pgac_cv__128bit_int=yes],
|
||||||
[pgac_cv__128bit_int=no])])
|
[pgac_cv__128bit_int=no])])
|
||||||
if test x"$pgac_cv__128bit_int" = xyes ; then
|
if test x"$pgac_cv__128bit_int" = xyes ; then
|
||||||
AC_DEFINE(PG_INT128_TYPE, __int128, [Define to the name of a signed 128-bit integer type.])
|
# Use of non-default alignment with __int128 tickles bugs in some compilers.
|
||||||
AC_CHECK_ALIGNOF(PG_INT128_TYPE)
|
# If not cross-compiling, we can test for bugs and disable use of __int128
|
||||||
|
# with buggy compilers. If cross-compiling, hope for the best.
|
||||||
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
|
||||||
|
AC_CACHE_CHECK([for __int128 alignment bug], [pgac_cv__128bit_int_bug],
|
||||||
|
[AC_RUN_IFELSE([AC_LANG_PROGRAM([
|
||||||
|
/* This must match the corresponding code in c.h: */
|
||||||
|
#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
|
||||||
|
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
|
||||||
|
#endif
|
||||||
|
typedef __int128 int128a
|
||||||
|
#if defined(pg_attribute_aligned)
|
||||||
|
pg_attribute_aligned(8)
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
int128a holder;
|
||||||
|
void pass_by_val(void *buffer, int128a par) { holder = par; }
|
||||||
|
],[
|
||||||
|
long int i64 = 97656225L << 12;
|
||||||
|
int128a q;
|
||||||
|
pass_by_val(main, (int128a) i64);
|
||||||
|
q = (int128a) i64;
|
||||||
|
if (q != holder)
|
||||||
|
return 1;
|
||||||
|
])],
|
||||||
|
[pgac_cv__128bit_int_bug=ok],
|
||||||
|
[pgac_cv__128bit_int_bug=broken],
|
||||||
|
[pgac_cv__128bit_int_bug="assuming ok"])])
|
||||||
|
if test x"$pgac_cv__128bit_int_bug" != xbroken ; then
|
||||||
|
AC_DEFINE(PG_INT128_TYPE, __int128, [Define to the name of a signed 128-bit integer type.])
|
||||||
|
AC_CHECK_ALIGNOF(PG_INT128_TYPE)
|
||||||
|
fi
|
||||||
fi])# PGAC_TYPE_128BIT_INT
|
fi])# PGAC_TYPE_128BIT_INT
|
||||||
|
|
||||||
|
|
||||||
|
72
configure
vendored
72
configure
vendored
@ -14355,12 +14355,15 @@ else
|
|||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* We don't actually run this test, just link it to verify that any support
|
||||||
|
* functions needed for __int128 are present.
|
||||||
|
*
|
||||||
* These are globals to discourage the compiler from folding all the
|
* These are globals to discourage the compiler from folding all the
|
||||||
* arithmetic tests down to compile-time constants. We do not have
|
* arithmetic tests down to compile-time constants. We do not have
|
||||||
* convenient support for 64bit literals at this point...
|
* convenient support for 128bit literals at this point...
|
||||||
*/
|
*/
|
||||||
__int128 a = 48828125;
|
__int128 a = 48828125;
|
||||||
__int128 b = 97656255;
|
__int128 b = 97656250;
|
||||||
|
|
||||||
int
|
int
|
||||||
main ()
|
main ()
|
||||||
@ -14369,13 +14372,12 @@ main ()
|
|||||||
__int128 c,d;
|
__int128 c,d;
|
||||||
a = (a << 12) + 1; /* 200000000001 */
|
a = (a << 12) + 1; /* 200000000001 */
|
||||||
b = (b << 12) + 5; /* 400000000005 */
|
b = (b << 12) + 5; /* 400000000005 */
|
||||||
/* use the most relevant arithmetic ops */
|
/* try the most relevant arithmetic ops */
|
||||||
c = a * b;
|
c = a * b;
|
||||||
d = (c + b) / b;
|
d = (c + b) / b;
|
||||||
/* return different values, to prevent optimizations */
|
/* must use the results, else compiler may optimize arithmetic away */
|
||||||
if (d != a+1)
|
if (d != a+1)
|
||||||
return 0;
|
return 1;
|
||||||
return 1;
|
|
||||||
|
|
||||||
;
|
;
|
||||||
return 0;
|
return 0;
|
||||||
@ -14392,10 +14394,65 @@ fi
|
|||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__128bit_int" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__128bit_int" >&5
|
||||||
$as_echo "$pgac_cv__128bit_int" >&6; }
|
$as_echo "$pgac_cv__128bit_int" >&6; }
|
||||||
if test x"$pgac_cv__128bit_int" = xyes ; then
|
if test x"$pgac_cv__128bit_int" = xyes ; then
|
||||||
|
# Use of non-default alignment with __int128 tickles bugs in some compilers.
|
||||||
|
# If not cross-compiling, we can test for bugs and disable use of __int128
|
||||||
|
# with buggy compilers. If cross-compiling, hope for the best.
|
||||||
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128 alignment bug" >&5
|
||||||
|
$as_echo_n "checking for __int128 alignment bug... " >&6; }
|
||||||
|
if ${pgac_cv__128bit_int_bug+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
if test "$cross_compiling" = yes; then :
|
||||||
|
pgac_cv__128bit_int_bug="assuming ok"
|
||||||
|
else
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
/* This must match the corresponding code in c.h: */
|
||||||
|
#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
|
||||||
|
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
|
||||||
|
#endif
|
||||||
|
typedef __int128 int128a
|
||||||
|
#if defined(pg_attribute_aligned)
|
||||||
|
pg_attribute_aligned(8)
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
int128a holder;
|
||||||
|
void pass_by_val(void *buffer, int128a par) { holder = par; }
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
|
||||||
|
long int i64 = 97656225L << 12;
|
||||||
|
int128a q;
|
||||||
|
pass_by_val(main, (int128a) i64);
|
||||||
|
q = (int128a) i64;
|
||||||
|
if (q != holder)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_run "$LINENO"; then :
|
||||||
|
pgac_cv__128bit_int_bug=ok
|
||||||
|
else
|
||||||
|
pgac_cv__128bit_int_bug=broken
|
||||||
|
fi
|
||||||
|
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
|
||||||
|
conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__128bit_int_bug" >&5
|
||||||
|
$as_echo "$pgac_cv__128bit_int_bug" >&6; }
|
||||||
|
if test x"$pgac_cv__128bit_int_bug" != xbroken ; then
|
||||||
|
|
||||||
$as_echo "#define PG_INT128_TYPE __int128" >>confdefs.h
|
$as_echo "#define PG_INT128_TYPE __int128" >>confdefs.h
|
||||||
|
|
||||||
# The cast to long int works around a bug in the HP C Compiler,
|
# The cast to long int works around a bug in the HP C Compiler,
|
||||||
# see AC_CHECK_SIZEOF for more information.
|
# see AC_CHECK_SIZEOF for more information.
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of PG_INT128_TYPE" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of PG_INT128_TYPE" >&5
|
||||||
$as_echo_n "checking alignment of PG_INT128_TYPE... " >&6; }
|
$as_echo_n "checking alignment of PG_INT128_TYPE... " >&6; }
|
||||||
@ -14430,6 +14487,7 @@ cat >>confdefs.h <<_ACEOF
|
|||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
|
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for various atomic operations now that we have checked how to declare
|
# Check for various atomic operations now that we have checked how to declare
|
||||||
|
Loading…
x
Reference in New Issue
Block a user