From 8122e1437e332e156d971a0274879b0ee76e488a Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 20 Mar 2015 10:26:17 +0100 Subject: [PATCH] Add, optional, support for 128bit integers. We will, for the foreseeable future, not expose 128 bit datatypes to SQL. But being able to use 128bit math will allow us, in a later patch, to use 128bit accumulators for some aggregates; leading to noticeable speedups over using numeric. So far we only detect a gcc/clang extension that supports 128bit math, but no 128bit literals, and no *printf support. We might want to expand this in the future to further compilers; if there are any that that provide similar support. Discussion: 544BB5F1.50709@proxel.se Author: Andreas Karlsson, with significant editorializing by me Reviewed-By: Peter Geoghegan, Oskari Saarenmaa --- config/c-compiler.m4 | 37 +++++++++++++++++++++++++ configure | 52 +++++++++++++++++++++++++++++++++++ configure.in | 3 ++ src/include/c.h | 11 ++++++++ src/include/pg_config.h.in | 3 ++ src/include/pg_config.h.win32 | 3 ++ 6 files changed, 109 insertions(+) diff --git a/config/c-compiler.m4 b/config/c-compiler.m4 index 509f96139f..38aab11bc6 100644 --- a/config/c-compiler.m4 +++ b/config/c-compiler.m4 @@ -125,6 +125,43 @@ undefine([Ac_cachevar])dnl ])# PGAC_TYPE_64BIT_INT +# PGAC_TYPE_128BIT_INT +# --------------------- +# Check if __int128 is a working 128 bit integer type, and if so +# define PG_INT128_TYPE to that typename. This currently only detects +# a GCC/clang extension, but support for different environments may be +# added in the future. +# +# For the moment we only test for support for 128bit math; support for +# 128bit literals and snprintf is not required. +AC_DEFUN([PGAC_TYPE_128BIT_INT], +[AC_CACHE_CHECK([for __int128], [pgac_cv__128bit_int], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([ +/* + * 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... + */ +__int128 a = 48828125; +__int128 b = 97656255; +],[ +__int128 c,d; +a = (a << 12) + 1; /* 200000000001 */ +b = (b << 12) + 5; /* 400000000005 */ +/* use the most relevant arithmetic ops */ +c = a * b; +d = (c + b) / b; +/* return different values, to prevent optimizations */ +if (d != a+1) + return 0; +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.]) +fi])# PGAC_TYPE_128BIT_INT + # PGAC_C_FUNCNAME_SUPPORT # ----------------------- diff --git a/configure b/configure index 379dab16ab..2c9b3a7c71 100755 --- a/configure +++ b/configure @@ -13803,6 +13803,58 @@ _ACEOF fi +# Check for extensions offering the integer scalar type __int128. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5 +$as_echo_n "checking for __int128... " >&6; } +if ${pgac_cv__128bit_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* + * 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... + */ +__int128 a = 48828125; +__int128 b = 97656255; + +int +main () +{ + +__int128 c,d; +a = (a << 12) + 1; /* 200000000001 */ +b = (b << 12) + 5; /* 400000000005 */ +/* use the most relevant arithmetic ops */ +c = a * b; +d = (c + b) / b; +/* return different values, to prevent optimizations */ +if (d != a+1) + return 0; +return 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv__128bit_int=yes +else + pgac_cv__128bit_int=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +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 + +$as_echo "#define PG_INT128_TYPE __int128" >>confdefs.h + +fi + # Check for various atomic operations now that we have checked how to declare # 64bit integers. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for builtin __sync char locking functions" >&5 diff --git a/configure.in b/configure.in index ca29e93eee..b2c1ce71d2 100644 --- a/configure.in +++ b/configure.in @@ -1771,6 +1771,9 @@ AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [], # C, but is missing on some old platforms. AC_CHECK_TYPES(sig_atomic_t, [], [], [#include ]) +# Check for extensions offering the integer scalar type __int128. +PGAC_TYPE_128BIT_INT + # Check for various atomic operations now that we have checked how to declare # 64bit integers. PGAC_HAVE_GCC__SYNC_CHAR_TAS diff --git a/src/include/c.h b/src/include/c.h index a2d4a2c5c5..744721860c 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -293,6 +293,17 @@ typedef unsigned long long int uint64; #define HAVE_INT64_TIMESTAMP #endif +/* + * 128-bit signed and unsigned integers + * There currently is only a limited support for the type. E.g. 128bit + * literals and snprintf are not supported; but math is. + */ +#if defined(PG_INT128_TYPE) +#define HAVE_INT128 +typedef PG_INT128_TYPE int128; +typedef unsigned PG_INT128_TYPE uint128; +#endif + /* sig_atomic_t is required by ANSI C, but may be missing on old platforms */ #ifndef HAVE_SIG_ATOMIC_T typedef int sig_atomic_t; diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index ece57c81cc..202c51a34a 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -711,6 +711,9 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION +/* Define to the name of a signed 128-bit integer type. */ +#undef PG_INT128_TYPE + /* Define to the name of a signed 64-bit integer type. */ #undef PG_INT64_TYPE diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32 index 3f858c658b..1baf64f005 100644 --- a/src/include/pg_config.h.win32 +++ b/src/include/pg_config.h.win32 @@ -562,6 +562,9 @@ /* Define to the version of this package. */ #define PACKAGE_VERSION "9.5devel" +/* Define to the name of a signed 128-bit integer type. */ +#undef PG_INT128_TYPE + /* Define to the name of a signed 64-bit integer type. */ #define PG_INT64_TYPE long long int -- 2.40.0