public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Add simd testsuite
@ 2020-12-16 11:58 Matthias Kretz
  2020-12-17 13:10 ` Jonathan Wakely
  0 siblings, 1 reply; 3+ messages in thread
From: Matthias Kretz @ 2020-12-16 11:58 UTC (permalink / raw)
  To: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 12786 bytes --]

This is the second patch for std::experimental::simd, adding the testsuite. As 
discussed with Jonathan, the simd testsuite comes via its own check-simd 
target. The testsuite is so large that even marking all tests as "expensive", 
it still increased make check -j8 (with 8 cores) by more than 4 minutes (only 
to determine to compile and run nothing).

From: Matthias Kretz <kretz@kde.org>

The new check-simd target creates a subdirectory, generates the
necessary Makefiles, and spawns submakes to build and run the tests.

libstdc++-v3/ChangeLog:
	* scripts/check_simd: New file. This script is called from the
	the check-simd target. It determines a set of compiler flags and
	simulator setups for calling generate_makefile.sh and passes the
	information back to the check-simd target, which recurses to the
	generated Makefiles.
	* scripts/create_testsuite_files: Remove files below simd/tests/
	from testsuite_files and place them in testsuite_files_simd.
	* testsuite/Makefile.am: Add testsuite_files_simd. Add
	check-simd target.
	* testsuite/experimental/simd/driver.sh: New file. This script
	compiles and runs a given simd test, logging its output and
	status. It uses the timeout command to implement compile and
	test timeouts.
	* testsuite/experimental/simd/generate_makefile.sh: New file.
	This script generates a Makefile which uses driver.sh to compile
	and run the tests and collect the logs into a single log file.
	* testsuite/experimental/simd/tests/abs.cc: New file. Tests
	abs(simd).
	* testsuite/experimental/simd/tests/algorithms.cc: New file.
	Tests min/max(simd, simd).
	* testsuite/experimental/simd/tests/bits/conversions.h: New
	file. Contains functions to support tests involving conversions.
	* testsuite/experimental/simd/tests/bits/make_vec.h: New file.
	Support functions make_mask and make_vec.
	* testsuite/experimental/simd/tests/bits/mathreference.h: New
	file. Support functions to supply precomputed math function
	reference data.
	* testsuite/experimental/simd/tests/bits/metahelpers.h: New
	file. Support code for SFINAE testing.
	* testsuite/experimental/simd/tests/bits/simd_view.h: New file.
	* testsuite/experimental/simd/tests/bits/test_values.h: New
	file. Test functions to easily drive a test with simd objects
	initialized from a given list of values and a range of random
	values.
	* testsuite/experimental/simd/tests/bits/ulp.h: New file.
	Support code to determine the ULP distance of simd objects.
	* testsuite/experimental/simd/tests/bits/verify.h: New file.
	Test framework for COMPARE'ing simd objects and instantiating
	the test templates with value_type and ABI tag.
	* testsuite/experimental/simd/tests/broadcast.cc: New file. Test
	simd broadcasts.
	* testsuite/experimental/simd/tests/casts.cc: New file. Test
	simd casts.
	* testsuite/experimental/simd/tests/fpclassify.cc: New file.
	Test floating-point classification functions.
	* testsuite/experimental/simd/tests/frexp.cc: New file. Test
	frexp(simd).
	* testsuite/experimental/simd/tests/generator.cc: New file. Test
	simd generator constructor.
	* testsuite/experimental/simd/tests/hypot3_fma.cc: New file.
	Test 3-arg hypot(simd,simd,simd) and fma(simd,simd,sim).
	* testsuite/experimental/simd/tests/integer_operators.cc: New
	file. Test integer operators.
	* testsuite/experimental/simd/tests/ldexp_scalbn_scalbln_modf.cc:
	New file. Test ldexp(simd), scalbn(simd), scalbln(simd), and
	modf(simd).
	* testsuite/experimental/simd/tests/loadstore.cc: New file. Test
	(converting) simd loads and stores.
	* testsuite/experimental/simd/tests/logarithm.cc: New file. Test
	log*(simd).
	* testsuite/experimental/simd/tests/mask_broadcast.cc: New file.
	Test simd_mask broadcasts.
	* testsuite/experimental/simd/tests/mask_conversions.cc: New
	file. Test simd_mask conversions.
	* testsuite/experimental/simd/tests/mask_implicit_cvt.cc: New
	file. Test simd_mask implicit conversions.
	* testsuite/experimental/simd/tests/mask_loadstore.cc: New file.
	Test simd_mask loads and stores.
	* testsuite/experimental/simd/tests/mask_operator_cvt.cc: New
	file. Test simd_mask operators convert as specified.
	* testsuite/experimental/simd/tests/mask_operators.cc: New file.
	Test simd_mask compares, subscripts, and negation.
	* testsuite/experimental/simd/tests/mask_reductions.cc: New
	file. Test simd_mask reductions.
	* testsuite/experimental/simd/tests/math_1arg.cc: New file. Test
	1-arg math functions on simd.
	* testsuite/experimental/simd/tests/math_2arg.cc: New file. Test
	2-arg math functions on simd.
	* testsuite/experimental/simd/tests/operator_cvt.cc: New file.
	Test implicit conversions on simd binary operators behave as
	specified.
	* testsuite/experimental/simd/tests/operators.cc: New file. Test
	simd compares, subscripts, not, unary minus, plus, minus,
	multiplies, divides, increment, and decrement.
	* testsuite/experimental/simd/tests/reductions.cc: New file.
	Test reduce(simd).
	* testsuite/experimental/simd/tests/remqo.cc: New file. Test
	remqo(simd).
	* testsuite/experimental/simd/tests/simd.cc: New file. Basic
	sanity checks of simd types.
	* testsuite/experimental/simd/tests/sincos.cc: New file. Test
	sin(simd) and cos(simd).
	* testsuite/experimental/simd/tests/split_concat.cc: New file.
	Test split(simd) and concat(simd, simd).
	* testsuite/experimental/simd/tests/splits.cc: New file. Test
	split(simd_mask).
	* testsuite/experimental/simd/tests/trigonometric.cc: New file.
	Test remaining trigonometric functions on simd.
	* testsuite/experimental/simd/tests/trunc_ceil_floor.cc: New
	file. Test trunc(simd), ceil(simd), and floor(simd).
	* testsuite/experimental/simd/tests/where.cc: New file. Test
	masked operations using where.
---
 libstdc++-v3/scripts/check_simd               |   76 ++
 libstdc++-v3/scripts/create_testsuite_files   |    6 +-
 libstdc++-v3/testsuite/Makefile.am            |   17 +-
 .../testsuite/experimental/simd/driver.sh     |  249 ++++
 .../experimental/simd/generate_makefile.sh    |  250 ++++
 .../testsuite/experimental/simd/tests/abs.cc  |   24 +
 .../experimental/simd/tests/algorithms.cc     |   13 +
 .../simd/tests/bits/conversions.h             |  167 +++
 .../experimental/simd/tests/bits/make_vec.h   |   69 ++
 .../simd/tests/bits/mathreference.h           |  143 +++
 .../simd/tests/bits/metahelpers.h             |  147 +++
 .../experimental/simd/tests/bits/simd_view.h  |  131 ++
 .../simd/tests/bits/test_values.h             |  366 ++++++
 .../experimental/simd/tests/bits/ulp.h        |  111 ++
 .../experimental/simd/tests/bits/verify.h     |  336 ++++++
 .../experimental/simd/tests/broadcast.cc      |   87 ++
 .../experimental/simd/tests/casts.cc          |  152 +++
 .../experimental/simd/tests/fpclassify.cc     |   89 ++
 .../experimental/simd/tests/frexp.cc          |   68 ++
 .../experimental/simd/tests/generator.cc      |   41 +
 .../experimental/simd/tests/hypot3_fma.cc     |  134 +++
 .../simd/tests/integer_operators.cc           |  218 ++++
 .../simd/tests/ldexp_scalbn_scalbln_modf.cc   |  152 +++
 .../experimental/simd/tests/loadstore.cc      |  212 ++++
 .../experimental/simd/tests/logarithm.cc      |   66 ++
 .../experimental/simd/tests/mask_broadcast.cc |   50 +
 .../simd/tests/mask_conversions.cc            |   96 ++
 .../simd/tests/mask_implicit_cvt.cc           |   85 ++
 .../experimental/simd/tests/mask_loadstore.cc |  144 +++
 .../simd/tests/mask_operator_cvt.cc           |   94 ++
 .../experimental/simd/tests/mask_operators.cc |   40 +
 .../simd/tests/mask_reductions.cc             |  209 ++++
 .../experimental/simd/tests/math_1arg.cc      |   90 ++
 .../experimental/simd/tests/math_2arg.cc      |   62 +
 .../experimental/simd/tests/operator_cvt.cc   | 1055 +++++++++++++++++
 .../experimental/simd/tests/operators.cc      |  297 +++++
 .../experimental/simd/tests/reductions.cc     |   80 ++
 .../experimental/simd/tests/remqo.cc          |   53 +
 .../testsuite/experimental/simd/tests/simd.cc |   29 +
 .../experimental/simd/tests/sincos.cc         |   29 +
 .../experimental/simd/tests/split_concat.cc   |  166 +++
 .../experimental/simd/tests/splits.cc         |   21 +
 .../experimental/simd/tests/trigonometric.cc  |   24 +
 .../simd/tests/trunc_ceil_floor.cc            |   92 ++
 .../experimental/simd/tests/where.cc          |  119 ++
 45 files changed, 6156 insertions(+), 3 deletions(-)
 create mode 100755 libstdc++-v3/scripts/check_simd
 create mode 100755 libstdc++-v3/testsuite/experimental/simd/driver.sh
 create mode 100755 libstdc++-v3/testsuite/experimental/simd/
generate_makefile.sh
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/abs.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
algorithms.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/bits/
conversions.h
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/bits/
make_vec.h
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/bits/
mathreference.h
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/bits/
metahelpers.h
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/bits/
simd_view.h
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/bits/
test_values.h
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/bits/ulp.h
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/bits/
verify.h
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
broadcast.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/casts.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
fpclassify.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/frexp.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
generator.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
hypot3_fma.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
integer_operators.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
ldexp_scalbn_scalbln_modf.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
loadstore.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
logarithm.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
mask_broadcast.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
mask_conversions.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
mask_implicit_cvt.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
mask_loadstore.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
mask_operator_cvt.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
mask_operators.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
mask_reductions.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
math_1arg.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
math_2arg.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
operator_cvt.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
operators.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
reductions.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/remqo.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/simd.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/sincos.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
split_concat.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/splits.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
trigonometric.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/
trunc_ceil_floor.cc
 create mode 100644 libstdc++-v3/testsuite/experimental/simd/tests/where.cc


--
──────────────────────────────────────────────────────────────────────────
 Dr. Matthias Kretz                           https://mattkretz.github.io
 GSI Helmholtz Centre for Heavy Ion Research               https://gsi.de
 std::experimental::simd              https://github.com/VcDevel/std-simd
──────────────────────────────────────────────────────────────────────────

[-- Attachment #2: 0001-Add-simd-testsuite.patch --]
[-- Type: text/x-patch, Size: 232361 bytes --]

diff --git a/libstdc++-v3/scripts/check_simd b/libstdc++-v3/scripts/check_simd
new file mode 100755
index 00000000000..2b7a17a64c9
--- /dev/null
+++ b/libstdc++-v3/scripts/check_simd
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+# check_simd <srcdir> <builddir> <CXXFLAGS>
+# Read config from $CHECK_SIMD_CONFIG file or $target_list
+
+scriptdir="$(cd "${0%/*}" && pwd)"
+srcdir="$1"
+builddir="$2"
+shift 2
+testdir="$builddir/testsuite"
+
+CXX="$("$builddir/scripts/testsuite_flags" --build-cxx)"
+CXXFLAGS="$("$builddir/scripts/testsuite_flags" --cxxflags) $1 -Wno-psabi"
+shift
+INCLUDES="$("$builddir/scripts/testsuite_flags" --build-includes)"
+
+target_triplet=$($CXX -dumpmachine)
+
+define_target() {
+  name="$1"
+  flags="$2"
+  sim="$3"
+  eval "$name=\"flags=\\\"$flags\\\"
+sim=\\\"$sim\\\"\""
+}
+
+if [ -f "$CHECK_SIMD_CONFIG" ]; then
+  . "$CHECK_SIMD_CONFIG"
+elif [ -z "$CHECK_SIMD_CONFIG"]; then
+  if [ -z "$target_list" ]; then
+    target_list="unix"
+    case "$target_triplet" in
+      x86_64-*)      target_list="unix/-march=native" ;;
+      i?86-*)        target_list="unix/-march=native" ;;
+      powerpc64le-*) target_list="unix/-mcpu=power8" ;;
+      aarch64-*)     target_list="unix/-mcpu=cortex-a53" ;;
+      arm-*)         target_list="unix/-mcpu=cortex-a7" ;;
+    esac
+  fi
+else
+  echo "Error: File not found: \$CHECK_SIMD_CONFIG='$CHECK_SIMD_CONFIG'" 1>&2
+  exit 1
+fi
+
+# define unix with no flags and no simulator:
+define_target unix
+
+list="$target_list"
+
+# expand a{b,c} to a/b a/c
+while [ "${list#*\{}" != "${list}" ]; do
+  list="$(echo "$list" | \
+    sed -e 's#\([^ ]\+\){\([^{},]*\),\([^{}]*\)}\(/[^ ]*\)\?#\1/\2\4 \1{\3}\4#g' \
+        -e 's#{\([^{},]*\)}#/\1#g' \
+        -e 's#/ # #g' -e 's#/$##')"
+done
+
+# per a/b/c block extract flags and simulator, then make check-simd
+while [ ${#list} -gt 0 ]; do
+  a="${list%% *}"
+  if [ "$a" = "$list" ]; then
+    list=""
+  else
+    list="${list#${a} }"
+  fi
+  b="${a%%/*}"
+  eval "eval \"\$$b\""
+  flags="${flags}$(echo "${a#${b}}"|sed 's#/# #g')"
+  subdir="simd/$(echo "$flags" | sed 's#[= /-]##g')"
+  rm -f "${subdir}/Makefile"
+  $srcdir/testsuite/experimental/simd/generate_makefile.sh \
+    --destination="$testdir/$subdir" $CXX $INCLUDES $CXXFLAGS -static
+  echo "$subdir
+$flags
+$sim"
+done
diff --git a/libstdc++-v3/scripts/create_testsuite_files b/libstdc++-v3/scripts/create_testsuite_files
index 52bbb5cda5a..174c24ec05a 100755
--- a/libstdc++-v3/scripts/create_testsuite_files
+++ b/libstdc++-v3/scripts/create_testsuite_files
@@ -27,6 +27,7 @@ tmp="${TMPDIR:-/tmp}/ctt$$"
 tests_file_normal="$outdir/testsuite_files"
 tests_file_inter="$outdir/testsuite_files_interactive"
 tests_file_perf="$outdir/testsuite_files_performance"
+tests_file_simd="$outdir/testsuite_files_simd"
 
 cd $srcdir
 # This is the ugly version of "everything but the current directory".  It's
@@ -49,8 +50,11 @@ grep -v _xin $tmp.1 > $tmp.4
 grep performance $tmp.4 > $tests_file_perf
 grep -v performance $tmp.4 > $tmp.5
 
+grep simd/tests/ $tmp.5 > $tests_file_simd
+grep -v simd/tests/ $tmp.5 > $tmp.6
+
 # ...more filters go here.
-cp $tmp.5 $tests_file_normal
+cp $tmp.6 $tests_file_normal
 
 rm $tmp*
 exit 0
diff --git a/libstdc++-v3/testsuite/Makefile.am b/libstdc++-v3/testsuite/Makefile.am
index 7b412411bfe..d2e282b62b9 100644
--- a/libstdc++-v3/testsuite/Makefile.am
+++ b/libstdc++-v3/testsuite/Makefile.am
@@ -31,7 +31,8 @@ include $(top_srcdir)/fragment.am
 lists_of_files = \
    testsuite_files \
    testsuite_files_interactive \
-   testsuite_files_performance
+   testsuite_files_performance \
+   testsuite_files_simd
 
 # This rule generates all of the testsuite_files* lists at once.
 ${lists_of_files}:
@@ -185,6 +186,18 @@ check-performance: testsuite_files_performance ${performance_script}
 	  CXXFLAGS='$(CXXFLAGS)'; export CXXFLAGS; \
 	  ${check_performance_script} ${glibcxx_srcdir} ${glibcxx_builddir})
 
+# Runs the simd tests.
+check-simd: $(srcdir)/experimental/simd/generate_makefile.sh \
+	    ${glibcxx_srcdir}/scripts/check_simd \
+	    testsuite_files_simd \
+	    ${glibcxx_builddir}/scripts/testsuite_flags
+	${glibcxx_srcdir}/scripts/check_simd "${glibcxx_srcdir}" "${glibcxx_builddir}" "$(CXXFLAGS)" | \
+	  while read subdir && read flags && read sim; do \
+	    $(MAKE) -C "$${subdir}" TESTFLAGS="$${flags}" GCC_TEST_SIMULATOR="$${sim}"; \
+	    tail -n6 $${subdir}/simd_testsuite.sum >> .simd.summary; \
+	  done; \
+	  cat .simd.summary && rm .simd.summary
+
 # Runs the testsuite in debug mode.
 debug_flags = "unix/-D_GLIBCXX_DEBUG"
 
@@ -234,4 +247,4 @@ CLEANFILES = *.txt *.tst *.exe core* filebuf_* tmp* ostream_* *.log *.sum \
 
 # To remove directories.
 clean-local:
-	rm -rf de fr debug parallel binaries normal*
+	rm -rf de fr debug parallel binaries normal* simd
diff --git a/libstdc++-v3/testsuite/experimental/simd/driver.sh b/libstdc++-v3/testsuite/experimental/simd/driver.sh
new file mode 100755
index 00000000000..aabef316f47
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/driver.sh
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+type=float
+abi=0
+name=
+srcdir="$(cd "${0%/*}" && pwd)/tests"
+sim="$GCC_TEST_SIMULATOR"
+quiet=false
+verbose=false
+timeout=180
+run_expensive=false
+if [ -n "$GCC_TEST_RUN_EXPENSIVE" ]; then
+  run_expensive=true
+fi
+keep_failed=false
+only=
+
+usage() {
+  cat <<EOF
+Usage: $0 [Options] <g++ invocation>
+
+Options:
+  -h, --help          Print this message and exit.
+  -q, --quiet         Only print failures.
+  -v, --verbose       Print compiler and test output on failure.
+  -t <type>, --type <type>
+                      The value_type to test (default: $type).
+  -a [0-9], --abi [0-9]
+                      The ABI tag subset to test (default: $abi).
+  -n <name>, --name <name>
+                      The name of the test (required).
+  -k, --keep-failed   Keep executables of failed tests.
+  --srcdir <path>     The source directory of the tests (default: $srcdir).
+  --sim <executable>  Path to an executable that is prepended to the test
+                      execution binary (default: the value of
+                      GCC_TEST_SIMULATOR).
+  --timeout-factor <x>
+                      Multiply the default timeout with x.
+  --run-expensive     Compile and run tests marked as expensive (default:
+                      true if GCC_TEST_RUN_EXPENSIVE is set, false otherwise).
+  --only <pattern>    Compile and run only tests matching the given pattern.
+EOF
+}
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+  -h|--help)
+    usage
+    exit
+    ;;
+  -q|--quiet)
+    quiet=true
+    ;;
+  -v|--verbose)
+    verbose=true
+    ;;
+  --run-expensive)
+    run_expensive=true
+    ;;
+  -k|--keep-failed)
+    keep_failed=true
+    ;;
+  --only)
+    only="$2"
+    shift
+    ;;
+  --only=*)
+    only="${1#--only=}"
+    ;;
+  -t|--type)
+    type="$2"
+    shift
+    ;;
+  --type=*)
+    type="${1#--type=}"
+    ;;
+  -a|--abi)
+    abi="$2"
+    shift
+    ;;
+  --abi=*)
+    abi="${1#--abi=}"
+    ;;
+  -n|--name)
+    name="$2"
+    shift
+    ;;
+  --name=*)
+    name="${1#--name=}"
+    ;;
+  --srcdir)
+    srcdir="$2"
+    shift
+    ;;
+  --srcdir=*)
+    srcdir="${1#--srcdir=}"
+    ;;
+  --sim)
+    sim="$2"
+    shift
+    ;;
+  --sim=*)
+    sim="${1#--sim=}"
+    ;;
+  --timeout-factor)
+    timeout=$(awk "BEGIN { print int($timeout * $2) }")
+    shift
+    ;;
+  --timeout-factor=*)
+    x=${1#--timeout-factor=}
+    timeout=$(awk "BEGIN { print int($timeout * $x) }")
+    ;;
+  --)
+    shift
+    break
+    ;;
+  *)
+    break
+    ;;
+  esac
+  shift
+done
+
+CXX="$1"
+shift
+CXXFLAGS="$@"
+src="${srcdir}/${name}.cc"
+shorttype=$(echo $type|sed -e 's/long /l/' -e 's/unsigned /u/' -e 's/signed /s/')
+testname="${name}-${shorttype}-${abi}"
+exe="${testname}.exe"
+log="${testname}.log"
+sum="${testname}.sum"
+if [ -n "$only" ]; then
+  if echo "$testname"|awk "{ exit /$only/ }"; then
+    touch "$log" "$sum"
+    exit 0
+  fi
+fi
+
+if [ $abi -eq 0 ]; then
+  abi=""
+elif [ $abi -gt 0 -a $abi -lt 10 ]; then
+  abi="-DEXTENDEDTESTS=$((abi-1))"
+else
+  echo "Error: The -a argument must be a value between 0 and 9 (inclusive)." >&2
+  exit 1
+fi
+
+fail() {
+  echo "FAIL: $src $type $abi ($*)" | tee -a "$sum" "$log"
+}
+
+pass() {
+  $quiet || echo "PASS: $src $type $abi ($*)"
+  echo "PASS: $src $type $abi ($*)" >> "$sum"
+  echo "PASS: $src $type $abi ($*)" >> "$log"
+}
+
+unsupported() {
+  $quiet || echo "UNSUPPORTED: $src $type $abi ($*)"
+  echo "UNSUPPORTED: $src $type $abi ($*)" >> "$sum"
+  echo "UNSUPPORTED: $src $type $abi ($*)" >> "$log"
+}
+
+verify_compilation() {
+  failed=$1
+  if [ $failed -eq 0 ]; then
+    warnings=$(grep -ic 'warning:' "$log")
+    if [ $warnings -gt 0 ]; then
+      fail "excess warnings:" $warnings
+      if $verbose; then
+        cat "$log"
+      elif ! $quiet; then
+        grep -i 'warning:' "$log" | head -n5
+      fi
+    else
+      pass "test for excess errors"
+    fi
+  else
+    if [ $failed -eq 124 ]; then
+      fail "timeout: test for excess errors"
+    else
+      errors=$(grep -ic 'error:' "$log")
+      fail "excess errors:" $errors
+    fi
+    if $verbose; then
+      cat "$log"
+    elif ! $quiet; then
+      grep -i 'error:' "$log" | head -n5
+    fi
+    exit 0
+  fi
+}
+
+verify_test() {
+  failed=$1
+  if [ $failed -eq 0 ]; then
+    rm "$exe"
+    pass "execution test"
+  else
+    $keep_failed || rm "$exe"
+    if [ $failed -eq 124 ]; then
+      fail "timeout: execution test"
+    else
+      fail "execution test"
+    fi
+    if $verbose; then
+      if [ $(cat "$log"|wc -l) -gt 1000 ]; then
+        echo "[...]"
+        tail -n1000 "$log"
+      else
+        cat "$log"
+      fi
+    elif ! $quiet; then
+      grep -i fail "$log" | head -n5
+    fi
+    exit 0
+  fi
+}
+
+write_log_and_verbose() {
+  echo "$*" >> "$log"
+  if $verbose; then
+    echo "$*"
+  fi
+}
+
+rm -f "$log" "$sum"
+touch "$log" "$sum"
+
+if ! $run_expensive && [ -n "$abi" ]; then
+  unsupported "skip expensive tests"
+  exit 0
+fi
+
+write_log_and_verbose "$CXX $src $@ -D_GLIBCXX_SIMD_TESTTYPE=$type $abi -o $exe"
+timeout $timeout "$CXX" "$src" "$@" "-D_GLIBCXX_SIMD_TESTTYPE=$type" $abi -o "$exe" >> "$log" 2>&1
+verify_compilation $?
+if [ -n "$sim" ]; then
+  write_log_and_verbose "$sim ./$exe"
+  timeout $timeout $sim "./$exe" >> "$log" 2>&1 <&-
+else
+  write_log_and_verbose "./$exe"
+  timeout=$(awk "BEGIN { print int($timeout / 2) }")
+  timeout $timeout "./$exe" >> "$log" 2>&1 <&-
+fi
+verify_test $?
+
+# vim: sw=2 et cc=81 si
diff --git a/libstdc++-v3/testsuite/experimental/simd/generate_makefile.sh b/libstdc++-v3/testsuite/experimental/simd/generate_makefile.sh
new file mode 100755
index 00000000000..a8caa4bcd4e
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/generate_makefile.sh
@@ -0,0 +1,250 @@
+#!/bin/sh
+
+srcdir="$(cd "${0%/*}" && pwd)"
+driver="$srcdir/driver.sh"
+srcdir="$srcdir/tests"
+sim=
+rm_logs=true
+dst=.
+
+usage() {
+  cat <<EOF
+Usage: $0 [Options] <g++ invocation>
+
+Options:
+  -h, --help          Print this message and exit.
+  --srcdir <path>     The source directory of the tests (default: $srcdir).
+  --sim <executable>  Path to an executable that is prepended to the test
+                      execution binary (default: none).
+  --keep-intermediate-logs
+                      Keep intermediate logs.
+  -d <path>, --destination <path>
+                      Destination for the generated Makefile. If the directory
+                      does not exist it is created (default: $dst).
+EOF
+}
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+  -h|--help)
+    usage
+    exit
+    ;;
+  -d|--destination)
+    dst="$2"
+    shift
+    ;;
+  --destination=*)
+    dst="${1#--destination=}"
+    ;;
+  --keep-intermediate-logs)
+    rm_logs=false
+    ;;
+  --srcdir)
+    srcdir="$2"
+    shift
+    ;;
+  --srcdir=*)
+    srcdir="${1#--srcdir=}"
+    ;;
+  --sim)
+    sim="$2"
+    shift
+    ;;
+  --sim=*)
+    sim="${1#--sim=}"
+    ;;
+  --)
+    shift
+    break
+    ;;
+  *)
+    break
+    ;;
+  esac
+  shift
+done
+
+mkdir -p "$dst"
+dst="$dst/Makefile"
+if [ -f "$dst" ]; then
+  echo "Error: $dst already exists. Aborting." 1>&2
+  exit 1
+fi
+
+CXX="$1"
+shift
+
+echo "TESTFLAGS ?=" > "$dst"
+echo CXXFLAGS = "$@" "\$(TESTFLAGS)" >> "$dst"
+cat >> "$dst" <<EOF
+srcdir = ${srcdir}
+CXX = ${CXX}
+DRIVER = ${driver}
+DRIVEROPTS ?=
+
+all: simd_testsuite.sum
+
+simd_testsuite.sum: simd_testsuite.log
+	@echo "\n\t\t=== simd_testsuite \$(TESTFLAGS) Summary ===\n\n"\\
+	"# of expected passes:\t\t\$(shell grep -c '^PASS:' \$@)\n"\\
+	"# of unexpected failures:\t\$(shell grep -c '^FAIL:' \$@)\n"\\
+	"# of unsupported tests:\t\t\$(shell grep -c '^UNSUPPORTED:' \$@)"\\
+	  | tee -a \$@
+
+EOF
+
+all_types() {
+  src="$1"
+  cat <<EOF
+long double
+ldouble
+double
+double
+float
+float
+EOF
+  ([ -n "$src" ] && grep -q "test only floattypes" "$src") || \
+  cat <<EOF
+long long
+llong
+unsigned long long
+ullong
+unsigned long
+ulong
+long
+long
+int
+int
+unsigned int
+uint
+short
+short
+unsigned short
+ushort
+char
+char
+signed char
+schar
+unsigned char
+uchar
+char32_t
+char32_t
+char16_t
+char16_t
+wchar_t
+wchar_t
+EOF
+}
+
+all_tests() {
+  if [ -f testsuite_files_simd ]; then
+    sed 's,^experimental/simd/tests/,,' testsuite_files_simd | while read file; do
+      echo "$srcdir/$file"
+      echo "${file%.cc}"
+    done
+  else
+    for file in ${srcdir}/*.cc; do
+      echo "$file"
+      name="${file%.cc}"
+      echo "${name##*/}"
+    done
+  fi
+}
+
+{
+  rmline=""
+  if $rm_logs; then
+    rmline="
+	@rm \$^ \$(^:log=sum)"
+  fi
+  echo -n "simd_testsuite.log:"
+  all_tests | while read file && read name; do
+    echo -n " $name.log"
+  done
+  cat <<EOF
+
+	@cat $^ > \$@
+	@cat \$(^:log=sum) > \$(@:log=sum)${rmline}
+
+EOF
+  all_tests | while read file && read name; do
+    echo -n "$name.log:"
+    all_types "$file" | while read t && read type; do
+      echo -n " $name-$type.log"
+    done
+    cat <<EOF
+
+	@cat $^ > \$@
+	@cat \$(^:log=sum) > \$(@:log=sum)${rmline}
+
+EOF
+  done
+  all_types | while read t && read type; do
+    cat <<EOF
+%-$type.log: %-$type-0.log %-$type-1.log %-$type-2.log %-$type-3.log \
+%-$type-4.log %-$type-5.log %-$type-6.log %-$type-7.log \
+%-$type-8.log %-$type-9.log
+	@cat $^ > \$@
+	@cat \$(^:log=sum) > \$(@:log=sum)${rmline}
+
+EOF
+    for i in $(seq 0 9); do
+      cat <<EOF
+%-$type-$i.log: \$(srcdir)/%.cc
+	@\$(DRIVER) \$(DRIVEROPTS) -t "$t" -a $i -n \$* \$(CXX) \$(CXXFLAGS)
+
+EOF
+    done
+  done
+  echo 'run-%: export GCC_TEST_RUN_EXPENSIVE=yes\n'
+  all_tests | while read file && read name; do
+    echo "run-$name: $name.log"
+    all_types "$file" | while read t && read type; do
+      echo "run-$name-$type: $name-$type.log"
+      for i in $(seq 0 9); do
+        echo "run-$name-$type-$i: $name-$type-$i.log"
+      done
+    done
+    echo
+  done
+  cat <<EOF
+help:
+	@echo "use DRIVEROPTS=<options> to pass the following options:\n"\\
+	"-q, --quiet         Only print failures.\n"\\
+	"-v, --verbose       Print compiler and test output on failure.\n"\\
+	"-k, --keep-failed   Keep executables of failed tests.\n"\\
+	"--sim <executable>  Path to an executable that is prepended to the test\n"\\
+	"                    execution binary (default: the value of\n"\\
+	"                    GCC_TEST_SIMULATOR).\n"\\
+	"--timeout-factor <x>\n"\\
+	"                    Multiply the default timeout with x.\n"\\
+	"--run-expensive     Compile and run tests marked as expensive (default:\n"\\
+	"                    true if GCC_TEST_RUN_EXPENSIVE is set, false otherwise).\n"\\
+	"--only <pattern>    Compile and run only tests matching the given pattern.\n"
+	@echo "use TESTFLAGS=<flags> to pass additional compiler flags\n"
+	@echo "The following are some of the valid targets for this Makefile:"
+	@echo "... all"
+	@echo "... clean"
+	@echo "... help"
+EOF
+  all_tests | while read file && read name; do
+    echo "\t@echo '... run-${name}'"
+    all_types | while read t && read type; do
+      echo "\t@echo '... run-${name}-${type}'"
+      for i in $(seq 0 9); do
+        echo "\t@echo '... run-${name}-${type}-$i'"
+      done
+    done
+  done
+  cat <<EOF
+
+clean:
+	rm -f -- *.sum *.log
+
+.PHONY: clean help
+
+.PRECIOUS: %.log %.sum
+EOF
+} >> "$dst"
+
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc b/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc
new file mode 100644
index 00000000000..3f81bf03a40
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc
@@ -0,0 +1,24 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include <cmath>    // abs & sqrt
+#include <cstdlib>  // integer abs
+#include "bits/test_values.h"
+
+template <typename V>
+  void
+  test()
+  {
+    if constexpr (std::is_signed_v<typename V::value_type>)
+      {
+	using std::abs;
+	using T = typename V::value_type;
+	test_values<V>({std::__finite_max_v<T>, std::__norm_min_v<T>,
+			-std::__norm_min_v<T>, std::__finite_min_v<T>,
+			std::__finite_min_v<T> / 2, T(), -T(), T(-1), T(-2)},
+		       {1000}, [](V input) {
+			 const V expected(
+			   [&](auto i) { return T(std::abs(T(input[i]))); });
+			 COMPARE(abs(input), expected) << "input: " << input;
+		       });
+      }
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc b/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc
new file mode 100644
index 00000000000..f79bb6b63d2
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc
@@ -0,0 +1,13 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+    V a{[](auto i) -> T { return i & 1u; }};
+    V b{[](auto i) -> T { return (i + 1u) & 1u; }};
+    COMPARE(min(a, b), V{0});
+    COMPARE(max(a, b), V{1});
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h
new file mode 100644
index 00000000000..601b783cec6
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h
@@ -0,0 +1,167 @@
+#include <array>
+
+// is_conversion_undefined
+/* implementation-defined
+ * ======================
+ * §4.7 p3 (integral conversions)
+ *  If the destination type is signed, the value is unchanged if it can be
+ *  represented in the destination type (and bit-field width); otherwise, the
+ *  value is implementation-defined.
+ *
+ * undefined
+ * =========
+ * §4.9/1  (floating-point conversions)
+ *  If the source value is neither exactly represented in the destination type
+ *  nor between two adjacent destination values the result is undefined.
+ *
+ * §4.10/1 (floating-integral conversions)
+ *  floating point type can be converted to integer type.
+ *  The behavior is undefined if the truncated value cannot be
+ *  represented in the destination type.
+ *
+ * §4.10/2
+ *  integer can be converted to floating point type.
+ *  If the value being converted is outside the range of values that can be
+ *  represented, the behavior is undefined.
+ */
+template <typename To, typename From>
+  constexpr bool
+  is_conversion_undefined_impl(From x, std::true_type)
+  {
+    return x > static_cast<long double>(std::__finite_max_v<To>)
+	     || x < static_cast<long double>(std::__finite_min_v<To>);
+  }
+
+template <typename To, typename From>
+  constexpr bool
+  is_conversion_undefined_impl(From, std::false_type)
+  { return false; }
+
+template <typename To, typename From>
+  constexpr bool
+  is_conversion_undefined(From x)
+  {
+    static_assert(std::is_arithmetic<From>::value,
+		  "this overload is only meant for builtin arithmetic types");
+    return is_conversion_undefined_impl<To, From>(
+	     x, std::integral_constant<
+		  bool, std::is_floating_point<From>::value
+			  && (std::is_integral<To>::value
+				|| (std::is_floating_point<To>::value
+				      && sizeof(From) > sizeof(To)))>());
+  }
+
+static_assert(is_conversion_undefined<uint>(float(0x100000000LL)),
+	      "testing my expectations of is_conversion_undefined");
+static_assert(!is_conversion_undefined<float>(0x100000000LL),
+	      "testing my expectations of is_conversion_undefined");
+
+template <typename To, typename T, typename A>
+  inline std::experimental::simd_mask<T, A>
+  is_conversion_undefined(const std::experimental::simd<T, A>& x)
+  {
+    std::experimental::simd_mask<T, A> k = false;
+    for (std::size_t i = 0; i < x.size(); ++i)
+      k[i] = is_conversion_undefined(x[i]);
+    return k;
+  }
+
+template <class T>
+  constexpr T
+  genHalfBits()
+  { return std::__finite_max_v<T> >> (std::__digits_v<T> / 2); }
+
+template <>
+  constexpr long double
+  genHalfBits<long double>()
+  { return 0; }
+
+template <>
+  constexpr double
+  genHalfBits<double>()
+  { return 0; }
+
+template <>
+  constexpr float
+  genHalfBits<float>()
+  { return 0; }
+
+template <class U, class T, class UU>
+  constexpr U
+  avoid_ub(UU x)
+  { return is_conversion_undefined<T>(U(x)) ? U(0) : U(x); }
+
+template <class U, class T, class UU>
+  constexpr U
+  avoid_ub2(UU x)
+  { return is_conversion_undefined<U>(x) ? U(0) : avoid_ub<U, T>(x); }
+
+// conversion test input data
+template <class U, class T>
+  static const std::array<U, 53> cvt_input_data = {{
+    avoid_ub<U, T>(0xc0000080U),
+    avoid_ub<U, T>(0xc0000081U),
+    avoid_ub<U, T>(0xc0000082U),
+    avoid_ub<U, T>(0xc0000084U),
+    avoid_ub<U, T>(0xc0000088U),
+    avoid_ub<U, T>(0xc0000090U),
+    avoid_ub<U, T>(0xc00000A0U),
+    avoid_ub<U, T>(0xc00000C0U),
+    avoid_ub<U, T>(0xc000017fU),
+    avoid_ub<U, T>(0xc0000180U),
+    avoid_ub<U, T>(0x100000001LL),
+    avoid_ub<U, T>(0x100000011LL),
+    avoid_ub<U, T>(0x100000111LL),
+    avoid_ub<U, T>(0x100001111LL),
+    avoid_ub<U, T>(0x100011111LL),
+    avoid_ub<U, T>(0x100111111LL),
+    avoid_ub<U, T>(0x101111111LL),
+    avoid_ub<U, T>(-0x100000001LL),
+    avoid_ub<U, T>(-0x100000011LL),
+    avoid_ub<U, T>(-0x100000111LL),
+    avoid_ub<U, T>(-0x100001111LL),
+    avoid_ub<U, T>(-0x100011111LL),
+    avoid_ub<U, T>(-0x100111111LL),
+    avoid_ub<U, T>(-0x101111111LL),
+    avoid_ub<U, T>(std::__norm_min_v<U>),
+    avoid_ub<U, T>(std::__norm_min_v<U> + 1),
+    avoid_ub<U, T>(std::__finite_min_v<U>),
+    avoid_ub<U, T>(std::__finite_min_v<U> + 1),
+    avoid_ub<U, T>(-1),
+    avoid_ub<U, T>(-10),
+    avoid_ub<U, T>(-100),
+    avoid_ub<U, T>(-1000),
+    avoid_ub<U, T>(-10000),
+    avoid_ub<U, T>(0),
+    avoid_ub<U, T>(1),
+    avoid_ub<U, T>(genHalfBits<U>() - 1),
+    avoid_ub<U, T>(genHalfBits<U>()),
+    avoid_ub<U, T>(genHalfBits<U>() + 1),
+    avoid_ub<U, T>(std::__finite_max_v<U> - 1),
+    avoid_ub<U, T>(std::__finite_max_v<U>),
+    avoid_ub<U, T>(std::__finite_max_v<U> - 0xff),
+    avoid_ub<U, T>(std::__finite_max_v<U> - 0xff),
+    avoid_ub<U, T>(std::__finite_max_v<U> - 0x55),
+    avoid_ub<U, T>(-(std::__finite_min_v<U> + 1)),
+    avoid_ub<U, T>(-std::__finite_max_v<U>),
+    avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 6 - 1)),
+    avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 6 - 1)),
+    avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 4 - 1)),
+    avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 4 - 1)),
+    avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 2 - 1)),
+    avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 2 - 1)),
+    avoid_ub<U, T>(std::__finite_max_v<T> - 1),
+    avoid_ub<U, T>(std::__finite_max_v<T> * 0.75),
+  }};
+
+template <class T, class U>
+  struct cvt_inputs
+  {
+    static constexpr size_t
+    size()
+    { return cvt_input_data<U, T>.size(); }
+
+    U
+    operator[](size_t i) const
+    { return cvt_input_data<U, T>[i]; }
+  };
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/make_vec.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/make_vec.h
new file mode 100644
index 00000000000..f81135900e8
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/make_vec.h
@@ -0,0 +1,69 @@
+/*  This file is part of the Vc library. {
+Copyright © 2017 Matthias Kretz <kretz@kde.org>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the names of contributing organizations nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+}*/
+
+#include <experimental/simd>
+
+template <class M>
+  inline M
+  make_mask(const std::initializer_list<bool> &init)
+  {
+    std::size_t i = 0;
+    M r = {};
+    for (;;)
+      {
+	for (bool x : init)
+	  {
+	    r[i] = x;
+	    if (++i == M::size())
+	      {
+		return r;
+	      }
+	  }
+      }
+  }
+
+template <class V>
+  inline V
+  make_vec(const std::initializer_list<typename V::value_type> &init,
+	   typename V::value_type inc = 0)
+  {
+    std::size_t i = 0;
+    V r = {};
+    typename V::value_type base = 0;
+    for (;;)
+      {
+	for (auto x : init)
+	  {
+	    r[i] = base + x;
+	    if (++i == V::size())
+	      {
+		return r;
+	      }
+	  }
+	base += inc;
+      }
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/mathreference.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/mathreference.h
new file mode 100644
index 00000000000..3e5892c2624
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/mathreference.h
@@ -0,0 +1,143 @@
+#include <tuple>
+#include <utility>
+#include <cstdio>
+
+template <typename T>
+  struct SincosReference
+  {
+    T x, s, c;
+
+    std::tuple<const T &, const T &, const T &>
+    as_tuple() const
+    { return std::tie(x, s, c); }
+  };
+
+template <typename T>
+  struct Reference {
+    T x, ref;
+
+    std::tuple<const T &, const T &>
+    as_tuple() const
+    { return std::tie(x, ref); }
+  };
+
+template <typename T>
+  struct Array
+  {
+    std::size_t size_;
+    const T *data_;
+
+    Array()
+    : size_(0), data_(nullptr) {}
+
+    Array(size_t s, const T *p)
+    : size_(s), data_(p) {}
+
+    const T*
+    begin() const
+    { return data_; }
+
+    const T*
+    end() const
+    { return data_ + size_; }
+
+    std::size_t
+    size() const
+    { return size_; }
+  };
+
+namespace function {
+  struct sincos{ static constexpr const char *const str = "sincos"; };
+  struct atan  { static constexpr const char *const str = "atan"; };
+  struct asin  { static constexpr const char *const str = "asin"; };
+  struct acos  { static constexpr const char *const str = "acos"; };
+  struct log   { static constexpr const char *const str = "ln"; };
+  struct log2  { static constexpr const char *const str = "log2"; };
+  struct log10 { static constexpr const char *const str = "log10"; };
+}
+
+template <class F>
+  struct testdatatype_for_function
+  {
+    template <class T>
+      using type = Reference<T>;
+  };
+
+template <>
+  struct testdatatype_for_function<function::sincos>
+  {
+    template <class T>
+      using type = SincosReference<T>;
+  };
+
+template <class F, class T>
+  using testdatatype_for_function_t
+    = typename testdatatype_for_function<F>::template type<T>;
+
+template<typename T>
+  struct StaticDeleter
+  {
+    const T *ptr;
+
+    StaticDeleter(const T *p)
+    : ptr(p) {}
+
+    ~StaticDeleter()
+    { delete[] ptr; }
+  };
+
+template <class F, class T>
+  inline std::string filename()
+  {
+    static_assert(std::is_floating_point<T>::value, "");
+    static const auto cache
+      = std::string("reference-") + F::str
+      + (sizeof(T) == 4 && std::__digits_v<T> == 24
+	 && std::__max_exponent_v<T> == 128
+	 ? "-sp"
+	 : (sizeof(T) == 8
+	    && std::__digits_v<T> == 53
+	    && std::__max_exponent_v<T> == 1024
+	    ? "-dp"
+	    : (sizeof(T) == 16 && std::__digits_v<T> == 64
+	       && std::__max_exponent_v<T> == 16384
+	       ? "-ep"
+	       : (sizeof(T) == 16 && std::__digits_v<T> == 113
+		  && std::__max_exponent_v<T> == 16384
+		  ? "-qp"
+		  : "-unknown"))))
+      + ".dat";
+    return cache;
+  }
+
+template <class Fun, class T, class Ref = testdatatype_for_function_t<Fun, T>>
+  Array<Ref>
+  referenceData()
+  {
+    static Array<Ref> data;
+    if (data.data_ == nullptr)
+      {
+	FILE* file = std::fopen(filename<Fun, T>().c_str(), "rb");
+	if (file)
+	  {
+	    std::fseek(file, 0, SEEK_END);
+	    const size_t size = std::ftell(file) / sizeof(Ref);
+	    std::rewind(file);
+	    auto                      mem = new Ref[size];
+	    static StaticDeleter<Ref> _cleanup(data.data_);
+	    data.size_ = std::fread(mem, sizeof(Ref), size, file);
+	    data.data_ = mem;
+	    std::fclose(file);
+	  }
+	else
+	  {
+	    __builtin_fprintf(
+		stderr,
+		"%s:%d: the reference data %s does not exist in the current "
+		"working directory.\n",
+		__FILE__, __LINE__, filename<Fun, T>().c_str());
+	    __builtin_abort();
+	  }
+      }
+    return data;
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/metahelpers.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/metahelpers.h
new file mode 100644
index 00000000000..16c6b287690
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/metahelpers.h
@@ -0,0 +1,147 @@
+#ifndef VC_TESTS_METAHELPERS_H_
+#define VC_TESTS_METAHELPERS_H_
+
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+namespace vir
+{
+  namespace test
+  {
+    template <class A, class B, class Op>
+      constexpr bool
+      operator_is_substitution_failure_impl(float)
+      { return true; }
+
+    template <class A, class B, class Op>
+      constexpr typename std::conditional<true, bool, decltype(
+	  Op()(std::declval<A>(), std::declval<B>()))>::type
+      operator_is_substitution_failure_impl(int)
+      { return false; }
+
+    template <class... Ts>
+      constexpr bool
+      operator_is_substitution_failure()
+      { return operator_is_substitution_failure_impl<Ts...>(int()); }
+
+    template <class... Args, class F>
+      constexpr auto
+      sfinae_is_callable_impl(int, F &&f) -> typename std::conditional<
+	true, std::true_type,
+	decltype(std::forward<F>(f)(std::declval<Args>()...))>::type;
+
+    template <class... Args, class F>
+      constexpr std::false_type
+      sfinae_is_callable_impl(float, const F &);
+
+    template <class... Args, class F>
+      constexpr bool
+      sfinae_is_callable(F &&)
+      {
+	return decltype(
+	    sfinae_is_callable_impl<Args...>(int(), std::declval<F>()))::value;
+      }
+
+    template <class... Args, class F>
+      constexpr auto sfinae_is_callable_t(F &&f)
+	-> decltype(sfinae_is_callable_impl<Args...>(int(), std::declval<F>()));
+
+    template <class A, class B>
+      constexpr bool
+      has_less_bits()
+      { return std::__digits_v<A> < std::__digits_v<B>; }
+
+  }  // namespace test
+}  // namespace vir
+
+struct assignment
+{
+  template <class A, class B>
+    constexpr decltype(std::declval<A>() = std::declval<B>())
+    operator()(A &&a, B &&b) const noexcept(noexcept(
+	std::forward<A>(a) = std::forward<B>(b)))
+    { return std::forward<A>(a) = std::forward<B>(b); }
+};
+
+struct bit_shift_left
+{
+  template <class A, class B>
+    constexpr decltype(std::declval<A>() << std::declval<B>())
+    operator()(A &&a, B &&b) const noexcept(noexcept(
+	std::forward<A>(a) << std::forward<B>(b)))
+    { return std::forward<A>(a) << std::forward<B>(b); }
+};
+
+struct bit_shift_right
+{
+  template <class A, class B>
+    constexpr decltype(std::declval<A>() >> std::declval<B>())
+    operator()(A &&a, B &&b) const noexcept(noexcept(
+	std::forward<A>(a) >> std::forward<B>(b)))
+    { return std::forward<A>(a) >> std::forward<B>(b); }
+};
+
+struct assign_modulus
+{
+  template <class A, class B>
+    constexpr decltype(std::declval<A>() %= std::declval<B>())
+    operator()(A &&a, B &&b) const noexcept(noexcept(
+	std::forward<A>(a) %= std::forward<B>(b)))
+    { return std::forward<A>(a) %= std::forward<B>(b); }
+};
+
+struct assign_bit_and
+{
+  template <class A, class B>
+    constexpr decltype(std::declval<A>() &= std::declval<B>())
+    operator()(A &&a, B &&b) const noexcept(noexcept(
+	std::forward<A>(a) &= std::forward<B>(b)))
+    { return std::forward<A>(a) &= std::forward<B>(b); }
+};
+
+struct assign_bit_or
+{
+  template <class A, class B>
+    constexpr decltype(std::declval<A>() |= std::declval<B>())
+    operator()(A &&a, B &&b) const noexcept(noexcept(
+	std::forward<A>(a) |= std::forward<B>(b)))
+    { return std::forward<A>(a) |= std::forward<B>(b); }
+};
+
+struct assign_bit_xor
+{
+  template <class A, class B>
+    constexpr decltype(std::declval<A>() ^= std::declval<B>())
+    operator()(A &&a, B &&b) const noexcept(noexcept(
+	std::forward<A>(a) ^= std::forward<B>(b)))
+    { return std::forward<A>(a) ^= std::forward<B>(b); }
+};
+
+struct assign_bit_shift_left
+{
+  template <class A, class B>
+    constexpr decltype(std::declval<A>() <<= std::declval<B>())
+    operator()(A &&a, B &&b) const noexcept(noexcept(
+	std::forward<A>(a) <<= std::forward<B>(b)))
+    { return std::forward<A>(a) <<= std::forward<B>(b); }
+};
+
+struct assign_bit_shift_right
+{
+  template <class A, class B>
+    constexpr decltype(std::declval<A>() >>= std::declval<B>())
+    operator()(A &&a, B &&b) const noexcept(noexcept(
+	std::forward<A>(a) >>= std::forward<B>(b)))
+    { return std::forward<A>(a) >>= std::forward<B>(b); }
+};
+
+template <class A, class B, class Op = std::plus<>>
+  constexpr bool is_substitution_failure
+    = vir::test::operator_is_substitution_failure<A, B, Op>();
+
+using vir::test::sfinae_is_callable;
+
+using vir::test::has_less_bits;
+
+#endif  // VC_TESTS_METAHELPERS_H_
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/simd_view.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/simd_view.h
new file mode 100644
index 00000000000..b7fbaf883bf
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/simd_view.h
@@ -0,0 +1,131 @@
+/*  This file is part of the Vc library. {
+Copyright © 2018 Matthias Kretz <kretz@kde.org>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the names of contributing organizations nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+}*/
+
+#ifndef VC_TESTS_SIMD_VIEW_H_
+#define VC_TESTS_SIMD_VIEW_H_
+
+#include <experimental/simd>
+
+_GLIBCXX_SIMD_BEGIN_NAMESPACE
+
+namespace experimental
+{
+  namespace imported_begin_end
+  {
+    using std::begin;
+    using std::end;
+
+    template <class T>
+      using begin_type = decltype(begin(std::declval<T>()));
+
+    template <class T>
+      using end_type = decltype(end(std::declval<T>()));
+  }  // namespace imported_begin_end
+
+  template <class V, class It, class End>
+    class viewer
+    {
+      It it;
+      const End end;
+
+      template <class F>
+	void
+	for_each_impl(F &&fun, std::index_sequence<0, 1, 2>)
+	{
+	  for (; it + V::size() <= end; it += V::size())
+	    {
+	      fun(V([&](auto i) { return std::get<0>(it[i].as_tuple()); }),
+		  V([&](auto i) { return std::get<1>(it[i].as_tuple()); }),
+		  V([&](auto i) { return std::get<2>(it[i].as_tuple()); }));
+	    }
+	  if (it != end)
+	    {
+	      fun(V([&](auto i)
+	      {
+		auto ii = it + i < end ? i + 0 : 0;
+		return std::get<0>(it[ii].as_tuple());
+	      }),
+		  V([&](auto i) {
+		    auto ii = it + i < end ? i + 0 : 0;
+		    return std::get<1>(it[ii].as_tuple());
+		  }),
+		  V([&](auto i) {
+		    auto ii = it + i < end ? i + 0 : 0;
+		    return std::get<2>(it[ii].as_tuple());
+		  }));
+	    }
+	}
+
+      template <class F>
+	void
+	for_each_impl(F &&fun, std::index_sequence<0, 1>)
+	{
+	  for (; it + V::size() <= end; it += V::size())
+	    {
+	      fun(V([&](auto i) { return std::get<0>(it[i].as_tuple()); }),
+		  V([&](auto i) { return std::get<1>(it[i].as_tuple()); }));
+	    }
+	  if (it != end)
+	    {
+	      fun(V([&](auto i) {
+		auto ii = it + i < end ? i + 0 : 0;
+		return std::get<0>(it[ii].as_tuple());
+	      }),
+		  V([&](auto i) {
+		    auto ii = it + i < end ? i + 0 : 0;
+		    return std::get<1>(it[ii].as_tuple());
+		  }));
+	    }
+	}
+
+    public:
+      viewer(It _it, End _end)
+      : it(_it), end(_end) {}
+
+      template <class F>
+	void
+	for_each(F &&fun)
+	{
+	  constexpr size_t N
+	    = std::tuple_size<std::decay_t<decltype(it->as_tuple())>>::value;
+	  for_each_impl(std::forward<F>(fun), std::make_index_sequence<N>());
+	}
+    };
+
+  template <class V, class Cont>
+    viewer<V, imported_begin_end::begin_type<const Cont &>,
+	   imported_begin_end::end_type<const Cont &>>
+    simd_view(const Cont &data)
+    {
+      using std::begin;
+      using std::end;
+      return {begin(data), end(data)};
+    }
+}  // namespace experimental
+_GLIBCXX_SIMD_END_NAMESPACE
+
+#endif  // VC_TESTS_SIMD_VIEW_H_
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h
new file mode 100644
index 00000000000..7acbb832900
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h
@@ -0,0 +1,366 @@
+#include <experimental/simd>
+#include <initializer_list>
+#include <random>
+#include <cfenv>
+
+template <class T, class A>
+  std::experimental::simd<T, A>
+  iif(std::experimental::simd_mask<T, A> k,
+      const typename std::experimental::simd_mask<T, A>::simd_type& t,
+      const std::experimental::simd<T, A>& f)
+  {
+    auto r = f;
+    where(k, r) = t;
+    return r;
+  }
+
+template <class V>
+  V
+  epilogue_load(const typename V::value_type* mem, const std::size_t size)
+  {
+    const int rem = size % V::size();
+    return where(V([](int i) { return i; }) < rem, V(0))
+	     .copy_from(mem + size / V::size() * V::size(),
+			std::experimental::element_aligned);
+  }
+
+template <class V, class... F>
+  void
+  test_values(const std::initializer_list<typename V::value_type>& inputs,
+	      F&&... fun_pack)
+  {
+    for (auto it = inputs.begin(); it + V::size() <= inputs.end();
+	 it += V::size())
+      {
+	[](auto...) {
+	}((fun_pack(V(&it[0], std::experimental::element_aligned)), 0)...);
+      }
+    [](auto...) {
+    }((fun_pack(epilogue_load<V>(inputs.begin(), inputs.size())), 0)...);
+  }
+
+template <class V>
+  struct RandomValues
+  {
+    using T = typename V::value_type;
+    static constexpr bool isfp = std::is_floating_point_v<T>;
+    const std::size_t count;
+
+    std::conditional_t<std::is_floating_point_v<T>,
+		       std::uniform_real_distribution<T>,
+		       std::uniform_int_distribution<T>>
+      dist;
+
+    const bool uniform;
+
+    const T abs_max = std::__finite_max_v<T>;
+
+    RandomValues(std::size_t count_, T min, T max)
+    : count(count_), dist(min, max), uniform(true)
+    {
+      if constexpr (std::is_floating_point_v<T>)
+	VERIFY(max - min <= std::__finite_max_v<T>);
+    }
+
+    RandomValues(std::size_t count_)
+    : count(count_), dist(isfp ? 1 : std::__finite_min_v<T>,
+			  isfp ? 2 : std::__finite_max_v<T>),
+      uniform(!isfp)
+    {}
+
+    RandomValues(std::size_t count_, T abs_max_)
+    : count(count_), dist(isfp ? 1 : -abs_max_, isfp ? 2 : abs_max_),
+      uniform(!isfp), abs_max(abs_max_)
+    {}
+
+    template <typename URBG>
+      V
+      operator()(URBG& gen)
+      {
+	if constexpr (!isfp)
+	  return V([&](int) { return dist(gen); });
+	else if (uniform)
+	  return V([&](int) { return dist(gen); });
+	else
+	  {
+	    auto exp_dist
+	      = std::normal_distribution<float>(0.f,
+						std::__max_exponent_v<T> * .5f);
+	    return V([&](int) {
+		     const T mant = dist(gen);
+		     T fp = 0;
+		     do {
+		       const int exp = exp_dist(gen);
+		       fp = std::ldexp(mant, exp);
+		     } while (fp >= abs_max || fp <= std::__denorm_min_v<T>);
+		     fp = gen() & 0x4 ? fp : -fp;
+		     return fp;
+		   });
+	  }
+      }
+  };
+
+static std::mt19937 g_mt_gen{0};
+
+template <class V, class... F>
+  void
+  test_values(const std::initializer_list<typename V::value_type>& inputs,
+	      RandomValues<V> random, F&&... fun_pack)
+  {
+    test_values<V>(inputs, fun_pack...);
+    for (size_t i = 0; i < (random.count + V::size() - 1) / V::size(); ++i)
+      {
+	[](auto...) {}((fun_pack(random(g_mt_gen)), 0)...);
+      }
+  }
+
+template <class V, class... F>
+  void
+  test_values_2arg(const std::initializer_list<typename V::value_type>& inputs,
+		   F&&... fun_pack)
+  {
+    for (auto scalar_it = inputs.begin(); scalar_it != inputs.end();
+	 ++scalar_it)
+      {
+	for (auto it = inputs.begin(); it + V::size() <= inputs.end();
+	     it += V::size())
+	  {
+	    [](auto...) {
+	    }((fun_pack(V(&it[0], std::experimental::element_aligned),
+			V(*scalar_it)),
+	       0)...);
+	  }
+	[](auto...) {
+	}((fun_pack(epilogue_load<V>(inputs.begin(), inputs.size()),
+		    V(*scalar_it)),
+	   0)...);
+      }
+  }
+
+template <class V, class... F>
+  void
+  test_values_2arg(const std::initializer_list<typename V::value_type>& inputs,
+		   RandomValues<V> random, F&&... fun_pack)
+  {
+    test_values_2arg<V>(inputs, fun_pack...);
+    for (size_t i = 0; i < (random.count + V::size() - 1) / V::size(); ++i)
+      {
+	[](auto...) {}((fun_pack(random(g_mt_gen), random(g_mt_gen)), 0)...);
+      }
+  }
+
+template <class V, class... F>
+  void
+  test_values_3arg(const std::initializer_list<typename V::value_type>& inputs,
+		   F&&... fun_pack)
+  {
+    for (auto scalar_it1 = inputs.begin(); scalar_it1 != inputs.end();
+	 ++scalar_it1)
+      {
+	for (auto scalar_it2 = inputs.begin(); scalar_it2 != inputs.end();
+	     ++scalar_it2)
+	  {
+	    for (auto it = inputs.begin(); it + V::size() <= inputs.end();
+		 it += V::size())
+	      {
+		[](auto...) {
+		}((fun_pack(V(&it[0], std::experimental::element_aligned),
+			    V(*scalar_it1), V(*scalar_it2)),
+		   0)...);
+	      }
+	    [](auto...) {
+	    }((fun_pack(epilogue_load<V>(inputs.begin(), inputs.size()),
+			V(*scalar_it1), V(*scalar_it2)),
+	       0)...);
+	  }
+      }
+  }
+
+template <class V, class... F>
+  void
+  test_values_3arg(const std::initializer_list<typename V::value_type>& inputs,
+		   RandomValues<V> random, F&&... fun_pack)
+  {
+    test_values_3arg<V>(inputs, fun_pack...);
+    for (size_t i = 0; i < (random.count + V::size() - 1) / V::size(); ++i)
+      {
+	[](auto...) {
+	}((fun_pack(random(g_mt_gen), random(g_mt_gen), random(g_mt_gen)),
+	   0)...);
+      }
+  }
+
+#if __GCC_IEC_559 < 2
+// Without IEC559 we consider -0, subnormals, +/-inf, and all NaNs to be
+// invalid (potential UB when used or "produced"). This can't use isnormal (or
+// any other classification function), since they know about the UB.
+template <class V>
+  typename V::mask_type
+  isvalid(V x)
+  {
+    using namespace std::experimental::parallelism_v2;
+    using namespace std::experimental::parallelism_v2::__proposed;
+    using T = typename V::value_type;
+    if constexpr (sizeof(T) <= sizeof(double))
+      {
+	using I = rebind_simd_t<__int_for_sizeof_t<T>, V>;
+	const I abs_x = __bit_cast<I>(abs(x));
+	const I min = __bit_cast<I>(V(std::__norm_min_v<T>));
+	const I max = __bit_cast<I>(V(std::__finite_max_v<T>));
+	return static_simd_cast<typename V::mask_type>(
+		 __bit_cast<I>(x) == 0 || (abs_x >= min && abs_x <= max));
+      }
+    else
+      {
+	const V abs_x = abs(x);
+	const V min = std::__norm_min_v<T>;
+	// Make max non-const static to inhibit constprop. Otherwise the
+	// compiler might decide `abs_x <= max` is constexpr true, by definition
+	// (-ffinite-math-only)
+	static V max = std::__finite_max_v<T>;
+	return (x == 0 && copysign(V(1), x) == V(1))
+		 || (abs_x >= min && abs_x <= max);
+      }
+  }
+
+#define MAKE_TESTER_2(name_, reference_)                                       \
+  [&](auto... inputs) {                                                        \
+    ((where(!isvalid(inputs), inputs) = 1), ...);                              \
+    const auto totest = name_(inputs...);                                      \
+    using R = std::remove_const_t<decltype(totest)>;                           \
+    auto&& expected = [&](const auto&... vs) -> const R {                      \
+      R tmp = {};                                                              \
+      for (std::size_t i = 0; i < R::size(); ++i)                              \
+	tmp[i] = reference_(vs[i]...);                                         \
+      return tmp;                                                              \
+    };                                                                         \
+    const R expect1 = expected(inputs...);                                     \
+    if constexpr (std::is_floating_point_v<typename R::value_type>)            \
+      {                                                                        \
+	((where(!isvalid(expect1), inputs) = 1), ...);                         \
+	const R expect2 = expected(inputs...);                                 \
+	((FUZZY_COMPARE(name_(inputs...), expect2) << "\ninputs = ")           \
+	 << ... << inputs);                                                    \
+      }                                                                        \
+    else                                                                       \
+      ((COMPARE(name_(inputs...), expect1) << "\n" #name_ "(")                 \
+       << ... << inputs)                                                       \
+	<< ")";                                                                \
+  }
+
+#define MAKE_TESTER_NOFPEXCEPT(name_)                                          \
+  [&](auto... inputs) {                                                        \
+    ((where(!isvalid(inputs), inputs) = 1), ...);                              \
+    using R = std::remove_const_t<decltype(name_(inputs...))>;                 \
+    auto&& expected = [&](const auto&... vs) -> const R {                      \
+      R tmp = {};                                                              \
+      for (std::size_t i = 0; i < R::size(); ++i)                              \
+	tmp[i] = std::name_(vs[i]...);                                         \
+      return tmp;                                                              \
+    };                                                                         \
+    const R expect1 = expected(inputs...);                                     \
+    if constexpr (std::is_floating_point_v<typename R::value_type>)            \
+      {                                                                        \
+	((where(!isvalid(expect1), inputs) = 1), ...);                         \
+	std::feclearexcept(FE_ALL_EXCEPT);                                     \
+	asm volatile("");                                                      \
+	auto totest = name_(inputs...);                                        \
+	asm volatile("");                                                      \
+	((COMPARE(std::fetestexcept(FE_ALL_EXCEPT), 0) << "\n" #name_ "(")     \
+	 << ... << inputs)                                                     \
+	  << ")";                                                              \
+	const R expect2 = expected(inputs...);                                 \
+	std::feclearexcept(FE_ALL_EXCEPT);                                     \
+	asm volatile("");                                                      \
+	totest = name_(inputs...);                                             \
+	asm volatile("");                                                      \
+	((COMPARE(std::fetestexcept(FE_ALL_EXCEPT), 0) << "\n" #name_ "(")     \
+	 << ... << inputs)                                                     \
+	  << ")";                                                              \
+	((FUZZY_COMPARE(totest, expect2) << "\n" #name_ "(") << ... << inputs) \
+	  << ")";                                                              \
+      }                                                                        \
+    else                                                                       \
+      {                                                                        \
+	std::feclearexcept(FE_ALL_EXCEPT);                                     \
+	asm volatile("");                                                      \
+	auto totest = name_(inputs...);                                        \
+	asm volatile("");                                                      \
+	((COMPARE(std::fetestexcept(FE_ALL_EXCEPT), 0) << "\n" #name_ "(")     \
+	 << ... << inputs)                                                     \
+	  << ")";                                                              \
+	((COMPARE(totest, expect1) << "\n" #name_ "(") << ... << inputs)       \
+	  << ")";                                                              \
+      }                                                                        \
+  }
+
+#else
+
+#define MAKE_TESTER_2(name_, reference_)                                       \
+  [&](auto... inputs) {                                                        \
+    const auto totest = name_(inputs...);                                      \
+    using R = std::remove_const_t<decltype(totest)>;                           \
+    auto&& expected = [&](const auto&... vs) -> const R {                      \
+      R tmp = {};                                                              \
+      for (std::size_t i = 0; i < R::size(); ++i)                              \
+	tmp[i] = reference_(vs[i]...);                                         \
+      return tmp;                                                              \
+    };                                                                         \
+    const R expect1 = expected(inputs...);                                     \
+    if constexpr (std::is_floating_point_v<typename R::value_type>)            \
+      {                                                                        \
+	((COMPARE(isnan(totest), isnan(expect1)) << #name_ "(")                \
+	 << ... << inputs)                                                     \
+	  << ") = " << totest << " != " << expect1;                            \
+	((where(isnan(expect1), inputs) = 0), ...);                            \
+	((FUZZY_COMPARE(name_(inputs...), expected(inputs...))                 \
+	  << "\nclean = ")                                                     \
+	 << ... << inputs);                                                    \
+      }                                                                        \
+    else                                                                       \
+      ((COMPARE(name_(inputs...), expect1) << "\n" #name_ "(")                 \
+       << ... << inputs)                                                       \
+	<< ")";                                                                \
+  }
+
+#define MAKE_TESTER_NOFPEXCEPT(name_)                                          \
+  [&](auto... inputs) {                                                        \
+    std::feclearexcept(FE_ALL_EXCEPT);                                         \
+    auto totest = name_(inputs...);                                            \
+    ((COMPARE(std::fetestexcept(FE_ALL_EXCEPT), 0) << "\n" #name_ "(")         \
+     << ... << inputs)                                                         \
+      << ")";                                                                  \
+    using R = std::remove_const_t<decltype(totest)>;                           \
+    auto&& expected = [&](const auto&... vs) -> const R {                      \
+      R tmp = {};                                                              \
+      for (std::size_t i = 0; i < R::size(); ++i)                              \
+	tmp[i] = std::name_(vs[i]...);                                         \
+      return tmp;                                                              \
+    };                                                                         \
+    const R expect1 = expected(inputs...);                                     \
+    if constexpr (std::is_floating_point_v<typename R::value_type>)            \
+      {                                                                        \
+	((COMPARE(isnan(totest), isnan(expect1)) << #name_ "(")                \
+	 << ... << inputs)                                                     \
+	  << ") = " << totest << " != " << expect1;                            \
+	((where(isnan(expect1), inputs) = 0), ...);                            \
+	const R expect2 = expected(inputs...);                                 \
+	std::feclearexcept(FE_ALL_EXCEPT);                                     \
+	asm volatile("");                                                      \
+	totest = name_(inputs...);                                             \
+	asm volatile("");                                                      \
+	((COMPARE(std::fetestexcept(FE_ALL_EXCEPT), 0) << "\n" #name_ "(")     \
+	 << ... << inputs)                                                     \
+	  << ")";                                                              \
+	FUZZY_COMPARE(totest, expect2);                                        \
+      }                                                                        \
+    else                                                                       \
+      {                                                                        \
+	((COMPARE(totest, expect1) << "\n" #name_ "(") << ... << inputs)       \
+	  << ")";                                                              \
+      }                                                                        \
+  }
+
+#endif
+
+#define MAKE_TESTER(name_) MAKE_TESTER_2(name_, std::name_)
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/ulp.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/ulp.h
new file mode 100644
index 00000000000..c1b9e7adb07
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/ulp.h
@@ -0,0 +1,111 @@
+/*{
+Copyright © 2011-2018 Matthias Kretz <kretz@kde.org>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the names of contributing organizations nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+}*/
+
+#ifndef ULP_H
+#define ULP_H
+
+#include <cmath>
+#include <experimental/simd>
+#include <type_traits>
+#include <cfenv>
+
+namespace vir {
+  namespace test {
+    template <typename T, typename R = typename T::value_type>
+      R
+      value_type_impl(int);
+
+    template <typename T>
+      T
+      value_type_impl(float);
+
+    template <typename T>
+      using value_type_t = decltype(value_type_impl<T>(int()));
+
+    template <typename T>
+      inline T
+      ulp_distance(const T& val_, const T& ref_)
+      {
+        if constexpr (std::is_floating_point_v<value_type_t<T>>)
+          {
+            const int fp_exceptions = std::fetestexcept(FE_ALL_EXCEPT);
+            T val = val_;
+            T ref = ref_;
+
+            T diff = T();
+
+            using std::abs;
+            using std::fpclassify;
+            using std::frexp;
+            using std::isnan;
+            using std::isinf;
+            using std::ldexp;
+            using std::max;
+            using std::experimental::where;
+            using TT = value_type_t<T>;
+
+            where(ref == 0, val) = abs(val);
+            where(ref == 0, diff) = 1;
+            where(ref == 0, ref) = std::__norm_min_v<TT>;
+            where(isinf(ref) && ref == val, ref)
+              = 0; // where(val_ == ref_) = 0 below will fix it up
+
+            where(val == 0, ref) = abs(ref);
+            where(val == 0, diff) += 1;
+            where(val == 0, val) = std::__norm_min_v<TT>;
+
+            using I = decltype(fpclassify(std::declval<T>()));
+            I exp = {};
+            frexp(ref, &exp);
+            // lower bound for exp must be min_exponent to scale the resulting
+            // difference from a denormal correctly
+            exp = max(exp, I(std::__min_exponent_v<TT>));
+            diff += ldexp(abs(ref - val), std::__digits_v<TT> - exp);
+            where(val_ == ref_ || (isnan(val_) && isnan(ref_)), diff) = T();
+            std::feclearexcept(FE_ALL_EXCEPT ^ fp_exceptions);
+            return diff;
+          }
+        else
+          {
+            if (val_ > ref_)
+              return val_ - ref_;
+            else
+              return ref_ - val_;
+          }
+      }
+
+    template <typename T>
+      inline T
+      ulp_distance_signed(const T& _val, const T& _ref)
+      {
+        using std::copysign;
+        return copysign(ulp_distance(_val, _ref), _val - _ref);
+      }
+  } // namespace test
+} // namespace vir
+
+#endif // ULP_H
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/verify.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/verify.h
new file mode 100644
index 00000000000..7ec6de7f16b
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/verify.h
@@ -0,0 +1,336 @@
+#ifndef TESTS_BITS_VERIFY_H_
+#define TESTS_BITS_VERIFY_H_
+
+#include <experimental/simd>
+#include <sstream>
+#include <iomanip>
+#include "ulp.h"
+
+#ifdef _GLIBCXX_SIMD_HAVE_NEON
+// work around PR89357:
+#define alignas(...) __attribute__((aligned(__VA_ARGS__)))
+#endif
+
+using schar = signed char;
+using uchar = unsigned char;
+using ushort = unsigned short;
+using uint = unsigned int;
+using ulong = unsigned long;
+using llong = long long;
+using ullong = unsigned long long;
+using ldouble = long double;
+using wchar = wchar_t;
+using char16 = char16_t;
+using char32 = char32_t;
+
+template <class T>
+  T
+  make_value_unknown(const T& x)
+  {
+    if constexpr (std::is_constructible_v<T, const volatile T&>)
+      {
+	const volatile T& y = x;
+	return y;
+      }
+    else
+      {
+	T y = x;
+	asm("" : "+m"(y));
+	return y;
+      }
+  }
+
+class verify
+{
+  const bool m_failed = false;
+
+  template <typename T,
+	    typename = decltype(std::declval<std::stringstream&>()
+				<< std::declval<const T&>())>
+    void
+    print(const T& x, int) const
+    {
+      std::stringstream ss;
+      ss << x;
+      __builtin_fprintf(stderr, "%s", ss.str().c_str());
+    }
+
+  template <typename T>
+    void
+    print(const T& x, ...) const
+    {
+      if constexpr (std::experimental::is_simd_v<T>)
+	{
+	  std::stringstream ss;
+	  if constexpr (std::is_floating_point_v<typename T::value_type>)
+	    {
+	      ss << '(' << x[0] << " == " << std::hexfloat << x[0]
+		<< std::defaultfloat << ')';
+	      for (unsigned i = 1; i < x.size(); ++i)
+		{
+		  ss << (i % 4 == 0 ? ",\n(" : ", (") << x[i]
+		    << " == " << std::hexfloat << x[i] << std::defaultfloat
+		    << ')';
+		}
+	    }
+	  else
+	    {
+	      ss << +x[0];
+	      for (unsigned i = 1; i < x.size(); ++i)
+		{
+		  ss << ", " << +x[i];
+		}
+	    }
+	  __builtin_fprintf(stderr, "%s", ss.str().c_str());
+	}
+      else if constexpr (std::experimental::is_simd_mask_v<T>)
+	{
+	  __builtin_fprintf(stderr, (x[0] ? "[1" : "[0"));
+	  for (unsigned i = 1; i < x.size(); ++i)
+	    {
+	      __builtin_fprintf(stderr, (x[i] ? "1" : "0"));
+	    }
+	  __builtin_fprintf(stderr, "]");
+	}
+      else
+	{
+	  print_hex(&x, sizeof(T));
+	}
+    }
+
+  void
+  print_hex(const void* x, std::size_t n) const
+  {
+    __builtin_fprintf(stderr, "0x");
+    const auto* bytes = static_cast<const unsigned char*>(x);
+    for (std::size_t i = 0; i < n; ++i)
+      {
+	__builtin_fprintf(stderr, (i && i % 4 == 0) ? "'%02x" : "%02x",
+			  bytes[i]);
+      }
+  }
+
+public:
+  template <typename... Ts>
+    verify(bool ok, size_t ip, const char* file, const int line,
+	   const char* func, const char* cond, const Ts&... extra_info)
+    : m_failed(!ok)
+    {
+      if (m_failed)
+	{
+	  __builtin_fprintf(stderr, "%s:%d: (%s):\nInstruction Pointer: %x\n"
+				    "Assertion '%s' failed.\n",
+			    file, line, func, ip, cond);
+	  (print(extra_info, int()), ...);
+	}
+    }
+
+  ~verify()
+  {
+    if (m_failed)
+      {
+	__builtin_fprintf(stderr, "\n");
+	__builtin_abort();
+      }
+  }
+
+  template <typename T>
+    const verify&
+    operator<<(const T& x) const
+    {
+      if (m_failed)
+	{
+	  print(x, int());
+	}
+      return *this;
+    }
+
+  template <typename... Ts>
+    const verify&
+    on_failure(const Ts&... xs) const
+    {
+      if (m_failed)
+	(print(xs, int()), ...);
+      return *this;
+    }
+
+  [[gnu::always_inline]] static inline size_t
+  get_ip()
+  {
+    size_t _ip = 0;
+#ifdef __x86_64__
+    asm volatile("lea 0(%%rip),%0" : "=r"(_ip));
+#elif defined __i386__
+    asm volatile("1: movl $1b,%0" : "=r"(_ip));
+#elif defined __arm__
+    asm volatile("mov %0,pc" : "=r"(_ip));
+#elif defined __aarch64__
+    asm volatile("adr %0,." : "=r"(_ip));
+#endif
+    return _ip;
+  }
+};
+
+#if __FLT_EVAL_METHOD__ != 0
+template <typename T>
+  [[gnu::always_inline]] inline decltype(auto)
+  force_fp_truncation(const T& x)
+  {
+    namespace stdx = std::experimental;
+    if constexpr (stdx::is_simd_v<T>)
+      {
+	using U = typename T::value_type;
+	if constexpr (std::is_floating_point_v<typename T::value_type>
+		      && sizeof(U) <= 8 && (sizeof(T) < 16 || std::is_same_v<
+		  T, stdx::fixed_size_simd<U, T::size()>>))
+	  {
+	    T y = x;
+	    asm("" : "+m"(y));
+	    return y;
+	  }
+	else
+	  return x;
+      }
+    else if constexpr (std::is_floating_point_v<T> && sizeof(T) <= 8)
+      {
+	T y = x;
+	asm("" : "+m"(y));
+	return y;
+      }
+    else
+      return x;
+  }
+
+#define COMPARE(_a, _b)                                                        \
+  [&](auto&& _aa, auto&& _bb) {                                                \
+    return verify(std::experimental::all_of(_aa == _bb), verify::get_ip(),     \
+		  __FILE__, __LINE__, __PRETTY_FUNCTION__,                     \
+		  "all_of(" #_a " == " #_b ")", #_a " = ", _aa,                \
+		  "\n" #_b " = ", _bb);                                        \
+  }(force_fp_truncation(_a), force_fp_truncation(_b))
+#else
+#define COMPARE(_a, _b)                                                        \
+  [&](auto&& _aa, auto&& _bb) {                                                \
+    return verify(std::experimental::all_of(_aa == _bb), verify::get_ip(),     \
+		  __FILE__, __LINE__, __PRETTY_FUNCTION__,                     \
+		  "all_of(" #_a " == " #_b ")", #_a " = ", _aa,                \
+		  "\n" #_b " = ", _bb);                                        \
+  }((_a), (_b))
+#endif
+
+#define VERIFY(_test)                                                          \
+  verify(_test, verify::get_ip(), __FILE__, __LINE__, __PRETTY_FUNCTION__,     \
+	 #_test)
+
+  // ulp_distance_signed can raise FP exceptions and thus must be conditionally
+  // executed
+#define ULP_COMPARE(_a, _b, _allowed_distance)                                 \
+  [&](auto&& _aa, auto&& _bb) {                                                \
+    const bool success = std::experimental::all_of(                            \
+      vir::test::ulp_distance(_aa, _bb) <= (_allowed_distance));               \
+    return verify(success, verify::get_ip(), __FILE__, __LINE__,               \
+		  __PRETTY_FUNCTION__, "all_of(" #_a " ~~ " #_b ")",           \
+		  #_a " = ", _aa, "\n" #_b " = ", _bb, "\ndistance = ",        \
+		  success ? 0 : vir::test::ulp_distance_signed(_aa, _bb));     \
+  }((_a), (_b))
+
+namespace vir {
+  namespace test
+  {
+    template <typename T>
+      inline T _S_fuzzyness = 0;
+
+    template <typename T>
+      void
+      setFuzzyness(T x)
+      { _S_fuzzyness<T> = x; }
+  } // namespace test
+} // namespace vir
+
+#define FUZZY_COMPARE(_a, _b)                                                  \
+  ULP_COMPARE(                                                                 \
+    _a, _b,                                                                    \
+    vir::test::_S_fuzzyness<vir::test::value_type_t<decltype((_a) + (_b))>>)
+
+template <typename V>
+  void
+  test();
+
+template <typename V>
+  void
+  invoke_test(...)
+  {}
+
+template <typename V, typename = decltype(V())>
+  void
+  invoke_test(int)
+  {
+    test<V>();
+    __builtin_fprintf(stderr, "PASS: %s\n", __PRETTY_FUNCTION__);
+  }
+
+template <class T>
+  void
+  iterate_abis()
+  {
+    using namespace std::experimental::parallelism_v2;
+#ifndef EXTENDEDTESTS
+    invoke_test<simd<T, simd_abi::scalar>>(int());
+    invoke_test<simd<T, simd_abi::_VecBuiltin<16>>>(int());
+    invoke_test<simd<T, simd_abi::_VecBltnBtmsk<64>>>(int());
+#elif EXTENDEDTESTS == 0
+    invoke_test<simd<T, simd_abi::_VecBuiltin<8>>>(int());
+    invoke_test<simd<T, simd_abi::_VecBuiltin<12>>>(int());
+    invoke_test<simd<T, simd_abi::_VecBuiltin<24>>>(int());
+    invoke_test<simd<T, simd_abi::_VecBuiltin<32>>>(int());
+    invoke_test<simd<T, simd_abi::_VecBltnBtmsk<56>>>(int());
+#elif EXTENDEDTESTS == 1
+    invoke_test<simd<T, simd_abi::fixed_size<8>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<16>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<24>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<32>>>(int());
+#elif EXTENDEDTESTS == 2
+    invoke_test<simd<T, simd_abi::fixed_size<1>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<9>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<17>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<25>>>(int());
+#elif EXTENDEDTESTS == 3
+    invoke_test<simd<T, simd_abi::fixed_size<2>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<10>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<18>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<26>>>(int());
+#elif EXTENDEDTESTS == 4
+    invoke_test<simd<T, simd_abi::fixed_size<3>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<19>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<11>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<27>>>(int());
+#elif EXTENDEDTESTS == 5
+    invoke_test<simd<T, simd_abi::fixed_size<4>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<12>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<20>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<28>>>(int());
+#elif EXTENDEDTESTS == 6
+    invoke_test<simd<T, simd_abi::fixed_size<5>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<13>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<21>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<29>>>(int());
+#elif EXTENDEDTESTS == 7
+    invoke_test<simd<T, simd_abi::fixed_size<6>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<14>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<22>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<30>>>(int());
+#elif EXTENDEDTESTS == 8
+    invoke_test<simd<T, simd_abi::fixed_size<7>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<15>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<23>>>(int());
+    invoke_test<simd<T, simd_abi::fixed_size<31>>>(int());
+#endif
+  }
+
+int main()
+{
+  iterate_abis<_GLIBCXX_SIMD_TESTTYPE>();
+  return 0;
+}
+
+#endif  // TESTS_BITS_VERIFY_H_
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/broadcast.cc b/libstdc++-v3/testsuite/experimental/simd/tests/broadcast.cc
new file mode 100644
index 00000000000..529280d87d4
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/broadcast.cc
@@ -0,0 +1,87 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+
+enum unscoped_enum
+{ foo };
+
+enum class scoped_enum
+{ bar };
+
+struct convertible
+{
+  operator int();
+  operator float();
+};
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+    VERIFY(std::experimental::is_simd_v<V>);
+    VERIFY(std::experimental::is_abi_tag_v<typename V::abi_type>);
+
+    {
+      V x;     // not initialized
+      x = V{}; // default broadcasts 0
+      COMPARE(x, V(0));
+      COMPARE(x, V());
+      COMPARE(x, V{});
+      x = V(); // default broadcasts 0
+      COMPARE(x, V(0));
+      COMPARE(x, V());
+      COMPARE(x, V{});
+      x = 0;
+      COMPARE(x, V(0));
+      COMPARE(x, V());
+      COMPARE(x, V{});
+
+      for (std::size_t i = 0; i < V::size(); ++i)
+	{
+	  COMPARE(T(x[i]), T(0)) << "i = " << i;
+	  COMPARE(x[i], T(0)) << "i = " << i;
+	}
+    }
+
+    V x = 3;
+    V y = T(0);
+    for (std::size_t i = 0; i < V::size(); ++i)
+      {
+	COMPARE(x[i], T(3)) << "i = " << i;
+	COMPARE(y[i], T(0)) << "i = " << i;
+      }
+    y = 3;
+    COMPARE(x, y);
+
+    VERIFY(!(is_substitution_failure<V&, unscoped_enum, assignment>) );
+    VERIFY((is_substitution_failure<V&, scoped_enum, assignment>) );
+    COMPARE((is_substitution_failure<V&, convertible, assignment>),
+	    (!std::is_convertible<convertible, T>::value));
+    COMPARE((is_substitution_failure<V&, long double, assignment>),
+	    (sizeof(long double) > sizeof(T) || std::is_integral<T>::value));
+    COMPARE((is_substitution_failure<V&, double, assignment>),
+	    (sizeof(double) > sizeof(T) || std::is_integral<T>::value));
+    COMPARE((is_substitution_failure<V&, float, assignment>),
+	    (sizeof(float) > sizeof(T) || std::is_integral<T>::value));
+    COMPARE((is_substitution_failure<V&, long long, assignment>),
+	    (has_less_bits<T, long long>() || std::is_unsigned<T>::value));
+    COMPARE((is_substitution_failure<V&, unsigned long long, assignment>),
+	    (has_less_bits<T, unsigned long long>()));
+    COMPARE((is_substitution_failure<V&, long, assignment>),
+	    (has_less_bits<T, long>() || std::is_unsigned<T>::value));
+    COMPARE((is_substitution_failure<V&, unsigned long, assignment>),
+	    (has_less_bits<T, unsigned long>()));
+    // int broadcast *always* works:
+    VERIFY(!(is_substitution_failure<V&, int, assignment>) );
+    // uint broadcast works for any unsigned T:
+    COMPARE((is_substitution_failure<V&, unsigned int, assignment>),
+	    (!std::is_unsigned<T>::value && has_less_bits<T, unsigned int>()));
+    COMPARE((is_substitution_failure<V&, short, assignment>),
+	    (has_less_bits<T, short>() || std::is_unsigned<T>::value));
+    COMPARE((is_substitution_failure<V&, unsigned short, assignment>),
+	    (has_less_bits<T, unsigned short>()));
+    COMPARE((is_substitution_failure<V&, signed char, assignment>),
+	    (has_less_bits<T, signed char>() || std::is_unsigned<T>::value));
+    COMPARE((is_substitution_failure<V&, unsigned char, assignment>),
+	    (has_less_bits<T, unsigned char>()));
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/casts.cc b/libstdc++-v3/testsuite/experimental/simd/tests/casts.cc
new file mode 100644
index 00000000000..e2c0b108879
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/casts.cc
@@ -0,0 +1,152 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/conversions.h"
+
+using std::experimental::simd_cast;
+using std::experimental::static_simd_cast;
+
+template <class T, size_t N>
+  struct gen_cast
+  {
+    std::array<T, N> data;
+
+    template <class V>
+      gen_cast(const V& v)
+      {
+	for (size_t i = 0; i < V::size(); ++i)
+	  {
+	    data[i] = static_cast<T>(v[i]);
+	  }
+      }
+
+    template <class I>
+      constexpr T
+      operator()(I)
+      { return data[I::value]; }
+  };
+
+template <class V, class To>
+  struct gen_seq_t
+  {
+    using From = typename V::value_type;
+    const size_t N = cvt_input_data<From, To>.size();
+    size_t offset = 0;
+
+    constexpr void
+    operator++()
+    { offset += V::size(); }
+
+    explicit constexpr operator bool() const
+    { return offset < N; }
+
+    template <class I>
+      constexpr From
+      operator()(I) const
+      {
+	size_t i = I::value + offset;
+	return i < N ? cvt_input_data<From, To>[i] : From(i);
+      }
+  };
+
+template <class To>
+  struct foo
+  {
+    template <class T>
+      auto
+      operator()(const T& v) -> decltype(simd_cast<To>(v));
+  };
+
+template <typename V, typename To>
+  void
+  casts()
+  {
+    using From = typename V::value_type;
+    constexpr auto N = V::size();
+    if constexpr (N <= std::experimental::simd_abi::max_fixed_size<To>)
+      {
+	using W = std::experimental::fixed_size_simd<To, N>;
+
+	if constexpr (std::is_integral_v<From>)
+	  {
+	    using A = typename V::abi_type;
+	    using TU = std::make_unsigned_t<From>;
+	    using TS = std::make_signed_t<From>;
+	    COMPARE(typeid(static_simd_cast<TU>(V())),
+		    typeid(std::experimental::simd<TU, A>));
+	    COMPARE(typeid(static_simd_cast<TS>(V())),
+		    typeid(std::experimental::simd<TS, A>));
+	  }
+
+	using is_simd_cast_allowed
+	  = decltype(vir::test::sfinae_is_callable_t<const V&>(foo<To>()));
+
+	COMPARE(is_simd_cast_allowed::value,
+		std::__digits<From>::value <= std::__digits<To>::value
+		  && std::__finite_max<From>::value
+		  <= std::__finite_max<To>::value
+		  && !(std::is_signed<From>::value
+		       && std::is_unsigned<To>::value));
+
+	if constexpr (is_simd_cast_allowed::value)
+	  {
+	    for (gen_seq_t<V, To> gen_seq; gen_seq; ++gen_seq)
+	      {
+		const V seq(gen_seq);
+		COMPARE(simd_cast<V>(seq), seq);
+		COMPARE(simd_cast<W>(seq), W(gen_cast<To, N>(seq)))
+		  << "seq = " << seq;
+		auto test = simd_cast<To>(seq);
+		// decltype(test) is not W if
+		// a) V::abi_type is not fixed_size and
+		// b.1) V::value_type and To are integral and of equal rank or
+		// b.2) V::value_type and To are equal
+		COMPARE(test, decltype(test)(gen_cast<To, N>(seq)));
+		if (std::is_same<To, From>::value)
+		  {
+		    COMPARE(typeid(decltype(test)), typeid(V));
+		  }
+	      }
+	  }
+
+	for (gen_seq_t<V, To> gen_seq; gen_seq; ++gen_seq)
+	  {
+	    const V seq(gen_seq);
+	    COMPARE(static_simd_cast<V>(seq), seq);
+	    COMPARE(static_simd_cast<W>(seq), W(gen_cast<To, N>(seq))) << '\n'
+	      << seq;
+	    auto test = static_simd_cast<To>(seq);
+	    // decltype(test) is not W if
+	    // a) V::abi_type is not fixed_size and
+	    // b.1) V::value_type and To are integral and of equal rank or
+	    // b.2) V::value_type and To are equal
+	    COMPARE(test, decltype(test)(gen_cast<To, N>(seq)));
+	    if (std::is_same<To, From>::value)
+	      {
+		COMPARE(typeid(decltype(test)), typeid(V));
+	      }
+	  }
+      }
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    casts<V, long double>();
+    casts<V, double>();
+    casts<V, float>();
+    casts<V, long long>();
+    casts<V, unsigned long long>();
+    casts<V, unsigned long>();
+    casts<V, long>();
+    casts<V, int>();
+    casts<V, unsigned int>();
+    casts<V, short>();
+    casts<V, unsigned short>();
+    casts<V, char>();
+    casts<V, signed char>();
+    casts<V, unsigned char>();
+    casts<V, char32_t>();
+    casts<V, char16_t>();
+    casts<V, wchar_t>();
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/fpclassify.cc b/libstdc++-v3/testsuite/experimental/simd/tests/fpclassify.cc
new file mode 100644
index 00000000000..87a80308ae9
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/fpclassify.cc
@@ -0,0 +1,89 @@
+// test only floattypes
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/test_values.h"
+#include <cfenv>
+
+template <typename F>
+  auto
+  verify_no_fp_exceptions(F&& fun)
+  {
+    std::feclearexcept(FE_ALL_EXCEPT);
+    auto r = fun();
+    COMPARE(std::fetestexcept(FE_ALL_EXCEPT), 0);
+    return r;
+  }
+
+#define NOFPEXCEPT(...) verify_no_fp_exceptions([&]() { return __VA_ARGS__; })
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+    using intv = std::experimental::fixed_size_simd<int, V::size()>;
+    constexpr T inf = std::__infinity_v<T>;
+    constexpr T denorm_min = std::__infinity_v<T>;
+    constexpr T nan = std::__quiet_NaN_v<T>;
+    constexpr T max = std::__finite_max_v<T>;
+    constexpr T norm_min = std::__norm_min_v<T>;
+    test_values<V>(
+      {0., 1., -1.,
+#if __GCC_IEC_559 >= 2
+       -0., inf, -inf, denorm_min, -denorm_min, nan,
+       norm_min * 0.9, -norm_min * 0.9,
+#endif
+       max, -max, norm_min, -norm_min
+      },
+      [](const V input) {
+	COMPARE(NOFPEXCEPT(isfinite(input)),
+		!V([&](auto i) { return std::isfinite(input[i]) ? 0 : 1; }))
+	  << input;
+	COMPARE(NOFPEXCEPT(isinf(input)),
+		!V([&](auto i) { return std::isinf(input[i]) ? 0 : 1; }))
+	  << input;
+	COMPARE(NOFPEXCEPT(isnan(input)),
+		!V([&](auto i) { return std::isnan(input[i]) ? 0 : 1; }))
+	  << input;
+	COMPARE(NOFPEXCEPT(isnormal(input)),
+		!V([&](auto i) { return std::isnormal(input[i]) ? 0 : 1; }))
+	  << input;
+	COMPARE(NOFPEXCEPT(signbit(input)),
+		!V([&](auto i) { return std::signbit(input[i]) ? 0 : 1; }))
+	  << input;
+	COMPARE(NOFPEXCEPT(isunordered(input, V())),
+		!V([&](auto i) { return std::isunordered(input[i], 0) ? 0 : 1; }))
+	  << input;
+	COMPARE(NOFPEXCEPT(isunordered(V(), input)),
+		!V([&](auto i) { return std::isunordered(0, input[i]) ? 0 : 1; }))
+	  << input;
+	COMPARE(NOFPEXCEPT(fpclassify(input)),
+		intv([&](auto i) { return std::fpclassify(input[i]); }))
+	  << input;
+      });
+#ifdef __SUPPORT_SNAN__
+    const V snan = std::__signaling_NaN_v<T>;
+    COMPARE(isfinite(snan),
+	    !V([&](auto i) { return std::isfinite(snan[i]) ? 0 : 1; }))
+      << snan;
+    COMPARE(isinf(snan), !V([&](auto i) { return std::isinf(snan[i]) ? 0 : 1; }))
+      << snan;
+    COMPARE(isnan(snan), !V([&](auto i) { return std::isnan(snan[i]) ? 0 : 1; }))
+      << snan;
+    COMPARE(isnormal(snan),
+	    !V([&](auto i) { return std::isnormal(snan[i]) ? 0 : 1; }))
+      << snan;
+    COMPARE(signbit(snan),
+	    !V([&](auto i) { return std::signbit(snan[i]) ? 0 : 1; }))
+      << snan;
+    COMPARE(isunordered(snan, V()),
+	    !V([&](auto i) { return std::isunordered(snan[i], 0) ? 0 : 1; }))
+      << snan;
+    COMPARE(isunordered(V(), snan),
+	    !V([&](auto i) { return std::isunordered(0, snan[i]) ? 0 : 1; }))
+      << snan;
+    COMPARE(fpclassify(snan),
+	    intv([&](auto i) { return std::fpclassify(snan[i]); }))
+      << snan;
+#endif
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/frexp.cc b/libstdc++-v3/testsuite/experimental/simd/tests/frexp.cc
new file mode 100644
index 00000000000..1f9b30162cb
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/frexp.cc
@@ -0,0 +1,68 @@
+// test only floattypes
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/test_values.h"
+
+template <typename V>
+  void
+  test()
+  {
+    using int_v = std::experimental::fixed_size_simd<int, V::size()>;
+    using T = typename V::value_type;
+    constexpr auto denorm_min = std::__denorm_min_v<T>;
+    constexpr auto norm_min = std::__norm_min_v<T>;
+    constexpr auto max = std::__finite_max_v<T>;
+    constexpr auto nan = std::__quiet_NaN_v<T>;
+    constexpr auto inf = std::__infinity_v<T>;
+    test_values<V>(
+      {0, 0.25, 0.5, 1, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+       20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 31, -0., -0.25, -0.5, -1,
+       -3, -4, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18,
+       -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -32, -31,
+#if __GCC_IEC_559 >= 2
+       denorm_min, -denorm_min, norm_min / 2, -norm_min / 2,
+#endif
+       max, -max, max * 0.123f, -max * 0.123f},
+      [](const V input) {
+	V expectedFraction;
+	const int_v expectedExponent([&](auto i) {
+	  int exp;
+	  expectedFraction[i] = std::frexp(input[i], &exp);
+	  return exp;
+	});
+	int_v exponent = {};
+	const V fraction = frexp(input, &exponent);
+	COMPARE(fraction, expectedFraction) << ", input = " << input
+	  << ", delta: " << fraction - expectedFraction;
+	COMPARE(exponent, expectedExponent)
+	  << "\ninput: " << input << ", fraction: " << fraction;
+      });
+#ifdef __STDC_IEC_559__
+    test_values<V>(
+      // If x is a NaN, a NaN is returned, and the value of *exp is unspecified.
+      //
+      // If x is positive  infinity  (negative  infinity),  positive  infinity
+      // (negative infinity) is returned, and the value of *exp is unspecified.
+      // This behavior is only guaranteed with C's Annex F when __STDC_IEC_559__
+      // is defined.
+      {nan, inf, -inf, denorm_min, denorm_min * 1.72, -denorm_min,
+       -denorm_min * 1.72, 0., -0., 1, -1},
+      [](const V input) {
+	const V expectedFraction([&](auto i) {
+	  int exp;
+	  return std::frexp(input[i], &exp);
+	});
+	int_v exponent = {};
+	const V fraction = frexp(input, &exponent);
+	COMPARE(isnan(fraction), isnan(expectedFraction))
+	  << fraction << ", input = " << input
+	  << ", delta: " << fraction - expectedFraction;
+	COMPARE(isinf(fraction), isinf(expectedFraction))
+	  << fraction << ", input = " << input
+	  << ", delta: " << fraction - expectedFraction;
+	COMPARE(signbit(fraction), signbit(expectedFraction))
+	  << fraction << ", input = " << input
+	  << ", delta: " << fraction - expectedFraction;
+      });
+#endif
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/generator.cc b/libstdc++-v3/testsuite/experimental/simd/tests/generator.cc
new file mode 100644
index 00000000000..62ec716c82d
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/generator.cc
@@ -0,0 +1,41 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+
+template <class V>
+  struct call_generator
+  {
+    template <class F>
+      auto
+      operator()(const F& f) -> decltype(V(f));
+  };
+
+using schar = signed char;
+using uchar = unsigned char;
+using ullong = unsigned long long;
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+    V x([](int) { return T(1); });
+    COMPARE(x, V(1));
+    // unconditionally returns int from generator lambda
+    x = V([](int) { return 1; });
+    COMPARE(x, V(1));
+    x = V([](auto i) { return T(i); });
+    COMPARE(x, V([](T i) { return i; }));
+
+    VERIFY((// that int always works
+	sfinae_is_callable<int (&)(int)>(call_generator<V>())));
+    COMPARE(sfinae_is_callable<schar (&)(int)>(call_generator<V>()),
+	    std::is_signed<T>::value);
+    COMPARE(sfinae_is_callable<uchar (&)(int)>(call_generator<V>()),
+	    !(std::is_signed_v<T> && sizeof(T) <= sizeof(uchar)));
+    COMPARE(sfinae_is_callable<float (&)(int)>(call_generator<V>()),
+	    (std::is_floating_point<T>::value));
+
+    COMPARE(sfinae_is_callable<ullong (&)(int)>(call_generator<V>()),
+      std::__finite_max_v<T> >= std::__finite_max_v<ullong>
+      && std::__digits_v<T> >= std::__digits_v<ullong>);
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/hypot3_fma.cc b/libstdc++-v3/testsuite/experimental/simd/tests/hypot3_fma.cc
new file mode 100644
index 00000000000..330a79400ee
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/hypot3_fma.cc
@@ -0,0 +1,134 @@
+// test only floattypes
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/test_values.h"
+
+// 3-arg std::hypot needs to be fixed, this is a better reference:
+template <typename T>
+  [[gnu::optimize("-fno-unsafe-math-optimizations")]]
+  T
+  hypot3(T x, T y, T z)
+  {
+    x = std::abs(x);
+    y = std::abs(y);
+    z = std::abs(z);
+    if (std::isinf(x) || std::isinf(y) || std::isinf(z))
+      return std::__infinity_v<T>;
+    else if (std::isnan(x) || std::isnan(y) || std::isnan(z))
+      return std::__quiet_NaN_v<T>;
+    else if (x == y && y == z)
+      return x * std::sqrt(T(3));
+    else if (z == 0 && y == 0)
+      return x;
+    else if (x == 0 && z == 0)
+      return y;
+    else if (x == 0 && y == 0)
+      return z;
+    else
+      {
+	T hi = std::max(std::max(x, y), z);
+	T lo0 = std::min(std::max(x, y), z);
+	T lo1 = std::min(x, y);
+	int e = 0;
+	hi = std::frexp(hi, &e);
+	lo0 = std::ldexp(lo0, -e);
+	lo1 = std::ldexp(lo1, -e);
+	T lo = lo0 * lo0 + lo1 * lo1;
+	return std::ldexp(std::sqrt(hi * hi + lo), e);
+      }
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    vir::test::setFuzzyness<float>(1);
+    vir::test::setFuzzyness<double>(1);
+    vir::test::setFuzzyness<long double>(2); // because of the bad reference
+
+    using T = typename V::value_type;
+    test_values_3arg<V>(
+      {
+#ifdef __STDC_IEC_559__
+	std::__quiet_NaN_v<T>,
+	std::__infinity_v<T>,
+	-std::__infinity_v<T>,
+	std::__norm_min_v<T> / 3,
+	-0.,
+	std::__denorm_min_v<T>,
+#endif
+	0.,
+	1.,
+	-1.,
+	std::__norm_min_v<T>,
+	-std::__norm_min_v<T>,
+	2.,
+	-2.,
+	std::__finite_max_v<T> / 5,
+	std::__finite_max_v<T> / 3,
+	std::__finite_max_v<T> / 2,
+	-std::__finite_max_v<T> / 5,
+	-std::__finite_max_v<T> / 3,
+	-std::__finite_max_v<T> / 2,
+#ifdef __FAST_MATH__
+	// fast-math hypot is imprecise for the max exponent
+      },
+      {100000, std::__finite_max_v<T> / 2},
+#else
+	std::__finite_max_v<T>, -std::__finite_max_v<T>},
+      {100000},
+#endif
+      MAKE_TESTER_2(hypot, hypot3));
+#if !__FINITE_MATH_ONLY__
+    COMPARE(hypot(V(std::__finite_max_v<T>), V(std::__finite_max_v<T>), V()),
+	    V(std::__infinity_v<T>));
+    COMPARE(hypot(V(std::__finite_max_v<T>), V(), V(std::__finite_max_v<T>)),
+	    V(std::__infinity_v<T>));
+    COMPARE(hypot(V(), V(std::__finite_max_v<T>), V(std::__finite_max_v<T>)),
+	    V(std::__infinity_v<T>));
+#endif
+    COMPARE(hypot(V(std::__norm_min_v<T>), V(std::__norm_min_v<T>),
+		  V(std::__norm_min_v<T>)),
+	    V(std::__norm_min_v<T> * std::sqrt(T(3))));
+    auto&& hypot3_test
+      = [](auto a, auto b, auto c) -> decltype(hypot(a, b, c)) { return {}; };
+    VERIFY((sfinae_is_callable<V, V, V>(hypot3_test)));
+    VERIFY((sfinae_is_callable<T, T, V>(hypot3_test)));
+    VERIFY((sfinae_is_callable<V, T, T>(hypot3_test)));
+    VERIFY((sfinae_is_callable<T, V, T>(hypot3_test)));
+    VERIFY((sfinae_is_callable<T, V, V>(hypot3_test)));
+    VERIFY((sfinae_is_callable<V, T, V>(hypot3_test)));
+    VERIFY((sfinae_is_callable<V, V, T>(hypot3_test)));
+    VERIFY((sfinae_is_callable<int, int, V>(hypot3_test)));
+    VERIFY((sfinae_is_callable<int, V, int>(hypot3_test)));
+    VERIFY((sfinae_is_callable<V, T, int>(hypot3_test)));
+    VERIFY(!(sfinae_is_callable<bool, V, V>(hypot3_test)));
+    VERIFY(!(sfinae_is_callable<V, bool, V>(hypot3_test)));
+    VERIFY(!(sfinae_is_callable<V, V, bool>(hypot3_test)));
+
+    vir::test::setFuzzyness<float>(0);
+    vir::test::setFuzzyness<double>(0);
+    test_values_3arg<V>(
+      {
+#ifdef __STDC_IEC_559__
+	std::__quiet_NaN_v<T>, std::__infinity_v<T>, -std::__infinity_v<T>, -0.,
+	std::__norm_min_v<T> / 3, std::__denorm_min_v<T>,
+#endif
+	0., std::__norm_min_v<T>, std::__finite_max_v<T>},
+      {10000, -std::__finite_max_v<T> / 2, std::__finite_max_v<T> / 2},
+      MAKE_TESTER(fma));
+    auto&& fma_test
+      = [](auto a, auto b, auto c) -> decltype(fma(a, b, c)) { return {}; };
+    VERIFY((sfinae_is_callable<V, V, V>(fma_test)));
+    VERIFY((sfinae_is_callable<T, T, V>(fma_test)));
+    VERIFY((sfinae_is_callable<V, T, T>(fma_test)));
+    VERIFY((sfinae_is_callable<T, V, T>(fma_test)));
+    VERIFY((sfinae_is_callable<T, V, V>(fma_test)));
+    VERIFY((sfinae_is_callable<V, T, V>(fma_test)));
+    VERIFY((sfinae_is_callable<V, V, T>(fma_test)));
+    VERIFY((sfinae_is_callable<int, int, V>(fma_test)));
+    VERIFY((sfinae_is_callable<int, V, int>(fma_test)));
+    VERIFY((sfinae_is_callable<V, T, int>(fma_test)));
+    VERIFY((!sfinae_is_callable<V, T, bool>(fma_test)));
+    VERIFY((!sfinae_is_callable<bool, V, V>(fma_test)));
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/integer_operators.cc b/libstdc++-v3/testsuite/experimental/simd/tests/integer_operators.cc
new file mode 100644
index 00000000000..9205d865aed
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/integer_operators.cc
@@ -0,0 +1,218 @@
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "bits/verify.h"
+#include "bits/make_vec.h"
+#include "bits/metahelpers.h"
+
+template <typename T, T Begin, T End, T Stride = 1, typename F>
+  void
+  for_constexpr(F&& fun)
+  {
+    if constexpr (Begin <= End)
+      {
+	fun(std::integral_constant<T, Begin>());
+	if constexpr (Begin < End)
+	  {
+	    for_constexpr<T, Begin + Stride, End, Stride>(static_cast<F&&>(fun));
+	  }
+      }
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+    if constexpr (std::is_integral_v<T>)
+      {
+	constexpr int nbits(sizeof(T) * __CHAR_BIT__);
+	constexpr int n_promo_bits
+	  = std::max(nbits, int(sizeof(int) * __CHAR_BIT__));
+
+	// complement
+	COMPARE(~V(), V(~T()));
+	COMPARE(~V(~T()), V());
+
+	{ // modulus
+	  V x = make_vec<V>({3, 4}, 2);
+	  COMPARE(x % x, V(0));
+	  V y = x - 1;
+	  COMPARE(x % y, V(1));
+	  y = x + 1;
+	  COMPARE(x % y, x);
+	  if (std::is_signed<T>::value)
+	    {
+	      x = -x;
+	      COMPARE(x % y, x);
+	      x = -y;
+	      COMPARE(x % y, V(0));
+	      x = x - 1;
+	      COMPARE(x % y, V(-1));
+	      x %= y;
+	      COMPARE(x, V(-1));
+	    }
+	}
+
+	{ // bit_and
+	  V x = make_vec<V>({3, 4, 5}, 8);
+	  COMPARE(x & x, x);
+	  COMPARE(x & ~x, V());
+	  COMPARE(x & V(), V());
+	  COMPARE(V() & x, V());
+	  V y = make_vec<V>({1, 5, 3}, 8);
+	  COMPARE(x & y, make_vec<V>({1, 4, 1}, 8));
+	  x &= y;
+	  COMPARE(x, make_vec<V>({1, 4, 1}, 8));
+	}
+
+	{ // bit_or
+	  V x = make_vec<V>({3, 4, 5}, 8);
+	  COMPARE(x | x, x);
+	  COMPARE(x | ~x, ~V());
+	  COMPARE(x | V(), x);
+	  COMPARE(V() | x, x);
+	  V y = make_vec<V>({1, 5, 3}, 8);
+	  COMPARE(x | y, make_vec<V>({3, 5, 7}, 8));
+	  x |= y;
+	  COMPARE(x, make_vec<V>({3, 5, 7}, 8));
+	}
+
+	{ // bit_xor
+	  V x = make_vec<V>({3, 4, 5}, 8);
+	  COMPARE(x ^ x, V());
+	  COMPARE(x ^ ~x, ~V());
+	  COMPARE(x ^ V(), x);
+	  COMPARE(V() ^ x, x);
+	  V y = make_vec<V>({1, 5, 3}, 8);
+	  COMPARE(x ^ y, make_vec<V>({2, 1, 6}, 0));
+	  x ^= y;
+	  COMPARE(x, make_vec<V>({2, 1, 6}, 0));
+	}
+
+	{ // bit_shift_left
+	  // Note:
+	  // - negative RHS or RHS >= max(#bits(T), #bits(int)) is UB
+	  // - negative LHS is UB
+	  // - shifting into (or over) the sign bit is UB
+	  // - unsigned LHS overflow is modulo arithmetic
+	  COMPARE(V() << 1, V());
+	  for (int i = 0; i < nbits - 1; ++i)
+	    {
+	      COMPARE(V(1) << i, V(T(1) << i)) << "i: " << i;
+	    }
+	  for_constexpr<int, 0, n_promo_bits - 1>(
+	    [](auto shift_ic) {
+	      constexpr int shift = shift_ic;
+	      const V seq = make_value_unknown(V([&](T i) {
+		if constexpr (std::is_signed_v<T>)
+		  {
+		    const T max = std::__finite_max_v<T> >> shift;
+		    return max == 0 ? 1 : (std::abs(max - i) % max) + 1;
+		  }
+		else
+		  {
+		    return ~T() - i;
+		  }
+	      }));
+	      const V ref([&](T i) { return T(seq[i] << shift); });
+	      COMPARE(seq << shift, ref) << "seq: " << seq
+	       	<< ", shift: " << shift;
+	      COMPARE(seq << make_value_unknown(shift), ref)
+		<< "seq: " << seq << ", shift: " << shift;
+	    });
+	  {
+	    V seq = make_vec<V>({0, 1}, nbits - 2);
+	    seq %= nbits - 1;
+	    COMPARE(make_vec<V>({0, 1}, 0) << seq,
+		    V([&](auto i) { return T(T(i & 1) << seq[i]); }))
+	      << "seq = " << seq;
+	    COMPARE(make_vec<V>({1, 0}, 0) << seq,
+		    V([&](auto i) { return T(T(~i & 1) << seq[i]); }));
+	    COMPARE(V(1) << seq, V([&](auto i) { return T(T(1) << seq[i]); }));
+	  }
+	  if (std::is_unsigned<T>::value)
+	    {
+	      constexpr int shift_count = nbits - 1;
+	      COMPARE(V(1) << shift_count, V(T(1) << shift_count));
+	      constexpr T max = // avoid overflow warning in the last COMPARE
+		std::is_unsigned<T>::value ? std::__finite_max_v<T> : T(1);
+	      COMPARE(V(max) << shift_count, V(max << shift_count))
+		<< "shift_count: " << shift_count;
+	    }
+	}
+
+	{ // bit_shift_right
+	  // Note:
+	  // - negative LHS is implementation defined
+	  // - negative RHS or RHS >= #bits is UB
+	  // - no other UB
+	  COMPARE(V(~T()) >> V(0), V(~T()));
+	  COMPARE(V(~T()) >> V(make_value_unknown(0)), V(~T()));
+	  for (int s = 1; s < nbits; ++s)
+	    {
+	      COMPARE(V(~T()) >> V(s), V(T(~T()) >> s)) << "s: " << s;
+	    }
+	  for (int s = 1; s < nbits; ++s)
+	    {
+	      COMPARE(V(~T(1)) >> V(s), V(T(~T(1)) >> s)) << "s: " << s;
+	    }
+	  COMPARE(V(0) >> V(1), V(0));
+	  COMPARE(V(1) >> V(1), V(0));
+	  COMPARE(V(2) >> V(1), V(1));
+	  COMPARE(V(3) >> V(1), V(1));
+	  COMPARE(V(7) >> V(2), V(1));
+	  for (int j = 0; j < 100; ++j)
+	    {
+	      const V seq([&](auto i) -> T { return (j + i) % n_promo_bits; });
+	      COMPARE(V(1) >> seq, V([&](auto i) { return T(T(1) >> seq[i]); }))
+		<< "seq = " << seq;
+	      COMPARE(make_value_unknown(V(1)) >> make_value_unknown(seq),
+		V([&](auto i) { return T(T(1) >> seq[i]); }))
+		<< "seq = " << seq;
+	    }
+	  for_constexpr<int, 0, n_promo_bits - 1>([](auto shift_ic) {
+	    constexpr int shift = shift_ic;
+	    const V seq = make_value_unknown(V([&](int i) {
+	      using U = std::make_unsigned_t<T>;
+	      return T(~U() >> (i % 32));
+	    }));
+	    const V ref([&](T i) { return T(seq[i] >> shift); });
+	    COMPARE(seq >> shift, ref)
+	      << "seq: " << seq << ", shift: " << shift;
+	    COMPARE(seq >> make_value_unknown(shift), ref)
+	      << "seq: " << seq << ", shift: " << shift;
+	  });
+	}
+      }
+    else
+      {
+	VERIFY((is_substitution_failure<V, V, std::modulus<>>));
+	VERIFY((is_substitution_failure<V, V, std::bit_and<>>));
+	VERIFY((is_substitution_failure<V, V, std::bit_or<>>));
+	VERIFY((is_substitution_failure<V, V, std::bit_xor<>>));
+	VERIFY((is_substitution_failure<V, V, bit_shift_left>));
+	VERIFY((is_substitution_failure<V, V, bit_shift_right>));
+
+	VERIFY((is_substitution_failure<V&, V, assign_modulus>));
+	VERIFY((is_substitution_failure<V&, V, assign_bit_and>));
+	VERIFY((is_substitution_failure<V&, V, assign_bit_or>));
+	VERIFY((is_substitution_failure<V&, V, assign_bit_xor>));
+	VERIFY((is_substitution_failure<V&, V, assign_bit_shift_left>));
+	VERIFY((is_substitution_failure<V&, V, assign_bit_shift_right>));
+      }
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/ldexp_scalbn_scalbln_modf.cc b/libstdc++-v3/testsuite/experimental/simd/tests/ldexp_scalbn_scalbln_modf.cc
new file mode 100644
index 00000000000..e8a519612e8
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/ldexp_scalbn_scalbln_modf.cc
@@ -0,0 +1,152 @@
+// test only floattypes
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/test_values.h"
+
+template <typename V>
+  void
+  test()
+  {
+    vir::test::setFuzzyness<float>(0);
+    vir::test::setFuzzyness<double>(0);
+
+    using T = typename V::value_type;
+
+    // See https://sourceware.org/bugzilla/show_bug.cgi?id=18031
+    const bool modf_is_broken = [] {
+      volatile T x = T(5e20) / 7;
+      T tmp;
+      return std::fabs(std::modf(x, &tmp)) >= 1;
+    }();
+    if (modf_is_broken)
+      __builtin_fprintf(stderr,
+			"NOTE: Skipping modf because std::modf is broken.\n");
+
+    test_values<V>(
+      {
+#ifdef __STDC_IEC_559__
+	std::__quiet_NaN_v<T>,
+	std::__infinity_v<T>,
+	-std::__infinity_v<T>,
+	-0.,
+	std::__denorm_min_v<T>,
+	std::__norm_min_v<T> / 3,
+	-std::__denorm_min_v<T>,
+	-std::__norm_min_v<T> / 3,
+#endif
+	+0.,
+	+1.3,
+	-1.3,
+	2.1,
+	-2.1,
+	0.99,
+	0.9,
+	-0.9,
+	-0.99,
+	std::__norm_min_v<T>,
+	std::__finite_max_v<T>,
+	-std::__norm_min_v<T>,
+	-std::__finite_max_v<T>},
+      {10000},
+      [](const V input) {
+	for (int exp : {-10000, -100, -10, -1, 0, 1, 10, 100, 10000})
+	  {
+	    const auto totest = ldexp(input, exp);
+	    using R = std::remove_const_t<decltype(totest)>;
+	    auto&& expected = [&](const auto& v) -> const R {
+	      R tmp = {};
+	      using std::ldexp;
+	      for (std::size_t i = 0; i < R::size(); ++i)
+		{
+		  tmp[i] = ldexp(v[i], exp);
+		}
+	      return tmp;
+	    };
+	    const R expect1 = expected(input);
+	    COMPARE(isnan(totest), isnan(expect1))
+	      << "ldexp(" << input << ", " << exp << ") = " << totest
+	      << " != " << expect1;
+	    FUZZY_COMPARE(ldexp(iif(isnan(expect1), 0, input), exp),
+			  expected(iif(isnan(expect1), 0, input)))
+	      << "\nclean = " << iif(isnan(expect1), 0, input);
+	  }
+      },
+      [](const V input) {
+	for (int exp : {-10000, -100, -10, -1, 0, 1, 10, 100, 10000})
+	  {
+	    const auto totest = scalbn(input, exp);
+	    using R = std::remove_const_t<decltype(totest)>;
+	    auto&& expected = [&](const auto& v) -> const R {
+	      R tmp = {};
+	      using std::scalbn;
+	      for (std::size_t i = 0; i < R::size(); ++i)
+		{
+		  tmp[i] = scalbn(v[i], exp);
+		}
+	      return tmp;
+	    };
+	    const R expect1 = expected(input);
+	    COMPARE(isnan(totest), isnan(expect1))
+	      << "scalbn(" << input << ", " << exp << ") = " << totest
+	      << " != " << expect1;
+	    FUZZY_COMPARE(scalbn(iif(isnan(expect1), 0, input), exp),
+			  expected(iif(isnan(expect1), 0, input)))
+	      << "\nclean = " << iif(isnan(expect1), 0, input);
+	  }
+      },
+      [](const V input) {
+	for (long exp : {-10000, -100, -10, -1, 0, 1, 10, 100, 10000})
+	  {
+	    const auto totest = scalbln(input, exp);
+	    using R = std::remove_const_t<decltype(totest)>;
+	    auto&& expected = [&](const auto& v) -> const R {
+	      R tmp = {};
+	      using std::scalbln;
+	      for (std::size_t i = 0; i < R::size(); ++i)
+		{
+		  tmp[i] = scalbln(v[i], exp);
+		}
+	      return tmp;
+	    };
+	    const R expect1 = expected(input);
+	    COMPARE(isnan(totest), isnan(expect1))
+	      << "scalbln(" << input << ", " << exp << ") = " << totest
+	      << " != " << expect1;
+	    FUZZY_COMPARE(scalbln(iif(isnan(expect1), 0, input), exp),
+			  expected(iif(isnan(expect1), 0, input)))
+	      << "\nclean = " << iif(isnan(expect1), 0, input);
+	  }
+      },
+      [modf_is_broken](const V input) {
+	if (modf_is_broken)
+	  return;
+	V integral = {};
+	const V totest = modf(input, &integral);
+	auto&& expected = [&](const auto& v) -> std::pair<const V, const V> {
+	  std::pair<V, V> tmp = {};
+	  using std::modf;
+	  for (std::size_t i = 0; i < V::size(); ++i)
+	    {
+	      typename V::value_type tmp2;
+	      tmp.first[i] = modf(v[i], &tmp2);
+	      tmp.second[i] = tmp2;
+	    }
+	  return tmp;
+	};
+	const auto expect1 = expected(input);
+#ifdef __STDC_IEC_559__
+	COMPARE(isnan(totest), isnan(expect1.first))
+	  << "modf(" << input << ", iptr) = " << totest << " != " << expect1;
+	COMPARE(isnan(integral), isnan(expect1.second))
+	  << "modf(" << input << ", iptr) = " << totest << " != " << expect1;
+	COMPARE(isnan(totest), isnan(integral))
+	  << "modf(" << input << ", iptr) = " << totest << " != " << expect1;
+	const V clean = iif(isnan(totest), V(), input);
+#else
+	const V clean = iif(isnormal(input), input, V());
+#endif
+	const auto expect2 = expected(clean);
+	COMPARE(modf(clean, &integral), expect2.first) << "\nclean = " << clean;
+	COMPARE(integral, expect2.second);
+      });
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/loadstore.cc b/libstdc++-v3/testsuite/experimental/simd/tests/loadstore.cc
new file mode 100644
index 00000000000..329c89688ed
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/loadstore.cc
@@ -0,0 +1,212 @@
+#include "bits/verify.h"
+#include "bits/make_vec.h"
+#include "bits/conversions.h"
+
+template <typename V, typename U>
+  void
+  load_store()
+  {
+    // types, tags, and constants
+    using T = typename V::value_type;
+    auto&& gen = make_vec<V>;
+    using std::experimental::element_aligned;
+    using std::experimental::vector_aligned;
+
+    // stride_alignment: consider V::size() == 6. The only reliable alignment is
+    // 2 * sizeof(U). I.e. if the first address is aligned to 8 * sizeof(U),
+    // then the next address is 6 * sizeof(U) larger, thus only aligned to 2 *
+    // sizeof(U).
+    // => the LSB determines the stride alignment
+    constexpr size_t stride_alignment = size_t(1) << __builtin_ctz(V::size());
+    using stride_aligned_t = std::conditional_t<
+      V::size() == stride_alignment, decltype(vector_aligned),
+      std::experimental::overaligned_tag<stride_alignment * sizeof(U)>>;
+    constexpr stride_aligned_t stride_aligned = {};
+    constexpr size_t alignment
+      = 2 * std::experimental::memory_alignment_v<V, U>;
+    constexpr auto overaligned = std::experimental::overaligned<alignment>;
+    const V indexes_from_0([](auto i) { return i; });
+    for (std::size_t i = 0; i < V::size(); ++i)
+      {
+	COMPARE(indexes_from_0[i], T(i));
+      }
+
+    // loads
+    cvt_inputs<T, U> test_values;
+
+    constexpr auto mem_size
+      = test_values.size() > 3 * V::size() ? test_values.size() : 3 * V::size();
+    alignas(std::experimental::memory_alignment_v<V, U> * 2) U mem[mem_size]
+      = {};
+    alignas(std::experimental::memory_alignment_v<V, T> * 2)
+      T reference[mem_size]
+      = {};
+    for (std::size_t i = 0; i < test_values.size(); ++i)
+      {
+	const U value = test_values[i];
+	mem[i] = value;
+	reference[i] = static_cast<T>(value);
+      }
+    for (std::size_t i = test_values.size(); i < mem_size; ++i)
+      {
+	mem[i] = U(i);
+	reference[i] = mem[i];
+      }
+
+    V x(&mem[V::size()], stride_aligned);
+    auto&& compare = [&](const std::size_t offset) {
+      static int n = 0;
+      const V ref(&reference[offset], element_aligned);
+      for (auto i = 0ul; i < V::size(); ++i)
+	{
+	  if (is_conversion_undefined<T>(mem[i + offset]))
+	    {
+	      continue;
+	    }
+	  COMPARE(x[i], reference[i + offset])
+	    << "\nbefore conversion: " << mem[i + offset]
+	    << "\n   offset = " << offset << "\n        x = " << x
+	    << "\nreference = " << ref << "\nx == ref  = " << (x == ref)
+	    << "\ncall no. " << n;
+	}
+      ++n;
+    };
+    compare(V::size());
+    x = V{mem, overaligned};
+    compare(0);
+    x = {&mem[1], element_aligned};
+    compare(1);
+
+    x.copy_from(&mem[V::size()], stride_aligned);
+    compare(V::size());
+    x.copy_from(&mem[1], element_aligned);
+    compare(1);
+    x.copy_from(mem, vector_aligned);
+    compare(0);
+
+    for (std::size_t i = 0; i < mem_size - V::size(); ++i)
+      {
+	x.copy_from(&mem[i], element_aligned);
+	compare(i);
+      }
+
+    for (std::size_t i = 0; i < test_values.size(); ++i)
+      {
+	mem[i] = U(i);
+      }
+    x = indexes_from_0;
+    using M = typename V::mask_type;
+    const M alternating_mask = make_mask<M>({0, 1});
+    where(alternating_mask, x).copy_from(&mem[V::size()], stride_aligned);
+
+    const V indexes_from_size = gen({T(V::size())}, 1);
+    COMPARE(x == indexes_from_size, alternating_mask)
+      << "x: " << x << "\nindexes_from_size: " << indexes_from_size;
+    COMPARE(x == indexes_from_0, !alternating_mask);
+    where(alternating_mask, x).copy_from(&mem[1], element_aligned);
+
+    const V indexes_from_1 = gen({1, 2, 3, 4}, 4);
+    COMPARE(x == indexes_from_1, alternating_mask);
+    COMPARE(x == indexes_from_0, !alternating_mask);
+    where(!alternating_mask, x).copy_from(mem, overaligned);
+    COMPARE(x == indexes_from_0, !alternating_mask);
+    COMPARE(x == indexes_from_1, alternating_mask);
+
+    x = where(alternating_mask, V()).copy_from(&mem[V::size()], stride_aligned);
+    COMPARE(x == indexes_from_size, alternating_mask);
+    COMPARE(x == 0, !alternating_mask);
+
+    x = where(!alternating_mask, V()).copy_from(&mem[1], element_aligned);
+    COMPARE(x == indexes_from_1, !alternating_mask);
+    COMPARE(x == 0, alternating_mask);
+
+    // stores
+    auto&& init_mem = [&mem](U init) {
+      for (auto i = mem_size; i; --i)
+	{
+	  mem[i - 1] = init;
+	}
+    };
+    init_mem(-1);
+    x = indexes_from_1;
+    x.copy_to(&mem[V::size()], stride_aligned);
+    std::size_t i = 0;
+    for (; i < V::size(); ++i)
+      {
+	COMPARE(mem[i], U(-1)) << "i: " << i;
+      }
+    for (; i < 2 * V::size(); ++i)
+      {
+	COMPARE(mem[i], U(i - V::size() + 1)) << "i: " << i;
+      }
+    for (; i < 3 * V::size(); ++i)
+      {
+	COMPARE(mem[i], U(-1)) << "i: " << i;
+      }
+
+    init_mem(-1);
+    x.copy_to(&mem[1], element_aligned);
+    COMPARE(mem[0], U(-1));
+    for (i = 1; i <= V::size(); ++i)
+      {
+	COMPARE(mem[i], U(i));
+      }
+    for (; i < 3 * V::size(); ++i)
+      {
+	COMPARE(mem[i], U(-1));
+      }
+
+    init_mem(-1);
+    x.copy_to(mem, vector_aligned);
+    for (i = 0; i < V::size(); ++i)
+      {
+	COMPARE(mem[i], U(i + 1));
+      }
+    for (; i < 3 * V::size(); ++i)
+      {
+	COMPARE(mem[i], U(-1));
+      }
+
+    init_mem(-1);
+    where(alternating_mask, indexes_from_0)
+      .copy_to(&mem[V::size()], stride_aligned);
+    for (i = 0; i < V::size() + 1; ++i)
+      {
+	COMPARE(mem[i], U(-1));
+      }
+    for (; i < 2 * V::size(); i += 2)
+      {
+	COMPARE(mem[i], U(i - V::size()));
+      }
+    for (i = V::size() + 2; i < 2 * V::size(); i += 2)
+      {
+	COMPARE(mem[i], U(-1));
+      }
+    for (; i < 3 * V::size(); ++i)
+      {
+	COMPARE(mem[i], U(-1));
+      }
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    load_store<V, long double>();
+    load_store<V, double>();
+    load_store<V, float>();
+    load_store<V, long long>();
+    load_store<V, unsigned long long>();
+    load_store<V, unsigned long>();
+    load_store<V, long>();
+    load_store<V, int>();
+    load_store<V, unsigned int>();
+    load_store<V, short>();
+    load_store<V, unsigned short>();
+    load_store<V, char>();
+    load_store<V, signed char>();
+    load_store<V, unsigned char>();
+    load_store<V, char32_t>();
+    load_store<V, char16_t>();
+    load_store<V, wchar_t>();
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/logarithm.cc b/libstdc++-v3/testsuite/experimental/simd/tests/logarithm.cc
new file mode 100644
index 00000000000..7578f1a8561
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/logarithm.cc
@@ -0,0 +1,66 @@
+// test only floattypes
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/mathreference.h"
+#include "bits/test_values.h"
+
+template <typename V>
+  void
+  test()
+  {
+    vir::test::setFuzzyness<float>(1);
+    vir::test::setFuzzyness<double>(1);
+
+    using T = typename V::value_type;
+    constexpr T nan = std::__quiet_NaN_v<T>;
+    constexpr T inf = std::__infinity_v<T>;
+    constexpr T denorm_min = std::__denorm_min_v<T>;
+    constexpr T norm_min = std::__norm_min_v<T>;
+    constexpr T min = std::__finite_min_v<T>;
+    constexpr T max = std::__finite_max_v<T>;
+    test_values<V>({1,
+		    2,
+		    4,
+		    8,
+		    16,
+		    32,
+		    64,
+		    128,
+		    256,
+		    512,
+		    1024,
+		    2048,
+		    3,
+		    5,
+		    7,
+		    15,
+		    17,
+		    31,
+		    33,
+		    63,
+		    65,
+#ifdef __STDC_IEC_559__
+		    nan,
+		    inf,
+		    -inf,
+		    denorm_min,
+		    -denorm_min,
+		    norm_min / 3,
+		    -norm_min / 3,
+		    -T(),
+		    -norm_min,
+		    min,
+		    T(),
+#endif
+		    norm_min,
+		    max},
+		   {10000,
+#ifdef __STDC_IEC_559__
+		    min / 2,
+#else
+		    norm_min,
+#endif
+		    max / 2},
+		   MAKE_TESTER(log), MAKE_TESTER(log10), MAKE_TESTER(log1p),
+		   MAKE_TESTER(log2), MAKE_TESTER(logb));
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_broadcast.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_broadcast.cc
new file mode 100644
index 00000000000..6fbadc67af7
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_broadcast.cc
@@ -0,0 +1,50 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    static_assert(std::is_convertible<typename M::reference, bool>::value,
+		  "A smart_reference<simd_mask> must be convertible to bool.");
+    static_assert(
+      std::is_same<bool, decltype(std::declval<const typename M::reference&>()
+				  == true)>::value,
+      "A smart_reference<simd_mask> must be comparable against bool.");
+    static_assert(
+      vir::test::sfinae_is_callable<typename M::reference&&, bool>(
+	[](auto&& a, auto&& b) -> decltype(std::declval<decltype(a)>()
+					   == std::declval<decltype(b)>()) {
+	  return {};
+	}),
+      "A smart_reference<simd_mask> must be comparable against bool.");
+    VERIFY(std::experimental::is_simd_mask_v<M>);
+
+    {
+      M x;     // uninitialized
+      x = M{}; // default broadcasts 0
+      COMPARE(x, M(false));
+      COMPARE(x, M());
+      COMPARE(x, M{});
+      x = M(); // default broadcasts 0
+      COMPARE(x, M(false));
+      COMPARE(x, M());
+      COMPARE(x, M{});
+      x = x;
+      for (std::size_t i = 0; i < M::size(); ++i)
+	{
+	  COMPARE(x[i], false);
+	}
+    }
+
+    M x(true);
+    M y(false);
+    for (std::size_t i = 0; i < M::size(); ++i)
+      {
+	COMPARE(x[i], true);
+	COMPARE(y[i], false);
+      }
+    y = M(true);
+    COMPARE(x, y);
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_conversions.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_conversions.cc
new file mode 100644
index 00000000000..0248cd4cb47
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_conversions.cc
@@ -0,0 +1,96 @@
+#include "bits/verify.h"
+
+namespace stdx = std::experimental;
+
+template <typename From, typename To>
+  void
+  conversions()
+  {
+    using ToV = typename To::simd_type;
+
+    using stdx::simd_cast;
+    using stdx::static_simd_cast;
+    using stdx::__proposed::resizing_simd_cast;
+
+    auto x = resizing_simd_cast<To>(From());
+    COMPARE(typeid(x), typeid(To));
+    COMPARE(x, To());
+
+    x = resizing_simd_cast<To>(From(true));
+    const To ref = ToV([](auto i) { return i; }) < int(From::size());
+    COMPARE(x, ref) << "converted from: " << From(true);
+
+    const ullong all_bits = ~ullong() >> (64 - From::size());
+    for (ullong bit_pos = 1; bit_pos /*until overflow*/; bit_pos *= 2)
+      {
+	for (ullong bits : {bit_pos & all_bits, ~bit_pos & all_bits})
+	  {
+	    const auto from = From::__from_bitset(bits);
+	    const auto to = resizing_simd_cast<To>(from);
+	    COMPARE(to, To::__from_bitset(bits))
+	      << "\nfrom: " << from << "\nbits: " << std::hex << bits << std::dec;
+	    for (std::size_t i = 0; i < To::size(); ++i)
+	      {
+		COMPARE(to[i], (bits >> i) & 1)
+		  << "\nfrom: " << from << "\nto: " << to
+		  << "\nbits: " << std::hex << bits << std::dec << "\ni: " << i;
+	      }
+	  }
+      }
+  }
+
+template <typename T, typename V, typename = void>
+  struct rebind_or_max_fixed
+  {
+    using type = stdx::rebind_simd_t<
+      T, stdx::resize_simd_t<stdx::simd_abi::max_fixed_size<T>, V>>;
+  };
+
+template <typename T, typename V>
+  struct rebind_or_max_fixed<T, V, std::void_t<stdx::rebind_simd_t<T, V>>>
+  {
+    using type = stdx::rebind_simd_t<T, V>;
+  };
+
+template <typename From, typename To>
+  void
+  apply_abis()
+  {
+    using M0 = typename rebind_or_max_fixed<To, From>::type;
+    using M1 = stdx::native_simd_mask<To>;
+    using M2 = stdx::simd_mask<To>;
+    using M3 = stdx::simd_mask<To, stdx::simd_abi::scalar>;
+
+    using std::is_same_v;
+    conversions<From, M0>();
+    if constexpr (!is_same_v<M1, M0>)
+      conversions<From, M1>();
+    if constexpr (!is_same_v<M2, M0> && !is_same_v<M2, M1>)
+      conversions<From, M2>();
+    if constexpr (!is_same_v<M3, M0> && !is_same_v<M3, M1> && !is_same_v<M3, M2>)
+      conversions<From, M3>();
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    apply_abis<M, ldouble>();
+    apply_abis<M, double>();
+    apply_abis<M, float>();
+    apply_abis<M, ullong>();
+    apply_abis<M, llong>();
+    apply_abis<M, ulong>();
+    apply_abis<M, long>();
+    apply_abis<M, uint>();
+    apply_abis<M, int>();
+    apply_abis<M, ushort>();
+    apply_abis<M, short>();
+    apply_abis<M, uchar>();
+    apply_abis<M, schar>();
+    apply_abis<M, char>();
+    apply_abis<M, wchar_t>();
+    apply_abis<M, char16_t>();
+    apply_abis<M, char32_t>();
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_implicit_cvt.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_implicit_cvt.cc
new file mode 100644
index 00000000000..3fa8dab5799
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_implicit_cvt.cc
@@ -0,0 +1,85 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+
+template <class M, class M2>
+  constexpr bool assign_should_work
+    = std::is_same<M, M2>::value
+	|| (std::is_same<typename M::abi_type,
+			 std::experimental::simd_abi::fixed_size<M::size()>>::value
+	      && std::is_same<typename M::abi_type, typename M2::abi_type>::value);
+
+template <class M, class M2>
+  constexpr bool assign_should_not_work = !assign_should_work<M, M2>;
+
+template <class L, class R>
+  std::enable_if_t<assign_should_work<L, R>>
+  implicit_conversions_test()
+  {
+    L x = R(true);
+    COMPARE(x, L(true));
+    x = R(false);
+    COMPARE(x, L(false));
+    R y(false);
+    y[0] = true;
+    x = y;
+    L ref(false);
+    ref[0] = true;
+    COMPARE(x, ref);
+  }
+
+template <class L, class R>
+  std::enable_if_t<assign_should_not_work<L, R>>
+  implicit_conversions_test()
+  {
+    VERIFY((is_substitution_failure<L&, R, assignment>) );
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    using std::experimental::fixed_size_simd_mask;
+    using std::experimental::native_simd_mask;
+    using std::experimental::simd_mask;
+
+    implicit_conversions_test<M, simd_mask<ldouble>>();
+    implicit_conversions_test<M, simd_mask<double>>();
+    implicit_conversions_test<M, simd_mask<float>>();
+    implicit_conversions_test<M, simd_mask<ullong>>();
+    implicit_conversions_test<M, simd_mask<llong>>();
+    implicit_conversions_test<M, simd_mask<ulong>>();
+    implicit_conversions_test<M, simd_mask<long>>();
+    implicit_conversions_test<M, simd_mask<uint>>();
+    implicit_conversions_test<M, simd_mask<int>>();
+    implicit_conversions_test<M, simd_mask<ushort>>();
+    implicit_conversions_test<M, simd_mask<short>>();
+    implicit_conversions_test<M, simd_mask<uchar>>();
+    implicit_conversions_test<M, simd_mask<schar>>();
+    implicit_conversions_test<M, native_simd_mask<ldouble>>();
+    implicit_conversions_test<M, native_simd_mask<double>>();
+    implicit_conversions_test<M, native_simd_mask<float>>();
+    implicit_conversions_test<M, native_simd_mask<ullong>>();
+    implicit_conversions_test<M, native_simd_mask<llong>>();
+    implicit_conversions_test<M, native_simd_mask<ulong>>();
+    implicit_conversions_test<M, native_simd_mask<long>>();
+    implicit_conversions_test<M, native_simd_mask<uint>>();
+    implicit_conversions_test<M, native_simd_mask<int>>();
+    implicit_conversions_test<M, native_simd_mask<ushort>>();
+    implicit_conversions_test<M, native_simd_mask<short>>();
+    implicit_conversions_test<M, native_simd_mask<uchar>>();
+    implicit_conversions_test<M, native_simd_mask<schar>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<ldouble, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<double, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<float, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<ullong, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<llong, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<ulong, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<long, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<uint, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<int, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<ushort, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<short, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<uchar, M::size()>>();
+    implicit_conversions_test<M, fixed_size_simd_mask<schar, M::size()>>();
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_loadstore.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_loadstore.cc
new file mode 100644
index 00000000000..5e3fd6d867c
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_loadstore.cc
@@ -0,0 +1,144 @@
+#include "bits/verify.h"
+
+// simd_mask generator functions
+template <class M>
+  M
+  make_mask(const std::initializer_list<bool>& init)
+  {
+    std::size_t i = 0;
+    M r = {};
+    for (;;)
+      {
+	for (bool x : init)
+	  {
+	    r[i] = x;
+	    if (++i == M::size())
+	      {
+		return r;
+	      }
+	  }
+      }
+  }
+
+template <class M>
+  M
+  make_alternating_mask()
+  {
+    return make_mask<M>({false, true});
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    // loads
+    constexpr size_t alignment = 2 * std::experimental::memory_alignment_v<M>;
+    alignas(alignment) bool mem[3 * M::size()];
+    std::memset(mem, 0, sizeof(mem));
+    for (std::size_t i = 1; i < sizeof(mem) / sizeof(*mem); i += 2)
+      {
+	COMPARE(mem[i - 1], false);
+	mem[i] = true;
+      }
+    using std::experimental::element_aligned;
+    using std::experimental::vector_aligned;
+    constexpr size_t stride_alignment
+      = M::size() & 1
+	  ? 1
+	  : M::size() & 2
+	  ? 2
+	  : M::size() & 4
+	  ? 4
+	  : M::size() & 8
+	  ? 8
+	  : M::size() & 16
+	  ? 16
+	  : M::size() & 32
+	  ? 32
+	  : M::size() & 64
+	  ? 64
+	  : M::size() & 128 ? 128
+			    : M::size() & 256 ? 256 : 512;
+    using stride_aligned_t = std::conditional_t<
+      M::size() == stride_alignment, decltype(vector_aligned),
+      std::experimental::overaligned_tag<stride_alignment * sizeof(bool)>>;
+    constexpr stride_aligned_t stride_aligned = {};
+    constexpr auto overaligned = std::experimental::overaligned<alignment>;
+
+    const M alternating_mask = make_alternating_mask<M>();
+
+    M x(&mem[M::size()], stride_aligned);
+    COMPARE(x, M::size() % 2 == 1 ? !alternating_mask : alternating_mask)
+      << x.__to_bitset()
+      << ", alternating_mask: " << alternating_mask.__to_bitset();
+    x = {&mem[1], element_aligned};
+    COMPARE(x, !alternating_mask);
+    x = M{mem, overaligned};
+    COMPARE(x, alternating_mask);
+
+    x.copy_from(&mem[M::size()], stride_aligned);
+    COMPARE(x, M::size() % 2 == 1 ? !alternating_mask : alternating_mask);
+    x.copy_from(&mem[1], element_aligned);
+    COMPARE(x, !alternating_mask);
+    x.copy_from(mem, vector_aligned);
+    COMPARE(x, alternating_mask);
+
+    x = !alternating_mask;
+    where(alternating_mask, x).copy_from(&mem[M::size()], stride_aligned);
+    COMPARE(x, M::size() % 2 == 1 ? !alternating_mask : M{true});
+    x = M(true);                                                    // 1111
+    where(alternating_mask, x).copy_from(&mem[1], element_aligned); // load .0.0
+    COMPARE(x, !alternating_mask);                                  // 1010
+    where(alternating_mask, x).copy_from(mem, overaligned);         // load .1.1
+    COMPARE(x, M{true});                                            // 1111
+
+    // stores
+    memset(mem, 0, sizeof(mem));
+    x = M(true);
+    x.copy_to(&mem[M::size()], stride_aligned);
+    std::size_t i = 0;
+    for (; i < M::size(); ++i)
+      {
+	COMPARE(mem[i], false);
+      }
+    for (; i < 2 * M::size(); ++i)
+      {
+	COMPARE(mem[i], true) << "i: " << i << ", x: " << x;
+      }
+    for (; i < 3 * M::size(); ++i)
+      {
+	COMPARE(mem[i], false);
+      }
+    memset(mem, 0, sizeof(mem));
+    x.copy_to(&mem[1], element_aligned);
+    COMPARE(mem[0], false);
+    for (i = 1; i <= M::size(); ++i)
+      {
+	COMPARE(mem[i], true);
+      }
+    for (; i < 3 * M::size(); ++i)
+      {
+	COMPARE(mem[i], false);
+      }
+    memset(mem, 0, sizeof(mem));
+    alternating_mask.copy_to(mem, overaligned);
+    for (i = 0; i < M::size(); ++i)
+      {
+	COMPARE(mem[i], (i & 1) == 1);
+      }
+    for (; i < 3 * M::size(); ++i)
+      {
+	COMPARE(mem[i], false);
+      }
+    x.copy_to(mem, vector_aligned);
+    where(alternating_mask, !x).copy_to(mem, overaligned);
+    for (i = 0; i < M::size(); ++i)
+      {
+	COMPARE(mem[i], i % 2 == 0);
+      }
+    for (; i < 3 * M::size(); ++i)
+      {
+	COMPARE(mem[i], false);
+      }
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_operator_cvt.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_operator_cvt.cc
new file mode 100644
index 00000000000..cb968d02785
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_operator_cvt.cc
@@ -0,0 +1,94 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+
+using schar = signed char;
+using uchar = unsigned char;
+using ushort = unsigned short;
+using uint = unsigned int;
+using ulong = unsigned long;
+using llong = long long;
+using ullong = unsigned long long;
+using ldouble = long double;
+using wchar = wchar_t;
+using char16 = char16_t;
+using char32 = char32_t;
+
+template <typename M0, typename M1>
+  constexpr bool
+  bit_and_is_illformed()
+  {
+    return is_substitution_failure<M0, M1, std::bit_and<>>;
+  }
+
+template <typename M0, typename M1>
+  void
+  test_binary_op_cvt()
+  {
+    COMPARE((bit_and_is_illformed<M0, M1>()), !(std::is_same_v<M0, M1>) );
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    // binary ops without conversions work
+    COMPARE(typeid(M() & M()), typeid(M));
+
+    // nothing else works: no implicit conv. or ambiguous
+    using std::experimental::fixed_size_simd_mask;
+    using std::experimental::native_simd_mask;
+    using std::experimental::simd_mask;
+    test_binary_op_cvt<M, bool>();
+
+    test_binary_op_cvt<M, simd_mask<ldouble>>();
+    test_binary_op_cvt<M, simd_mask<double>>();
+    test_binary_op_cvt<M, simd_mask<float>>();
+    test_binary_op_cvt<M, simd_mask<ullong>>();
+    test_binary_op_cvt<M, simd_mask<llong>>();
+    test_binary_op_cvt<M, simd_mask<ulong>>();
+    test_binary_op_cvt<M, simd_mask<long>>();
+    test_binary_op_cvt<M, simd_mask<uint>>();
+    test_binary_op_cvt<M, simd_mask<int>>();
+    test_binary_op_cvt<M, simd_mask<ushort>>();
+    test_binary_op_cvt<M, simd_mask<short>>();
+    test_binary_op_cvt<M, simd_mask<uchar>>();
+    test_binary_op_cvt<M, simd_mask<schar>>();
+    test_binary_op_cvt<M, simd_mask<wchar>>();
+    test_binary_op_cvt<M, simd_mask<char16>>();
+    test_binary_op_cvt<M, simd_mask<char32>>();
+
+    test_binary_op_cvt<M, native_simd_mask<ldouble>>();
+    test_binary_op_cvt<M, native_simd_mask<double>>();
+    test_binary_op_cvt<M, native_simd_mask<float>>();
+    test_binary_op_cvt<M, native_simd_mask<ullong>>();
+    test_binary_op_cvt<M, native_simd_mask<llong>>();
+    test_binary_op_cvt<M, native_simd_mask<ulong>>();
+    test_binary_op_cvt<M, native_simd_mask<long>>();
+    test_binary_op_cvt<M, native_simd_mask<uint>>();
+    test_binary_op_cvt<M, native_simd_mask<int>>();
+    test_binary_op_cvt<M, native_simd_mask<ushort>>();
+    test_binary_op_cvt<M, native_simd_mask<short>>();
+    test_binary_op_cvt<M, native_simd_mask<uchar>>();
+    test_binary_op_cvt<M, native_simd_mask<schar>>();
+    test_binary_op_cvt<M, native_simd_mask<wchar>>();
+    test_binary_op_cvt<M, native_simd_mask<char16>>();
+    test_binary_op_cvt<M, native_simd_mask<char32>>();
+
+    test_binary_op_cvt<M, fixed_size_simd_mask<ldouble, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<double, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<float, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<ullong, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<llong, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<ulong, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<long, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<uint, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<int, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<ushort, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<short, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<uchar, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<schar, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<wchar, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<char16, 2>>();
+    test_binary_op_cvt<M, fixed_size_simd_mask<char32, 2>>();
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_operators.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_operators.cc
new file mode 100644
index 00000000000..f729adc55bf
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_operators.cc
@@ -0,0 +1,40 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    { // compares
+      M x(true), y(false);
+      VERIFY(all_of(x == x));
+      VERIFY(all_of(x != y));
+      VERIFY(all_of(y != x));
+      VERIFY(!all_of(x != x));
+      VERIFY(!all_of(x == y));
+      VERIFY(!all_of(y == x));
+    }
+    { // subscripting
+      M x(true);
+      for (std::size_t i = 0; i < M::size(); ++i)
+	{
+	  COMPARE(x[i], true) << "\nx: " << x << ", i: " << i;
+	  x[i] = !x[i];
+	}
+      COMPARE(x, M{false});
+      for (std::size_t i = 0; i < M::size(); ++i)
+	{
+	  COMPARE(x[i], false) << "\nx: " << x << ", i: " << i;
+	  x[i] = !x[i];
+	}
+      COMPARE(x, M{true});
+    }
+    { // negation
+      M x(false);
+      M y = !x;
+      COMPARE(y, M{true});
+      COMPARE(!y, x);
+    }
+  }
+
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_reductions.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_reductions.cc
new file mode 100644
index 00000000000..99912aad9c0
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_reductions.cc
@@ -0,0 +1,209 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+
+// simd_mask generator functions
+template <class M>
+  M
+  make_mask(const std::initializer_list<bool>& init)
+  {
+    std::size_t i = 0;
+    M r = {};
+    for (;;)
+      {
+	for (bool x : init)
+	  {
+	    r[i] = x;
+	    if (++i == M::size())
+	      {
+		return r;
+	      }
+	  }
+      }
+  }
+
+template <class M>
+  M
+  make_alternating_mask()
+  {
+    return make_mask<M>({false, true});
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    const M alternating_mask = make_alternating_mask<M>();
+    COMPARE(alternating_mask[0], false); // assumption below
+    auto&& gen = make_mask<M>;
+
+    // all_of
+    VERIFY(all_of(M{true}));
+    VERIFY(!all_of(alternating_mask));
+    VERIFY(!all_of(M{false}));
+    using std::experimental::all_of;
+    VERIFY(all_of(true));
+    VERIFY(!all_of(false));
+    VERIFY(sfinae_is_callable<bool>(
+	[](auto x) -> decltype(std::experimental::all_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<int>(
+	[](auto x) -> decltype(std::experimental::all_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<float>(
+	[](auto x) -> decltype(std::experimental::all_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<char>(
+	[](auto x) -> decltype(std::experimental::all_of(x)) { return {}; }));
+
+    // any_of
+    VERIFY(any_of(M{true}));
+    COMPARE(any_of(alternating_mask), M::size() > 1);
+    VERIFY(!any_of(M{false}));
+    using std::experimental::any_of;
+    VERIFY(any_of(true));
+    VERIFY(!any_of(false));
+    VERIFY(sfinae_is_callable<bool>(
+	[](auto x) -> decltype(std::experimental::any_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<int>(
+	[](auto x) -> decltype(std::experimental::any_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<float>(
+	[](auto x) -> decltype(std::experimental::any_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<char>(
+	[](auto x) -> decltype(std::experimental::any_of(x)) { return {}; }));
+
+    // none_of
+    VERIFY(!none_of(M{true}));
+    COMPARE(none_of(alternating_mask), M::size() == 1);
+    VERIFY(none_of(M{false}));
+    using std::experimental::none_of;
+    VERIFY(!none_of(true));
+    VERIFY(none_of(false));
+    VERIFY(sfinae_is_callable<bool>(
+	[](auto x) -> decltype(std::experimental::none_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<int>(
+	[](auto x) -> decltype(std::experimental::none_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<float>(
+	[](auto x) -> decltype(std::experimental::none_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<char>(
+	[](auto x) -> decltype(std::experimental::none_of(x)) { return {}; }));
+
+    // some_of
+    VERIFY(!some_of(M{true}));
+    VERIFY(!some_of(M{false}));
+    if (M::size() > 1)
+      {
+	VERIFY(some_of(gen({true, false})));
+	VERIFY(some_of(gen({false, true})));
+	if (M::size() > 3)
+	  {
+	    VERIFY(some_of(gen({0, 0, 0, 1})));
+	  }
+      }
+    using std::experimental::some_of;
+    VERIFY(!some_of(true));
+    VERIFY(!some_of(false));
+    VERIFY(sfinae_is_callable<bool>(
+	[](auto x) -> decltype(std::experimental::some_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<int>(
+	[](auto x) -> decltype(std::experimental::some_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<float>(
+	[](auto x) -> decltype(std::experimental::some_of(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<char>(
+	[](auto x) -> decltype(std::experimental::some_of(x)) { return {}; }));
+
+    // popcount
+    COMPARE(popcount(M{true}), int(M::size()));
+    COMPARE(popcount(alternating_mask), int(M::size()) / 2);
+    COMPARE(popcount(M{false}), 0);
+    COMPARE(popcount(gen({0, 0, 1})), int(M::size()) / 3);
+    COMPARE(popcount(gen({0, 0, 0, 1})), int(M::size()) / 4);
+    COMPARE(popcount(gen({0, 0, 0, 0, 1})), int(M::size()) / 5);
+    COMPARE(std::experimental::popcount(true), 1);
+    COMPARE(std::experimental::popcount(false), 0);
+    VERIFY(sfinae_is_callable<bool>(
+	[](auto x) -> decltype(std::experimental::popcount(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<int>(
+	[](auto x) -> decltype(std::experimental::popcount(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<float>(
+	[](auto x) -> decltype(std::experimental::popcount(x)) { return {}; }));
+    VERIFY(!sfinae_is_callable<char>(
+	[](auto x) -> decltype(std::experimental::popcount(x)) { return {}; }));
+
+    // find_first_set
+    {
+      M x(false);
+      for (int i = int(M::size() / 2 - 1); i >= 0; --i)
+	{
+	  x[i] = true;
+	  COMPARE(find_first_set(x), i) << x;
+	}
+      x = M(false);
+      for (int i = int(M::size() - 1); i >= 0; --i)
+	{
+	  x[i] = true;
+	  COMPARE(find_first_set(x), i) << x;
+	}
+    }
+    COMPARE(find_first_set(M{true}), 0);
+    if (M::size() > 1)
+      {
+	COMPARE(find_first_set(gen({0, 1})), 1);
+      }
+    if (M::size() > 2)
+      {
+	COMPARE(find_first_set(gen({0, 0, 1})), 2);
+      }
+    COMPARE(std::experimental::find_first_set(true), 0);
+    VERIFY(sfinae_is_callable<bool>(
+	[](auto x) -> decltype(std::experimental::find_first_set(x)) {
+	  return {};
+	}));
+    VERIFY(!sfinae_is_callable<int>(
+	[](auto x) -> decltype(std::experimental::find_first_set(x)) {
+	  return {};
+	}));
+    VERIFY(!sfinae_is_callable<float>(
+	[](auto x) -> decltype(std::experimental::find_first_set(x)) {
+	  return {};
+	}));
+    VERIFY(!sfinae_is_callable<char>(
+	[](auto x) -> decltype(std::experimental::find_first_set(x)) {
+	  return {};
+	}));
+
+    // find_last_set
+    {
+      M x(false);
+      for (int i = 0; i < int(M::size()); ++i)
+	{
+	  x[i] = true;
+	  COMPARE(find_last_set(x), i) << x;
+	}
+    }
+    COMPARE(find_last_set(M{true}), int(M::size()) - 1);
+    if (M::size() > 1)
+      {
+	COMPARE(find_last_set(gen({1, 0})),
+		int(M::size()) - 2 + int(M::size() & 1));
+      }
+    if (M::size() > 3 && (M::size() & 3) == 0)
+      {
+	COMPARE(find_last_set(gen({1, 0, 0, 0})),
+		int(M::size()) - 4 - int(M::size() & 3));
+      }
+    COMPARE(std::experimental::find_last_set(true), 0);
+    VERIFY(sfinae_is_callable<bool>(
+	[](auto x) -> decltype(std::experimental::find_last_set(x)) {
+	  return {};
+	}));
+    VERIFY(!sfinae_is_callable<int>(
+	[](auto x) -> decltype(std::experimental::find_last_set(x)) {
+	  return {};
+	}));
+    VERIFY(!sfinae_is_callable<float>(
+	[](auto x) -> decltype(std::experimental::find_last_set(x)) {
+	  return {};
+	}));
+    VERIFY(!sfinae_is_callable<char>(
+	[](auto x) -> decltype(std::experimental::find_last_set(x)) {
+	  return {};
+	}));
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/math_1arg.cc b/libstdc++-v3/testsuite/experimental/simd/tests/math_1arg.cc
new file mode 100644
index 00000000000..748fd1d3866
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/math_1arg.cc
@@ -0,0 +1,90 @@
+// test only floattypes
+#include "bits/verify.h"
+#include "bits/test_values.h"
+
+template <typename V>
+  void
+  test()
+  {
+    vir::test::setFuzzyness<float>(0);
+    vir::test::setFuzzyness<double>(0);
+
+    using T = typename V::value_type;
+    constexpr T inf = std::__infinity_v<T>;
+    constexpr T nan = std::__quiet_NaN_v<T>;
+    constexpr T denorm_min = std::__denorm_min_v<T>;
+    constexpr T norm_min = std::__norm_min_v<T>;
+    constexpr T max = std::__finite_max_v<T>;
+#if defined __LONG_DOUBLE_IBM128__
+    // On POWER with IBM128 long double, 1+eps and 2-eps is not a constant
+    // expression. Until this is fixed, just use const instead of constexpr.
+    // (error: '(1.0e+0l + 4.94065645841246544176568792868221e-324l)' is not a
+    // constant expression)
+    const T after_one = 1 + std::__epsilon_v<T>;
+    const T before_one = (2 - std::__epsilon_v<T>) / 2;
+#else
+    constexpr T after_one = 1 + std::__epsilon_v<T>;
+    constexpr T before_one = (2 - std::__epsilon_v<T>) / 2;
+#endif
+    const std::initializer_list<T>
+      input_values = {+0.,
+		      0.5,
+		      -0.5,
+		      before_one,
+		      -before_one,
+		      after_one,
+		      -after_one,
+		      1.5,
+		      -1.5,
+		      2 * before_one,
+		      -2 * before_one,
+		      2 * after_one,
+		      -2 * after_one,
+		      2.5,
+		      -2.5,
+		      0x1.fffffffffffffp52,
+		      -0x1.fffffffffffffp52,
+		      0x1.ffffffffffffep52,
+		      -0x1.ffffffffffffep52,
+		      0x1.ffffffffffffdp52,
+		      -0x1.ffffffffffffdp52,
+		      0x1.fffffep21,
+		      -0x1.fffffep21,
+		      0x1.fffffcp21,
+		      -0x1.fffffcp21,
+		      0x1.fffffep22,
+		      -0x1.fffffep22,
+		      0x1.fffffcp22,
+		      -0x1.fffffcp22,
+		      0x1.fffffep23,
+		      -0x1.fffffep23,
+		      0x1.fffffcp23,
+		      -0x1.fffffcp23,
+		      0x1.8p23,
+		      -0x1.8p23,
+		      inf,
+		      -inf,
+		      -0.,
+		      nan,
+		      denorm_min,
+		      norm_min / 3,
+		      norm_min,
+		      max};
+    test_values<V>(input_values, {10000}, MAKE_TESTER(erf), MAKE_TESTER(erfc),
+		   MAKE_TESTER(tgamma), MAKE_TESTER(lgamma), MAKE_TESTER(ceil),
+		   MAKE_TESTER(floor), MAKE_TESTER(trunc), MAKE_TESTER(round),
+		   MAKE_TESTER(lround), MAKE_TESTER(llround),
+		   MAKE_TESTER(nearbyint), MAKE_TESTER(rint), MAKE_TESTER(lrint),
+		   MAKE_TESTER(llrint), MAKE_TESTER(ilogb));
+
+    // sqrt(x) on x87 is precise in 80 bits, but the subsequent rounding can be
+    // wrong (up to 1 ULP)
+#if __FLT_EVAL_METHOD__ == 1
+    vir::test::setFuzzyness<float>(1);
+    vir::test::setFuzzyness<double>(0);
+#elif __FLT_EVAL_METHOD__ == 2
+    vir::test::setFuzzyness<float>(1);
+    vir::test::setFuzzyness<double>(1);
+#endif
+    test_values<V>(input_values, {10000}, MAKE_TESTER(sqrt));
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/math_2arg.cc b/libstdc++-v3/testsuite/experimental/simd/tests/math_2arg.cc
new file mode 100644
index 00000000000..ef425fa4221
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/math_2arg.cc
@@ -0,0 +1,62 @@
+// test only floattypes
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/test_values.h"
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+
+    vir::test::setFuzzyness<float>(1);
+    vir::test::setFuzzyness<double>(1);
+    vir::test::setFuzzyness<long double>(1);
+    test_values_2arg<V>(
+      {
+#ifdef __STDC_IEC_559__
+	std::__quiet_NaN_v<T>, std::__infinity_v<T>, -std::__infinity_v<T>, -0.,
+	std::__denorm_min_v<T>, std::__norm_min_v<T> / 3,
+#endif
+	+0., std::__norm_min_v<T>, 1., 2., std::__finite_max_v<T> / 5,
+	std::__finite_max_v<T> / 3, std::__finite_max_v<T> / 2,
+#ifdef __FAST_MATH__
+	// fast-math hypot is imprecise for the max exponent
+      },
+      {100000, std::__finite_max_v<T> / 2},
+#else
+	std::__finite_max_v<T>},
+      {100000},
+#endif
+      MAKE_TESTER(hypot));
+#if !__FINITE_MATH_ONLY__
+    COMPARE(hypot(V(std::__finite_max_v<T>), V(std::__finite_max_v<T>)),
+	    V(std::__infinity_v<T>));
+#endif
+    COMPARE(hypot(V(std::__norm_min_v<T>), V(std::__norm_min_v<T>)),
+	    V(std::__norm_min_v<T> * std::sqrt(T(2))));
+    VERIFY((sfinae_is_callable<V, V>(
+	  [](auto a, auto b) -> decltype(hypot(a, b)) { return {}; })));
+    VERIFY((sfinae_is_callable<typename V::value_type, V>(
+	  [](auto a, auto b) -> decltype(hypot(a, b)) { return {}; })));
+    VERIFY((sfinae_is_callable<V, typename V::value_type>(
+	  [](auto a, auto b) -> decltype(hypot(a, b)) { return {}; })));
+
+    vir::test::setFuzzyness<float>(0);
+    vir::test::setFuzzyness<double>(0);
+    vir::test::setFuzzyness<long double>(0);
+    test_values_2arg<V>(
+      {
+#ifdef __STDC_IEC_559__
+	std::__quiet_NaN_v<T>, std::__infinity_v<T>, -std::__infinity_v<T>,
+	std::__denorm_min_v<T>, std::__norm_min_v<T> / 3, -0.,
+#endif
+	+0., std::__norm_min_v<T>, std::__finite_max_v<T>},
+      {10000}, MAKE_TESTER(pow), MAKE_TESTER(fmod), MAKE_TESTER(remainder),
+      MAKE_TESTER_NOFPEXCEPT(copysign),
+      MAKE_TESTER(nextafter), // MAKE_TESTER(nexttoward),
+      MAKE_TESTER(fdim), MAKE_TESTER(fmax), MAKE_TESTER(fmin),
+      MAKE_TESTER_NOFPEXCEPT(isgreater), MAKE_TESTER_NOFPEXCEPT(isgreaterequal),
+      MAKE_TESTER_NOFPEXCEPT(isless), MAKE_TESTER_NOFPEXCEPT(islessequal),
+      MAKE_TESTER_NOFPEXCEPT(islessgreater), MAKE_TESTER_NOFPEXCEPT(isunordered));
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/operator_cvt.cc b/libstdc++-v3/testsuite/experimental/simd/tests/operator_cvt.cc
new file mode 100644
index 00000000000..1c73e299981
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/operator_cvt.cc
@@ -0,0 +1,1055 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+
+// type with sizeof(char) but different signedness
+using xchar = std::conditional_t<std::is_unsigned_v<char>, schar, uchar>;
+
+using vschar = std::experimental::native_simd<schar>;
+using vuchar = std::experimental::native_simd<uchar>;
+using vshort = std::experimental::native_simd<short>;
+using vushort = std::experimental::native_simd<ushort>;
+using vint = std::experimental::native_simd<int>;
+using vuint = std::experimental::native_simd<uint>;
+using vlong = std::experimental::native_simd<long>;
+using vulong = std::experimental::native_simd<ulong>;
+using vllong = std::experimental::native_simd<llong>;
+using vullong = std::experimental::native_simd<ullong>;
+using vfloat = std::experimental::native_simd<float>;
+using vdouble = std::experimental::native_simd<double>;
+using vldouble = std::experimental::native_simd<long double>;
+using vchar = std::experimental::native_simd<char>;
+using vxchar = std::experimental::native_simd<xchar>;
+
+template <typename T>
+  using vi8 = std::experimental::fixed_size_simd<T, vschar::size()>;
+template <typename T>
+  using vi16 = std::experimental::fixed_size_simd<T, vshort::size()>;
+template <typename T>
+  using vf32 = std::experimental::fixed_size_simd<T, vfloat::size()>;
+template <typename T>
+  using vi32 = std::experimental::fixed_size_simd<T, vint::size()>;
+template <typename T>
+  using vf64 = std::experimental::fixed_size_simd<T, vdouble::size()>;
+template <typename T>
+  using vi64 = std::experimental::fixed_size_simd<T, vllong::size()>;
+template <typename T>
+  using vl = typename std::conditional<sizeof(long) == sizeof(llong), vi64<T>,
+				       vi32<T>>::type;
+
+template <class A, class B, class Expected = A>
+  void
+  binary_op_return_type()
+  {
+    using namespace vir::test;
+    static_assert(std::is_same<A, Expected>::value, "");
+    using AC = std::add_const_t<A>;
+    using BC = std::add_const_t<B>;
+    COMPARE(typeid(A() + B()), typeid(Expected));
+    COMPARE(typeid(B() + A()), typeid(Expected));
+    COMPARE(typeid(AC() + BC()), typeid(Expected));
+    COMPARE(typeid(BC() + AC()), typeid(Expected));
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+    namespace simd_abi = std::experimental::simd_abi;
+    binary_op_return_type<V, V, V>();
+    binary_op_return_type<V, T, V>();
+    binary_op_return_type<V, int, V>();
+
+    if constexpr (std::is_same_v<V, vfloat>)
+      {
+	binary_op_return_type<vfloat, schar>();
+	binary_op_return_type<vfloat, uchar>();
+	binary_op_return_type<vfloat, short>();
+	binary_op_return_type<vfloat, ushort>();
+
+	binary_op_return_type<vf32<float>, schar>();
+	binary_op_return_type<vf32<float>, uchar>();
+	binary_op_return_type<vf32<float>, short>();
+	binary_op_return_type<vf32<float>, ushort>();
+	binary_op_return_type<vf32<float>, int>();
+	binary_op_return_type<vf32<float>, float>();
+
+	binary_op_return_type<vf32<float>, vf32<schar>>();
+	binary_op_return_type<vf32<float>, vf32<uchar>>();
+	binary_op_return_type<vf32<float>, vf32<short>>();
+	binary_op_return_type<vf32<float>, vf32<ushort>>();
+	binary_op_return_type<vf32<float>, vf32<float>>();
+
+	VERIFY((is_substitution_failure<vfloat, uint>));
+	VERIFY((is_substitution_failure<vfloat, long>));
+	VERIFY((is_substitution_failure<vfloat, ulong>));
+	VERIFY((is_substitution_failure<vfloat, llong>));
+	VERIFY((is_substitution_failure<vfloat, ullong>));
+	VERIFY((is_substitution_failure<vfloat, double>));
+	VERIFY((is_substitution_failure<vfloat, vf32<schar>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<uchar>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<short>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<ushort>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<int>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<uint>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<long>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<ulong>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<llong>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<ullong>>));
+	VERIFY((is_substitution_failure<vfloat, vf32<float>>));
+
+	VERIFY((is_substitution_failure<vf32<float>, vfloat>));
+	VERIFY((is_substitution_failure<vf32<float>, uint>));
+	VERIFY((is_substitution_failure<vf32<float>, long>));
+	VERIFY((is_substitution_failure<vf32<float>, ulong>));
+	VERIFY((is_substitution_failure<vf32<float>, llong>));
+	VERIFY((is_substitution_failure<vf32<float>, ullong>));
+	VERIFY((is_substitution_failure<vf32<float>, double>));
+	VERIFY((is_substitution_failure<vf32<float>, vf32<int>>));
+	VERIFY((is_substitution_failure<vf32<float>, vf32<uint>>));
+	VERIFY((is_substitution_failure<vf32<float>, vf32<long>>));
+	VERIFY((is_substitution_failure<vf32<float>, vf32<ulong>>));
+	VERIFY((is_substitution_failure<vf32<float>, vf32<llong>>));
+	VERIFY((is_substitution_failure<vf32<float>, vf32<ullong>>));
+
+	VERIFY((is_substitution_failure<vfloat, vf32<double>>));
+      }
+    else if constexpr (std::is_same_v<V, vdouble>)
+      {
+	binary_op_return_type<vdouble, float, vdouble>();
+	binary_op_return_type<vdouble, schar>();
+	binary_op_return_type<vdouble, uchar>();
+	binary_op_return_type<vdouble, short>();
+	binary_op_return_type<vdouble, ushort>();
+	binary_op_return_type<vdouble, uint>();
+
+	binary_op_return_type<vf64<double>, schar>();
+	binary_op_return_type<vf64<double>, uchar>();
+	binary_op_return_type<vf64<double>, short>();
+	binary_op_return_type<vf64<double>, ushort>();
+	binary_op_return_type<vf64<double>, uint>();
+	binary_op_return_type<vf64<double>, int, vf64<double>>();
+	binary_op_return_type<vf64<double>, float, vf64<double>>();
+	binary_op_return_type<vf64<double>, double, vf64<double>>();
+	binary_op_return_type<vf64<double>, vf64<double>, vf64<double>>();
+	binary_op_return_type<vf32<double>, schar>();
+	binary_op_return_type<vf32<double>, uchar>();
+	binary_op_return_type<vf32<double>, short>();
+	binary_op_return_type<vf32<double>, ushort>();
+	binary_op_return_type<vf32<double>, uint>();
+	binary_op_return_type<vf32<double>, int, vf32<double>>();
+	binary_op_return_type<vf32<double>, float, vf32<double>>();
+	binary_op_return_type<vf32<double>, double, vf32<double>>();
+	binary_op_return_type<vf64<double>, vf64<schar>>();
+	binary_op_return_type<vf64<double>, vf64<uchar>>();
+	binary_op_return_type<vf64<double>, vf64<short>>();
+	binary_op_return_type<vf64<double>, vf64<ushort>>();
+	binary_op_return_type<vf64<double>, vf64<int>>();
+	binary_op_return_type<vf64<double>, vf64<uint>>();
+	binary_op_return_type<vf64<double>, vf64<float>>();
+
+	VERIFY((is_substitution_failure<vdouble, llong>));
+	VERIFY((is_substitution_failure<vdouble, ullong>));
+	VERIFY((is_substitution_failure<vdouble, vf64<schar>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<uchar>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<short>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<ushort>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<int>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<uint>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<long>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<ulong>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<llong>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<ullong>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<float>>));
+	VERIFY((is_substitution_failure<vdouble, vf64<double>>));
+
+	VERIFY((is_substitution_failure<vf64<double>, vdouble>));
+	VERIFY((is_substitution_failure<vf64<double>, llong>));
+	VERIFY((is_substitution_failure<vf64<double>, ullong>));
+	VERIFY((is_substitution_failure<vf64<double>, vf64<llong>>));
+	VERIFY((is_substitution_failure<vf64<double>, vf64<ullong>>));
+
+	VERIFY((is_substitution_failure<vf32<double>, llong>));
+	VERIFY((is_substitution_failure<vf32<double>, ullong>));
+
+	if constexpr (sizeof(long) == sizeof(llong))
+	  {
+	    VERIFY((is_substitution_failure<vdouble, long>));
+	    VERIFY((is_substitution_failure<vdouble, ulong>));
+	    VERIFY((is_substitution_failure<vf64<double>, long>));
+	    VERIFY((is_substitution_failure<vf64<double>, ulong>));
+	    VERIFY((is_substitution_failure<vf64<double>, vf64<long>>));
+	    VERIFY((is_substitution_failure<vf64<double>, vf64<ulong>>));
+	    VERIFY((is_substitution_failure<vf32<double>, long>));
+	    VERIFY((is_substitution_failure<vf32<double>, ulong>));
+	  }
+	else
+	  {
+	    binary_op_return_type<vdouble, long>();
+	    binary_op_return_type<vdouble, ulong>();
+	    binary_op_return_type<vf64<double>, long>();
+	    binary_op_return_type<vf64<double>, ulong>();
+	    binary_op_return_type<vf64<double>, vf64<long>>();
+	    binary_op_return_type<vf64<double>, vf64<ulong>>();
+	    binary_op_return_type<vf32<double>, long>();
+	    binary_op_return_type<vf32<double>, ulong>();
+	  }
+      }
+    else if constexpr (std::is_same_v<V, vldouble>)
+      {
+	binary_op_return_type<vldouble, schar>();
+	binary_op_return_type<vldouble, uchar>();
+	binary_op_return_type<vldouble, short>();
+	binary_op_return_type<vldouble, ushort>();
+	binary_op_return_type<vldouble, uint>();
+	binary_op_return_type<vldouble, long>();
+	binary_op_return_type<vldouble, ulong>();
+	binary_op_return_type<vldouble, float>();
+	binary_op_return_type<vldouble, double>();
+
+	binary_op_return_type<vf64<long double>, schar>();
+	binary_op_return_type<vf64<long double>, uchar>();
+	binary_op_return_type<vf64<long double>, short>();
+	binary_op_return_type<vf64<long double>, ushort>();
+	binary_op_return_type<vf64<long double>, int>();
+	binary_op_return_type<vf64<long double>, uint>();
+	binary_op_return_type<vf64<long double>, long>();
+	binary_op_return_type<vf64<long double>, ulong>();
+	binary_op_return_type<vf64<long double>, float>();
+	binary_op_return_type<vf64<long double>, double>();
+	binary_op_return_type<vf64<long double>, vf64<long double>>();
+
+	using std::experimental::simd;
+	using A = simd_abi::fixed_size<vldouble::size()>;
+	binary_op_return_type<simd<long double, A>, schar>();
+	binary_op_return_type<simd<long double, A>, uchar>();
+	binary_op_return_type<simd<long double, A>, short>();
+	binary_op_return_type<simd<long double, A>, ushort>();
+	binary_op_return_type<simd<long double, A>, int>();
+	binary_op_return_type<simd<long double, A>, uint>();
+	binary_op_return_type<simd<long double, A>, long>();
+	binary_op_return_type<simd<long double, A>, ulong>();
+	binary_op_return_type<simd<long double, A>, float>();
+	binary_op_return_type<simd<long double, A>, double>();
+
+	if constexpr (sizeof(ldouble) == sizeof(double))
+	  {
+	    VERIFY((is_substitution_failure<vldouble, llong>));
+	    VERIFY((is_substitution_failure<vldouble, ullong>));
+	    VERIFY((is_substitution_failure<vf64<ldouble>, llong>));
+	    VERIFY((is_substitution_failure<vf64<ldouble>, ullong>));
+	    VERIFY((is_substitution_failure<simd<ldouble, A>, llong>));
+	    VERIFY((is_substitution_failure<simd<ldouble, A>, ullong>));
+	  }
+	else
+	  {
+	    binary_op_return_type<vldouble, llong>();
+	    binary_op_return_type<vldouble, ullong>();
+	    binary_op_return_type<vf64<long double>, llong>();
+	    binary_op_return_type<vf64<long double>, ullong>();
+	    binary_op_return_type<simd<long double, A>, llong>();
+	    binary_op_return_type<simd<long double, A>, ullong>();
+	  }
+
+	VERIFY((is_substitution_failure<vf64<long double>, vldouble>));
+	COMPARE((is_substitution_failure<simd<long double, A>, vldouble>),
+		(!std::is_same<A, vldouble::abi_type>::value));
+      }
+    else if constexpr (std::is_same_v<V, vlong>)
+      {
+	VERIFY((is_substitution_failure<vi32<long>, double>));
+	VERIFY((is_substitution_failure<vi32<long>, float>));
+	VERIFY((is_substitution_failure<vi32<long>, vi32<float>>));
+	if constexpr (sizeof(long) == sizeof(llong))
+	  {
+	    binary_op_return_type<vlong, uint>();
+	    binary_op_return_type<vlong, llong>();
+	    binary_op_return_type<vi32<long>, uint>();
+	    binary_op_return_type<vi32<long>, llong>();
+	    binary_op_return_type<vi64<long>, uint>();
+	    binary_op_return_type<vi64<long>, llong>();
+	    binary_op_return_type<vi32<long>, vi32<uint>>();
+	    binary_op_return_type<vi64<long>, vi64<uint>>();
+	    VERIFY((is_substitution_failure<vi32<long>, vi32<double>>));
+	    VERIFY((is_substitution_failure<vi64<long>, vi64<double>>));
+	  }
+	else
+	  {
+	    VERIFY((is_substitution_failure<vlong, uint>));
+	    VERIFY((is_substitution_failure<vlong, llong>));
+	    VERIFY((is_substitution_failure<vi32<long>, uint>));
+	    VERIFY((is_substitution_failure<vi32<long>, llong>));
+	    VERIFY((is_substitution_failure<vi64<long>, uint>));
+	    VERIFY((is_substitution_failure<vi64<long>, llong>));
+	    VERIFY((is_substitution_failure<vi32<long>, vi32<uint>>));
+	    VERIFY((is_substitution_failure<vi64<long>, vi64<uint>>));
+	    binary_op_return_type<vi32<double>, vi32<long>>();
+	    binary_op_return_type<vi64<double>, vi64<long>>();
+	  }
+
+	binary_op_return_type<vlong, schar, vlong>();
+	binary_op_return_type<vlong, uchar, vlong>();
+	binary_op_return_type<vlong, short, vlong>();
+	binary_op_return_type<vlong, ushort, vlong>();
+
+	binary_op_return_type<vi32<long>, schar, vi32<long>>();
+	binary_op_return_type<vi32<long>, uchar, vi32<long>>();
+	binary_op_return_type<vi32<long>, short, vi32<long>>();
+	binary_op_return_type<vi32<long>, ushort, vi32<long>>();
+	binary_op_return_type<vi32<long>, int, vi32<long>>();
+	binary_op_return_type<vi32<long>, long, vi32<long>>();
+	binary_op_return_type<vi32<long>, vi32<long>, vi32<long>>();
+	binary_op_return_type<vi64<long>, schar, vi64<long>>();
+	binary_op_return_type<vi64<long>, uchar, vi64<long>>();
+	binary_op_return_type<vi64<long>, short, vi64<long>>();
+	binary_op_return_type<vi64<long>, ushort, vi64<long>>();
+	binary_op_return_type<vi64<long>, int, vi64<long>>();
+	binary_op_return_type<vi64<long>, long, vi64<long>>();
+	binary_op_return_type<vi64<long>, vi64<long>, vi64<long>>();
+
+	VERIFY((is_substitution_failure<vlong, vulong>));
+	VERIFY((is_substitution_failure<vlong, ulong>));
+	VERIFY((is_substitution_failure<vlong, ullong>));
+	VERIFY((is_substitution_failure<vlong, float>));
+	VERIFY((is_substitution_failure<vlong, double>));
+	VERIFY((is_substitution_failure<vlong, vl<schar>>));
+	VERIFY((is_substitution_failure<vlong, vl<uchar>>));
+	VERIFY((is_substitution_failure<vlong, vl<short>>));
+	VERIFY((is_substitution_failure<vlong, vl<ushort>>));
+	VERIFY((is_substitution_failure<vlong, vl<int>>));
+	VERIFY((is_substitution_failure<vlong, vl<uint>>));
+	VERIFY((is_substitution_failure<vlong, vl<long>>));
+	VERIFY((is_substitution_failure<vlong, vl<ulong>>));
+	VERIFY((is_substitution_failure<vlong, vl<llong>>));
+	VERIFY((is_substitution_failure<vlong, vl<ullong>>));
+	VERIFY((is_substitution_failure<vlong, vl<float>>));
+	VERIFY((is_substitution_failure<vlong, vl<double>>));
+	VERIFY((is_substitution_failure<vl<long>, vlong>));
+	VERIFY((is_substitution_failure<vl<long>, vulong>));
+	VERIFY((is_substitution_failure<vi32<long>, ulong>));
+	VERIFY((is_substitution_failure<vi32<long>, ullong>));
+	binary_op_return_type<vi32<long>, vi32<schar>>();
+	binary_op_return_type<vi32<long>, vi32<uchar>>();
+	binary_op_return_type<vi32<long>, vi32<short>>();
+	binary_op_return_type<vi32<long>, vi32<ushort>>();
+	binary_op_return_type<vi32<long>, vi32<int>>();
+	VERIFY((is_substitution_failure<vi32<long>, vi32<ulong>>));
+	VERIFY((is_substitution_failure<vi32<long>, vi32<ullong>>));
+	VERIFY((is_substitution_failure<vi64<long>, ulong>));
+	VERIFY((is_substitution_failure<vi64<long>, ullong>));
+	VERIFY((is_substitution_failure<vi64<long>, float>));
+	VERIFY((is_substitution_failure<vi64<long>, double>));
+	binary_op_return_type<vi64<long>, vi64<schar>>();
+	binary_op_return_type<vi64<long>, vi64<uchar>>();
+	binary_op_return_type<vi64<long>, vi64<short>>();
+	binary_op_return_type<vi64<long>, vi64<ushort>>();
+	binary_op_return_type<vi64<long>, vi64<int>>();
+	VERIFY((is_substitution_failure<vi64<long>, vi64<ulong>>));
+	VERIFY((is_substitution_failure<vi64<long>, vi64<ullong>>));
+	VERIFY((is_substitution_failure<vi64<long>, vi64<float>>));
+
+	binary_op_return_type<vi32<llong>, vi32<long>>();
+	binary_op_return_type<vi64<llong>, vi64<long>>();
+      }
+    else if constexpr (std::is_same_v<V, vulong>)
+      {
+	if constexpr (sizeof(long) == sizeof(llong))
+	  {
+	    binary_op_return_type<vulong, ullong, vulong>();
+	    binary_op_return_type<vi32<ulong>, ullong, vi32<ulong>>();
+	    binary_op_return_type<vi64<ulong>, ullong, vi64<ulong>>();
+	    VERIFY((is_substitution_failure<vi32<ulong>, vi32<llong>>));
+	    VERIFY((is_substitution_failure<vi32<ulong>, vi32<double>>));
+	    VERIFY((is_substitution_failure<vi64<ulong>, vi64<llong>>));
+	    VERIFY((is_substitution_failure<vi64<ulong>, vi64<double>>));
+	  }
+	else
+	  {
+	    VERIFY((is_substitution_failure<vulong, ullong>));
+	    VERIFY((is_substitution_failure<vi32<ulong>, ullong>));
+	    VERIFY((is_substitution_failure<vi64<ulong>, ullong>));
+	    binary_op_return_type<vi32<llong>, vi32<ulong>>();
+	    binary_op_return_type<vi32<double>, vi32<ulong>>();
+	    binary_op_return_type<vi64<llong>, vi64<ulong>>();
+	    binary_op_return_type<vi64<double>, vi64<ulong>>();
+	  }
+
+	binary_op_return_type<vulong, uchar, vulong>();
+	binary_op_return_type<vulong, ushort, vulong>();
+	binary_op_return_type<vulong, uint, vulong>();
+	binary_op_return_type<vi32<ulong>, uchar, vi32<ulong>>();
+	binary_op_return_type<vi32<ulong>, ushort, vi32<ulong>>();
+	binary_op_return_type<vi32<ulong>, int, vi32<ulong>>();
+	binary_op_return_type<vi32<ulong>, uint, vi32<ulong>>();
+	binary_op_return_type<vi32<ulong>, ulong, vi32<ulong>>();
+	binary_op_return_type<vi32<ulong>, vi32<ulong>, vi32<ulong>>();
+	binary_op_return_type<vi64<ulong>, uchar, vi64<ulong>>();
+	binary_op_return_type<vi64<ulong>, ushort, vi64<ulong>>();
+	binary_op_return_type<vi64<ulong>, int, vi64<ulong>>();
+	binary_op_return_type<vi64<ulong>, uint, vi64<ulong>>();
+	binary_op_return_type<vi64<ulong>, ulong, vi64<ulong>>();
+	binary_op_return_type<vi64<ulong>, vi64<ulong>, vi64<ulong>>();
+
+	VERIFY((is_substitution_failure<vi32<ulong>, llong>));
+	VERIFY((is_substitution_failure<vi32<ulong>, float>));
+	VERIFY((is_substitution_failure<vi32<ulong>, double>));
+	VERIFY((is_substitution_failure<vi32<ulong>, vi32<float>>));
+	VERIFY((is_substitution_failure<vi64<ulong>, vi64<float>>));
+	VERIFY((is_substitution_failure<vulong, schar>));
+	VERIFY((is_substitution_failure<vulong, short>));
+	VERIFY((is_substitution_failure<vulong, vlong>));
+	VERIFY((is_substitution_failure<vulong, long>));
+	VERIFY((is_substitution_failure<vulong, llong>));
+	VERIFY((is_substitution_failure<vulong, float>));
+	VERIFY((is_substitution_failure<vulong, double>));
+	VERIFY((is_substitution_failure<vulong, vl<schar>>));
+	VERIFY((is_substitution_failure<vulong, vl<uchar>>));
+	VERIFY((is_substitution_failure<vulong, vl<short>>));
+	VERIFY((is_substitution_failure<vulong, vl<ushort>>));
+	VERIFY((is_substitution_failure<vulong, vl<int>>));
+	VERIFY((is_substitution_failure<vulong, vl<uint>>));
+	VERIFY((is_substitution_failure<vulong, vl<long>>));
+	VERIFY((is_substitution_failure<vulong, vl<ulong>>));
+	VERIFY((is_substitution_failure<vulong, vl<llong>>));
+	VERIFY((is_substitution_failure<vulong, vl<ullong>>));
+	VERIFY((is_substitution_failure<vulong, vl<float>>));
+	VERIFY((is_substitution_failure<vulong, vl<double>>));
+	VERIFY((is_substitution_failure<vl<ulong>, vlong>));
+	VERIFY((is_substitution_failure<vl<ulong>, vulong>));
+	VERIFY((is_substitution_failure<vi32<ulong>, schar>));
+	VERIFY((is_substitution_failure<vi32<ulong>, short>));
+	VERIFY((is_substitution_failure<vi32<ulong>, long>));
+	VERIFY((is_substitution_failure<vi32<ulong>, vi32<schar>>));
+	binary_op_return_type<vi32<ulong>, vi32<uchar>>();
+	VERIFY((is_substitution_failure<vi32<ulong>, vi32<short>>));
+	binary_op_return_type<vi32<ulong>, vi32<ushort>>();
+	VERIFY((is_substitution_failure<vi32<ulong>, vi32<int>>));
+	binary_op_return_type<vi32<ulong>, vi32<uint>>();
+	VERIFY((is_substitution_failure<vi32<ulong>, vi32<long>>));
+	binary_op_return_type<vi32<ullong>, vi32<ulong>>();
+	VERIFY((is_substitution_failure<vi64<ulong>, schar>));
+	VERIFY((is_substitution_failure<vi64<ulong>, short>));
+	VERIFY((is_substitution_failure<vi64<ulong>, long>));
+	VERIFY((is_substitution_failure<vi64<ulong>, llong>));
+	VERIFY((is_substitution_failure<vi64<ulong>, float>));
+	VERIFY((is_substitution_failure<vi64<ulong>, double>));
+	VERIFY((is_substitution_failure<vi64<ulong>, vi64<schar>>));
+	binary_op_return_type<vi64<ulong>, vi64<uchar>>();
+	VERIFY((is_substitution_failure<vi64<ulong>, vi64<short>>));
+	binary_op_return_type<vi64<ulong>, vi64<ushort>>();
+	VERIFY((is_substitution_failure<vi64<ulong>, vi64<int>>));
+	binary_op_return_type<vi64<ulong>, vi64<uint>>();
+	VERIFY((is_substitution_failure<vi64<ulong>, vi64<long>>));
+	binary_op_return_type<vi64<ullong>, vi64<ulong>>();
+      }
+    else if constexpr (std::is_same_v<V, vllong>)
+      {
+	binary_op_return_type<vllong, schar, vllong>();
+	binary_op_return_type<vllong, uchar, vllong>();
+	binary_op_return_type<vllong, short, vllong>();
+	binary_op_return_type<vllong, ushort, vllong>();
+	binary_op_return_type<vllong, uint, vllong>();
+	binary_op_return_type<vllong, long, vllong>();
+	binary_op_return_type<vi32<llong>, schar, vi32<llong>>();
+	binary_op_return_type<vi32<llong>, uchar, vi32<llong>>();
+	binary_op_return_type<vi32<llong>, short, vi32<llong>>();
+	binary_op_return_type<vi32<llong>, ushort, vi32<llong>>();
+	binary_op_return_type<vi32<llong>, int, vi32<llong>>();
+	binary_op_return_type<vi32<llong>, uint, vi32<llong>>();
+	binary_op_return_type<vi32<llong>, long, vi32<llong>>();
+	binary_op_return_type<vi32<llong>, llong, vi32<llong>>();
+	binary_op_return_type<vi32<llong>, vi32<llong>, vi32<llong>>();
+	binary_op_return_type<vi64<llong>, schar, vi64<llong>>();
+	binary_op_return_type<vi64<llong>, uchar, vi64<llong>>();
+	binary_op_return_type<vi64<llong>, short, vi64<llong>>();
+	binary_op_return_type<vi64<llong>, ushort, vi64<llong>>();
+	binary_op_return_type<vi64<llong>, int, vi64<llong>>();
+	binary_op_return_type<vi64<llong>, uint, vi64<llong>>();
+	binary_op_return_type<vi64<llong>, long, vi64<llong>>();
+	binary_op_return_type<vi64<llong>, llong, vi64<llong>>();
+	binary_op_return_type<vi64<llong>, vi64<llong>>();
+	binary_op_return_type<vi32<llong>, vi32<schar>>();
+	binary_op_return_type<vi32<llong>, vi32<uchar>>();
+	binary_op_return_type<vi32<llong>, vi32<short>>();
+	binary_op_return_type<vi32<llong>, vi32<ushort>>();
+	binary_op_return_type<vi32<llong>, vi32<int>>();
+	binary_op_return_type<vi32<llong>, vi32<uint>>();
+	binary_op_return_type<vi32<llong>, vi32<long>>();
+	if constexpr (sizeof(long) == sizeof(llong))
+	  {
+	    VERIFY((is_substitution_failure<vi32<llong>, vi32<ulong>>));
+	    VERIFY((is_substitution_failure<vi32<llong>, ulong>));
+	    VERIFY((is_substitution_failure<vi64<llong>, ulong>));
+	    VERIFY((is_substitution_failure<vllong, ulong>));
+	  }
+	else
+	  {
+	    binary_op_return_type<vi32<llong>, vi32<ulong>>();
+	    binary_op_return_type<vi32<llong>, ulong>();
+	    binary_op_return_type<vi64<llong>, ulong>();
+	    binary_op_return_type<vllong, ulong>();
+	  }
+
+	VERIFY((is_substitution_failure<vllong, vullong>));
+	VERIFY((is_substitution_failure<vllong, ullong>));
+	VERIFY((is_substitution_failure<vllong, float>));
+	VERIFY((is_substitution_failure<vllong, double>));
+	VERIFY((is_substitution_failure<vllong, vi64<schar>>));
+	VERIFY((is_substitution_failure<vllong, vi64<uchar>>));
+	VERIFY((is_substitution_failure<vllong, vi64<short>>));
+	VERIFY((is_substitution_failure<vllong, vi64<ushort>>));
+	VERIFY((is_substitution_failure<vllong, vi64<int>>));
+	VERIFY((is_substitution_failure<vllong, vi64<uint>>));
+	VERIFY((is_substitution_failure<vllong, vi64<long>>));
+	VERIFY((is_substitution_failure<vllong, vi64<ulong>>));
+	VERIFY((is_substitution_failure<vllong, vi64<llong>>));
+	VERIFY((is_substitution_failure<vllong, vi64<ullong>>));
+	VERIFY((is_substitution_failure<vllong, vi64<float>>));
+	VERIFY((is_substitution_failure<vllong, vi64<double>>));
+	VERIFY((is_substitution_failure<vi32<llong>, ullong>));
+	VERIFY((is_substitution_failure<vi32<llong>, float>));
+	VERIFY((is_substitution_failure<vi32<llong>, double>));
+	VERIFY((is_substitution_failure<vi32<llong>, vi32<ullong>>));
+	VERIFY((is_substitution_failure<vi32<llong>, vi32<float>>));
+	VERIFY((is_substitution_failure<vi32<llong>, vi32<double>>));
+	VERIFY((is_substitution_failure<vi64<llong>, vllong>));
+	VERIFY((is_substitution_failure<vi64<llong>, vullong>));
+	VERIFY((is_substitution_failure<vi64<llong>, ullong>));
+	VERIFY((is_substitution_failure<vi64<llong>, float>));
+	VERIFY((is_substitution_failure<vi64<llong>, double>));
+	binary_op_return_type<vi64<llong>, vi64<schar>>();
+	binary_op_return_type<vi64<llong>, vi64<uchar>>();
+	binary_op_return_type<vi64<llong>, vi64<short>>();
+	binary_op_return_type<vi64<llong>, vi64<ushort>>();
+	binary_op_return_type<vi64<llong>, vi64<int>>();
+	binary_op_return_type<vi64<llong>, vi64<uint>>();
+	binary_op_return_type<vi64<llong>, vi64<long>>();
+	if constexpr (sizeof(long) == sizeof(llong))
+	  {
+	    VERIFY((is_substitution_failure<vi64<llong>, vi64<ulong>>));
+	  }
+	else
+	  {
+	    binary_op_return_type<vi64<llong>, vi64<ulong>>();
+	  }
+	VERIFY((is_substitution_failure<vi64<llong>, vi64<ullong>>));
+	VERIFY((is_substitution_failure<vi64<llong>, vi64<float>>));
+	VERIFY((is_substitution_failure<vi64<llong>, vi64<double>>));
+      }
+    else if constexpr (std::is_same_v<V, vullong>)
+      {
+	binary_op_return_type<vullong, uchar, vullong>();
+	binary_op_return_type<vullong, ushort, vullong>();
+	binary_op_return_type<vullong, uint, vullong>();
+	binary_op_return_type<vullong, ulong, vullong>();
+	binary_op_return_type<vi32<ullong>, uchar, vi32<ullong>>();
+	binary_op_return_type<vi32<ullong>, ushort, vi32<ullong>>();
+	binary_op_return_type<vi32<ullong>, int, vi32<ullong>>();
+	binary_op_return_type<vi32<ullong>, uint, vi32<ullong>>();
+	binary_op_return_type<vi32<ullong>, ulong, vi32<ullong>>();
+	binary_op_return_type<vi32<ullong>, ullong, vi32<ullong>>();
+	binary_op_return_type<vi32<ullong>, vi32<ullong>, vi32<ullong>>();
+	binary_op_return_type<vi64<ullong>, uchar, vi64<ullong>>();
+	binary_op_return_type<vi64<ullong>, ushort, vi64<ullong>>();
+	binary_op_return_type<vi64<ullong>, int, vi64<ullong>>();
+	binary_op_return_type<vi64<ullong>, uint, vi64<ullong>>();
+	binary_op_return_type<vi64<ullong>, ulong, vi64<ullong>>();
+	binary_op_return_type<vi64<ullong>, ullong, vi64<ullong>>();
+	binary_op_return_type<vi64<ullong>, vi64<ullong>, vi64<ullong>>();
+
+	VERIFY((is_substitution_failure<vullong, schar>));
+	VERIFY((is_substitution_failure<vullong, short>));
+	VERIFY((is_substitution_failure<vullong, long>));
+	VERIFY((is_substitution_failure<vullong, llong>));
+	VERIFY((is_substitution_failure<vullong, vllong>));
+	VERIFY((is_substitution_failure<vullong, float>));
+	VERIFY((is_substitution_failure<vullong, double>));
+	VERIFY((is_substitution_failure<vullong, vi64<schar>>));
+	VERIFY((is_substitution_failure<vullong, vi64<uchar>>));
+	VERIFY((is_substitution_failure<vullong, vi64<short>>));
+	VERIFY((is_substitution_failure<vullong, vi64<ushort>>));
+	VERIFY((is_substitution_failure<vullong, vi64<int>>));
+	VERIFY((is_substitution_failure<vullong, vi64<uint>>));
+	VERIFY((is_substitution_failure<vullong, vi64<long>>));
+	VERIFY((is_substitution_failure<vullong, vi64<ulong>>));
+	VERIFY((is_substitution_failure<vullong, vi64<llong>>));
+	VERIFY((is_substitution_failure<vullong, vi64<ullong>>));
+	VERIFY((is_substitution_failure<vullong, vi64<float>>));
+	VERIFY((is_substitution_failure<vullong, vi64<double>>));
+	VERIFY((is_substitution_failure<vi32<ullong>, schar>));
+	VERIFY((is_substitution_failure<vi32<ullong>, short>));
+	VERIFY((is_substitution_failure<vi32<ullong>, long>));
+	VERIFY((is_substitution_failure<vi32<ullong>, llong>));
+	VERIFY((is_substitution_failure<vi32<ullong>, float>));
+	VERIFY((is_substitution_failure<vi32<ullong>, double>));
+	VERIFY((is_substitution_failure<vi32<ullong>, vi32<schar>>));
+	binary_op_return_type<vi32<ullong>, vi32<uchar>>();
+	VERIFY((is_substitution_failure<vi32<ullong>, vi32<short>>));
+	binary_op_return_type<vi32<ullong>, vi32<ushort>>();
+	VERIFY((is_substitution_failure<vi32<ullong>, vi32<int>>));
+	binary_op_return_type<vi32<ullong>, vi32<uint>>();
+	VERIFY((is_substitution_failure<vi32<ullong>, vi32<long>>));
+	binary_op_return_type<vi32<ullong>, vi32<ulong>>();
+	VERIFY((is_substitution_failure<vi32<ullong>, vi32<llong>>));
+	VERIFY((is_substitution_failure<vi32<ullong>, vi32<float>>));
+	VERIFY((is_substitution_failure<vi32<ullong>, vi32<double>>));
+	VERIFY((is_substitution_failure<vi64<ullong>, schar>));
+	VERIFY((is_substitution_failure<vi64<ullong>, short>));
+	VERIFY((is_substitution_failure<vi64<ullong>, long>));
+	VERIFY((is_substitution_failure<vi64<ullong>, llong>));
+	VERIFY((is_substitution_failure<vi64<ullong>, vllong>));
+	VERIFY((is_substitution_failure<vi64<ullong>, vullong>));
+	VERIFY((is_substitution_failure<vi64<ullong>, float>));
+	VERIFY((is_substitution_failure<vi64<ullong>, double>));
+	VERIFY((is_substitution_failure<vi64<ullong>, vi64<schar>>));
+	binary_op_return_type<vi64<ullong>, vi64<uchar>>();
+	VERIFY((is_substitution_failure<vi64<ullong>, vi64<short>>));
+	binary_op_return_type<vi64<ullong>, vi64<ushort>>();
+	VERIFY((is_substitution_failure<vi64<ullong>, vi64<int>>));
+	binary_op_return_type<vi64<ullong>, vi64<uint>>();
+	VERIFY((is_substitution_failure<vi64<ullong>, vi64<long>>));
+	binary_op_return_type<vi64<ullong>, vi64<ulong>>();
+	VERIFY((is_substitution_failure<vi64<ullong>, vi64<llong>>));
+	VERIFY((is_substitution_failure<vi64<ullong>, vi64<float>>));
+	VERIFY((is_substitution_failure<vi64<ullong>, vi64<double>>));
+      }
+    else if constexpr (std::is_same_v<V, vint>)
+      {
+	binary_op_return_type<vint, schar, vint>();
+	binary_op_return_type<vint, uchar, vint>();
+	binary_op_return_type<vint, short, vint>();
+	binary_op_return_type<vint, ushort, vint>();
+	binary_op_return_type<vi32<int>, schar, vi32<int>>();
+	binary_op_return_type<vi32<int>, uchar, vi32<int>>();
+	binary_op_return_type<vi32<int>, short, vi32<int>>();
+	binary_op_return_type<vi32<int>, ushort, vi32<int>>();
+	binary_op_return_type<vi32<int>, int, vi32<int>>();
+	binary_op_return_type<vi32<int>, vi32<int>, vi32<int>>();
+	binary_op_return_type<vi32<int>, vi32<schar>>();
+	binary_op_return_type<vi32<int>, vi32<uchar>>();
+	binary_op_return_type<vi32<int>, vi32<short>>();
+	binary_op_return_type<vi32<int>, vi32<ushort>>();
+
+	binary_op_return_type<vi32<llong>, vi32<int>>();
+	binary_op_return_type<vi32<double>, vi32<int>>();
+
+	// order is important for MSVC. This compiler is just crazy: It considers
+	// operators from unrelated simd template instantiations as candidates -
+	// but only after they have been tested. So e.g. vi32<int> + llong will
+	// produce a vi32<llong> if a vi32<llong> operator test is done before the
+	// vi32<int> + llong test.
+	VERIFY((is_substitution_failure<vi32<int>, double>));
+	VERIFY((is_substitution_failure<vi32<int>, float>));
+	VERIFY((is_substitution_failure<vi32<int>, llong>));
+	VERIFY((is_substitution_failure<vi32<int>, vi32<float>>));
+	VERIFY((is_substitution_failure<vint, vuint>));
+	VERIFY((is_substitution_failure<vint, uint>));
+	VERIFY((is_substitution_failure<vint, ulong>));
+	VERIFY((is_substitution_failure<vint, llong>));
+	VERIFY((is_substitution_failure<vint, ullong>));
+	VERIFY((is_substitution_failure<vint, float>));
+	VERIFY((is_substitution_failure<vint, double>));
+	VERIFY((is_substitution_failure<vint, vi32<schar>>));
+	VERIFY((is_substitution_failure<vint, vi32<uchar>>));
+	VERIFY((is_substitution_failure<vint, vi32<short>>));
+	VERIFY((is_substitution_failure<vint, vi32<ushort>>));
+	VERIFY((is_substitution_failure<vint, vi32<int>>));
+	VERIFY((is_substitution_failure<vint, vi32<uint>>));
+	VERIFY((is_substitution_failure<vint, vi32<long>>));
+	VERIFY((is_substitution_failure<vint, vi32<ulong>>));
+	VERIFY((is_substitution_failure<vint, vi32<llong>>));
+	VERIFY((is_substitution_failure<vint, vi32<ullong>>));
+	VERIFY((is_substitution_failure<vint, vi32<float>>));
+	VERIFY((is_substitution_failure<vint, vi32<double>>));
+	VERIFY((is_substitution_failure<vi32<int>, vint>));
+	VERIFY((is_substitution_failure<vi32<int>, vuint>));
+	VERIFY((is_substitution_failure<vi32<int>, uint>));
+	VERIFY((is_substitution_failure<vi32<int>, ulong>));
+	VERIFY((is_substitution_failure<vi32<int>, ullong>));
+	VERIFY((is_substitution_failure<vi32<int>, vi32<uint>>));
+	VERIFY((is_substitution_failure<vi32<int>, vi32<ulong>>));
+	VERIFY((is_substitution_failure<vi32<int>, vi32<ullong>>));
+
+	binary_op_return_type<vi32<long>, vi32<int>>();
+	if constexpr (sizeof(long) == sizeof(llong))
+	  {
+	    VERIFY((is_substitution_failure<vint, long>));
+	    VERIFY((is_substitution_failure<vi32<int>, long>));
+	  }
+	else
+	  {
+	    binary_op_return_type<vint, long>();
+	    binary_op_return_type<vi32<int>, long>();
+	  }
+      }
+    else if constexpr (std::is_same_v<V, vuint>)
+      {
+	VERIFY((is_substitution_failure<vi32<uint>, llong>));
+	VERIFY((is_substitution_failure<vi32<uint>, ullong>));
+	VERIFY((is_substitution_failure<vi32<uint>, float>));
+	VERIFY((is_substitution_failure<vi32<uint>, double>));
+	VERIFY((is_substitution_failure<vi32<uint>, vi32<float>>));
+
+	binary_op_return_type<vuint, uchar, vuint>();
+	binary_op_return_type<vuint, ushort, vuint>();
+	binary_op_return_type<vi32<uint>, uchar, vi32<uint>>();
+	binary_op_return_type<vi32<uint>, ushort, vi32<uint>>();
+	binary_op_return_type<vi32<uint>, int, vi32<uint>>();
+	binary_op_return_type<vi32<uint>, uint, vi32<uint>>();
+	binary_op_return_type<vi32<uint>, vi32<uint>, vi32<uint>>();
+	binary_op_return_type<vi32<uint>, vi32<uchar>>();
+	binary_op_return_type<vi32<uint>, vi32<ushort>>();
+
+	binary_op_return_type<vi32<llong>, vi32<uint>>();
+	binary_op_return_type<vi32<ullong>, vi32<uint>>();
+	binary_op_return_type<vi32<double>, vi32<uint>>();
+
+	VERIFY((is_substitution_failure<vuint, schar>));
+	VERIFY((is_substitution_failure<vuint, short>));
+	VERIFY((is_substitution_failure<vuint, vint>));
+	VERIFY((is_substitution_failure<vuint, long>));
+	VERIFY((is_substitution_failure<vuint, llong>));
+	VERIFY((is_substitution_failure<vuint, ullong>));
+	VERIFY((is_substitution_failure<vuint, float>));
+	VERIFY((is_substitution_failure<vuint, double>));
+	VERIFY((is_substitution_failure<vuint, vi32<schar>>));
+	VERIFY((is_substitution_failure<vuint, vi32<uchar>>));
+	VERIFY((is_substitution_failure<vuint, vi32<short>>));
+	VERIFY((is_substitution_failure<vuint, vi32<ushort>>));
+	VERIFY((is_substitution_failure<vuint, vi32<int>>));
+	VERIFY((is_substitution_failure<vuint, vi32<uint>>));
+	VERIFY((is_substitution_failure<vuint, vi32<long>>));
+	VERIFY((is_substitution_failure<vuint, vi32<ulong>>));
+	VERIFY((is_substitution_failure<vuint, vi32<llong>>));
+	VERIFY((is_substitution_failure<vuint, vi32<ullong>>));
+	VERIFY((is_substitution_failure<vuint, vi32<float>>));
+	VERIFY((is_substitution_failure<vuint, vi32<double>>));
+	VERIFY((is_substitution_failure<vi32<uint>, schar>));
+	VERIFY((is_substitution_failure<vi32<uint>, short>));
+	VERIFY((is_substitution_failure<vi32<uint>, vint>));
+	VERIFY((is_substitution_failure<vi32<uint>, vuint>));
+	VERIFY((is_substitution_failure<vi32<uint>, long>));
+	VERIFY((is_substitution_failure<vi32<uint>, vi32<schar>>));
+	VERIFY((is_substitution_failure<vi32<uint>, vi32<short>>));
+	VERIFY((is_substitution_failure<vi32<uint>, vi32<int>>));
+
+	binary_op_return_type<vi32<ulong>, vi32<uint>>();
+	if constexpr (sizeof(long) == sizeof(llong))
+	  {
+	    VERIFY((is_substitution_failure<vuint, ulong>));
+	    VERIFY((is_substitution_failure<vi32<uint>, ulong>));
+	    binary_op_return_type<vi32<long>, vi32<uint>>();
+	  }
+	else
+	  {
+	    binary_op_return_type<vuint, ulong>();
+	    binary_op_return_type<vi32<uint>, ulong>();
+	    VERIFY((is_substitution_failure<vi32<uint>, vi32<long>>));
+	  }
+      }
+    else if constexpr (std::is_same_v<V, vshort>)
+      {
+	binary_op_return_type<vshort, schar, vshort>();
+	binary_op_return_type<vshort, uchar, vshort>();
+	binary_op_return_type<vi16<short>, schar, vi16<short>>();
+	binary_op_return_type<vi16<short>, uchar, vi16<short>>();
+	binary_op_return_type<vi16<short>, short, vi16<short>>();
+	binary_op_return_type<vi16<short>, int, vi16<short>>();
+	binary_op_return_type<vi16<short>, vi16<schar>>();
+	binary_op_return_type<vi16<short>, vi16<uchar>>();
+	binary_op_return_type<vi16<short>, vi16<short>>();
+
+	binary_op_return_type<vi16<int>, vi16<short>>();
+	binary_op_return_type<vi16<long>, vi16<short>>();
+	binary_op_return_type<vi16<llong>, vi16<short>>();
+	binary_op_return_type<vi16<float>, vi16<short>>();
+	binary_op_return_type<vi16<double>, vi16<short>>();
+
+	VERIFY((is_substitution_failure<vi16<short>, double>));
+	VERIFY((is_substitution_failure<vi16<short>, llong>));
+	VERIFY((is_substitution_failure<vshort, vushort>));
+	VERIFY((is_substitution_failure<vshort, ushort>));
+	VERIFY((is_substitution_failure<vshort, uint>));
+	VERIFY((is_substitution_failure<vshort, long>));
+	VERIFY((is_substitution_failure<vshort, ulong>));
+	VERIFY((is_substitution_failure<vshort, llong>));
+	VERIFY((is_substitution_failure<vshort, ullong>));
+	VERIFY((is_substitution_failure<vshort, float>));
+	VERIFY((is_substitution_failure<vshort, double>));
+	VERIFY((is_substitution_failure<vshort, vi16<schar>>));
+	VERIFY((is_substitution_failure<vshort, vi16<uchar>>));
+	VERIFY((is_substitution_failure<vshort, vi16<short>>));
+	VERIFY((is_substitution_failure<vshort, vi16<ushort>>));
+	VERIFY((is_substitution_failure<vshort, vi16<int>>));
+	VERIFY((is_substitution_failure<vshort, vi16<uint>>));
+	VERIFY((is_substitution_failure<vshort, vi16<long>>));
+	VERIFY((is_substitution_failure<vshort, vi16<ulong>>));
+	VERIFY((is_substitution_failure<vshort, vi16<llong>>));
+	VERIFY((is_substitution_failure<vshort, vi16<ullong>>));
+	VERIFY((is_substitution_failure<vshort, vi16<float>>));
+	VERIFY((is_substitution_failure<vshort, vi16<double>>));
+	VERIFY((is_substitution_failure<vi16<short>, vshort>));
+	VERIFY((is_substitution_failure<vi16<short>, vushort>));
+	VERIFY((is_substitution_failure<vi16<short>, ushort>));
+	VERIFY((is_substitution_failure<vi16<short>, uint>));
+	VERIFY((is_substitution_failure<vi16<short>, long>));
+	VERIFY((is_substitution_failure<vi16<short>, ulong>));
+	VERIFY((is_substitution_failure<vi16<short>, ullong>));
+	VERIFY((is_substitution_failure<vi16<short>, float>));
+	VERIFY((is_substitution_failure<vi16<short>, vi16<ushort>>));
+	VERIFY((is_substitution_failure<vi16<short>, vi16<uint>>));
+	VERIFY((is_substitution_failure<vi16<short>, vi16<ulong>>));
+	VERIFY((is_substitution_failure<vi16<short>, vi16<ullong>>));
+      }
+    else if constexpr (std::is_same_v<V, vushort>)
+      {
+	binary_op_return_type<vushort, uchar, vushort>();
+	binary_op_return_type<vushort, uint, vushort>();
+	binary_op_return_type<vi16<ushort>, uchar, vi16<ushort>>();
+	binary_op_return_type<vi16<ushort>, ushort, vi16<ushort>>();
+	binary_op_return_type<vi16<ushort>, int, vi16<ushort>>();
+	binary_op_return_type<vi16<ushort>, uint, vi16<ushort>>();
+	binary_op_return_type<vi16<ushort>, vi16<uchar>>();
+	binary_op_return_type<vi16<ushort>, vi16<ushort>>();
+
+	binary_op_return_type<vi16<int>, vi16<ushort>>();
+	binary_op_return_type<vi16<long>, vi16<ushort>>();
+	binary_op_return_type<vi16<llong>, vi16<ushort>>();
+	binary_op_return_type<vi16<uint>, vi16<ushort>>();
+	binary_op_return_type<vi16<ulong>, vi16<ushort>>();
+	binary_op_return_type<vi16<ullong>, vi16<ushort>>();
+	binary_op_return_type<vi16<float>, vi16<ushort>>();
+	binary_op_return_type<vi16<double>, vi16<ushort>>();
+
+	VERIFY((is_substitution_failure<vi16<ushort>, llong>));
+	VERIFY((is_substitution_failure<vi16<ushort>, ullong>));
+	VERIFY((is_substitution_failure<vi16<ushort>, double>));
+	VERIFY((is_substitution_failure<vushort, schar>));
+	VERIFY((is_substitution_failure<vushort, short>));
+	VERIFY((is_substitution_failure<vushort, vshort>));
+	VERIFY((is_substitution_failure<vushort, long>));
+	VERIFY((is_substitution_failure<vushort, ulong>));
+	VERIFY((is_substitution_failure<vushort, llong>));
+	VERIFY((is_substitution_failure<vushort, ullong>));
+	VERIFY((is_substitution_failure<vushort, float>));
+	VERIFY((is_substitution_failure<vushort, double>));
+	VERIFY((is_substitution_failure<vushort, vi16<schar>>));
+	VERIFY((is_substitution_failure<vushort, vi16<uchar>>));
+	VERIFY((is_substitution_failure<vushort, vi16<short>>));
+	VERIFY((is_substitution_failure<vushort, vi16<ushort>>));
+	VERIFY((is_substitution_failure<vushort, vi16<int>>));
+	VERIFY((is_substitution_failure<vushort, vi16<uint>>));
+	VERIFY((is_substitution_failure<vushort, vi16<long>>));
+	VERIFY((is_substitution_failure<vushort, vi16<ulong>>));
+	VERIFY((is_substitution_failure<vushort, vi16<llong>>));
+	VERIFY((is_substitution_failure<vushort, vi16<ullong>>));
+	VERIFY((is_substitution_failure<vushort, vi16<float>>));
+	VERIFY((is_substitution_failure<vushort, vi16<double>>));
+	VERIFY((is_substitution_failure<vi16<ushort>, schar>));
+	VERIFY((is_substitution_failure<vi16<ushort>, short>));
+	VERIFY((is_substitution_failure<vi16<ushort>, vshort>));
+	VERIFY((is_substitution_failure<vi16<ushort>, vushort>));
+	VERIFY((is_substitution_failure<vi16<ushort>, long>));
+	VERIFY((is_substitution_failure<vi16<ushort>, ulong>));
+	VERIFY((is_substitution_failure<vi16<ushort>, float>));
+	VERIFY((is_substitution_failure<vi16<ushort>, vi16<schar>>));
+	VERIFY((is_substitution_failure<vi16<ushort>, vi16<short>>));
+      }
+    else if constexpr (std::is_same_v<V, vchar>)
+      {
+	binary_op_return_type<vi8<char>, char, vi8<char>>();
+	binary_op_return_type<vi8<char>, int, vi8<char>>();
+	binary_op_return_type<vi8<char>, vi8<char>, vi8<char>>();
+
+	if constexpr (vi8<schar>::size() <= simd_abi::max_fixed_size<short>)
+	  {
+	    VERIFY(!(is_substitution_failure<vi8<char>, vi8<short>>));
+	    VERIFY(!(is_substitution_failure<vi8<char>, vi8<int>>));
+	    VERIFY(!(is_substitution_failure<vi8<char>, vi8<long>>));
+	    VERIFY(!(is_substitution_failure<vi8<char>, vi8<llong>>));
+	    COMPARE((is_substitution_failure<vi8<char>, vi8<ushort>>),
+		    std::is_signed_v<char>);
+	    COMPARE((is_substitution_failure<vi8<char>, vi8<uint>>),
+		    std::is_signed_v<char>);
+	    COMPARE((is_substitution_failure<vi8<char>, vi8<ulong>>),
+		    std::is_signed_v<char>);
+	    COMPARE((is_substitution_failure<vi8<char>, vi8<ullong>>),
+		    std::is_signed_v<char>);
+	    if constexpr (std::is_signed_v<char>)
+	      {
+		binary_op_return_type<vi8<short>, vi8<char>>();
+		binary_op_return_type<vi8<int>, vi8<char>>();
+		binary_op_return_type<vi8<long>, vi8<char>>();
+		binary_op_return_type<vi8<llong>, vi8<char>>();
+	      }
+	    else
+	      {
+		binary_op_return_type<vi8<ushort>, vi8<char>>();
+		binary_op_return_type<vi8<uint>, vi8<char>>();
+		binary_op_return_type<vi8<ulong>, vi8<char>>();
+		binary_op_return_type<vi8<ullong>, vi8<char>>();
+	      }
+	    binary_op_return_type<vi8<float>, vi8<char>>();
+	    binary_op_return_type<vi8<double>, vi8<char>>();
+	  }
+
+	VERIFY((is_substitution_failure<vi8<char>, llong>));
+	VERIFY((is_substitution_failure<vi8<char>, double>));
+	VERIFY((is_substitution_failure<vchar, vxchar>));
+	VERIFY((is_substitution_failure<vchar, xchar>));
+	VERIFY((is_substitution_failure<vchar, short>));
+	VERIFY((is_substitution_failure<vchar, ushort>));
+	COMPARE((is_substitution_failure<vchar, uint>), std::is_signed_v<char>);
+	VERIFY((is_substitution_failure<vchar, long>));
+	VERIFY((is_substitution_failure<vchar, ulong>));
+	VERIFY((is_substitution_failure<vchar, llong>));
+	VERIFY((is_substitution_failure<vchar, ullong>));
+	VERIFY((is_substitution_failure<vchar, float>));
+	VERIFY((is_substitution_failure<vchar, double>));
+	VERIFY((is_substitution_failure<vchar, vi8<char>>));
+	VERIFY((is_substitution_failure<vchar, vi8<uchar>>));
+	VERIFY((is_substitution_failure<vchar, vi8<schar>>));
+	VERIFY((is_substitution_failure<vchar, vi8<short>>));
+	VERIFY((is_substitution_failure<vchar, vi8<ushort>>));
+	VERIFY((is_substitution_failure<vchar, vi8<int>>));
+	VERIFY((is_substitution_failure<vchar, vi8<uint>>));
+	VERIFY((is_substitution_failure<vchar, vi8<long>>));
+	VERIFY((is_substitution_failure<vchar, vi8<ulong>>));
+	VERIFY((is_substitution_failure<vchar, vi8<llong>>));
+	VERIFY((is_substitution_failure<vchar, vi8<ullong>>));
+	VERIFY((is_substitution_failure<vchar, vi8<float>>));
+	VERIFY((is_substitution_failure<vchar, vi8<double>>));
+	VERIFY((is_substitution_failure<vi8<char>, vchar>));
+	VERIFY((is_substitution_failure<vi8<char>, vuchar>));
+	VERIFY((is_substitution_failure<vi8<char>, vschar>));
+	VERIFY((is_substitution_failure<vi8<char>, xchar>));
+	VERIFY((is_substitution_failure<vi8<char>, short>));
+	VERIFY((is_substitution_failure<vi8<char>, ushort>));
+	COMPARE((is_substitution_failure<vi8<char>, uint>),
+		std::is_signed_v<char>);
+	VERIFY((is_substitution_failure<vi8<char>, long>));
+	VERIFY((is_substitution_failure<vi8<char>, ulong>));
+	VERIFY((is_substitution_failure<vi8<char>, ullong>));
+	VERIFY((is_substitution_failure<vi8<char>, float>));
+
+	// conversion between any char types must fail because the dst type's
+	// integer conversion rank isn't greater (as required by 9.6.4p4.3)
+	VERIFY((is_substitution_failure<vi8<char>, vi8<schar>>));
+	VERIFY((is_substitution_failure<vi8<char>, vi8<uchar>>));
+      }
+    else if constexpr (std::is_same_v<V, vschar>)
+      {
+	binary_op_return_type<vi8<schar>, schar, vi8<schar>>();
+	binary_op_return_type<vi8<schar>, int, vi8<schar>>();
+	binary_op_return_type<vi8<schar>, vi8<schar>, vi8<schar>>();
+
+	if constexpr (vi8<schar>::size() <= simd_abi::max_fixed_size<short>)
+	  {
+	    binary_op_return_type<vi8<short>, vi8<schar>>();
+	    binary_op_return_type<vi8<int>, vi8<schar>>();
+	    binary_op_return_type<vi8<long>, vi8<schar>>();
+	    binary_op_return_type<vi8<llong>, vi8<schar>>();
+	    binary_op_return_type<vi8<float>, vi8<schar>>();
+	    binary_op_return_type<vi8<double>, vi8<schar>>();
+	  }
+
+	VERIFY((is_substitution_failure<vi8<schar>, llong>));
+	VERIFY((is_substitution_failure<vi8<schar>, double>));
+	VERIFY((is_substitution_failure<vschar, vuchar>));
+	VERIFY((is_substitution_failure<vschar, uchar>));
+	VERIFY((is_substitution_failure<vschar, short>));
+	VERIFY((is_substitution_failure<vschar, ushort>));
+	VERIFY((is_substitution_failure<vschar, uint>));
+	VERIFY((is_substitution_failure<vschar, long>));
+	VERIFY((is_substitution_failure<vschar, ulong>));
+	VERIFY((is_substitution_failure<vschar, llong>));
+	VERIFY((is_substitution_failure<vschar, ullong>));
+	VERIFY((is_substitution_failure<vschar, float>));
+	VERIFY((is_substitution_failure<vschar, double>));
+	VERIFY((is_substitution_failure<vschar, vi8<schar>>));
+	VERIFY((is_substitution_failure<vschar, vi8<uchar>>));
+	VERIFY((is_substitution_failure<vschar, vi8<short>>));
+	VERIFY((is_substitution_failure<vschar, vi8<ushort>>));
+	VERIFY((is_substitution_failure<vschar, vi8<int>>));
+	VERIFY((is_substitution_failure<vschar, vi8<uint>>));
+	VERIFY((is_substitution_failure<vschar, vi8<long>>));
+	VERIFY((is_substitution_failure<vschar, vi8<ulong>>));
+	VERIFY((is_substitution_failure<vschar, vi8<llong>>));
+	VERIFY((is_substitution_failure<vschar, vi8<ullong>>));
+	VERIFY((is_substitution_failure<vschar, vi8<float>>));
+	VERIFY((is_substitution_failure<vschar, vi8<double>>));
+	VERIFY((is_substitution_failure<vi8<schar>, vschar>));
+	VERIFY((is_substitution_failure<vi8<schar>, vuchar>));
+	VERIFY((is_substitution_failure<vi8<schar>, uchar>));
+	VERIFY((is_substitution_failure<vi8<schar>, short>));
+	VERIFY((is_substitution_failure<vi8<schar>, ushort>));
+	VERIFY((is_substitution_failure<vi8<schar>, uint>));
+	VERIFY((is_substitution_failure<vi8<schar>, long>));
+	VERIFY((is_substitution_failure<vi8<schar>, ulong>));
+	VERIFY((is_substitution_failure<vi8<schar>, ullong>));
+	VERIFY((is_substitution_failure<vi8<schar>, float>));
+	VERIFY((is_substitution_failure<vi8<schar>, vi8<uchar>>));
+	VERIFY((is_substitution_failure<vi8<schar>, vi8<ushort>>));
+	VERIFY((is_substitution_failure<vi8<schar>, vi8<uint>>));
+	VERIFY((is_substitution_failure<vi8<schar>, vi8<ulong>>));
+	VERIFY((is_substitution_failure<vi8<schar>, vi8<ullong>>));
+      }
+    else if constexpr (std::is_same_v<V, vuchar>)
+      {
+	VERIFY((is_substitution_failure<vi8<uchar>, llong>));
+
+	binary_op_return_type<vuchar, uint, vuchar>();
+	binary_op_return_type<vi8<uchar>, uchar, vi8<uchar>>();
+	binary_op_return_type<vi8<uchar>, int, vi8<uchar>>();
+	binary_op_return_type<vi8<uchar>, uint, vi8<uchar>>();
+	binary_op_return_type<vi8<uchar>, vi8<uchar>, vi8<uchar>>();
+
+	if constexpr (vi8<schar>::size() <= simd_abi::max_fixed_size<short>)
+	  {
+	    binary_op_return_type<vi8<short>, vi8<uchar>>();
+	    binary_op_return_type<vi8<ushort>, vi8<uchar>>();
+	    binary_op_return_type<vi8<int>, vi8<uchar>>();
+	    binary_op_return_type<vi8<uint>, vi8<uchar>>();
+	    binary_op_return_type<vi8<long>, vi8<uchar>>();
+	    binary_op_return_type<vi8<ulong>, vi8<uchar>>();
+	    binary_op_return_type<vi8<llong>, vi8<uchar>>();
+	    binary_op_return_type<vi8<ullong>, vi8<uchar>>();
+	    binary_op_return_type<vi8<float>, vi8<uchar>>();
+	    binary_op_return_type<vi8<double>, vi8<uchar>>();
+	  }
+
+	VERIFY((is_substitution_failure<vi8<uchar>, ullong>));
+	VERIFY((is_substitution_failure<vi8<uchar>, double>));
+	VERIFY((is_substitution_failure<vuchar, schar>));
+	VERIFY((is_substitution_failure<vuchar, vschar>));
+	VERIFY((is_substitution_failure<vuchar, short>));
+	VERIFY((is_substitution_failure<vuchar, ushort>));
+	VERIFY((is_substitution_failure<vuchar, long>));
+	VERIFY((is_substitution_failure<vuchar, ulong>));
+	VERIFY((is_substitution_failure<vuchar, llong>));
+	VERIFY((is_substitution_failure<vuchar, ullong>));
+	VERIFY((is_substitution_failure<vuchar, float>));
+	VERIFY((is_substitution_failure<vuchar, double>));
+	VERIFY((is_substitution_failure<vuchar, vi8<schar>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<uchar>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<short>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<ushort>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<int>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<uint>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<long>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<ulong>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<llong>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<ullong>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<float>>));
+	VERIFY((is_substitution_failure<vuchar, vi8<double>>));
+	VERIFY((is_substitution_failure<vi8<uchar>, schar>));
+	VERIFY((is_substitution_failure<vi8<uchar>, vschar>));
+	VERIFY((is_substitution_failure<vi8<uchar>, vuchar>));
+	VERIFY((is_substitution_failure<vi8<uchar>, short>));
+	VERIFY((is_substitution_failure<vi8<uchar>, ushort>));
+	VERIFY((is_substitution_failure<vi8<uchar>, long>));
+	VERIFY((is_substitution_failure<vi8<uchar>, ulong>));
+	VERIFY((is_substitution_failure<vi8<uchar>, float>));
+	VERIFY((is_substitution_failure<vi8<uchar>, vi8<schar>>));
+      }
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/operators.cc b/libstdc++-v3/testsuite/experimental/simd/tests/operators.cc
new file mode 100644
index 00000000000..566c5c994e8
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/operators.cc
@@ -0,0 +1,297 @@
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "bits/verify.h"
+#include "bits/make_vec.h"
+#include "bits/test_values.h"
+
+template <class T>
+  constexpr T
+  genHalfBits()
+  {
+    if constexpr (std::is_floating_point_v<T>)
+      return 0;
+    else
+      return std::__finite_max_v<T> >> (std::__digits_v<T> / 2);
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    using T = typename V::value_type;
+    constexpr auto min = std::__finite_min_v<T>;
+    constexpr auto norm_min = std::__norm_min_v<T>;
+    constexpr auto max = std::__finite_max_v<T>;
+    { // compares
+      COMPARE(V(0) == make_vec<V>({0, 1}, 0), make_mask<M>({1, 0}));
+      COMPARE(V(0) == make_vec<V>({0, 1, 2}, 0), make_mask<M>({1, 0, 0}));
+      COMPARE(V(1) == make_vec<V>({0, 1, 2}, 0), make_mask<M>({0, 1, 0}));
+      COMPARE(V(2) == make_vec<V>({0, 1, 2}, 0), make_mask<M>({0, 0, 1}));
+      COMPARE(V(0) < make_vec<V>({0, 1, 2}, 0), make_mask<M>({0, 1, 1}));
+
+      constexpr T half = genHalfBits<T>();
+      for (T lo_ : {min, T(min + 1), T(-1), T(0), norm_min, T(1), T(half - 1),
+		    half, T(half + 1), T(max - 1)})
+	{
+	  for (T hi_ : {T(min + 1), T(-1), T(0), norm_min, T(1), T(half - 1),
+			half, T(half + 1), T(max - 1), max})
+	    {
+	      if (hi_ <= lo_)
+		continue;
+
+	      for (std::size_t pos = 0; pos < V::size(); ++pos)
+		{
+		  V lo = lo_;
+		  V hi = hi_;
+		  lo[pos] = 0; // have a different value in the vector in case
+		  hi[pos] = 1; // this affects neighbors
+		  COMPARE(hi, hi);
+		  VERIFY(all_of(hi != lo)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(all_of(lo != hi)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(none_of(hi != hi)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(none_of(hi == lo)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(none_of(lo == hi)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(all_of(lo < hi)) << "hi: " << hi << ", lo: " << lo
+					  << ", lo < hi: " << (lo < hi);
+		  VERIFY(none_of(hi < lo)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(none_of(hi <= lo)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(all_of(hi <= hi)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(all_of(hi > lo)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(none_of(lo > hi)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(all_of(hi >= lo)) << "hi: " << hi << ", lo: " << lo;
+		  VERIFY(all_of(hi >= hi)) << "hi: " << hi << ", lo: " << lo;
+		}
+	    }
+	}
+    }
+    { // subscripting
+      V x = max;
+      for (std::size_t i = 0; i < V::size(); ++i)
+	{
+	  COMPARE(x[i], max);
+	  x[i] = 0;
+	}
+      COMPARE(x, V{0});
+      for (std::size_t i = 0; i < V::size(); ++i)
+	{
+	  COMPARE(x[i], T(0));
+	  x[i] = max;
+	}
+      COMPARE(x, V{max});
+      COMPARE(typeid(x[0] * x[0]), typeid(T() * T()));
+      COMPARE(typeid(x[0] * T()), typeid(T() * T()));
+      COMPARE(typeid(T() * x[0]), typeid(T() * T()));
+      COMPARE(typeid(x * x[0]), typeid(x));
+      COMPARE(typeid(x[0] * x), typeid(x));
+
+      x = V([](auto i) -> T { return i; });
+      for (std::size_t i = 0; i < V::size(); ++i)
+	{
+	  COMPARE(x[i], T(i));
+	}
+      for (std::size_t i = 0; i + 1 < V::size(); i += 2)
+	{
+	  using std::swap;
+	  swap(x[i], x[i + 1]);
+	}
+      for (std::size_t i = 0; i + 1 < V::size(); i += 2)
+	{
+	  COMPARE(x[i], T(i + 1)) << x;
+	  COMPARE(x[i + 1], T(i)) << x;
+	}
+      x = 1;
+      V y = 0;
+      COMPARE(x[0], T(1));
+      x[0] = y[0]; // make sure non-const smart_reference assignment works
+      COMPARE(x[0], T(0));
+      x = 1;
+      x[0] = x[0]; // self-assignment on smart_reference
+      COMPARE(x[0], T(1));
+
+      std::experimental::simd<typename V::value_type,
+			      std::experimental::simd_abi::scalar>
+      z = 2;
+      x[0] = z[0];
+      COMPARE(x[0], T(2));
+      x = 3;
+      z[0] = x[0];
+      COMPARE(z[0], T(3));
+
+      // TODO: check that only value-preserving conversions happen on subscript
+      // assignment
+    }
+    { // not
+      V x = 0;
+      COMPARE(!x, M{true});
+      V y = 1;
+      COMPARE(!y, M{false});
+    }
+
+    { // unary minus
+      V x = 0;
+      COMPARE(-x, V(T(-T(0))));
+      V y = 1;
+      COMPARE(-y, V(T(-T(1))));
+    }
+
+    { // plus
+      V x = 0;
+      V y = 0;
+      COMPARE(x + y, x);
+      COMPARE(x = x + T(1), V(1));
+      COMPARE(x + x, V(2));
+      y = make_vec<V>({1, 2, 3, 4, 5, 6, 7});
+      COMPARE(x = x + y, make_vec<V>({2, 3, 4, 5, 6, 7, 8}));
+      COMPARE(x = x + -y, V(1));
+      COMPARE(x += y, make_vec<V>({2, 3, 4, 5, 6, 7, 8}));
+      COMPARE(x, make_vec<V>({2, 3, 4, 5, 6, 7, 8}));
+      COMPARE(x += -y, V(1));
+      COMPARE(x, V(1));
+    }
+
+    { // minus
+      V x = 1;
+      V y = 0;
+      COMPARE(x - y, x);
+      COMPARE(x - T(1), y);
+      COMPARE(y, x - T(1));
+      COMPARE(x - x, y);
+      y = make_vec<V>({1, 2, 3, 4, 5, 6, 7});
+      COMPARE(x = y - x, make_vec<V>({0, 1, 2, 3, 4, 5, 6}));
+      COMPARE(x = y - x, V(1));
+      COMPARE(y -= x, make_vec<V>({0, 1, 2, 3, 4, 5, 6}));
+      COMPARE(y, make_vec<V>({0, 1, 2, 3, 4, 5, 6}));
+      COMPARE(y -= y, V(0));
+      COMPARE(y, V(0));
+    }
+
+    { // multiplies
+      V x = 1;
+      V y = 0;
+      COMPARE(x * y, y);
+      COMPARE(x = x * T(2), V(2));
+      COMPARE(x * x, V(4));
+      y = make_vec<V>({1, 2, 3, 4, 5, 6, 7});
+      COMPARE(x = x * y, make_vec<V>({2, 4, 6, 8, 10, 12, 14}));
+      y = 2;
+      // don't test norm_min/2*2 in the following. There's no guarantee, in
+      // general, that the result isn't flushed to zero (e.g. NEON without
+      // subnormals)
+      for (T n :
+      {T(max - 1), std::is_floating_point_v<T> ? T(norm_min * 3) : min})
+	{
+	  x = n / 2;
+	  COMPARE(x * y, V(n));
+	}
+      if (std::is_integral<T>::value && std::is_unsigned<T>::value)
+	{
+	  // test modulo arithmetics
+	  T n = max;
+	  x = n;
+	  for (T m : {T(2), T(7), T(max / 127), max})
+	    {
+	      y = m;
+	      // if T is of lower rank than int, `n * m` will promote to int
+	      // before executing the multiplication. In this case an overflow
+	      // will be UB (and ubsan will warn about it). The solution is to
+	      // cast to uint in that case.
+	      using U
+		= std::conditional_t<(sizeof(T) < sizeof(int)), unsigned, T>;
+	      COMPARE(x * y, V(T(U(n) * U(m))));
+	    }
+	}
+      x = 2;
+      COMPARE(x *= make_vec<V>({1, 2, 3}), make_vec<V>({2, 4, 6}));
+      COMPARE(x, make_vec<V>({2, 4, 6}));
+    }
+
+    // divides
+    constexpr bool is_iec559 = __GCC_IEC_559 >= 2;
+    if constexpr (std::is_floating_point_v<T> && !is_iec559)
+      { // avoid testing subnormals and expect minor deltas for non-IEC559 float
+	V x = 2;
+	ULP_COMPARE(x / x, V(1), 1);
+	ULP_COMPARE(T(3) / x, V(T(3) / T(2)), 1);
+	ULP_COMPARE(x / T(3), V(T(2) / T(3)), 1);
+	V y = make_vec<V>({1, 2, 3, 4, 5, 6, 7});
+	ULP_COMPARE(y / x,
+		    make_vec<V>(
+		      {T(.5), T(1), T(1.5), T(2), T(2.5), T(3), T(3.5)}),
+		    1);
+
+	test_values<V>({norm_min * 1024, T(1), T(), T(-1), max / 1024,
+			max / 4.1, max, min},
+		       [&](V a) {
+			 V b = 2;
+			 V ref([&](auto i) { return a[i] / 2; });
+			 ULP_COMPARE(a / b, ref, 1);
+			 where(a == 0, a) = 1;
+			 // -freciprocal-math together with flush-to-zero makes
+			 // the following range restriction necessary (i.e.
+			 // 1/|a| must be >= min). Intel vrcpps and vrcp14ps
+			 // need some extra slack (use 1.1 instead of 1).
+			 where(abs(a) >= T(1.1) / norm_min, a) = 1;
+			 ULP_COMPARE(a / a, V(1), 1) << "\na = " << a;
+			 ref = V([&](auto i) { return 2 / a[i]; });
+			 ULP_COMPARE(b / a, ref, 1) << "\na = " << a;
+			 ULP_COMPARE(b /= a, ref, 1);
+			 ULP_COMPARE(b, ref, 1);
+		       });
+      }
+    else
+      {
+	V x = 2;
+	COMPARE(x / x, V(1));
+	COMPARE(T(3) / x, V(T(3) / T(2)));
+	COMPARE(x / T(3), V(T(2) / T(3)));
+	V y = make_vec<V>({1, 2, 3, 4, 5, 6, 7});
+	COMPARE(y / x,
+		make_vec<V>({T(.5), T(1), T(1.5), T(2), T(2.5), T(3), T(3.5)}));
+
+	y = make_vec<V>({max, norm_min});
+	V ref = make_vec<V>({T(max / 2), T(norm_min / 2)});
+	COMPARE(y / x, ref);
+
+	y = make_vec<V>({norm_min, max});
+	ref = make_vec<V>({T(norm_min / 2), T(max / 2)});
+	COMPARE(y / x, ref);
+
+	y = make_vec<V>({max, T(norm_min + 1)});
+	COMPARE(y / y, V(1));
+
+	ref = make_vec<V>({T(2 / max), T(2 / (norm_min + 1))});
+	COMPARE(x / y, ref);
+	COMPARE(x /= y, ref);
+	COMPARE(x, ref);
+      }
+
+    { // increment & decrement
+      const V from0 = make_vec<V>({0, 1, 2, 3}, 4);
+      V x = from0;
+      COMPARE(x++, from0);
+      COMPARE(x, from0 + 1);
+      COMPARE(++x, from0 + 2);
+      COMPARE(x, from0 + 2);
+
+      COMPARE(x--, from0 + 2);
+      COMPARE(x, from0 + 1);
+      COMPARE(--x, from0);
+      COMPARE(x, from0);
+    }
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/reductions.cc b/libstdc++-v3/testsuite/experimental/simd/tests/reductions.cc
new file mode 100644
index 00000000000..a663db23a61
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/reductions.cc
@@ -0,0 +1,80 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/test_values.h"
+#include <random>
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+    COMPARE(reduce(V(1)), T(V::size()));
+    {
+      V x = 1;
+      COMPARE(reduce(x, std::multiplies<>()), T(1));
+      x[0] = 2;
+      COMPARE(reduce(x, std::multiplies<>()), T(2));
+      if constexpr (V::size() > 1)
+	{
+	  x[V::size() - 1] = 3;
+	  COMPARE(reduce(x, std::multiplies<>()), T(6));
+	}
+    }
+    COMPARE(reduce(V([](int i) { return i & 1; })), T(V::size() / 2));
+    COMPARE(reduce(V([](int i) { return i % 3; })),
+	    T(3 * (V::size() / 3)   // 0+1+2 for every complete 3 elements in V
+		+ (V::size() % 3) / 2 // 0->0, 1->0, 2->1 adjustment
+	     ));
+    if ((1 + V::size()) * V::size() / 2 <= std::__finite_max_v<T>)
+      {
+	COMPARE(reduce(V([](int i) { return i + 1; })),
+		T((1 + V::size()) * V::size() / 2));
+      }
+
+    {
+      const V y = 2;
+      COMPARE(reduce(y), T(2 * V::size()));
+      COMPARE(reduce(where(y > 2, y)), T(0));
+      COMPARE(reduce(where(y == 2, y)), T(2 * V::size()));
+    }
+
+    {
+      const V z([](T i) { return i + 1; });
+      COMPARE(std::experimental::reduce(z,
+					[](auto a, auto b) {
+					  using std::min;
+					  return min(a, b);
+					}),
+	      T(1))
+	<< "z: " << z;
+      COMPARE(std::experimental::reduce(z,
+					[](auto a, auto b) {
+					  using std::max;
+					  return max(a, b);
+					}),
+	      T(V::size()))
+	<< "z: " << z;
+      COMPARE(std::experimental::reduce(where(z > 1, z), 117,
+					[](auto a, auto b) {
+					  using std::min;
+					  return min(a, b);
+					}),
+	      T(V::size() == 1 ? 117 : 2))
+	<< "z: " << z;
+    }
+
+    test_values<V>({}, {1000}, [](V x) {
+      // avoid over-/underflow on signed integers:
+      if constexpr (std::is_signed_v<T> && std::is_integral_v<T>)
+	x /= int(V::size());
+      // The error in the following could be huge if catastrophic
+      // cancellation occurs. (e.g. `a-a+b+b` vs. `a+b+b-a`).
+      // Avoid catastrophic cancellation for floating point:
+      if constexpr (std::is_floating_point_v<T>)
+	x = abs(x);
+      T acc = x[0];
+      for (size_t i = 1; i < V::size(); ++i)
+	acc += x[i];
+      ULP_COMPARE(reduce(x), acc, V::size() / 2).on_failure("x = ", x);
+    });
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/remqo.cc b/libstdc++-v3/testsuite/experimental/simd/tests/remqo.cc
new file mode 100644
index 00000000000..87eb21ef098
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/remqo.cc
@@ -0,0 +1,53 @@
+// test only floattypes
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/test_values.h"
+
+template <typename V>
+  void
+  test()
+  {
+    vir::test::setFuzzyness<float>(0);
+    vir::test::setFuzzyness<double>(0);
+
+    using T = typename V::value_type;
+    test_values_2arg<V>(
+      {
+#ifdef __STDC_IEC_559__
+	std::__quiet_NaN_v<T>, std::__infinity_v<T>, -std::__infinity_v<T>,
+	std::__denorm_min_v<T>, std::__norm_min_v<T> / 3, -0.,
+#endif
+	+0., std::__norm_min_v<T>, std::__finite_max_v<T>},
+      {10000}, [](V a, V b) {
+
+#ifndef __STDC_IEC_559__
+	// without __STDC_IEC_559__, remquo(a, 0) is unspecified
+	where(b == 0, b) = 1;
+#endif
+	using IV = std::experimental::fixed_size_simd<int, V::size()>;
+	IV quo = {};
+	const V totest = remquo(a, b, &quo);
+	auto&& expected
+	  = [&](const auto& v, const auto& w) -> std::pair<const V, const IV> {
+	    std::pair<V, IV> tmp = {};
+	    using std::remquo;
+	    for (std::size_t i = 0; i < V::size(); ++i)
+	      {
+		int tmp2;
+		tmp.first[i] = remquo(v[i], w[i], &tmp2);
+		tmp.second[i] = tmp2;
+	      }
+	    return tmp;
+	  };
+	const auto expect1 = expected(a, b);
+	COMPARE(isnan(totest), isnan(expect1.first))
+	  << "remquo(" << a << ", " << b << ", quo) = " << totest
+	  << " != " << expect1.first;
+	const V clean_a = iif(isnan(totest), 0, a);
+	const V clean_b = iif(isnan(totest), 1, b);
+	const auto expect2 = expected(clean_a, clean_b);
+	COMPARE(remquo(clean_a, clean_b, &quo), expect2.first)
+	  << "\nclean_a/b = " << clean_a << ", " << clean_b;
+	COMPARE(quo, expect2.second);
+      });
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/simd.cc b/libstdc++-v3/testsuite/experimental/simd/tests/simd.cc
new file mode 100644
index 00000000000..0744be5e191
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/simd.cc
@@ -0,0 +1,29 @@
+#include "bits/verify.h"
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+
+    // V must store V::size() values of type T giving us the lower bound on the
+    // sizeof
+    VERIFY(sizeof(V) >= sizeof(T) * V::size());
+
+    // For fixed_size, V should not pad more than to the next-power-of-2 of
+    // sizeof(T) * V::size() (for ABI stability of V), giving us the upper bound
+    // on the sizeof. For non-fixed_size we give the implementation a bit more
+    // slack to trade space vs. efficiency.
+    auto n = sizeof(T) * V::size();
+    if (n & (n - 1))
+      {
+	n = ((n << 1) & ~n) & ~((n >> 1) | (n >> 3));
+	while (n & (n - 1))
+	  n &= n - 1;
+      }
+    if constexpr (
+      !std::is_same_v<typename V::abi_type,
+		      std::experimental::simd_abi::fixed_size<V::size()>>)
+      n *= 2;
+    VERIFY(sizeof(V) <= n) << "\nsizeof(V): " << sizeof(V) << "\nn: " << n;
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/sincos.cc b/libstdc++-v3/testsuite/experimental/simd/tests/sincos.cc
new file mode 100644
index 00000000000..ced3be49136
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/sincos.cc
@@ -0,0 +1,29 @@
+// test only floattypes
+// { dg-additional-files "reference-sincos-sp.dat" }
+// { dg-additional-files "reference-sincos-ep.dat" }
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/mathreference.h"
+#include "bits/simd_view.h"
+#include "bits/test_values.h"
+
+template <typename V>
+  void
+  test()
+  {
+    using std::cos;
+    using std::sin;
+    using T = typename V::value_type;
+
+    vir::test::setFuzzyness<float>(2);
+    vir::test::setFuzzyness<double>(1);
+
+    const auto& testdata = referenceData<function::sincos, T>();
+    std::experimental::experimental::simd_view<V>(testdata).for_each(
+      [&](const V input, const V expected_sin, const V expected_cos) {
+	FUZZY_COMPARE(sin(input), expected_sin) << " input = " << input;
+	FUZZY_COMPARE(sin(-input), -expected_sin) << " input = " << input;
+	FUZZY_COMPARE(cos(input), expected_cos) << " input = " << input;
+	FUZZY_COMPARE(cos(-input), expected_cos) << " input = " << input;
+      });
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/split_concat.cc b/libstdc++-v3/testsuite/experimental/simd/tests/split_concat.cc
new file mode 100644
index 00000000000..2e7cf66b227
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/split_concat.cc
@@ -0,0 +1,166 @@
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/conversions.h"
+
+using std::experimental::simd_cast;
+
+template <typename V, bool ConstProp, typename F>
+  auto
+  gen(const F& fun)
+  {
+    if constexpr (ConstProp)
+      return V(fun);
+    else
+      return make_value_unknown(V(fun));
+  }
+
+template <typename V, bool ConstProp>
+  void
+  split_concat()
+  {
+    using T = typename V::value_type;
+    if constexpr (V::size() * 3
+		    <= std::experimental::simd_abi::max_fixed_size<T>)
+      {
+	V a(0), b(1), c(2);
+	auto x = concat(a, b, c);
+	COMPARE(x.size(), a.size() * 3);
+	std::size_t i = 0;
+	for (; i < a.size(); ++i)
+	  {
+	    COMPARE(x[i], T(0));
+	  }
+	for (; i < 2 * a.size(); ++i)
+	  {
+	    COMPARE(x[i], T(1));
+	  }
+	for (; i < 3 * a.size(); ++i)
+	  {
+	    COMPARE(x[i], T(2));
+	  }
+      }
+
+    if constexpr (V::size() >= 4)
+      {
+	const V a = gen<V, ConstProp>([](auto i) -> T { return i; });
+	constexpr auto N0 = V::size() / 4u;
+	constexpr auto N1 = V::size() - 2 * N0;
+	using V0 = std::experimental::simd<
+		     T, std::experimental::simd_abi::deduce_t<T, N0>>;
+	using V1 = std::experimental::simd<
+		     T, std::experimental::simd_abi::deduce_t<T, N1>>;
+	{
+	  auto x = std::experimental::split<N0, N0, N1>(a);
+	  COMPARE(std::tuple_size<decltype(x)>::value, 3u);
+	  COMPARE(std::get<0>(x), V0([](auto i) -> T { return i; }));
+	  COMPARE(std::get<1>(x), V0([](auto i) -> T { return i + N0; }));
+	  COMPARE(std::get<2>(x), V1([](auto i) -> T { return i + 2 * N0; }));
+	  auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x));
+	  // a and b may have different types if a was fixed_size<N> such that
+	  // another ABI tag exists with equal N, then b will have the
+	  // non-fixed-size ABI tag.
+	  COMPARE(a.size(), b.size());
+	  COMPARE(
+	    b, decltype(b)([](auto i) -> T { return (N0 + i) % V::size(); }));
+	}
+	{
+	  auto x = std::experimental::split<N0, N1, N0>(a);
+	  COMPARE(std::tuple_size<decltype(x)>::value, 3u);
+	  COMPARE(std::get<0>(x), V0([](auto i) -> T { return i; }));
+	  COMPARE(std::get<1>(x), V1([](auto i) -> T { return i + N0; }));
+	  COMPARE(std::get<2>(x), V0([](auto i) -> T { return i + N0 + N1; }));
+	  auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x));
+	  // a and b may have different types if a was fixed_size<N> such that
+	  // another ABI tag exists with equal N, then b will have the
+	  // non-fixed-size ABI tag.
+	  COMPARE(a.size(), b.size());
+	  COMPARE(
+	    b, decltype(b)([](auto i) -> T { return (N0 + i) % V::size(); }));
+	}
+	{
+	  auto x = std::experimental::split<N1, N0, N0>(a);
+	  COMPARE(std::tuple_size<decltype(x)>::value, 3u);
+	  COMPARE(std::get<0>(x), V1([](auto i) -> T { return i; }));
+	  COMPARE(std::get<1>(x), V0([](auto i) -> T { return i + N1; }));
+	  COMPARE(std::get<2>(x), V0([](auto i) -> T { return i + N0 + N1; }));
+	  auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x));
+	  // a and b may have different types if a was fixed_size<N> such that
+	  // another ABI tag exists with equal N, then b will have the
+	  // non-fixed-size ABI tag.
+	  COMPARE(a.size(), b.size());
+	  COMPARE(
+	    b, decltype(b)([](auto i) -> T { return (N1 + i) % V::size(); }));
+	}
+      }
+
+    if constexpr (V::size() % 3 == 0)
+      {
+	const V a = gen<V, ConstProp>([](auto i) -> T { return i; });
+	constexpr auto N0 = V::size() / 3;
+	using V0 = std::experimental::simd<
+		     T, std::experimental::simd_abi::deduce_t<T, N0>>;
+	using V1 = std::experimental::simd<
+	  T, std::experimental::simd_abi::deduce_t<T, 2 * N0>>;
+	{
+	  auto [x, y, z] = std::experimental::split<N0, N0, N0>(a);
+	  COMPARE(x, V0([](auto i) -> T { return i; }));
+	  COMPARE(y, V0([](auto i) -> T { return i + N0; }));
+	  COMPARE(z, V0([](auto i) -> T { return i + N0 * 2; }));
+	  auto b = concat(x, y, z);
+	  COMPARE(a.size(), b.size());
+	  COMPARE(b, simd_cast<decltype(b)>(a));
+	  COMPARE(simd_cast<V>(b), a);
+	}
+	{
+	  auto [x, y] = std::experimental::split<N0, 2 * N0>(a);
+	  COMPARE(x, V0([](auto i) -> T { return i; }));
+	  COMPARE(y, V1([](auto i) -> T { return i + N0; }));
+	  auto b = concat(x, y);
+	  COMPARE(a.size(), b.size());
+	  COMPARE(b, simd_cast<decltype(b)>(a));
+	  COMPARE(simd_cast<V>(b), a);
+	}
+	{
+	  auto [x, y] = std::experimental::split<2 * N0, N0>(a);
+	  COMPARE(x, V1([](auto i) -> T { return i; }));
+	  COMPARE(y, V0([](auto i) -> T { return i + 2 * N0; }));
+	  auto b = concat(x, y);
+	  COMPARE(a.size(), b.size());
+	  COMPARE(b, simd_cast<decltype(b)>(a));
+	  COMPARE(simd_cast<V>(b), a);
+	}
+      }
+
+    if constexpr ((V::size() & 1) == 0)
+      {
+	using std::experimental::simd;
+	using std::experimental::simd_abi::deduce_t;
+	using V0 = simd<T, deduce_t<T, V::size()>>;
+	using V2 = simd<T, deduce_t<T, 2>>;
+	using V3 = simd<T, deduce_t<T, V::size() / 2>>;
+
+	const V a = gen<V, ConstProp>([](auto i) -> T { return i; });
+
+	std::array<V2, V::size() / 2> v2s = std::experimental::split<V2>(a);
+	int offset = 0;
+	for (V2 test : v2s)
+	  {
+	    COMPARE(test, V2([&](auto i) -> T { return i + offset; }));
+	    offset += 2;
+	  }
+	COMPARE(concat(v2s), simd_cast<V0>(a));
+
+	std::array<V3, 2> v3s = std::experimental::split<V3>(a);
+	COMPARE(v3s[0], V3([](auto i) -> T { return i; }));
+	COMPARE(v3s[1], V3([](auto i) -> T { return i + V3::size(); }));
+	COMPARE(concat(v3s), simd_cast<V0>(a));
+      }
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    split_concat<V, true>();
+    split_concat<V, false>();
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/splits.cc b/libstdc++-v3/testsuite/experimental/simd/tests/splits.cc
new file mode 100644
index 00000000000..31db384f798
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/splits.cc
@@ -0,0 +1,21 @@
+#include "bits/verify.h"
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    using namespace std::experimental::parallelism_v2;
+    using T = typename V::value_type;
+    if constexpr (V::size() / simd_size_v<T> * simd_size_v<T> == V::size())
+      {
+	M k(true);
+	VERIFY(all_of(k)) << k;
+	const auto parts = split<simd_mask<T>>(k);
+	for (auto k2 : parts)
+	  {
+	    VERIFY(all_of(k2)) << k2;
+	    COMPARE(typeid(k2), typeid(simd_mask<T>));
+	  }
+      }
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/trigonometric.cc b/libstdc++-v3/testsuite/experimental/simd/tests/trigonometric.cc
new file mode 100644
index 00000000000..51fef12a87f
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/trigonometric.cc
@@ -0,0 +1,24 @@
+// test only floattypes
+#include "bits/verify.h"
+#include "bits/metahelpers.h"
+#include "bits/test_values.h"
+
+template <typename V>
+  void
+  test()
+  {
+    vir::test::setFuzzyness<float>(1);
+    vir::test::setFuzzyness<double>(1);
+
+    using T = typename V::value_type;
+    test_values<V>(
+      {
+#ifdef __STDC_IEC_559__
+	std::__quiet_NaN_v<T>, std::__infinity_v<T>, -std::__infinity_v<T>, -0.,
+	std::__denorm_min_v<T>, std::__norm_min_v<T> / 3,
+#endif
+	+0., std::__norm_min_v<T>, std::__finite_max_v<T>},
+      {10000}, MAKE_TESTER(acos), MAKE_TESTER(tan), MAKE_TESTER(acosh),
+      MAKE_TESTER(asinh), MAKE_TESTER(atanh), MAKE_TESTER(cosh),
+      MAKE_TESTER(sinh), MAKE_TESTER(tanh));
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/trunc_ceil_floor.cc b/libstdc++-v3/testsuite/experimental/simd/tests/trunc_ceil_floor.cc
new file mode 100644
index 00000000000..df105530efe
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/trunc_ceil_floor.cc
@@ -0,0 +1,92 @@
+// test only floattypes
+#include "bits/test_values.h"
+#include "bits/verify.h"
+
+template <typename V>
+  void
+  test()
+  {
+    using T = typename V::value_type;
+    constexpr T inf = std::__infinity_v<T>;
+    constexpr T denorm_min = std::__denorm_min_v<T>;
+    constexpr T norm_min = std::__norm_min_v<T>;
+    constexpr T max = std::__finite_max_v<T>;
+    constexpr T min = std::__finite_min_v<T>;
+    test_values<V>(
+      {2.1,
+       2.0,
+       2.9,
+       2.5,
+       2.499,
+       1.5,
+       1.499,
+       1.99,
+       0.99,
+       0.5,
+       0.499,
+       0.,
+       -2.1,
+       -2.0,
+       -2.9,
+       -2.5,
+       -2.499,
+       -1.5,
+       -1.499,
+       -1.99,
+       -0.99,
+       -0.5,
+       -0.499,
+       3 << 21,
+       3 << 22,
+       3 << 23,
+       -(3 << 21),
+       -(3 << 22),
+       -(3 << 23),
+#ifdef __STDC_IEC_559__
+       -0.,
+       inf,
+       -inf,
+       denorm_min,
+       norm_min * 0.9,
+       -denorm_min,
+       -norm_min * 0.9,
+#endif
+       max,
+       norm_min,
+       min,
+       -norm_min
+      },
+      [](const V input) {
+	const V expected([&](auto i) { return std::trunc(input[i]); });
+	COMPARE(trunc(input), expected) << input;
+      },
+      [](const V input) {
+	const V expected([&](auto i) { return std::ceil(input[i]); });
+	COMPARE(ceil(input), expected) << input;
+      },
+      [](const V input) {
+	const V expected([&](auto i) { return std::floor(input[i]); });
+	COMPARE(floor(input), expected) << input;
+      });
+
+#ifdef __STDC_IEC_559__
+    test_values<V>(
+      {
+#ifdef __SUPPORT_SNAN__
+	std::__signaling_NaN_v<T>,
+#endif
+	std::__quiet_NaN_v<T>},
+      [](const V input) {
+	const V expected([&](auto i) { return std::trunc(input[i]); });
+	COMPARE(isnan(trunc(input)), isnan(expected)) << input;
+      },
+      [](const V input) {
+	const V expected([&](auto i) { return std::ceil(input[i]); });
+	COMPARE(isnan(ceil(input)), isnan(expected)) << input;
+      },
+      [](const V input) {
+	const V expected([&](auto i) { return std::floor(input[i]); });
+	COMPARE(isnan(floor(input)), isnan(expected)) << input;
+      });
+#endif
+  }
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/where.cc b/libstdc++-v3/testsuite/experimental/simd/tests/where.cc
new file mode 100644
index 00000000000..603e5a4b262
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/where.cc
@@ -0,0 +1,119 @@
+#include "bits/verify.h"
+#include "bits/make_vec.h"
+#include "bits/metahelpers.h"
+
+template <class V>
+  struct Convertible
+  {
+    operator V() const { return V(4); }
+  };
+
+template <class M, class T>
+  constexpr bool
+  where_is_ill_formed_impl(M, const T&, float)
+  {
+    return true;
+  }
+
+template <class M, class T>
+  constexpr auto
+  where_is_ill_formed_impl(M m, const T& v, int)
+    -> std::conditional_t<true, bool, decltype(std::experimental::where(m, v))>
+  {
+    return false;
+  }
+
+template <class M, class T>
+  constexpr bool
+  where_is_ill_formed(M m, const T& v)
+  {
+    return where_is_ill_formed_impl(m, v, int());
+  }
+
+template <typename T>
+  void
+  where_fundamental()
+  {
+    using std::experimental::where;
+    T x = T();
+    where(true, x) = x + 1;
+    COMPARE(x, T(1));
+    where(false, x) = x - 1;
+    COMPARE(x, T(1));
+    where(true, x) += T(1);
+    COMPARE(x, T(2));
+  }
+
+template <typename V>
+  void
+  test()
+  {
+    using M = typename V::mask_type;
+    using T = typename V::value_type;
+    where_fundamental<T>();
+    VERIFY(!(sfinae_is_callable<V>(
+	       [](auto x) -> decltype(where(true, x))* { return nullptr; })));
+
+    const V indexes([](int i) { return i + 1; });
+    const M alternating_mask = make_mask<M>({true, false});
+    V x = 0;
+    where(alternating_mask, x) = indexes;
+    COMPARE(alternating_mask, x == indexes);
+
+    where(!alternating_mask, x) = T(2);
+    COMPARE(!alternating_mask, x == T(2)) << x;
+
+    where(!alternating_mask, x) = Convertible<V>();
+    COMPARE(!alternating_mask, x == T(4));
+
+    x = 0;
+    COMPARE(x, T(0));
+    where(alternating_mask, x) += indexes;
+    COMPARE(alternating_mask, x == indexes);
+
+    x = 10;
+    COMPARE(x, T(10));
+    where(!alternating_mask, x) += T(1);
+    COMPARE(!alternating_mask, x == T(11));
+    where(alternating_mask, x) -= Convertible<V>();
+    COMPARE(alternating_mask, x == T(6));
+    constexpr bool fast_math =
+#ifdef __FAST_MATH__
+      true;
+#else
+      false;
+#endif
+    if constexpr (fast_math && std::is_floating_point_v<T>)
+      where(alternating_mask, x) *= T(.5);
+    else
+    where(alternating_mask, x) /= T(2);
+    COMPARE(alternating_mask, x == T(3)) << "\nx = " << x;
+    where(alternating_mask, x) *= T(3);
+    COMPARE(alternating_mask, x == T(9));
+    COMPARE(!alternating_mask, x == T(11));
+
+    x = 10;
+    where(alternating_mask, x)++;
+    COMPARE(alternating_mask, x == T(11));
+    ++where(alternating_mask, x);
+    COMPARE(alternating_mask, x == T(12));
+    where(alternating_mask, x)--;
+    COMPARE(alternating_mask, x == T(11));
+    --where(alternating_mask, x);
+    --where(alternating_mask, x);
+    COMPARE(alternating_mask, x == T(9));
+    COMPARE(alternating_mask, -where(alternating_mask, x) == T(-T(9)));
+
+    const auto y = x;
+    VERIFY(where_is_ill_formed(true, y));
+    VERIFY(where_is_ill_formed(true, x));
+    VERIFY(where_is_ill_formed(true, V(x)));
+
+    M test = alternating_mask;
+    where(alternating_mask, test) = M(true);
+    COMPARE(test, alternating_mask);
+    where(alternating_mask, test) = M(false);
+    COMPARE(test, M(false));
+    where(alternating_mask, test) = M(true);
+    COMPARE(test, alternating_mask);
+  }

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Add simd testsuite
  2020-12-16 11:58 [PATCH] Add simd testsuite Matthias Kretz
@ 2020-12-17 13:10 ` Jonathan Wakely
  2020-12-18 15:25   ` Matthias Kretz
  0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Wakely @ 2020-12-17 13:10 UTC (permalink / raw)
  To: Matthias Kretz; +Cc: gcc-patches, libstdc++

On 16/12/20 12:58 +0100, Matthias Kretz wrote:
>--- /dev/null
>+++ b/libstdc++-v3/scripts/check_simd
>@@ -0,0 +1,76 @@
>+#!/bin/sh
>+
>+# check_simd <srcdir> <builddir> <CXXFLAGS>
>+# Read config from $CHECK_SIMD_CONFIG file or $target_list
>+
>+scriptdir="$(cd "${0%/*}" && pwd)"

The ${0%/*} substitution is required by POSIX sh since at least 2001,
but it looks like autoconf uses dirname for this instead. I think this
is OK, we can change to dirname if somebody reports a problem.

+# per a/b/c block extract flags and simulator, then make check-simd
>+while [ ${#list} -gt 0 ]; do
>+  a="${list%% *}"
>+  if [ "$a" = "$list" ]; then
>+    list=""
>+  else
>+    list="${list#${a} }"
>+  fi
>+  b="${a%%/*}"
>+  eval "eval \"\$$b\""
>+  flags="${flags}$(echo "${a#${b}}"|sed 's#/# #g')"
>+  subdir="simd/$(echo "$flags" | sed 's#[= /-]##g')"
>+  rm -f "${subdir}/Makefile"
>+  $srcdir/testsuite/experimental/simd/generate_makefile.sh \
>+    --destination="$testdir/$subdir" $CXX $INCLUDES $CXXFLAGS -static

Is the -static here to avoid needing LD_LIBRARY_PATH to find
libstdc++.so?

If you don't have libc.a installed it won't work. How about
using -static-libgcc -static-libstdc++ instead?


>diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc b/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc
>new file mode 100644
>index 00000000000..3f81bf03a40
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc
>@@ -0,0 +1,24 @@
>+#include "bits/verify.h"
>+#include "bits/metahelpers.h"

We'd usually put these testsuite helper files in testsuite/util, maybe
in a testsuite/util/simd sub-dir, but I suppose keeping them local to
the tests is OK too.

>+#include <cmath>    // abs & sqrt
>+#include <cstdlib>  // integer abs
>+#include "bits/test_values.h"
>+
>+template <typename V>
>+  void
>+  test()
>+  {
>+    if constexpr (std::is_signed_v<typename V::value_type>)
>+      {
>+	using std::abs;
>+	using T = typename V::value_type;
>+	test_values<V>({std::__finite_max_v<T>, std::__norm_min_v<T>,
>+			-std::__norm_min_v<T>, std::__finite_min_v<T>,
>+			std::__finite_min_v<T> / 2, T(), -T(), T(-1), T(-2)},
>+		       {1000}, [](V input) {
>+			 const V expected(
>+			   [&](auto i) { return T(std::abs(T(input[i]))); });
>+			 COMPARE(abs(input), expected) << "input: " << input;
>+		       });
>+      }
>+  }
>diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc b/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc
>new file mode 100644
>index 00000000000..f79bb6b63d2
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc
>@@ -0,0 +1,13 @@
>+#include "bits/verify.h"
>+#include "bits/metahelpers.h"
>+
>+template <typename V>
>+  void
>+  test()
>+  {
>+    using T = typename V::value_type;
>+    V a{[](auto i) -> T { return i & 1u; }};
>+    V b{[](auto i) -> T { return (i + 1u) & 1u; }};
>+    COMPARE(min(a, b), V{0});
>+    COMPARE(max(a, b), V{1});
>+  }
>diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h
>new file mode 100644
>index 00000000000..601b783cec6
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h
>@@ -0,0 +1,167 @@
>+#include <array>
>+
>+// is_conversion_undefined
>+/* implementation-defined
>+ * ======================
>+ * §4.7 p3 (integral conversions)

These section signs will cause errors if the testsuite is run with
something like -finput-charset=ascii, but I suppose we can say "don't
do that". We have tests that use that option and include all the
libstdc++ headers, so there should be no need to run the entire
testsuite with that option. So it's OK.

Apart from the -static question, this looks fine. The custom test
harness is unconventional, but I think it's the right solution here
given that it would be impolite to enable all these tests for the
default "make check" target, and the overhead of having DejaGnu skip
them by default is unacceptable.

Thanks for finding a way to add the tests without slowing down
everybody's testers.




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Add simd testsuite
  2020-12-17 13:10 ` Jonathan Wakely
@ 2020-12-18 15:25   ` Matthias Kretz
  0 siblings, 0 replies; 3+ messages in thread
From: Matthias Kretz @ 2020-12-18 15:25 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 3271 bytes --]

On Donnerstag, 17. Dezember 2020 14:10:51 CET Jonathan Wakely wrote:
> On 16/12/20 12:58 +0100, Matthias Kretz wrote:
> >+  $srcdir/testsuite/experimental/simd/generate_makefile.sh \
> >+    --destination="$testdir/$subdir" $CXX $INCLUDES $CXXFLAGS -static
> 
> Is the -static here to avoid needing LD_LIBRARY_PATH to find
> libstdc++.so?
> 
> If you don't have libc.a installed it won't work. How about
> using -static-libgcc -static-libstdc++ instead?

I need the -static for qemu and simple remote execution (copy binary via scp, 
execute via ssh). And yes, -static makes it much easier to avoid the 
LD_LIBRARY_PATH issue.

I'll make -static optional, and default to -static-libgcc -static-libstdc++. 
The latter should still work for most remote execution setups (works for me, 
at least).

> >--- /dev/null
> >+++ b/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc
> >@@ -0,0 +1,24 @@
> >+#include "bits/verify.h"
> >+#include "bits/metahelpers.h"
> 
> We'd usually put these testsuite helper files in testsuite/util, maybe
> in a testsuite/util/simd sub-dir, but I suppose keeping them local to
> the tests is OK too.

At this point the simd testsuite is very close to being usable for other 
Parallelism TS 2 implementations. That's a feature I'd support if there's 
interest outside of libstdc++.

> >--- /dev/null
> >+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h
> >@@ -0,0 +1,167 @@
> >+#include <array>
> >+
> >+// is_conversion_undefined
> >+/* implementation-defined
> >+ * ======================
> >+ * §4.7 p3 (integral conversions)
> 
> These section signs will cause errors if the testsuite is run with
> something like -finput-charset=ascii, but I suppose we can say "don't
> do that". We have tests that use that option and include all the
> libstdc++ headers, so there should be no need to run the entire
> testsuite with that option. So it's OK.

Ah, but good point. I have comments in simd_math.h (i.e. the other patch) 
like: "Fold @p x into [-¼π, ¼π] and [...]". These comments are not in the 
testsuite. I guess I need to replace all non-ASCII chars there?

Attached is the diff to the previous patch. In addition to the -static change 
I added license headers (as noted on IRC) and I improved the Makefile 
generator: Instead of only passing TESTFLAGS and GCC_TEST_SIMULATOR as 
environment variables, place the initial values into the generated Makefile. 
This makes it much easier to work on tests or fixes for failures.

I'll top-post the squashed simd patches. 

-- 
──────────────────────────────────────────────────────────────────────────
 Dr. Matthias Kretz                           https://mattkretz.github.io
 GSI Helmholtz Centre for Heavy Ion Research               https://gsi.de
 std::experimental::simd              https://github.com/VcDevel/std-simd
──────────────────────────────────────────────────────────────────────────

[-- Attachment #2: 0001-No-static-by-default-more-usable-Makefiles.patch --]
[-- Type: text/x-patch, Size: 57803 bytes --]

diff --git a/libstdc++-v3/scripts/check_simd b/libstdc++-v3/scripts/check_simd
index 2b7a17a64c9..25acf64c841 100755
--- a/libstdc++-v3/scripts/check_simd
+++ b/libstdc++-v3/scripts/check_simd
@@ -26,7 +26,7 @@ sim=\\\"$sim\\\"\""
 
 if [ -f "$CHECK_SIMD_CONFIG" ]; then
   . "$CHECK_SIMD_CONFIG"
-elif [ -z "$CHECK_SIMD_CONFIG"]; then
+elif [ -z "$CHECK_SIMD_CONFIG" ]; then
   if [ -z "$target_list" ]; then
     target_list="unix"
     case "$target_triplet" in
@@ -69,8 +69,7 @@ while [ ${#list} -gt 0 ]; do
   subdir="simd/$(echo "$flags" | sed 's#[= /-]##g')"
   rm -f "${subdir}/Makefile"
   $srcdir/testsuite/experimental/simd/generate_makefile.sh \
-    --destination="$testdir/$subdir" $CXX $INCLUDES $CXXFLAGS -static
-  echo "$subdir
-$flags
-$sim"
+    --destination="$testdir/$subdir" --sim="$sim" --testflags="$flags" \
+    $CXX $INCLUDES $CXXFLAGS -static-libgcc -static-libstdc++
+  echo "$subdir"
 done
diff --git a/libstdc++-v3/testsuite/Makefile.am b/libstdc++-v3/testsuite/Makefile.am
index d2e282b62b9..fa9cc4753f3 100644
--- a/libstdc++-v3/testsuite/Makefile.am
+++ b/libstdc++-v3/testsuite/Makefile.am
@@ -192,9 +192,10 @@ check-simd: $(srcdir)/experimental/simd/generate_makefile.sh \
 	    testsuite_files_simd \
 	    ${glibcxx_builddir}/scripts/testsuite_flags
 	${glibcxx_srcdir}/scripts/check_simd "${glibcxx_srcdir}" "${glibcxx_builddir}" "$(CXXFLAGS)" | \
-	  while read subdir && read flags && read sim; do \
-	    $(MAKE) -C "$${subdir}" TESTFLAGS="$${flags}" GCC_TEST_SIMULATOR="$${sim}"; \
-	    tail -n6 $${subdir}/simd_testsuite.sum >> .simd.summary; \
+	  while read subdir; do \
+	    $(MAKE) -C "$${subdir}"; \
+	    tail -n20 $${subdir}/simd_testsuite.sum | \
+	      grep -A20 -B1 'Summary ===' >> .simd.summary; \
 	  done; \
 	  cat .simd.summary && rm .simd.summary
 
diff --git a/libstdc++-v3/testsuite/Makefile.in b/libstdc++-v3/testsuite/Makefile.in
index 08b8fc05fa5..fadc93e027c 100644
--- a/libstdc++-v3/testsuite/Makefile.in
+++ b/libstdc++-v3/testsuite/Makefile.in
@@ -707,14 +707,16 @@ check-performance: testsuite_files_performance ${performance_script}
 	  CXXFLAGS='$(CXXFLAGS)'; export CXXFLAGS; \
 	  ${check_performance_script} ${glibcxx_srcdir} ${glibcxx_builddir})
 
+# Runs the simd tests.
 check-simd: $(srcdir)/experimental/simd/generate_makefile.sh \
 	    ${glibcxx_srcdir}/scripts/check_simd \
 	    testsuite_files_simd \
 	    ${glibcxx_builddir}/scripts/testsuite_flags
 	${glibcxx_srcdir}/scripts/check_simd "${glibcxx_srcdir}" "${glibcxx_builddir}" "$(CXXFLAGS)" | \
-	  while read subdir && read flags && read sim; do \
-	    $(MAKE) -C "$${subdir}" TESTFLAGS="$${flags}" GCC_TEST_SIMULATOR="$${sim}"; \
-	    tail -n6 $${subdir}/simd_testsuite.sum >> .simd.summary; \
+	  while read subdir; do \
+	    $(MAKE) -C "$${subdir}"; \
+	    tail -n20 $${subdir}/simd_testsuite.sum | \
+	      grep -A20 -B1 'Summary ===' >> .simd.summary; \
 	  done; \
 	  cat .simd.summary && rm .simd.summary
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/generate_makefile.sh b/libstdc++-v3/testsuite/experimental/simd/generate_makefile.sh
index 8172d9bb54c..85a7f87271e 100755
--- a/libstdc++-v3/testsuite/experimental/simd/generate_makefile.sh
+++ b/libstdc++-v3/testsuite/experimental/simd/generate_makefile.sh
@@ -6,6 +6,7 @@ srcdir="$srcdir/tests"
 sim=
 rm_logs=true
 dst=.
+testflags=
 
 usage() {
   cat <<EOF
@@ -18,6 +19,7 @@ Options:
                       execution binary (default: none).
   --keep-intermediate-logs
                       Keep intermediate logs.
+  --testflags <flags> Force initial TESTFLAGS contents.
   -d <path>, --destination <path>
                       Destination for the generated Makefile. If the directory
                       does not exist it is created (default: $dst).
@@ -30,6 +32,13 @@ while [ $# -gt 0 ]; do
     usage
     exit
     ;;
+  --testflags)
+    testflags="$2"
+    shift
+    ;;
+  --testflags=*)
+    testflags="${1#--testflags=}"
+    ;;
   -d|--destination)
     dst="$2"
     shift
@@ -76,7 +85,9 @@ CXX="$1"
 shift
 
 echo "TESTFLAGS ?=" > "$dst"
+[ -n "$testflags" ] && echo "TESTFLAGS := $testflags \$(TESTFLAGS)" >> "$dst"
 echo CXXFLAGS = "$@" "\$(TESTFLAGS)" >> "$dst"
+[ -n "$sim" ] && echo "export GCC_TEST_SIMULATOR = $sim" >> "$dst"
 cat >> "$dst" <<EOF
 srcdir = ${srcdir}
 CXX = ${CXX}
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc b/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc
index 3f81bf03a40..7d94cf47e1c 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/abs.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include <cmath>    // abs & sqrt
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc b/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc
index f79bb6b63d2..78bce35f59c 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/algorithms.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h
index 601b783cec6..e89221e1ede 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include <array>
 
 // is_conversion_undefined
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/make_vec.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/make_vec.h
index f81135900e8..ee0d436f9ae 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/bits/make_vec.h
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/make_vec.h
@@ -1,29 +1,19 @@
-/*  This file is part of the Vc library. {
-Copyright © 2017 Matthias Kretz <kretz@kde.org>
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-    * Neither the names of contributing organizations nor the
-      names of its contributors may be used to endorse or promote products
-      derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-}*/
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
 
 #include <experimental/simd>
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/mathreference.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/mathreference.h
index 3e5892c2624..2ed2bb35e3c 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/bits/mathreference.h
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/mathreference.h
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include <tuple>
 #include <utility>
 #include <cstdio>
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/metahelpers.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/metahelpers.h
index 16c6b287690..e9516537e60 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/bits/metahelpers.h
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/metahelpers.h
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #ifndef VC_TESTS_METAHELPERS_H_
 #define VC_TESTS_METAHELPERS_H_
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/simd_view.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/simd_view.h
index b7fbaf883bf..a221708df39 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/bits/simd_view.h
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/simd_view.h
@@ -1,29 +1,19 @@
-/*  This file is part of the Vc library. {
-Copyright © 2018 Matthias Kretz <kretz@kde.org>
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-    * Neither the names of contributing organizations nor the
-      names of its contributors may be used to endorse or promote products
-      derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-}*/
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
 
 #ifndef VC_TESTS_SIMD_VIEW_H_
 #define VC_TESTS_SIMD_VIEW_H_
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h
index 7acbb832900..01988aef327 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include <experimental/simd>
 #include <initializer_list>
 #include <random>
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/ulp.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/ulp.h
index c1b9e7adb07..3b6966dd85d 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/bits/ulp.h
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/ulp.h
@@ -1,29 +1,19 @@
-/*{
-Copyright © 2011-2018 Matthias Kretz <kretz@kde.org>
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-    * Neither the names of contributing organizations nor the
-      names of its contributors may be used to endorse or promote products
-      derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-}*/
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
 
 #ifndef ULP_H
 #define ULP_H
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/verify.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/verify.h
index 7ec6de7f16b..5da47b35536 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/bits/verify.h
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/verify.h
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #ifndef TESTS_BITS_VERIFY_H_
 #define TESTS_BITS_VERIFY_H_
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/broadcast.cc b/libstdc++-v3/testsuite/experimental/simd/tests/broadcast.cc
index 529280d87d4..c107de3380b 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/broadcast.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/broadcast.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/casts.cc b/libstdc++-v3/testsuite/experimental/simd/tests/casts.cc
index e2c0b108879..df169e100de 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/casts.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/casts.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/conversions.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/fpclassify.cc b/libstdc++-v3/testsuite/experimental/simd/tests/fpclassify.cc
index 87a80308ae9..eef26108f5f 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/fpclassify.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/fpclassify.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/test_values.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/frexp.cc b/libstdc++-v3/testsuite/experimental/simd/tests/frexp.cc
index 1f9b30162cb..e2d90dd1e3f 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/frexp.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/frexp.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/test_values.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/generator.cc b/libstdc++-v3/testsuite/experimental/simd/tests/generator.cc
index 62ec716c82d..221064dc476 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/generator.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/generator.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/hypot3_fma.cc b/libstdc++-v3/testsuite/experimental/simd/tests/hypot3_fma.cc
index 330a79400ee..0c8e55983a2 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/hypot3_fma.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/hypot3_fma.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/test_values.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/integer_operators.cc b/libstdc++-v3/testsuite/experimental/simd/tests/integer_operators.cc
index 9205d865aed..975e69a9e35 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/integer_operators.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/integer_operators.cc
@@ -1,16 +1,16 @@
-// Copyright (C) 2018 Free Software Foundation, Inc.
+// Copyright (C) 2020 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
 // terms of the GNU General Public License as published by the
 // Free Software Foundation; either version 3, or (at your option)
 // any later version.
-
+//
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 // GNU General Public License for more details.
-
+//
 // You should have received a copy of the GNU General Public License along
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/ldexp_scalbn_scalbln_modf.cc b/libstdc++-v3/testsuite/experimental/simd/tests/ldexp_scalbn_scalbln_modf.cc
index e8a519612e8..6d994572bf8 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/ldexp_scalbn_scalbln_modf.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/ldexp_scalbn_scalbln_modf.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/test_values.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/loadstore.cc b/libstdc++-v3/testsuite/experimental/simd/tests/loadstore.cc
index 329c89688ed..994227c7d5a 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/loadstore.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/loadstore.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/make_vec.h"
 #include "bits/conversions.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/logarithm.cc b/libstdc++-v3/testsuite/experimental/simd/tests/logarithm.cc
index 7578f1a8561..29c686db697 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/logarithm.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/logarithm.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/mathreference.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_broadcast.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_broadcast.cc
index 6fbadc67af7..7fc8201caf6 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/mask_broadcast.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_broadcast.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_conversions.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_conversions.cc
index 0248cd4cb47..8cec912250a 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/mask_conversions.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_conversions.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 
 namespace stdx = std::experimental;
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_implicit_cvt.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_implicit_cvt.cc
index 3fa8dab5799..e1760e3f37f 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/mask_implicit_cvt.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_implicit_cvt.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_loadstore.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_loadstore.cc
index 5e3fd6d867c..0f43428b7c6 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/mask_loadstore.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_loadstore.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 
 // simd_mask generator functions
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_operator_cvt.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_operator_cvt.cc
index cb968d02785..738b97c3dca 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/mask_operator_cvt.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_operator_cvt.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_operators.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_operators.cc
index f729adc55bf..58255cf1e1b 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/mask_operators.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_operators.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/mask_reductions.cc b/libstdc++-v3/testsuite/experimental/simd/tests/mask_reductions.cc
index 99912aad9c0..1190eaf5457 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/mask_reductions.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/mask_reductions.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/math_1arg.cc b/libstdc++-v3/testsuite/experimental/simd/tests/math_1arg.cc
index 748fd1d3866..bce01264f3c 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/math_1arg.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/math_1arg.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/test_values.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/math_2arg.cc b/libstdc++-v3/testsuite/experimental/simd/tests/math_2arg.cc
index ef425fa4221..57b7b3aeb5c 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/math_2arg.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/math_2arg.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/test_values.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/operator_cvt.cc b/libstdc++-v3/testsuite/experimental/simd/tests/operator_cvt.cc
index 1c73e299981..a04cd34e3d4 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/operator_cvt.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/operator_cvt.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/operators.cc b/libstdc++-v3/testsuite/experimental/simd/tests/operators.cc
index 566c5c994e8..cee696cc69b 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/operators.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/operators.cc
@@ -1,16 +1,16 @@
-// Copyright (C) 2018 Free Software Foundation, Inc.
+// Copyright (C) 2020 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
 // terms of the GNU General Public License as published by the
 // Free Software Foundation; either version 3, or (at your option)
 // any later version.
-
+//
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 // GNU General Public License for more details.
-
+//
 // You should have received a copy of the GNU General Public License along
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/reductions.cc b/libstdc++-v3/testsuite/experimental/simd/tests/reductions.cc
index a663db23a61..6f4ba40133f 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/reductions.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/reductions.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/test_values.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/remqo.cc b/libstdc++-v3/testsuite/experimental/simd/tests/remqo.cc
index 87eb21ef098..bdbacc6ef8e 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/remqo.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/remqo.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/test_values.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/simd.cc b/libstdc++-v3/testsuite/experimental/simd/tests/simd.cc
index 0744be5e191..657646c0ac5 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/simd.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/simd.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 
 template <typename V>
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/sincos.cc b/libstdc++-v3/testsuite/experimental/simd/tests/sincos.cc
index ced3be49136..acef488e214 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/sincos.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/sincos.cc
@@ -1,6 +1,21 @@
 // test only floattypes
-// { dg-additional-files "reference-sincos-sp.dat" }
-// { dg-additional-files "reference-sincos-ep.dat" }
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/mathreference.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/split_concat.cc b/libstdc++-v3/testsuite/experimental/simd/tests/split_concat.cc
index 2e7cf66b227..3a79a1f8e3d 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/split_concat.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/split_concat.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/conversions.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/splits.cc b/libstdc++-v3/testsuite/experimental/simd/tests/splits.cc
index 31db384f798..8b61635c2a6 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/splits.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/splits.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 
 template <typename V>
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/trigonometric.cc b/libstdc++-v3/testsuite/experimental/simd/tests/trigonometric.cc
index 51fef12a87f..24730f1856c 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/trigonometric.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/trigonometric.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/metahelpers.h"
 #include "bits/test_values.h"
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/trunc_ceil_floor.cc b/libstdc++-v3/testsuite/experimental/simd/tests/trunc_ceil_floor.cc
index df105530efe..e516926ae1d 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/trunc_ceil_floor.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/trunc_ceil_floor.cc
@@ -1,4 +1,21 @@
 // test only floattypes
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/test_values.h"
 #include "bits/verify.h"
 
diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/where.cc b/libstdc++-v3/testsuite/experimental/simd/tests/where.cc
index 603e5a4b262..5e73a3b1989 100644
--- a/libstdc++-v3/testsuite/experimental/simd/tests/where.cc
+++ b/libstdc++-v3/testsuite/experimental/simd/tests/where.cc
@@ -1,3 +1,20 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 #include "bits/verify.h"
 #include "bits/make_vec.h"
 #include "bits/metahelpers.h"

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-12-18 15:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-16 11:58 [PATCH] Add simd testsuite Matthias Kretz
2020-12-17 13:10 ` Jonathan Wakely
2020-12-18 15:25   ` Matthias Kretz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).