From 5db7d86a9a1b519ee8d8bdc5ce82a09f995cc929 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathandbossart@gmail.com>
Date: Mon, 20 Mar 2023 14:23:39 -0700
Subject: [PATCH v1 3/3] Add support for OpenBLAS.

If PostgreSQL is built with OpenBLAS support, euclidean_norm() and
dot_product() use the optimized OpenBLAS routines instead of the
open-coded formulas.
---
 configure                         | 269 ++++++++++++++++++++++++++++++
 configure.ac                      |  35 ++++
 doc/src/sgml/install-windows.sgml |   9 +
 doc/src/sgml/installation.sgml    |  19 +++
 meson.build                       |  21 +++
 meson_options.txt                 |   3 +
 src/Makefile.global.in            |   1 +
 src/backend/utils/adt/vector.c    |  12 ++
 src/include/pg_config.h.in        |   6 +
 src/makefiles/meson.build         |   1 +
 src/tools/msvc/Solution.pm        |  13 ++
 src/tools/msvc/config_default.pl  |   1 +
 12 files changed, 390 insertions(+)

diff --git a/configure b/configure
index 15daccc87f..d8f35ec6a3 100755
--- a/configure
+++ b/configure
@@ -649,6 +649,7 @@ PG_CRC32C_OBJS
 CFLAGS_CRC
 LIBOBJS
 OPENSSL
+OPENBLAS
 ZSTD
 LZ4
 UUID_LIBS
@@ -695,6 +696,9 @@ STRIP_STATIC_LIB
 STRIP
 LDFLAGS_SL
 LDFLAGS_EX
+OPENBLAS_LIBS
+OPENBLAS_CFLAGS
+with_openblas
 ZSTD_LIBS
 ZSTD_CFLAGS
 with_zstd
@@ -872,6 +876,7 @@ with_system_tzdata
 with_zlib
 with_lz4
 with_zstd
+with_openblas
 with_ssl
 with_openssl
 enable_largefile
@@ -902,6 +907,8 @@ LZ4_CFLAGS
 LZ4_LIBS
 ZSTD_CFLAGS
 ZSTD_LIBS
+OPENBLAS_CFLAGS
+OPENBLAS_LIBS
 LDFLAGS_EX
 LDFLAGS_SL
 PERL
@@ -1584,6 +1591,7 @@ Optional Packages:
   --without-zlib          do not use Zlib
   --with-lz4              build with LZ4 support
   --with-zstd             build with ZSTD support
+  --with-openblas         build with OpenBLAS support
   --with-ssl=LIB          use LIB for SSL/TLS support (openssl)
   --with-openssl          obsolete spelling of --with-ssl=openssl
 
@@ -1614,6 +1622,10 @@ Some influential environment variables:
   LZ4_LIBS    linker flags for LZ4, overriding pkg-config
   ZSTD_CFLAGS C compiler flags for ZSTD, overriding pkg-config
   ZSTD_LIBS   linker flags for ZSTD, overriding pkg-config
+  OPENBLAS_CFLAGS
+              C compiler flags for OPENBLAS, overriding pkg-config
+  OPENBLAS_LIBS
+              linker flags for OPENBLAS, overriding pkg-config
   LDFLAGS_EX  extra linker flags for linking executables only
   LDFLAGS_SL  extra linker flags for linking shared libraries only
   PERL        Perl program
@@ -9605,6 +9617,148 @@ fi
     esac
   done
 fi
+
+#
+# OpenBLAS
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with OpenBLAS support" >&5
+$as_echo_n "checking whether to build with OpenBLAS support... " >&6; }
+
+
+
+# Check whether --with-openblas was given.
+if test "${with_openblas+set}" = set; then :
+  withval=$with_openblas;
+  case $withval in
+    yes)
+
+$as_echo "#define USE_OPENBLAS 1" >>confdefs.h
+
+      ;;
+    no)
+      :
+      ;;
+    *)
+      as_fn_error $? "no argument expected for --with-openblas option" "$LINENO" 5
+      ;;
+  esac
+
+else
+  with_openblas=no
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_openblas" >&5
+$as_echo "$with_openblas" >&6; }
+
+
+if test "$with_openblas" = yes; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for openblas" >&5
+$as_echo_n "checking for openblas... " >&6; }
+
+if test -n "$OPENBLAS_CFLAGS"; then
+    pkg_cv_OPENBLAS_CFLAGS="$OPENBLAS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openblas\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "openblas") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_OPENBLAS_CFLAGS=`$PKG_CONFIG --cflags "openblas" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$OPENBLAS_LIBS"; then
+    pkg_cv_OPENBLAS_LIBS="$OPENBLAS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openblas\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "openblas") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_OPENBLAS_LIBS=`$PKG_CONFIG --libs "openblas" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        OPENBLAS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openblas" 2>&1`
+        else
+	        OPENBLAS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openblas" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$OPENBLAS_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (openblas) were not met:
+
+$OPENBLAS_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables OPENBLAS_CFLAGS
+and OPENBLAS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables OPENBLAS_CFLAGS
+and OPENBLAS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+	OPENBLAS_CFLAGS=$pkg_cv_OPENBLAS_CFLAGS
+	OPENBLAS_LIBS=$pkg_cv_OPENBLAS_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+  # We only care about -I, -D, and -L switches;
+  # note that -lopenblas will be added by AC_CHECK_LIB below.
+  for pgac_option in $OPENBLAS_CFLAGS; do
+    case $pgac_option in
+      -I*|-D*) CPPFLAGS="$CPPFLAGS $pgac_option";;
+    esac
+  done
+  for pgac_option in $OPENBLAS_LIBS; do
+    case $pgac_option in
+      -L*) LDFLAGS="$LDFLAGS $pgac_option";;
+    esac
+  done
+fi
+
 #
 # Assignments
 #
@@ -13276,6 +13430,56 @@ fi
 
 fi
 
+if test "$with_openblas" = yes ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cblas_dnrm2 in -lopenblas" >&5
+$as_echo_n "checking for cblas_dnrm2 in -lopenblas... " >&6; }
+if ${ac_cv_lib_openblas_cblas_dnrm2+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lopenblas  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char cblas_dnrm2 ();
+int
+main ()
+{
+return cblas_dnrm2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_openblas_cblas_dnrm2=yes
+else
+  ac_cv_lib_openblas_cblas_dnrm2=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_openblas_cblas_dnrm2" >&5
+$as_echo "$ac_cv_lib_openblas_cblas_dnrm2" >&6; }
+if test "x$ac_cv_lib_openblas_cblas_dnrm2" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBOPENBLAS 1
+_ACEOF
+
+  LIBS="-lopenblas $LIBS"
+
+else
+  as_fn_error $? "library 'openblas' is required for OPENBLAS support" "$LINENO" 5
+fi
+
+fi
+
 # Note: We can test for libldap_r only after we know PTHREAD_LIBS;
 # also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
@@ -14064,6 +14268,71 @@ else
 fi
 
 
+fi
+
+if test -z "$OPENBLAS"; then
+  for ac_prog in openblas
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_OPENBLAS+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $OPENBLAS in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_OPENBLAS="$OPENBLAS" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_OPENBLAS="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+OPENBLAS=$ac_cv_path_OPENBLAS
+if test -n "$OPENBLAS"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENBLAS" >&5
+$as_echo "$OPENBLAS" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$OPENBLAS" && break
+done
+
+else
+  # Report the value of OPENBLAS in configure's output in all cases.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENBLAS" >&5
+$as_echo_n "checking for OPENBLAS... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENBLAS" >&5
+$as_echo "$OPENBLAS" >&6; }
+fi
+
+if test "$with_openblas" = yes; then
+  ac_fn_c_check_header_mongrel "$LINENO" "cblas.h" "ac_cv_header_cblas_h" "$ac_includes_default"
+if test "x$ac_cv_header_cblas_h" = xyes; then :
+
+else
+  as_fn_error $? "cblas.h header file is required for OPENBLAS" "$LINENO" 5
+fi
+
+
 fi
 
 if test "$with_gssapi" = yes ; then
diff --git a/configure.ac b/configure.ac
index 97f5be6c73..e20ba144ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1147,6 +1147,32 @@ if test "$with_zstd" = yes; then
     esac
   done
 fi
+
+#
+# OpenBLAS
+#
+AC_MSG_CHECKING([whether to build with OpenBLAS support])
+PGAC_ARG_BOOL(with, openblas, no, [build with OpenBLAS support],
+              [AC_DEFINE([USE_OPENBLAS], 1, [Define to 1 to build with OpenBLAS support. (--with-openblas)])])
+AC_MSG_RESULT([$with_openblas])
+AC_SUBST(with_openblas)
+
+if test "$with_openblas" = yes; then
+  PKG_CHECK_MODULES(OPENBLAS, openblas)
+  # We only care about -I, -D, and -L switches;
+  # note that -lopenblas will be added by AC_CHECK_LIB below.
+  for pgac_option in $OPENBLAS_CFLAGS; do
+    case $pgac_option in
+      -I*|-D*) CPPFLAGS="$CPPFLAGS $pgac_option";;
+    esac
+  done
+  for pgac_option in $OPENBLAS_LIBS; do
+    case $pgac_option in
+      -L*) LDFLAGS="$LDFLAGS $pgac_option";;
+    esac
+  done
+fi
+
 #
 # Assignments
 #
@@ -1418,6 +1444,10 @@ if test "$with_zstd" = yes ; then
   AC_CHECK_LIB(zstd, ZSTD_compress, [], [AC_MSG_ERROR([library 'zstd' is required for ZSTD support])])
 fi
 
+if test "$with_openblas" = yes ; then
+  AC_CHECK_LIB(openblas, cblas_dnrm2, [], [AC_MSG_ERROR([library 'openblas' is required for OPENBLAS support])])
+fi
+
 # Note: We can test for libldap_r only after we know PTHREAD_LIBS;
 # also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
@@ -1563,6 +1593,11 @@ if test "$with_zstd" = yes; then
   AC_CHECK_HEADER(zstd.h, [], [AC_MSG_ERROR([zstd.h header file is required for ZSTD])])
 fi
 
+PGAC_PATH_PROGS(OPENBLAS, openblas)
+if test "$with_openblas" = yes; then
+  AC_CHECK_HEADER(cblas.h, [], [AC_MSG_ERROR([cblas.h header file is required for OPENBLAS])])
+fi
+
 if test "$with_gssapi" = yes ; then
   AC_CHECK_HEADERS(gssapi/gssapi.h, [],
 	[AC_CHECK_HEADERS(gssapi.h, [], [AC_MSG_ERROR([gssapi.h header file is required for GSSAPI])])])
diff --git a/doc/src/sgml/install-windows.sgml b/doc/src/sgml/install-windows.sgml
index cbc70a039c..a6409913d5 100644
--- a/doc/src/sgml/install-windows.sgml
+++ b/doc/src/sgml/install-windows.sgml
@@ -309,6 +309,15 @@ $ENV{MSBFLAGS}="/m";
      </para></listitem>
     </varlistentry>
 
+    <varlistentry>
+     <term><productname>OpenBLAS</productname></term>
+     <listitem><para>
+      Required for supporting optimized linear algebra routines using
+      <productname>OpenBLAS</productname>.  Binaries and source can be
+      downloaded from <ulink url="https://www.openblas.net/"></ulink>.
+     </para></listitem>
+    </varlistentry>
+
     <varlistentry>
      <term><productname>OpenSSL</productname></term>
      <listitem><para>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 75dc81a0a9..aa1191ced4 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -1009,6 +1009,15 @@ build-postgresql:
        </listitem>
       </varlistentry>
 
+      <varlistentry id="configure-option-with-openblas">
+       <term><option>--with-openblas</option></term>
+       <listitem>
+        <para>
+         Build with <productname>OpenBLAS</productname> support.
+        </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry id="configure-option-with-ssl">
        <term><option>--with-ssl=<replaceable>LIBRARY</replaceable></option>
        <indexterm>
@@ -2481,6 +2490,16 @@ ninja install
       </listitem>
      </varlistentry>
 
+     <varlistentry id="configure-with-openblas-meson">
+      <term><option>-Dopenblas={ auto | enabled | disabled }</option></term>
+      <listitem>
+       <para>
+        Build with <productname>OpenBLAS</productname> support.  Defaults to
+        auto.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="configure-with-ssl-meson">
       <term><option>-Dssl={ auto | <replaceable>LIBRARY</replaceable> }</option>
       <indexterm>
diff --git a/meson.build b/meson.build
index 096044628c..28ec293a7e 100644
--- a/meson.build
+++ b/meson.build
@@ -838,6 +838,25 @@ endif
 
 
 
+###############################################################
+# Library: OpenBLAS
+###############################################################
+
+openblasopt = get_option('openblas')
+if not openblasopt.disabled()
+  openblas = dependency('openblas', required: openblasopt)
+
+  if openblas.found()
+    cdata.set('USE_OPENBLAS', 1)
+    cdata.set('HAVE_OPENBLAS', 1)
+  endif
+
+else
+  openblas = not_found_dep
+endif
+
+
+
 ###############################################################
 # Library: Tcl (for pltcl)
 #
@@ -2848,6 +2867,7 @@ backend_both_deps += [
   libintl,
   libxml,
   lz4,
+  openblas,
   pam,
   ssl,
   systemd,
@@ -3378,6 +3398,7 @@ if meson.version().version_compare('>=0.57')
       'llvm': llvm,
       'lz4': lz4,
       'nls': libintl,
+      'openblas': openblas,
       'openssl': ssl,
       'pam': pam,
       'plperl': perl_dep,
diff --git a/meson_options.txt b/meson_options.txt
index 5b44a8829d..fbe0cf2ca1 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -118,6 +118,9 @@ option('lz4', type : 'feature', value: 'auto',
 option('nls', type: 'feature', value: 'auto',
   description: 'native language support')
 
+option('openblas', type: 'feature', value: 'auto',
+  description: 'OpenBLAS support')
+
 option('pam', type : 'feature', value: 'auto',
   description: 'build with PAM support')
 
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 772b91261d..8956f9a9fc 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -196,6 +196,7 @@ with_llvm	= @with_llvm@
 with_system_tzdata = @with_system_tzdata@
 with_uuid	= @with_uuid@
 with_zlib	= @with_zlib@
+with_openblas = @with_openblas@
 enable_rpath	= @enable_rpath@
 enable_nls	= @enable_nls@
 enable_debug	= @enable_debug@
diff --git a/src/backend/utils/adt/vector.c b/src/backend/utils/adt/vector.c
index dba1fd7eef..2cec20c4c5 100644
--- a/src/backend/utils/adt/vector.c
+++ b/src/backend/utils/adt/vector.c
@@ -20,6 +20,10 @@
 
 #include <float.h>
 
+#ifdef USE_OPENBLAS
+#include "cblas.h"
+#endif
+
 #include "catalog/pg_type.h"
 #include "common/int.h"
 #include "common/pg_prng.h"
@@ -95,10 +99,14 @@ euclidean_norm_internal(int n, const float8 *a)
 {
 	float8		en = 0.0;
 
+#ifdef USE_OPENBLAS
+	en = cblas_dnrm2(n, a, 1);
+#else
 	for (int i = 0; i < n; i++)
 		en = float8_pl(en, float8_mul(a[i], a[i]));
 
 	en = float8_sqrt(en);
+#endif
 
 	return en;
 }
@@ -160,8 +168,12 @@ dot_product(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("vectors must have the same number of elements")));
 
+#ifdef USE_OPENBLAS
+	dp = cblas_ddot(an, ad, 1, bd, 1);
+#else
 	for (int i = 0; i < an; i++)
 		dp = float8_pl(dp, float8_mul(ad[i], bd[i]));
+#endif
 
 	PG_RETURN_FLOAT8(dp);
 }
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 6d572c3820..5d1452f346 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -322,6 +322,9 @@
 /* Define to 1 if you have the `mkdtemp' function. */
 #undef HAVE_MKDTEMP
 
+/* Define to 1 if you have the 'OpenBLAS' library (-lopenblas). */
+#undef HAVE_OPENBLAS
+
 /* Define to 1 if you have the `OPENSSL_init_ssl' function. */
 #undef HAVE_OPENSSL_INIT_SSL
 
@@ -730,6 +733,9 @@
 /* Define to select named POSIX semaphores. */
 #undef USE_NAMED_POSIX_SEMAPHORES
 
+/* Define to 1 to build with OpenBLAS support. (--with-openblas) */
+#undef USE_OPENBLAS
+
 /* Define to 1 to build with OpenSSL support. (--with-ssl=openssl) */
 #undef USE_OPENSSL
 
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 13045cbd6e..47c75e1446 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -231,6 +231,7 @@ pgxs_deps = {
   'llvm': llvm,
   'lz4': lz4,
   'nls': libintl,
+  'openblas': openblas,
   'pam': pam,
   'perl': perl_dep,
   'python': python3_dep,
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index ef10cda576..a45dff7b30 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -304,6 +304,7 @@ sub GenerateFiles
 		HAVE_MEMORY_H               => 1,
 		HAVE_MEMSET_S               => undef,
 		HAVE_MKDTEMP                => undef,
+		HAVE_OPENBLAS               => undef,
 		HAVE_OPENSSL_INIT_SSL       => undef,
 		HAVE_OSSP_UUID_H            => undef,
 		HAVE_PAM_PAM_APPL_H         => undef,
@@ -436,6 +437,7 @@ sub GenerateFiles
 		USE_LDAP                   => $self->{options}->{ldap} ? 1 : undef,
 		USE_LLVM                   => undef,
 		USE_NAMED_POSIX_SEMAPHORES => undef,
+		USE_OPENBLAS               => undef,
 		USE_OPENSSL                => undef,
 		USE_PAM                    => undef,
 		USE_SLICING_BY_8_CRC32C    => undef,
@@ -485,6 +487,11 @@ sub GenerateFiles
 		$define{HAVE_LIBZSTD} = 1;
 		$define{USE_ZSTD}     = 1;
 	}
+	if ($self->{options}->{openblas})
+	{
+		$define{HAVE_OPENBLAS} = 1;
+		$define{USE_OPENBLAS}  = 1;
+	}
 	if ($self->{options}->{openssl})
 	{
 		$define{USE_OPENSSL} = 1;
@@ -1092,6 +1099,11 @@ sub AddProject
 		$proj->AddIncludeDir($self->{options}->{zstd} . '\include');
 		$proj->AddLibrary($self->{options}->{zstd} . '\lib\libzstd.lib');
 	}
+	if ($self->{options}->{openblas})
+	{
+		$proj->AddIncludeDir($self->{options}->{openblas} . '\include');
+		$proj->AddLibrary($self->{options}->{openblas} . '\lib\openblas.lib');
+	}
 	if ($self->{options}->{uuid})
 	{
 		$proj->AddIncludeDir($self->{options}->{uuid} . '\include');
@@ -1205,6 +1217,7 @@ sub GetFakeConfigure
 	$cfg .= ' --with-libxslt'       if ($self->{options}->{xslt});
 	$cfg .= ' --with-lz4'           if ($self->{options}->{lz4});
 	$cfg .= ' --with-zstd'          if ($self->{options}->{zstd});
+	$cfg .= ' --with-openblas'      if ($self->{options}->{openblas});
 	$cfg .= ' --with-gssapi'        if ($self->{options}->{gss});
 	$cfg .= ' --with-icu'           if ($self->{options}->{icu});
 	$cfg .= ' --with-tcl'           if ($self->{options}->{tcl});
diff --git a/src/tools/msvc/config_default.pl b/src/tools/msvc/config_default.pl
index 70b44d1531..8689439c0b 100644
--- a/src/tools/msvc/config_default.pl
+++ b/src/tools/msvc/config_default.pl
@@ -16,6 +16,7 @@ our $config = {
 	icu       => undef,    # --with-icu=<path>
 	lz4       => undef,    # --with-lz4=<path>
 	zstd      => undef,    # --with-zstd=<path>
+	openblas  => undef,    # --with-openblas=<path>
 	nls       => undef,    # --enable-nls=<path>
 	tap_tests => undef,    # --enable-tap-tests
 	tcl       => undef,    # --with-tcl=<path>
-- 
2.25.1

