diff --git a/config/c-compiler.m4 b/config/c-compiler.m4 index 4aa3422aa..eabc89288 100644 --- a/config/c-compiler.m4 +++ b/config/c-compiler.m4 @@ -121,6 +121,34 @@ fi])# PGAC_C_FUNCNAME_SUPPORT +# PGAC_CHECK_BUILTIN_FUNC +# ----------------------- +# This is similar to AC_CHECK_FUNCS(), except that it will work for compiler +# builtin functions, as that usually fails to. +# The first argument is the function name, eg [__builtin_clzl], and the +# second is its argument list, eg [unsigned long x]. The current coding +# works only for a single argument named x; we might generalize that later. +# It's assumed that the function's result type is coercible to int. +# On success, we define "HAVEfuncname" (there's usually more than enough +# underscores already, so we don't add another one). +AC_DEFUN([PGAC_CHECK_BUILTIN_FUNC], +[AC_CACHE_CHECK(for $1, pgac_cv$1, +[AC_LINK_IFELSE([AC_LANG_PROGRAM([ +int +call$1($2) +{ + return $1(x); +}], [])], +[pgac_cv$1=yes], +[pgac_cv$1=no])]) +if test x"${pgac_cv$1}" = xyes ; then +AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE$1]), 1, + [Define to 1 if your compiler understands $1.]) +fi])# PGAC_CHECK_BUILTIN_FUNC + + + + # PGAC_PROG_CC_CFLAGS_OPT # ----------------------- # Given a string, check if the compiler supports the string as a diff --git a/configure b/configure index e5645dd75..e37058133 100755 --- a/configure +++ b/configure @@ -18226,9 +18226,47 @@ fi # On PPC, check if assembler supports LWARX instruction's mutex hint bit case $host_cpu in + x86_64) + # On x86_64, check if we can compile a popcntq instruction + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether assembler supports x86_64 popcntq" >&5 +$as_echo_n "checking whether assembler supports x86_64 popcntq... " >&6; } +if ${pgac_cv_have_x86_64_popcntq+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +long long x = 1; long long r; + __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x)); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + pgac_cv_have_x86_64_popcntq=yes +else + pgac_cv_have_x86_64_popcntq=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_have_x86_64_popcntq" >&5 +$as_echo "$pgac_cv_have_x86_64_popcntq" >&6; } + if test x"$pgac_cv_have_x86_64_popcntq" = xyes ; then + +$as_echo "#define HAVE_X86_64_POPCNTQ 1" >>confdefs.h + + fi + ;; + ppc*|powerpc*) { $as_echo "$as_me:$LINENO: checking whether assembler supports lwarx hint bit" >&5 $as_echo_n "checking whether assembler supports lwarx hint bit... " >&6; } +if ${pgac_cv_have_ppc_mutex_hint+:} false; then : + $as_echo_n "(cached) " >&6 +else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF @@ -18272,6 +18310,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi { $as_echo "$as_me:$LINENO: result: $pgac_cv_have_ppc_mutex_hint" >&5 $as_echo "$pgac_cv_have_ppc_mutex_hint" >&6; } if test x"$pgac_cv_have_ppc_mutex_hint" = xyes ; then @@ -24851,6 +24890,237 @@ cat >>confdefs.h <<_ACEOF #define SIZEOF_VOID_P $ac_cv_sizeof_void_p _ACEOF +# These typically are compiler builtins, for which AC_CHECK_FUNCS fails. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_bswap16" >&5 +$as_echo_n "checking for __builtin_bswap16... " >&6; } +if ${pgac_cv__builtin_bswap16+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +call__builtin_bswap16(int x) +{ + return __builtin_bswap16(x); +} +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv__builtin_bswap16=yes +else + pgac_cv__builtin_bswap16=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__builtin_bswap16" >&5 +$as_echo "$pgac_cv__builtin_bswap16" >&6; } +if test x"${pgac_cv__builtin_bswap16}" = xyes ; then + +cat >>confdefs.h <<_ACEOF +#define HAVE__BUILTIN_BSWAP16 1 +_ACEOF + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_bswap32" >&5 +$as_echo_n "checking for __builtin_bswap32... " >&6; } +if ${pgac_cv__builtin_bswap32+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +call__builtin_bswap32(int x) +{ + return __builtin_bswap32(x); +} +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv__builtin_bswap32=yes +else + pgac_cv__builtin_bswap32=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__builtin_bswap32" >&5 +$as_echo "$pgac_cv__builtin_bswap32" >&6; } +if test x"${pgac_cv__builtin_bswap32}" = xyes ; then + +cat >>confdefs.h <<_ACEOF +#define HAVE__BUILTIN_BSWAP32 1 +_ACEOF + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_bswap64" >&5 +$as_echo_n "checking for __builtin_bswap64... " >&6; } +if ${pgac_cv__builtin_bswap64+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +call__builtin_bswap64(long int x) +{ + return __builtin_bswap64(x); +} +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv__builtin_bswap64=yes +else + pgac_cv__builtin_bswap64=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__builtin_bswap64" >&5 +$as_echo "$pgac_cv__builtin_bswap64" >&6; } +if test x"${pgac_cv__builtin_bswap64}" = xyes ; then + +cat >>confdefs.h <<_ACEOF +#define HAVE__BUILTIN_BSWAP64 1 +_ACEOF + +fi +# We assume that we needn't test all widths of these explicitly: +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_clz" >&5 +$as_echo_n "checking for __builtin_clz... " >&6; } +if ${pgac_cv__builtin_clz+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +call__builtin_clz(unsigned int x) +{ + return __builtin_clz(x); +} +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv__builtin_clz=yes +else + pgac_cv__builtin_clz=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__builtin_clz" >&5 +$as_echo "$pgac_cv__builtin_clz" >&6; } +if test x"${pgac_cv__builtin_clz}" = xyes ; then + +cat >>confdefs.h <<_ACEOF +#define HAVE__BUILTIN_CLZ 1 +_ACEOF + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_ctz" >&5 +$as_echo_n "checking for __builtin_ctz... " >&6; } +if ${pgac_cv__builtin_ctz+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +call__builtin_ctz(unsigned int x) +{ + return __builtin_ctz(x); +} +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv__builtin_ctz=yes +else + pgac_cv__builtin_ctz=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__builtin_ctz" >&5 +$as_echo "$pgac_cv__builtin_ctz" >&6; } +if test x"${pgac_cv__builtin_ctz}" = xyes ; then + +cat >>confdefs.h <<_ACEOF +#define HAVE__BUILTIN_CTZ 1 +_ACEOF + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_popcount" >&5 +$as_echo_n "checking for __builtin_popcount... " >&6; } +if ${pgac_cv__builtin_popcount+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +call__builtin_popcount(unsigned int x) +{ + return __builtin_popcount(x); +} +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv__builtin_popcount=yes +else + pgac_cv__builtin_popcount=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__builtin_popcount" >&5 +$as_echo "$pgac_cv__builtin_popcount" >&6; } +if test x"${pgac_cv__builtin_popcount}" = xyes ; then + +cat >>confdefs.h <<_ACEOF +#define HAVE__BUILTIN_POPCOUNT 1 +_ACEOF + +fi + # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects diff --git a/configure.in b/configure.in index c0dff8fe3..d7b36c3ee 100644 --- a/configure.in +++ b/configure.in @@ -1186,6 +1186,19 @@ fi # On PPC, check if assembler supports LWARX instruction's mutex hint bit case $host_cpu in + x86_64) + # On x86_64, check if we can compile a popcntq instruction + AC_CACHE_CHECK([whether assembler supports x86_64 popcntq], + [pgac_cv_have_x86_64_popcntq], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], + [long long x = 1; long long r; + __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x));])], + [pgac_cv_have_x86_64_popcntq=yes], + [pgac_cv_have_x86_64_popcntq=no])]) + if test x"$pgac_cv_have_x86_64_popcntq" = xyes ; then + AC_DEFINE(HAVE_X86_64_POPCNTQ, 1, [Define to 1 if the assembler supports X86_64's POPCNTQ instruction.]) + fi + ;; ppc*|powerpc*) AC_MSG_CHECKING([whether assembler supports lwarx hint bit]) AC_TRY_COMPILE([], @@ -1234,6 +1247,9 @@ LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat readlink setproctitle setsid sigprocmask symlink sync_file_range towlower utime utimes waitpid wcstombs wcstombs_l]) +# We assume that we needn't test all widths of these explicitly: +PGAC_CHECK_BUILTIN_FUNC([__builtin_clz], [unsigned int x]) + AC_REPLACE_FUNCS(fseeko) case $host_os in # NetBSD uses a custom fseeko/ftello built on fsetpos/fgetpos diff --git a/contrib/intarray/_intbig_gist.cpp b/contrib/intarray/_intbig_gist.cpp index da41e0495..5ad6f04d9 100644 --- a/contrib/intarray/_intbig_gist.cpp +++ b/contrib/intarray/_intbig_gist.cpp @@ -6,6 +6,7 @@ #include "access/gist.h" #include "access/skey.h" +#include "port/pg_bitutils.h" #include "_int.h" @@ -29,264 +30,6 @@ extern "C" Datum g_intbig_picksplit(PG_FUNCTION_ARGS); extern "C" Datum g_intbig_union(PG_FUNCTION_ARGS); extern "C" Datum g_intbig_same(PG_FUNCTION_ARGS); -/* Number of one-bits in an unsigned byte */ -static const uint8 number_of_ones[256] = {0, - 1, - 1, - 2, - 1, - 2, - 2, - 3, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 5, - 6, - 6, - 7, - 6, - 7, - 7, - 8}; - PG_FUNCTION_INFO_V1(_intbig_in); extern "C" Datum _intbig_in(PG_FUNCTION_ARGS); @@ -428,11 +171,7 @@ Datum g_intbig_compress(PG_FUNCTION_ARGS) static int4 sizebitvec(BITVECP sign) { - int4 size = 0, i; - - LOOPBYTE - size += number_of_ones[(unsigned char)sign[i]]; - return size; + return pg_popcount(sign, SIGLEN); } static int hemdistsign(BITVECP a, BITVECP b) @@ -442,7 +181,8 @@ static int hemdistsign(BITVECP a, BITVECP b) LOOPBYTE { diff = (unsigned char)(a[i] ^ b[i]); - dist += number_of_ones[diff]; + /* Using the popcount functions here isn't likely to win */ + dist += pg_number_of_ones[diff]; } return dist; } diff --git a/contrib/ltree/_ltree_gist.cpp b/contrib/ltree/_ltree_gist.cpp index ee6d6bf6f..283fafcda 100644 --- a/contrib/ltree/_ltree_gist.cpp +++ b/contrib/ltree/_ltree_gist.cpp @@ -10,6 +10,7 @@ #include "access/gist.h" #include "access/skey.h" +#include "port/pg_bitutils.h" #include "crc32.h" #include "ltree.h" @@ -34,264 +35,6 @@ extern "C" Datum _ltree_consistent(PG_FUNCTION_ARGS); #define GETENTRY(vec, pos) ((ltree_gist*)DatumGetPointer((vec)->vector[(pos)].key)) #define NEXTVAL(x) ((ltree*)((char*)(x) + INTALIGN(VARSIZE(x)))) -/* Number of one-bits in an unsigned byte */ -static const uint8 number_of_ones[256] = {0, - 1, - 1, - 2, - 1, - 2, - 2, - 3, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 5, - 6, - 6, - 7, - 6, - 7, - 7, - 8}; - #define WISH_F(a, b, c) (double)(-(double)(((a) - (b)) * ((a) - (b)) * ((a) - (b))) * (c)) static void hashing(BITVECP sign, ltree* t) @@ -431,11 +174,7 @@ Datum _ltree_union(PG_FUNCTION_ARGS) static int4 sizebitvec(BITVECP sign) { - int4 size = 0, i; - - ALOOPBYTE - size += number_of_ones[(unsigned char)sign[i]]; - return size; + return pg_popcount((const char *) sign, ASIGLEN); } static int hemdistsign(BITVECP a, BITVECP b) @@ -445,7 +184,8 @@ static int hemdistsign(BITVECP a, BITVECP b) ALOOPBYTE { diff = (unsigned char)(a[i] ^ b[i]); - dist += number_of_ones[diff]; + /* Using the popcount functions here isn't likely to win */ + dist += pg_number_of_ones[diff]; } return dist; } diff --git a/contrib/pg_trgm/trgm_gist.cpp b/contrib/pg_trgm/trgm_gist.cpp index af5a1463a..8e2507f19 100644 --- a/contrib/pg_trgm/trgm_gist.cpp +++ b/contrib/pg_trgm/trgm_gist.cpp @@ -3,6 +3,7 @@ */ #include "postgres.h" #include "knl/knl_variable.h" +#include "port/pg_bitutils.h" #include "trgm.h" @@ -40,264 +41,6 @@ extern "C" Datum gtrgm_picksplit(PG_FUNCTION_ARGS); #define GETENTRY(vec, pos) ((TRGM*)DatumGetPointer((vec)->vector[(pos)].key)) -/* Number of one-bits in an unsigned byte */ -static const uint8 number_of_ones[256] = {0, - 1, - 1, - 2, - 1, - 2, - 2, - 3, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 1, - 2, - 2, - 3, - 2, - 3, - 3, - 4, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 2, - 3, - 3, - 4, - 3, - 4, - 4, - 5, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 3, - 4, - 4, - 5, - 4, - 5, - 5, - 6, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 4, - 5, - 5, - 6, - 5, - 6, - 6, - 7, - 5, - 6, - 6, - 7, - 6, - 7, - 7, - 8}; - Datum gtrgm_in(PG_FUNCTION_ARGS) { elog(ERROR, "not implemented"); @@ -677,11 +420,7 @@ Datum gtrgm_same(PG_FUNCTION_ARGS) static int4 sizebitvec(BITVECP sign) { - int4 size = 0, i; - - LOOPBYTE - size += number_of_ones[(unsigned char)sign[i]]; - return size; + return pg_popcount(sign, SIGLEN); } static int hemdistsign(BITVECP a, BITVECP b) @@ -691,7 +430,8 @@ static int hemdistsign(BITVECP a, BITVECP b) LOOPBYTE { diff = (unsigned char)(a[i] ^ b[i]); - dist += number_of_ones[diff]; + /* Using the popcount functions here isn't likely to win */ + dist += pg_number_of_ones[diff]; } return dist; } diff --git a/src/common/backend/nodes/bitmapset.cpp b/src/common/backend/nodes/bitmapset.cpp index 6f354a4d2..67157a77d 100644 --- a/src/common/backend/nodes/bitmapset.cpp +++ b/src/common/backend/nodes/bitmapset.cpp @@ -20,6 +20,7 @@ */ #include "postgres.h" #include "knl/knl_variable.h" +#include "port/pg_bitutils.h" #include "access/hash.h" @@ -49,35 +50,18 @@ #define HAS_MULTIPLE_ONES(x) ((bitmapword)RIGHTMOST_ONE(x) != (x)) -/* - * Lookup tables to avoid need for bit-by-bit groveling - * - * rightmost_one_pos[x] gives the bit number (0-7) of the rightmost one bit - * in a nonzero byte value x. The entry for x=0 is never used. - * - * number_of_ones[x] gives the number of one-bits (0-8) in a byte value x. - * - * We could make these tables larger and reduce the number of iterations - * in the functions that use them, but bytewise shifts and masks are - * especially fast on many machines, so working a byte at a time seems best. - */ -static const uint8 rightmost_one_pos[256] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, - 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, - 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, - 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, - 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, - 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, - 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, - 0, 1, 0}; - -static const uint8 number_of_ones[256] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, - 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, - 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, - 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, - 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, - 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, - 7, 8}; +/* Select appropriate bit-twiddling functions for bitmap word size */ +#if BITS_PER_BITMAPWORD == 32 +#define bmw_leftmost_one_pos(w) pg_leftmost_one_pos32(w) +#define bmw_rightmost_one_pos(w) pg_rightmost_one_pos32(w) +#define bmw_popcount(w) pg_popcount32(w) +#elif BITS_PER_BITMAPWORD == 64 +#define bmw_leftmost_one_pos(w) pg_leftmost_one_pos64(w) +#define bmw_rightmost_one_pos(w) pg_rightmost_one_pos64(w) +#define bmw_popcount(w) pg_popcount64(w) +#else +#error "invalid BITS_PER_BITMAPWORD" +#endif /* * bms_copy - make a palloc'd copy of a bitmapset @@ -478,11 +462,7 @@ int bms_singleton_member(const Bitmapset* a) (errmodule(MOD_CACHE), errcode(ERRCODE_DATA_EXCEPTION), errmsg("bitmapset has multiple members"))); } result = wordnum * BITS_PER_BITMAPWORD; - while ((w & 255) == 0) { - w >>= 8; - result += 8; - } - result += rightmost_one_pos[w & 255]; + result += bmw_rightmost_one_pos(w); } } if (result < 0) { @@ -507,11 +487,9 @@ int bms_num_members(const Bitmapset* a) for (wordnum = 0; wordnum < nwords; wordnum++) { bitmapword w = a->words[wordnum]; - /* we assume here that bitmapword is an unsigned type */ - while (w != 0) { - result += number_of_ones[w & 255]; - w >>= 8; - } + /* No need to count the bits in a zero word */ + if (w != 0) + result += bmw_popcount(w); } return result; } @@ -795,11 +773,7 @@ int bms_first_member(Bitmapset* a) a->words[wordnum] &= ~w; result = wordnum * BITS_PER_BITMAPWORD; - while ((w & 255) == 0) { - w >>= 8; - result += 8; - } - result += rightmost_one_pos[w & 255]; + result += bmw_rightmost_one_pos(w); return result; } } @@ -880,11 +854,7 @@ int bms_next_member(const Bitmapset* a, int prevbit) int result; result = wordnum * BITS_PER_BITMAPWORD; - while ((w & 255) == 0) { - w >>= 8; - result += 8; - } - result += rightmost_one_pos[w & 255]; + result += bmw_rightmost_one_pos(w); return result; } @@ -926,7 +896,7 @@ bool bms_get_singleton_member(const Bitmapset *a, int *member) w >>= BYTE_NUMBER; result += BYTE_NUMBER; } - result += rightmost_one_pos[w & BYTE_VALUE]; + result += bmw_rightmost_one_pos(w); } } if (result < 0) { @@ -962,7 +932,7 @@ int bms_member_index(const Bitmapset *a, int x) /* No need to count the bits in a zero word */ if (w != 0) { - result += number_of_ones[w & BYTE_VALUE]; + result += bmw_popcount(w); w >>= BYTE_NUMBER; } } @@ -975,7 +945,7 @@ int bms_member_index(const Bitmapset *a, int x) */ mask = ((bitmapword)1 << bitnum) - 1; bitmapword tmp = a->words[wordnum] & mask; - result += number_of_ones[tmp & BYTE_VALUE]; + result += bmw_popcount(tmp); tmp >>= BYTE_NUMBER; return result; diff --git a/src/common/backend/utils/adt/numutils.cpp b/src/common/backend/utils/adt/numutils.cpp index 562adab71..a248a6593 100644 --- a/src/common/backend/utils/adt/numutils.cpp +++ b/src/common/backend/utils/adt/numutils.cpp @@ -15,6 +15,7 @@ */ #include "postgres.h" #include "knl/knl_variable.h" +#include "port/pg_bitutils.h" #include #include diff --git a/src/common/backend/utils/adt/tsgistidx.cpp b/src/common/backend/utils/adt/tsgistidx.cpp index 45273dd81..192d0282a 100644 --- a/src/common/backend/utils/adt/tsgistidx.cpp +++ b/src/common/backend/utils/adt/tsgistidx.cpp @@ -14,6 +14,7 @@ #include "postgres.h" #include "knl/knl_variable.h" +#include "port/pg_bitutils.h" #include "access/gist.h" #include "access/tuptoaster.h" @@ -68,15 +69,6 @@ typedef struct { #define GETARR(x) ((int4*)((char*)(x) + GTHDRSIZE)) #define ARRNELEM(x) ((VARSIZE(x) - GTHDRSIZE) / sizeof(int4)) -/* Number of one-bits in an unsigned byte */ -static const uint8 number_of_ones[256] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, - 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, - 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, - 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, - 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, - 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, - 7, 8}; static int4 sizebitvec(BITVECP sign); @@ -430,12 +422,7 @@ Datum gtsvector_same(PG_FUNCTION_ARGS) static int4 sizebitvec(BITVECP sign) { - int4 size = 0; - uint32 i; - - LOOPBYTE - size += number_of_ones[(unsigned char)sign[i]]; - return size; + return pg_popcount(sign, SIGLEN); } static int hemdistsign(BITVECP a, BITVECP b) @@ -446,7 +433,8 @@ static int hemdistsign(BITVECP a, BITVECP b) LOOPBYTE { diff = (unsigned char)((unsigned char)a[i] ^ (unsigned char)b[i]); - dist += number_of_ones[diff]; + /* Using the popcount functions here isn't likely to win */ + dist += pg_number_of_ones[diff]; } return dist; } diff --git a/src/common/backend/utils/mmgr/aset.cpp b/src/common/backend/utils/mmgr/aset.cpp index 7896f3d70..f33d88b18 100644 --- a/src/common/backend/utils/mmgr/aset.cpp +++ b/src/common/backend/utils/mmgr/aset.cpp @@ -67,6 +67,7 @@ #include "postgres.h" #include "knl/knl_variable.h" +#include "port/pg_bitutils.h" #include "utils/dynahash.h" #include "utils/memutils.h" #include "utils/mmpool.h" @@ -157,43 +158,6 @@ typedef struct AllocMagicData { #define AllocPointerGetChunk(ptr) ((AllocChunk)(((char*)(ptr)) - ALLOC_CHUNKHDRSZ)) #define AllocChunkGetPointer(chk) ((AllocPointer)(((char*)(chk)) + ALLOC_CHUNKHDRSZ)) -/* - * Table for AllocSetFreeIndex - */ -#define LT16(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n - -static const unsigned char LogTable256[256] = {0, - 1, - 2, - 2, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - LT16(5), - LT16(6), - LT16(6), - LT16(7), - LT16(7), - LT16(7), - LT16(7), - LT16(8), - LT16(8), - LT16(8), - LT16(8), - LT16(8), - LT16(8), - LT16(8), - LT16(8)}; - /* ---------- * Debug macros * ---------- @@ -226,23 +190,40 @@ static const unsigned char LogTable256[256] = {0, static inline int AllocSetFreeIndex(Size size) { int idx; - unsigned int t, tsize; if (size > (1 << ALLOC_MINBITS)) { - tsize = (size - 1) >> ALLOC_MINBITS; + /*---------- + * At this point we must compute ceil(log2(size >> ALLOC_MINBITS)). + * This is the same as + * pg_leftmost_one_pos32((size - 1) >> ALLOC_MINBITS) + 1 + * or equivalently + * pg_leftmost_one_pos32(size - 1) - ALLOC_MINBITS + 1 + * + * However, rather than just calling that function, we duplicate the + * logic here, allowing an additional optimization. It's reasonable + * to assume that ALLOC_CHUNK_LIMIT fits in 16 bits, so we can unroll + * the byte-at-a-time loop in pg_leftmost_one_pos32 and just handle + * the last two bytes. + * + * Yes, this function is enough of a hot-spot to make it worth this + * much trouble. + *---------- + */ +#ifdef HAVE__BUILTIN_CLZ + idx = 31 - __builtin_clz((uint32) size - 1) - ALLOC_MINBITS + 1; +#else + uint32 t, + tsize; - /* - * At this point we need to obtain log2(tsize)+1, ie, the number of - * not-all-zero bits at the right. We used to do this with a - * shift-and-count loop, but this function is enough of a hotspot to - * justify micro-optimization effort. The best approach seems to be - * to use a lookup table. Note that this code assumes that - * ALLOCSET_NUM_FREELISTS <= 17, since we only cope with two bytes of - * the tsize value. - */ - t = tsize >> 8; - idx = t ? (LogTable256[t] + 8) : LogTable256[tsize]; + /* Statically assert that we only have a 16-bit input value. */ + StaticAssertStmt(ALLOC_CHUNK_LIMIT < (1 << 16), + "ALLOC_CHUNK_LIMIT must be less than 64kB"); + tsize = size - 1; + t = tsize >> 8; + idx = t ? pg_leftmost_one_pos[t] + 8 : pg_leftmost_one_pos[tsize]; + idx -= ALLOC_MINBITS - 1; +#endif Assert(idx < ALLOCSET_NUM_FREELISTS); } else idx = 0; diff --git a/src/common/port/CMakeLists.txt b/src/common/port/CMakeLists.txt index 735339d33..58e05213d 100755 --- a/src/common/port/CMakeLists.txt +++ b/src/common/port/CMakeLists.txt @@ -18,6 +18,7 @@ execute_process( COMMAND ln -fs ${CMAKE_CURRENT_SOURCE_DIR}/inet_net_ntop.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/inet_net_ntop.cpp COMMAND ln -fs ${CMAKE_CURRENT_SOURCE_DIR}/noblock.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/noblock.cpp COMMAND ln -fs ${CMAKE_CURRENT_SOURCE_DIR}/path.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/path.cpp + COMMAND ln -fs ${CMAKE_CURRENT_SOURCE_DIR}/pg_bitutils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/pg_bitutils.cpp COMMAND ln -fs ${CMAKE_CURRENT_SOURCE_DIR}/pgcheckdir.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/pgcheckdir.cpp COMMAND ln -fs ${CMAKE_CURRENT_SOURCE_DIR}/pgmkdirp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/pgmkdirp.cpp COMMAND ln -fs ${CMAKE_CURRENT_SOURCE_DIR}/pgsleep.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/pgsleep.cpp @@ -58,7 +59,8 @@ list(APPEND TGT_port_SRC ${CMAKE_CURRENT_SOURCE_DIR}/exec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/inet_net_ntop.cpp ${CMAKE_CURRENT_SOURCE_DIR}/noblock.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/path.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/path.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/pg_bitutils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pgcheckdir.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pgmkdirp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pgsleep.cpp @@ -127,7 +129,8 @@ list(APPEND TGT_pgport_srv_SRC ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/exec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/inet_net_ntop.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/noblock.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/path.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/path.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/pg_bitutils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/pgcheckdir.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/pgmkdirp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/port_srv/pgsleep.cpp @@ -191,6 +194,7 @@ set(TGT_pgport_tool_SRC ${CMAKE_CURRENT_SOURCE_DIR}/inet_net_ntop.cpp ${CMAKE_CURRENT_SOURCE_DIR}/noblock.cpp ${CMAKE_CURRENT_SOURCE_DIR}/path.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/pg_bitutils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pgcheckdir.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pgmkdirp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pgsleep.cpp diff --git a/src/common/port/Makefile b/src/common/port/Makefile index 8911d6f8c..38bdcf7bd 100644 --- a/src/common/port/Makefile +++ b/src/common/port/Makefile @@ -45,7 +45,7 @@ ifneq "$(MAKECMDGOALS)" "clean" endif OBJS = $(LIBOBJS) pg_crc32c_sse42.o pg_crc32c_sb8.o pg_crc32c_choose.o chklocale.o dirmod.o erand48.o exec.o fls.o inet_net_ntop.o \ - noblock.o path.o pgcheckdir.o pgmkdirp.o pgsleep.o \ + noblock.o path.o pg_bitutils.o pgcheckdir.o pgmkdirp.o pgsleep.o \ pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o flock.o pgstrcasestr.o\ gs_thread.o gs_env_r.o gs_getopt_r.o \ gs_readdir.o gs_strerror.o gs_syscall_lock.o \ @@ -55,7 +55,7 @@ OBJS = $(LIBOBJS) pg_crc32c_sse42.o pg_crc32c_sb8.o pg_crc32c_choose.o chklocale ifeq "${host_cpu}" "aarch64" OBJS = $(LIBOBJS) pg_crc32c_choose.o chklocale.o dirmod.o erand48.o exec.o fls.o inet_net_ntop.o \ - noblock.o path.o pgcheckdir.o pgmkdirp.o pgsleep.o \ + noblock.o path.o pg_bitutils.o pgcheckdir.o pgmkdirp.o pgsleep.o \ pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o flock.o pgstrcasestr.o\ gs_thread.o gs_env_r.o gs_getopt_r.o \ gs_readdir.o gs_strerror.o gs_syscall_lock.o \ @@ -73,7 +73,7 @@ ifeq "${host_cpu}" "aarch64" endif OBJS_TOOL = fls.o strlcat.o strlcpy.o getpeereid.o chklocale.o dirmod.o erand48.o exec.o inet_net_ntop.o \ - noblock.o path.o pgcheckdir.o pgmkdirp.o pgsleep.o pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o flock.o pgstrcasestr.o \ + noblock.o path.o pg_bitutils.o pgcheckdir.o pgmkdirp.o pgsleep.o pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o flock.o pgstrcasestr.o \ gs_thread.o gs_env_r.o gs_getopt_r.o gs_readdir.o gs_strerror.o gs_syscall_lock.o gs_system.o cipher.o \ $(top_builddir)/src/gausskernel/storage/file/fio_device.o $(top_builddir)/src/gausskernel/storage/dss/fio_dss.o tool_common.o diff --git a/src/common/port/pg_bitutils.cpp b/src/common/port/pg_bitutils.cpp new file mode 100644 index 000000000..adc75f6d0 --- /dev/null +++ b/src/common/port/pg_bitutils.cpp @@ -0,0 +1,308 @@ +/*------------------------------------------------------------------------- + * + * pg_bitutils.c + * Miscellaneous functions for bit-wise operations. + * + * Copyright (c) 2019-2021, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/common/port/pg_bitutils.cpp + * + *------------------------------------------------------------------------- + */ +#include "c.h" + +#ifdef HAVE__GET_CPUID +#include +#endif +#ifdef HAVE__CPUID +#include +#endif + +#ifdef FRONTEND +#include "postgres_fe.h" +#else +#include "postgres.h" +#endif + +#include "port/pg_bitutils.h" + +#ifndef Assert +#define Assert(x) assert(x) +#endif + +/* + * Array giving the position of the left-most set bit for each possible + * byte value. We count the right-most position as the 0th bit, and the + * left-most the 7th bit. The 0th entry of the array should not be used. + * + * Note: this is not used by the functions in pg_bitutils.h when + * HAVE__BUILTIN_CLZ is defined, but we provide it anyway, so that + * extensions possibly compiled with a different compiler can use it. + */ +const uint8 pg_leftmost_one_pos[256] = { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +}; + +/* + * Array giving the position of the right-most set bit for each possible + * byte value. We count the right-most position as the 0th bit, and the + * left-most the 7th bit. The 0th entry of the array should not be used. + * + * Note: this is not used by the functions in pg_bitutils.h when + * HAVE__BUILTIN_CTZ is defined, but we provide it anyway, so that + * extensions possibly compiled with a different compiler can use it. + */ +const uint8 pg_rightmost_one_pos[256] = { + 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* + * Array giving the number of 1-bits in each possible byte value. + * + * Note: we export this for use by functions in which explicit use + * of the popcount functions seems unlikely to be a win. + */ +const uint8 pg_number_of_ones[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; + +/* + * On x86_64, we can use the hardware popcount instruction, but only if + * we can verify that the CPU supports it via the cpuid instruction. + * + * Otherwise, we fall back to __builtin_popcount if the compiler has that, + * or a hand-rolled implementation if not. + */ +#ifdef HAVE_X86_64_POPCNTQ +#if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID) +#define USE_POPCNT_ASM 1 +#endif +#endif + +static int pg_popcount32_slow(uint32 word); +static int pg_popcount64_slow(uint64 word); + +#ifdef USE_POPCNT_ASM +static bool pg_popcount_available(void); +static int pg_popcount32_choose(uint32 word); +static int pg_popcount64_choose(uint64 word); +static int pg_popcount32_asm(uint32 word); +static int pg_popcount64_asm(uint64 word); + +int (*pg_popcount32)(uint32 word) = pg_popcount32_choose; +int (*pg_popcount64)(uint64 word) = pg_popcount64_choose; +#else +int (*pg_popcount32)(uint32 word) = pg_popcount32_slow; +int (*pg_popcount64)(uint64 word) = pg_popcount64_slow; +#endif /* USE_POPCNT_ASM */ + +#ifdef USE_POPCNT_ASM + +/* + * Return true if CPUID indicates that the POPCNT instruction is available. + */ +static bool pg_popcount_available(void) +{ + unsigned int exx[4] = {0, 0, 0, 0}; + +#if defined(HAVE__GET_CPUID) + __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); +#elif defined(HAVE__CPUID) + __cpuid(exx, 1); +#else +#error cpuid instruction not available +#endif + + return (exx[2] & (1 << 23)) != 0; /* POPCNT */ +} + +/* + * These functions get called on the first call to pg_popcount32 etc. + * They detect whether we can use the asm implementations, and replace + * the function pointers so that subsequent calls are routed directly to + * the chosen implementation. + */ +static int pg_popcount32_choose(uint32 word) +{ + if (pg_popcount_available()) { + pg_popcount32 = pg_popcount32_asm; + pg_popcount64 = pg_popcount64_asm; + } else { + pg_popcount32 = pg_popcount32_slow; + pg_popcount64 = pg_popcount64_slow; + } + + return pg_popcount32(word); +} + +static int pg_popcount64_choose(uint64 word) +{ + if (pg_popcount_available()) { + pg_popcount32 = pg_popcount32_asm; + pg_popcount64 = pg_popcount64_asm; + } else { + pg_popcount32 = pg_popcount32_slow; + pg_popcount64 = pg_popcount64_slow; + } + + return pg_popcount64(word); +} + +/* + * pg_popcount32_asm + * Return the number of 1 bits set in word + */ +static int pg_popcount32_asm(uint32 word) +{ + uint32 res; + + __asm__ __volatile__(" popcntl %1,%0\n" : "=q"(res) : "rm"(word) : "cc"); + return (int)res; +} + +/* + * pg_popcount64_asm + * Return the number of 1 bits set in word + */ +static int pg_popcount64_asm(uint64 word) +{ + uint64 res; + + __asm__ __volatile__(" popcntq %1,%0\n" : "=q"(res) : "rm"(word) : "cc"); + return (int)res; +} + +#endif /* USE_POPCNT_ASM */ + +/* + * pg_popcount32_slow + * Return the number of 1 bits set in word + */ +static int pg_popcount32_slow(uint32 word) +{ +#ifdef HAVE__BUILTIN_POPCOUNT + return __builtin_popcount(word); +#else /* !HAVE__BUILTIN_POPCOUNT */ + int result = 0; + + while (word != 0) { + result += pg_number_of_ones[word & 255]; + word >>= 8; + } + + return result; +#endif /* HAVE__BUILTIN_POPCOUNT */ +} + +/* + * pg_popcount64_slow + * Return the number of 1 bits set in word + */ +static int pg_popcount64_slow(uint64 word) +{ +#ifdef HAVE__BUILTIN_POPCOUNT +#if defined(HAVE_LONG_INT_64) + return __builtin_popcountl(word); +#elif defined(HAVE_LONG_LONG_INT_64) + return __builtin_popcountll(word); +#else +#error must have a working 64-bit integer datatype +#endif +#else /* !HAVE__BUILTIN_POPCOUNT */ + int result = 0; + + while (word != 0) { + result += pg_number_of_ones[word & 255]; + word >>= 8; + } + + return result; +#endif /* HAVE__BUILTIN_POPCOUNT */ +} + +/* + * pg_popcount + * Returns the number of 1-bits in buf + */ +uint64 pg_popcount(const char *buf, int bytes) +{ + uint64 popcnt = 0; + +#if SIZEOF_VOID_P >= 8 + /* Process in 64-bit chunks if the buffer is aligned. */ + if (buf == (const char *)TYPEALIGN(8, buf)) { + const uint64 *words = (const uint64 *)buf; + + while (bytes >= 8) { + popcnt += pg_popcount64(*words++); + bytes -= 8; + } + + buf = (const char *)words; + } +#else + /* Process in 32-bit chunks if the buffer is aligned. */ + if (buf == (const char *)TYPEALIGN(4, buf)) { + const uint32 *words = (const uint32 *)buf; + + while (bytes >= 4) { + popcnt += pg_popcount32(*words++); + bytes -= 4; + } + + buf = (const char *)words; + } +#endif + + /* Process any remaining bytes */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char)*buf++]; + + return popcnt; +} diff --git a/src/gausskernel/runtime/executor/nodeHash.cpp b/src/gausskernel/runtime/executor/nodeHash.cpp index 2c9fd5523..5bc0c4993 100644 --- a/src/gausskernel/runtime/executor/nodeHash.cpp +++ b/src/gausskernel/runtime/executor/nodeHash.cpp @@ -44,6 +44,7 @@ #include "utils/memutils.h" #include "utils/selfuncs.h" #include "utils/syscache.h" +#include "utils/hashutils.h" #include "vecexecutor/vechashtable.h" #include "vectorsonic/vsonicarray.h" #include "vectorsonic/vsonichash.h" @@ -1410,8 +1411,7 @@ bool ExecHashGetHashValue(HashJoinTable hashtable, ExprContext* econtext, List* } MemoryContextSwitchTo(oldContext); - hashkey = DatumGetUInt32(hash_uint32(hashkey)); - *hashvalue = hashkey; + *hashvalue = murmurhash32(hashkey); return true; } diff --git a/src/gausskernel/runtime/executor/nodeHashjoin.cpp b/src/gausskernel/runtime/executor/nodeHashjoin.cpp index 02dc75bd2..eb9a01deb 100755 --- a/src/gausskernel/runtime/executor/nodeHashjoin.cpp +++ b/src/gausskernel/runtime/executor/nodeHashjoin.cpp @@ -303,14 +303,6 @@ static TupleTableSlot* ExecHashJoin(PlanState* state) /* fall through */ case HJ_SCAN_BUCKET: - - /* - * We check for interrupts here because this corresponds to - * where we'd fetch a row from a child plan node in other join - * types. - */ - CHECK_FOR_INTERRUPTS(); - /* * Scan the selected hash bucket for matches to current outer */ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 07c4a0fae..71598f793 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -670,6 +670,18 @@ /* Define to build with Kerberos 5 support. (--with-krb5) */ #undef KRB5 +/* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */ +#undef HAVE_X86_64_POPCNTQ + +/* Define to 1 if your compiler understands __builtin_clz. */ +#undef HAVE__BUILTIN_CLZ + +/* Define to 1 if your compiler understands __builtin_ctz. */ +#undef HAVE__BUILTIN_CTZ + +/* Define to 1 if your compiler understands __builtin_popcount. */ +#undef HAVE__BUILTIN_POPCOUNT + /* Define to 1 if you have __cpuid. */ #undef HAVE__CPUID diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h new file mode 100644 index 000000000..940da8257 --- /dev/null +++ b/src/include/port/pg_bitutils.h @@ -0,0 +1,147 @@ +/*------------------------------------------------------------------------- + * + * pg_bitutils.h + * Miscellaneous functions for bit-wise operations. + * + * + * Copyright (c) 2019-2021, PostgreSQL Global Development Group + * + * src/include/port/pg_bitutils.h + * + *------------------------------------------------------------------------- + */ +#ifndef PG_BITUTILS_H +#define PG_BITUTILS_H + +#ifndef FRONTEND +extern PGDLLIMPORT const uint8 pg_leftmost_one_pos[256]; +extern PGDLLIMPORT const uint8 pg_rightmost_one_pos[256]; +extern PGDLLIMPORT const uint8 pg_number_of_ones[256]; +#else +extern const uint8 pg_leftmost_one_pos[256]; +extern const uint8 pg_rightmost_one_pos[256]; +extern const uint8 pg_number_of_ones[256]; +#endif + +/* + * pg_leftmost_one_pos32 + * Returns the position of the most significant set bit in "word", + * measured from the least significant bit. word must not be 0. + */ +static inline int pg_leftmost_one_pos32(uint32 word) +{ +#ifdef HAVE__BUILTIN_CLZ + Assert(word != 0); + + return 31 - __builtin_clz(word); +#else + int shift = 32 - 8; + + Assert(word != 0); + + while ((word >> shift) == 0) + shift -= 8; + + return shift + pg_leftmost_one_pos[(word >> shift) & 255]; +#endif /* HAVE__BUILTIN_CLZ */ +} + +/* + * pg_leftmost_one_pos64 + * As above, but for a 64-bit word. + */ +static inline int pg_leftmost_one_pos64(uint64 word) +{ +#ifdef HAVE__BUILTIN_CLZ + Assert(word != 0); + +#if defined(HAVE_LONG_INT_64) + return 63 - __builtin_clzl(word); +#elif defined(HAVE_LONG_LONG_INT_64) + return 63 - __builtin_clzll(word); +#else +#error must have a working 64-bit integer datatype +#endif +#else /* !HAVE__BUILTIN_CLZ */ + int shift = 64 - 8; + + Assert(word != 0); + + while ((word >> shift) == 0) + shift -= 8; + + return shift + pg_leftmost_one_pos[(word >> shift) & 255]; +#endif /* HAVE__BUIILTIN_CLZ */ +} + +/* + * pg_rightmost_one_pos32 + * Returns the position of the least significant set bit in "word", + * measured from the least significant bit. word must not be 0. + */ +static inline int pg_rightmost_one_pos32(uint32 word) +{ +#ifdef HAVE__BUILTIN_CTZ + Assert(word != 0); + + return __builtin_ctz(word); +#else + int result = 0; + + Assert(word != 0); + + while ((word & 255) == 0) { + word >>= 8; + result += 8; + } + result += pg_rightmost_one_pos[word & 255]; + return result; +#endif /* HAVE__BUILTIN_CTZ */ +} + +/* + * pg_rightmost_one_pos64 + * As above, but for a 64-bit word. + */ +static inline int pg_rightmost_one_pos64(uint64 word) +{ +#ifdef HAVE__BUILTIN_CTZ + Assert(word != 0); + +#if defined(HAVE_LONG_INT_64) + return __builtin_ctzl(word); +#elif defined(HAVE_LONG_LONG_INT_64) + return __builtin_ctzll(word); +#else +#error must have a working 64-bit integer datatype +#endif +#else /* !HAVE__BUILTIN_CTZ */ + int result = 0; + + Assert(word != 0); + + while ((word & 255) == 0) { + word >>= 8; + result += 8; + } + result += pg_rightmost_one_pos[word & 255]; + return result; +#endif /* HAVE__BUILTIN_CTZ */ +} + +/* Count the number of one-bits in a uint32 or uint64 */ +extern int (*pg_popcount32)(uint32 word); +extern int (*pg_popcount64)(uint64 word); + +/* Count the number of one-bits in a byte array */ +extern uint64 pg_popcount(const char *buf, int bytes); + +/* + * Rotate the bits of "word" to the right by n bits. + */ +static inline uint32 pg_rotate_right32(uint32 word, int n) +{ + return (word >> n) | (word << (sizeof(word) * BITS_PER_BYTE - n)); +} + +#endif /* PG_BITUTILS_H */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 89a1aac49..c16eac863 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -25,34 +25,6 @@ #endif #include "utils/sortsupport.h" -/* - * Array giving the position of the left-most set bit for each possible - * byte value. We count the right-most position as the 0th bit, and the - * left-most the 7th bit. The 0th entry of the array should not be used. - * - * Note: this is not used by the functions in pg_bitutils.h when - * HAVE__BUILTIN_CLZ is defined, but we provide it anyway, so that - * extensions possibly compiled with a different compiler can use it. - */ -const uint8 pg_leftmost_one_pos[256] = { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 -}; - /* * Defined in adt/ */ @@ -1843,59 +1815,8 @@ extern Datum compress_statistic_info(PG_FUNCTION_ARGS); extern Datum pg_read_binary_file_blocks(PG_FUNCTION_ARGS); #else -/* - * Array giving the position of the left-most set bit for each possible - * byte value. We count the right-most position as the 0th bit, and the - * left-most the 7th bit. The 0th entry of the array should not be used. - * - * Note: this is not used by the functions in pg_bitutils.h when - * HAVE__BUILTIN_CLZ is defined, but we provide it anyway, so that - * extensions possibly compiled with a different compiler can use it. - */ -PGDLLIMPORT const uint8 pg_leftmost_one_pos[256] = { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 -}; #endif extern char *pg_ultostr(char *str, uint32 value); extern char *pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth); - -/* - * pg_leftmost_one_pos32 - * Returns the position of the most significant set bit in "word", - * measured from the least significant bit. word must not be 0. - */ -static inline int pg_leftmost_one_pos32(uint32 word) -{ -#ifdef HAVE__BUILTIN_CLZ - Assert(word != 0); - - return 31 - __builtin_clz(word); -#else - int shift = 32 - 8; - - Assert(word != 0); - - while ((word >> shift) == 0) - shift -= 8; - - return shift + pg_leftmost_one_pos[(word >> shift) & 255]; -#endif /* HAVE__BUILTIN_CLZ */ -} - #endif /* BUILTINS_H */ diff --git a/src/test/regress/expected/single_node_type_sanity.out b/src/test/regress/expected/single_node_type_sanity.out index adcd1e57f..9c61b7f07 100644 --- a/src/test/regress/expected/single_node_type_sanity.out +++ b/src/test/regress/expected/single_node_type_sanity.out @@ -69,11 +69,11 @@ WHERE p1.typtype not in ('c','d','p') AND p1.typname NOT LIKE E'\\_%' p2.typelem = p1.oid and p1.typarray = p2.oid) AND p1.typname not in ('desc_tab', 'date_table', 'number_table', 'varchar2_table'); oid | typname ------+------------------ - 3272 | anyset 32 | oidvector_extend 210 | smgr - 194 | pg_node_tree 705 | unknown + 3272 | anyset + 194 | pg_node_tree (5 rows) -- Make sure typarray points to a varlena array type of our own base