!2376 hashjoin细节优化

Merge pull request !2376 from wanghao19920907/PR_2299
This commit is contained in:
opengauss-bot 2023-02-28 08:11:14 +00:00 committed by Gitee
commit 5f7ad14378
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
19 changed files with 864 additions and 1006 deletions

View File

@ -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

270
configure vendored
View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -15,6 +15,7 @@
*/
#include "postgres.h"
#include "knl/knl_variable.h"
#include "port/pg_bitutils.h"
#include <math.h>
#include <limits.h>

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 <cpuid.h>
#endif
#ifdef HAVE__CPUID
#include <intrin.h>
#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;
}

View File

@ -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;
}

View File

@ -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
*/

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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