Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2082b37

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 a063d84 commit 2082b37

File tree

2 files changed

+105
-15
lines changed

2 files changed

+105
-15
lines changed

config/c-compiler.m4

+40-8
Original file line numberDiff line numberDiff line change
@@ -108,29 +108,61 @@ AC_DEFUN([PGAC_TYPE_128BIT_INT],
108108
[AC_CACHE_CHECK([for __int128], [pgac_cv__128bit_int],
109109
[AC_LINK_IFELSE([AC_LANG_PROGRAM([
110110
/*
111+
* We don't actually run this test, just link it to verify that any support
112+
* functions needed for __int128 are present.
113+
*
111114
* These are globals to discourage the compiler from folding all the
112115
* arithmetic tests down to compile-time constants. We do not have
113-
* convenient support for 64bit literals at this point...
116+
* convenient support for 128bit literals at this point...
114117
*/
115118
__int128 a = 48828125;
116-
__int128 b = 97656255;
119+
__int128 b = 97656250;
117120
],[
118121
__int128 c,d;
119122
a = (a << 12) + 1; /* 200000000001 */
120123
b = (b << 12) + 5; /* 400000000005 */
121-
/* use the most relevant arithmetic ops */
124+
/* try the most relevant arithmetic ops */
122125
c = a * b;
123126
d = (c + b) / b;
124-
/* return different values, to prevent optimizations */
127+
/* must use the results, else compiler may optimize arithmetic away */
125128
if (d != a+1)
126-
return 0;
127-
return 1;
129+
return 1;
128130
])],
129131
[pgac_cv__128bit_int=yes],
130132
[pgac_cv__128bit_int=no])])
131133
if test x"$pgac_cv__128bit_int" = xyes ; then
132-
AC_DEFINE(PG_INT128_TYPE, __int128, [Define to the name of a signed 128-bit integer type.])
133-
AC_CHECK_ALIGNOF(PG_INT128_TYPE)
134+
# Use of non-default alignment with __int128 tickles bugs in some compilers.
135+
# If not cross-compiling, we can test for bugs and disable use of __int128
136+
# with buggy compilers. If cross-compiling, hope for the best.
137+
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
138+
AC_CACHE_CHECK([for __int128 alignment bug], [pgac_cv__128bit_int_bug],
139+
[AC_RUN_IFELSE([AC_LANG_PROGRAM([
140+
/* This must match the corresponding code in c.h: */
141+
#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
142+
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
143+
#endif
144+
typedef __int128 int128a
145+
#if defined(pg_attribute_aligned)
146+
pg_attribute_aligned(8)
147+
#endif
148+
;
149+
int128a holder;
150+
void pass_by_val(void *buffer, int128a par) { holder = par; }
151+
],[
152+
long int i64 = 97656225L << 12;
153+
int128a q;
154+
pass_by_val(main, (int128a) i64);
155+
q = (int128a) i64;
156+
if (q != holder)
157+
return 1;
158+
])],
159+
[pgac_cv__128bit_int_bug=ok],
160+
[pgac_cv__128bit_int_bug=broken],
161+
[pgac_cv__128bit_int_bug="assuming ok"])])
162+
if test x"$pgac_cv__128bit_int_bug" != xbroken ; then
163+
AC_DEFINE(PG_INT128_TYPE, __int128, [Define to the name of a signed 128-bit integer type.])
164+
AC_CHECK_ALIGNOF(PG_INT128_TYPE)
165+
fi
134166
fi])# PGAC_TYPE_128BIT_INT
135167

136168

configure

+65-7
Original file line numberDiff line numberDiff line change
@@ -14996,12 +14996,15 @@ else
1499614996
/* end confdefs.h. */
1499714997
1499814998
/*
14999+
* We don't actually run this test, just link it to verify that any support
15000+
* functions needed for __int128 are present.
15001+
*
1499915002
* These are globals to discourage the compiler from folding all the
1500015003
* arithmetic tests down to compile-time constants. We do not have
15001-
* convenient support for 64bit literals at this point...
15004+
* convenient support for 128bit literals at this point...
1500215005
*/
1500315006
__int128 a = 48828125;
15004-
__int128 b = 97656255;
15007+
__int128 b = 97656250;
1500515008
1500615009
int
1500715010
main ()
@@ -15010,13 +15013,12 @@ main ()
1501015013
__int128 c,d;
1501115014
a = (a << 12) + 1; /* 200000000001 */
1501215015
b = (b << 12) + 5; /* 400000000005 */
15013-
/* use the most relevant arithmetic ops */
15016+
/* try the most relevant arithmetic ops */
1501415017
c = a * b;
1501515018
d = (c + b) / b;
15016-
/* return different values, to prevent optimizations */
15019+
/* must use the results, else compiler may optimize arithmetic away */
1501715020
if (d != a+1)
15018-
return 0;
15019-
return 1;
15021+
return 1;
1502015022
1502115023
;
1502215024
return 0;
@@ -15033,10 +15035,65 @@ fi
1503315035
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__128bit_int" >&5
1503415036
$as_echo "$pgac_cv__128bit_int" >&6; }
1503515037
if test x"$pgac_cv__128bit_int" = xyes ; then
15038+
# Use of non-default alignment with __int128 tickles bugs in some compilers.
15039+
# If not cross-compiling, we can test for bugs and disable use of __int128
15040+
# with buggy compilers. If cross-compiling, hope for the best.
15041+
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
15042+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128 alignment bug" >&5
15043+
$as_echo_n "checking for __int128 alignment bug... " >&6; }
15044+
if ${pgac_cv__128bit_int_bug+:} false; then :
15045+
$as_echo_n "(cached) " >&6
15046+
else
15047+
if test "$cross_compiling" = yes; then :
15048+
pgac_cv__128bit_int_bug="assuming ok"
15049+
else
15050+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
15051+
/* end confdefs.h. */
15052+
15053+
/* This must match the corresponding code in c.h: */
15054+
#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
15055+
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
15056+
#endif
15057+
typedef __int128 int128a
15058+
#if defined(pg_attribute_aligned)
15059+
pg_attribute_aligned(8)
15060+
#endif
15061+
;
15062+
int128a holder;
15063+
void pass_by_val(void *buffer, int128a par) { holder = par; }
15064+
15065+
int
15066+
main ()
15067+
{
15068+
15069+
long int i64 = 97656225L << 12;
15070+
int128a q;
15071+
pass_by_val(main, (int128a) i64);
15072+
q = (int128a) i64;
15073+
if (q != holder)
15074+
return 1;
15075+
15076+
;
15077+
return 0;
15078+
}
15079+
_ACEOF
15080+
if ac_fn_c_try_run "$LINENO"; then :
15081+
pgac_cv__128bit_int_bug=ok
15082+
else
15083+
pgac_cv__128bit_int_bug=broken
15084+
fi
15085+
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
15086+
conftest.$ac_objext conftest.beam conftest.$ac_ext
15087+
fi
15088+
15089+
fi
15090+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__128bit_int_bug" >&5
15091+
$as_echo "$pgac_cv__128bit_int_bug" >&6; }
15092+
if test x"$pgac_cv__128bit_int_bug" != xbroken ; then
1503615093

1503715094
$as_echo "#define PG_INT128_TYPE __int128" >>confdefs.h
1503815095

15039-
# The cast to long int works around a bug in the HP C Compiler,
15096+
# The cast to long int works around a bug in the HP C Compiler,
1504015097
# see AC_CHECK_SIZEOF for more information.
1504115098
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of PG_INT128_TYPE" >&5
1504215099
$as_echo_n "checking alignment of PG_INT128_TYPE... " >&6; }
@@ -15071,6 +15128,7 @@ cat >>confdefs.h <<_ACEOF
1507115128
_ACEOF
1507215129

1507315130

15131+
fi
1507415132
fi
1507515133

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

0 commit comments

Comments
 (0)