summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-01-18 11:09:44 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2018-01-18 11:09:44 -0500
commit5dcbdcbdda488b53768a3093481a2f7d8210cc51 (patch)
tree898e9c86d40ef1d1b0f5e3c4d3f130c258143b31
parent3f05a30b50a7e283d2664719c2fa0832fcd37da0 (diff)
downloadpostgresql-5dcbdcbdda488b53768a3093481a2f7d8210cc51.tar.gz
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
-rw-r--r--config/c-compiler.m448
-rwxr-xr-xconfigure72
2 files changed, 105 insertions, 15 deletions
diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 8d9844abc6..4a512cedd4 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -108,29 +108,61 @@ AC_DEFUN([PGAC_TYPE_128BIT_INT],
[AC_CACHE_CHECK([for __int128], [pgac_cv__128bit_int],
[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
* 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 b = 97656255;
+__int128 b = 97656250;
],[
__int128 c,d;
a = (a << 12) + 1; /* 200000000001 */
b = (b << 12) + 5; /* 400000000005 */
-/* use the most relevant arithmetic ops */
+/* try the most relevant arithmetic ops */
c = a * 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)
- return 0;
-return 1;
+ return 1;
])],
[pgac_cv__128bit_int=yes],
[pgac_cv__128bit_int=no])])
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.])
- AC_CHECK_ALIGNOF(PG_INT128_TYPE)
+ # 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
+ 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
diff --git a/configure b/configure
index 853b375fc5..09e64d6bfe 100755
--- a/configure
+++ b/configure
@@ -14886,12 +14886,15 @@ else
/* 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
* 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 b = 97656255;
+__int128 b = 97656250;
int
main ()
@@ -14900,13 +14903,12 @@ main ()
__int128 c,d;
a = (a << 12) + 1; /* 200000000001 */
b = (b << 12) + 5; /* 400000000005 */
-/* use the most relevant arithmetic ops */
+/* try the most relevant arithmetic ops */
c = a * 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)
- return 0;
-return 1;
+ return 1;
;
return 0;
@@ -14923,10 +14925,65 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__128bit_int" >&5
$as_echo "$pgac_cv__128bit_int" >&6; }
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
- # 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.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of PG_INT128_TYPE" >&5
$as_echo_n "checking alignment of PG_INT128_TYPE... " >&6; }
@@ -14961,6 +15018,7 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+ fi
fi
# Check for various atomic operations now that we have checked how to declare