Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/Clang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
image: ghcr.io/mattkretz/cplusplus-ci/clang${{ matrix.version }}

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- name: Run test suite
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/GCC.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
image: ghcr.io/mattkretz/cplusplus-ci/gcc${{ matrix.version }}

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- name: Run test suite
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/fair-software.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
name: "fair-software"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
with:
repository: mattkretz/howfairis
path: howfairis
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/reuse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v5
uses: fsfe/reuse-action@v6
135 changes: 70 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,93 +5,98 @@
[![REUSE status](https://github.com/GSI-HPC/simd/actions/workflows/reuse.yml/badge.svg)](https://github.com/GSI-HPC/simd/actions/workflows/reuse.yml)
[![fair-software.eu](https://img.shields.io/badge/fair--software.eu-%E2%97%8F%20%20%E2%97%8B%20%20%E2%97%8B%20%20%E2%97%8B%20%20%E2%97%8B-red)](https://fair-software.eu)

## Build, install, use?

Parts of this implementation are already integrated into GCC 16.
If you want to try the development version you can either install this library via:
```sh
make prefix=~/.local install
```
or simply point your compiler's include path to this repository.

Alternatively you can also install into the compiler's standard library
directory:
```sh
make install-system
```
There is no support for uninstalling, since `install-system` overwrites the `std::simd` headers of libstdc++.

Build your own project with C++26 (latest GCC, PRs to support Clang are
welcome). Just include `<simd>` and you're good to go:
```c++
#include <simd>
```

To build the tests there are multiple targets available. `make help` will list all of them.

## Feature macros

By default all vectorizable types (including `complex`) are supported. More features can be enabled by defining the following macros:

| Macro | Description |
|-------|-------------|
| `VIR_EXTENSIONS` | Enable several optimizations and warnings on guaranteed precondition violations. |
| `VIR_PATCH_PERMUTE_DYNAMIC` | Implements [simd.permute.dynamic]. |
| `VIR_PATCH_MATH` | Implements [simd.math]. |
| `VIR_PATCH_IMPROVE_CX` | Implements `abs` and `norm` for `vec<complex<T>>`. Three different approaches `=1`, `=2`, and `=3` make different optimization/code-gen trade-offs. |
| `VIR_PATCH_MISSED_OPT` | Enable hand-written instruction selection for optimization patterns the compiler misses. Includes ktest-based mask reductions and pshufb-based type conversions on x86. |
| `VIR_PATCH_TEST_STORES` | Fix masked stores. |
| `VIR_CONSTEVAL_BROADCAST` | Use `consteval` broadcast constructor for value-preserving conversions: Either the value doesn't change or the program is ill-formed. Peace of mind. |

## Implementation status

| Feature | Status |
| ------- | ------ |
| [P1928R15](https://wg21.link/P1928R15) std::simd — merge data-parallel types from the Parallelism TS 2 | ✅ done (except math) |
| [P3430R3](https://wg21.link/P3430R3) simd issues: explicit, unsequenced, identity-element position, and members of disabled simd | ✅ done |
| [P3441R2](https://wg21.link/P3441R2) Rename simd_split to simd_chunk | ✅ done |
| [P3287R3](https://wg21.link/P3287R3) Exploration of namespaces for std::simd | ✅ done |
| [P2933R4](https://wg21.link/P2933R4) Extend ⟨bit⟩ header function with overloads for std::simd | ✅ done |
| [P2663R7](https://wg21.link/P2663R7) Interleaved complex values support in std::simd | ✅ done (except math) |
| [P2664R11](https://wg21.link/P2664R11) Proposal to extend std::simd with permutation API | 🟡 partial |
| [P2876R3](https://wg21.link/P2876R3) Proposal to extend std::simd with more constructors and accessors | ✅ done |
| [P2929R2](https://wg21.link/P2929R2) simd_invoke | 🔴 open (still in design phase) |
| [P2933R4](https://wg21.link/P2933R4) Extend ⟨bit⟩ header function with overloads for std::simd | ✅ done |
| [P2933R4](https://wg21.link/P2933R4) std::simd overloads for `<bit>` header | ✅ done (not optimized) |
| [P2964R2](https://wg21.link/P2964R2) Allowing user-defined types in std::simd | 🔴 open (still in design phase) |
| [P3287R3](https://wg21.link/P3287R3) Exploration of namespaces for std::simd | ✅ done |
| [P3430R3](https://wg21.link/P3430R3) simd issues: explicit, unsequenced, identity-element position, and members of disabled simd | ✅ done |
| [P3440R2](https://wg21.link/P3440R2) Add n_elements named constructor to std::simd | 🔴 open (still in design phase) |
| [P3441R2](https://wg21.link/P3441R2) Rename simd_split to simd_chunk | ✅ done |
| [P3480R6](https://wg21.link/P3480R6) std::simd is a range | ✅ done |
| [P3691R1](https://wg21.link/P3691R1) Reconsider naming of the namespace for 'std::simd' | ✅ done |
| [P3844R4](https://wg21.link/P3844R4) Reword [simd.math] for consteval conversions | ✅ done |
| [P3932R0](https://wg21.link/P3932R0) Fix LWG4470: Fix *integer-from* in [simd] | ✅ done |
| [P4042R0](https://wg21.link/P4042R0) Fix LWG4543: incorrect cast between `simd::vec` and `simd::mask` via conversion to and from impl-defined vector types | ✅ done |
| [P3440R2](https://wg21.link/P3440R2) Add n_elements named constructor to std::simd | 🔴 open (still in design phase) |
| [P2929R2](https://wg21.link/P2929R2) simd_invoke | 🔴 open (still in design phase) |
| [P2964R2](https://wg21.link/P2964R2) Allowing user-defined types in std::simd | 🔴 open (still in design phase) |
| [P3973R0](https://wg21.link/P3973R0) bit_cast_as: Element type reinterpretation for std::simd | 🔴 open (still in design phase) |
| [P3983R0](https://wg21.link/P3983R0) simd object representation | 🔴 open (still in design phase) |
| [P3985R0](https://wg21.link/P3985R0) Concepts for std::simd | 🔴 open (still in design phase) |
| [P3844R4](https://wg21.link/P3844R4) Reword [simd.math] for consteval conversions | ✅ done |
| [P4012R1](https://wg21.link/P4012R1) value-preserving consteval broadcast to simd::vec | 🔴 open |
| [P4042R0](https://wg21.link/P4042R0) Fix LWG4543: incorrect cast between `simd::vec` and `simd::mask` [...] | ✅ done |
| [P4012R1](https://wg21.link/P4012R1) value-preserving consteval broadcast to simd::vec | ✅ done |
| [P4042R0](https://wg21.link/P4042R0) Fix LWG4543: incorrect cast between `simd::vec` and `simd::mask` via conversion to and from impl-defined vector types | ✅ done |

| Issue | Status |
| ------- | ------ |
| [LWG4385](https://wg21.link/lwg4385) Including `<simd>` doesn't provide `std::begin/end` | ✅ done (via inclusion of `<span>`) |
| [LWG4409](https://wg21.link/lwg4409) Constant expression `ranges::size(r)` Constraints and Mandates in [simd] | 🔴 open |
| [LWG4420](https://wg21.link/lwg4420) §[simd] conversions (constructor, load, stores, gather, and scatter) are incorrectly constrained for `<stdfloat>` types | ✅ done |
| [LWG4470](https://wg21.link/lwg4470) The use of *integer-from*`<Bytes>` all over [simd] is incorrect for `Bytes=sizeof(complex<double>)` | ✅ done ([P3932R0](https://wg21.link/P3932R0)) |
| [LWG4535](https://wg21.link/lwg4535) Disallow user specialization of `<simd>` templates | ✅ done (not actionable) |
| [LWG4414](https://wg21.link/lwg4414) §[simd.expos.abi] *deduce-abi-t* is underspecified and incorrectly referenced from `rebind` and `resize` | ✅ done ([P3932R0](https://wg21.link/P3932R0)) |
| [LWG4412](https://wg21.link/lwg4412) Fix declaration of `zero_element` and `uninit_element` | ✅ done |
| [LWG4238](https://wg21.link/lwg4238) `simd_mask<complex<double>>::operator+/-/~` return a disabled simd specialization | ✅ done |
| [LWG4230](https://wg21.link/lwg4230) `simd<complex>::real/imag` is overconstrained | ✅ done |
| [LWG4231](https://wg21.link/lwg4231) `datapar::chunk<N>` should use *simd-size-type* instead of `size_t` | ✅ done |
| [LWG4518](https://wg21.link/lwg4518) `simd::cat` return type requires inefficient ABI tag change/conversion | ✅ done ([P3932R0](https://wg21.link/P3932R0)) |
| [LWG4413](https://wg21.link/lwg4413) Unused/left-over `simd::alignment` specialization for `basic_mask` | ✅ done |
| [LWG4232](https://wg21.link/lwg4232) `datapar::resize` does not resize | ✅ done |
| [LWG4543](https://wg21.link/lwg4543) Incorrect cast between `simd::vec` and `simd::mask` via conversion to and from impl-defined vector types | ✅ done ([P4042R0](https://wg21.link/P4042R0)) |
| [LWG4390](https://wg21.link/lwg4390) `simd::basic_vec(U&&)` default template parameter | ⚪ treated as NAD |
| [LWG4403](https://wg21.link/lwg4403) `simd::basic_vec` CTAD misses difference type casting | ✅ done |
| [LWG4407](https://wg21.link/lwg4407) *constexpr-wrapper-like* needs `remove_cvref_t` in `simd::basic_vec` constructor | ✅ done |
| [LWG4238](https://wg21.link/lwg4238) `simd_mask<complex<double>>::operator+/-/~` return a disabled simd specialization | ✅ done |
| [LWG4280](https://wg21.link/lwg4280) `simd::partial_load` uses undefined identifier `T` | 🔴 unclear |
| [LWG4375](https://wg21.link/lwg4375) `std::simd::bit_ceil` should not be `noexcept` | 🔴 unclear |
| [LWG4376](https://wg21.link/lwg4376) ABI tag in return type of [simd.mask.unary] is overconstrained | ✅ done |
| [LWG4230](https://wg21.link/lwg4230) `simd<complex>::real/imag` is overconstrained | ✅ done |
| [LWG4436](https://wg21.link/lwg4436) `simd` broadcast is overconstrained — `std::cw<0.f>` is not convertible to `simd::vec<float16_t>` | 🔴 unclear |
| [LWG4382](https://wg21.link/lwg4382) The `simd::basic_mask(bool)` overload needs to be more constrained | 🔴 unclear |
| [LWG4385](https://wg21.link/lwg4385) Including `<simd>` doesn't provide `std::begin/end` | ✅ done (via inclusion of `<span>`) |
| [LWG4386](https://wg21.link/lwg4386) `std::simd::select(bool c, const T& a, const U& b)` is underconstrained | 🔴 unclear |
| [LWG4390](https://wg21.link/lwg4390) `simd::basic_vec(U&&)` default template parameter | ⚪ treated as NAD |
| [LWG4391](https://wg21.link/lwg4391) Ambiguities of `simd::basic_vec` constructor | 🔴 unclear |
| [LWG4408](https://wg21.link/lwg4408) Hardening `simd::vec::operator[]` | 🔴 unclear |
| [LWG4392](https://wg21.link/lwg4392) `simd::unchecked_load` misses difference type casting | 🔴 unclear |
| [LWG4394](https://wg21.link/lwg4394) `simd::unchecked_load(I first, S last)` construct `span` maybe ill-formed | 🔴 unclear |
| [LWG4280](https://wg21.link/lwg4280) `simd::partial_load` uses undefined identifier `T` | 🔴 unclear |
| [LWG4393](https://wg21.link/lwg4393) `simd::unchecked_scatter_to` is underconstrained | 🔴 unclear |
| [LWG4386](https://wg21.link/lwg4386) `std::simd::select(bool c, const T& a, const U& b)` is underconstrained | 🔴 unclear |
| [LWG4375](https://wg21.link/lwg4375) `std::simd::bit_ceil` should not be `noexcept` | 🔴 unclear |
| [LWG4394](https://wg21.link/lwg4394) `simd::unchecked_load(I first, S last)` construct `span` maybe ill-formed | 🔴 unclear |
| [LWG4402](https://wg21.link/lwg4402) List-initialization of iterators in [simd.mask.overview] | 🔴 unclear |
| [LWG4382](https://wg21.link/lwg4382) The `simd::basic_mask(bool)` overload needs to be more constrained | 🔴 unclear |


## Build, install, use?

This implementation is not intended for use yet. Nevertheless, it should be
usable for experimenting. There is very simple build system support for
installation via:
```sh
make prefix=~/.local install
```
But you can also just point your compiler's include path to this repository
instead.

Alternatively you can also install into the compiler's standard library
directory:
```sh
make install-system
```
You can uninstall again with:
```sh
make uninstall-system
```

Build your own project with C++26 (latest GCC, PRs to support Clang are
welcome). Just include `<simd>` and you're good to go:
```c++
#include <simd>
```

To build the tests there are multiple targets available. `make help` will list
all of them.

| [LWG4403](https://wg21.link/lwg4403) `simd::basic_vec` CTAD misses difference type casting | ✅ done |
| [LWG4407](https://wg21.link/lwg4407) *constexpr-wrapper-like* needs `remove_cvref_t` in `simd::basic_vec` constructor | ✅ done |
| [LWG4408](https://wg21.link/lwg4408) Hardening `simd::vec::operator[]` | 🔴 unclear |
| [LWG4409](https://wg21.link/lwg4409) Constant expression `ranges::size(r)` Constraints and Mandates in [simd] | 🔴 open |
| [LWG4412](https://wg21.link/lwg4412) Fix declaration of `zero_element` and `uninit_element` | ✅ done |
| [LWG4413](https://wg21.link/lwg4413) Unused/left-over `simd::alignment` specialization for `basic_mask` | ✅ done |
| [LWG4414](https://wg21.link/lwg4414) §[simd.expos.abi] *deduce-abi-t* is underspecified and incorrectly referenced from `rebind` and `resize` | ✅ done ([P3932R0](https://wg21.link/P3932R0)) |
| [LWG4420](https://wg21.link/lwg4420) §[simd] conversions (constructor, load, stores, gather, and scatter) are incorrectly constrained for `<stdfloat>` types | ✅ done |
| [LWG4436](https://wg21.link/lwg4436) `simd` broadcast is overconstrained — `std::cw<0.f>` is not convertible to `simd::vec<float16_t>` | 🔴 unclear |
| [LWG4470](https://wg21.link/lwg4470) The use of *integer-from*`<Bytes>` all over [simd] is incorrect for `Bytes=sizeof(complex<double>)` | ✅ done ([P3932R0](https://wg21.link/P3932R0)) |
| [LWG4518](https://wg21.link/lwg4518) `simd::cat` return type requires inefficient ABI tag change/conversion | ✅ done ([P3932R0](https://wg21.link/P3932R0)) |
| [LWG4535](https://wg21.link/lwg4535) Disallow user specialization of `<simd>` templates | ✅ done (not actionable) |
| [LWG4543](https://wg21.link/lwg4543) Incorrect cast between `simd::vec` and `simd::mask` via conversion to and from impl-defined vector types | ✅ done ([P4042R0](https://wg21.link/P4042R0)) |
6 changes: 3 additions & 3 deletions codegen/select.c++
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ V0 test0b(V0::mask_type a)
{ return simd::select(a, char(1), char(0)); }

V0 test0c(V0::mask_type a)
{ return simd::select(a, V0(1), V0()); }
{ return simd::select(a, V0(char(1)), V0()); }

V0 test0d(V0 a, V0 b, V0 c)
{ return simd::select(a == a, b, c); }
Expand Down Expand Up @@ -92,7 +92,7 @@ V1 test1b(V1::mask_type a)
{ return simd::select(a, T1(1), T1()); }

V1 test1c(V1::mask_type a)
{ return simd::select(a, V1(1), V1()); }
{ return simd::select(a, V1(T1(1)), V1()); }

/* codegen
^"test2a(
Expand Down Expand Up @@ -123,7 +123,7 @@ V2 test2b(V2::mask_type a)
{ return simd::select(a, short(1), short()); }

V2 test2c(V2::mask_type a)
{ return simd::select(a, V2(1), V2()); }
{ return simd::select(a, V2(short(1)), V2()); }

V2 test2d(V2 a, V2 b, V2 c)
{ return simd::select(a == a, b, c); }
Expand Down
14 changes: 14 additions & 0 deletions constexpr_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,18 @@ namespace LWG4420
simd::vec<float, 4> vh2f_b = float16_t();

simd::vec<float16_t, 4> vf2h = {f4, simd::flag_convert};
#if VIR_CONSTEVAL_BROADCAST
simd::vec<float16_t, 4> vf2h_b{float()};
#endif

vh2f = vf2h;
vf2h = static_cast<decltype(vf2h)>(vh2f);

#if VIR_CONSTEVAL_BROADCAST
return all_of(vh2f == vh2f_b) && all_of(vf2h == vf2h_b);
#else
return all_of(vh2f == vh2f_b);
#endif
}());
}
#endif
Expand Down Expand Up @@ -141,7 +147,11 @@ namespace test02
// ensure 'true ? int : vec<float>' doesn't work
template <typename T>
concept has_type_member = requires { typename T::type; };
#if VIR_CONSTEVAL_BROADCAST
static_assert(has_type_member<common_type<int, simd::vec<float>>>);
#else
static_assert(!has_type_member<common_type<int, simd::vec<float>>>);
#endif

constexpr simd::vec<complex<double>>::mask_type k = {};
}
Expand Down Expand Up @@ -176,7 +186,11 @@ static_assert( std::convertible_to<Ic<1>, simd::vec<float>>);
static_assert(!std::convertible_to<Ic<1.1>, simd::vec<float>>);
static_assert(!std::convertible_to<simd::vec<int, 4>, simd::vec<float, 4>>);
static_assert(!std::convertible_to<simd::vec<float, 4>, simd::vec<int, 4>>);
#if VIR_CONSTEVAL_BROADCAST
static_assert( std::convertible_to<int, simd::vec<float>>);
#else
static_assert(!std::convertible_to<int, simd::vec<float>>);
#endif
static_assert( std::convertible_to<simd::vec<int, 4>, simd::vec<double, 4>>);

template <typename V>
Expand Down
41 changes: 27 additions & 14 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ set -e

# Source and destination directories
SRC_DIR="include/bits"
DEST_DIR="/home/mkretz/src/gcc-simd/libstdc++-v3/include/bits"
DEST_DIR="/home/mkretz/src/gcc-master/libstdc++-v3/include/bits"
TEST_DIR="/home/mkretz/src/gcc-master/libstdc++-v3/testsuite/std/simd"

# Create destination directory if it doesn't exist
mkdir -p "$DEST_DIR"
if ! test -d "$DEST_DIR"; then echo "$DEST_DIR is missing"; fi
if ! test -d "$TEST_DIR"; then echo "$TEST_DIR is missing"; fi

filter() {
invert=0
Expand Down Expand Up @@ -146,22 +147,34 @@ EOF
grep '^$' -A100000
}

all_filters() {
filter VIR_EXTENSIONS \
| filter VIR_PATCH_PERMUTE_DYNAMIC \
| filter VIR_PATCH_MATH \
| filter VIR_PATCH_IMPROVE_CX \
| filter VIR_PATCH_MISSED_OPT \
| filter VIR_PATCH_TEST_STORES \
| filter VIR_ASSERT_SANITY \
| filter VIR_CONSTEVAL_BROADCAST \
| fix_copyright
}

# Process each .h file in the source directory
for file in "$SRC_DIR"/*.h; do
if [ -f "$file" ]; then
filename=$(basename "$file")
echo "Processing $filename..."

# Use awk to handle VIR_EXTENSIONS conditional blocks
cat "$file" | filter VIR_EXTENSIONS \
| filter VIR_PATCH_PERMUTE_DYNAMIC \
| filter VIR_PATCH_MATH \
| filter VIR_PATCH_IMPROVE_CX \
| filter VIR_PATCH_MISSED_OPT \
| filter VIR_PATCH_TEST_STORES \
| filter VIR_ASSERT_SANITY \
| fix_copyright > "$DEST_DIR/$filename"
cat "$file" | all_filters > "$DEST_DIR/$filename"
fi
done

echo "Deployment complete. Processed files copied to $DEST_DIR/"
cat math-traits_tests.cpp | all_filters > "$TEST_DIR/traits_math.cc"
cat constexpr_tests.cpp | all_filters > "$TEST_DIR/traits_common.cc"
cat generic-traits_tests.cpp | all_filters > "$TEST_DIR/traits_impl.cc"
for file in tests/*.cpp; do
filename=$(basename "$file")
echo "Processing $filename..."
cat "$file" | all_filters > "$TEST_DIR/${filename%.cpp}.cc"
done

echo "Deployment complete. Processed files copied to $DEST_DIR/ and $TEST_DIR/"
Loading
Loading