Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix clang support #21

Merged
merged 14 commits into from
Nov 2, 2023
Merged
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
31 changes: 28 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
strategy:
fail-fast: false
matrix:
version: [15]
version: [16, 17]

runs-on: ubuntu-22.04

Expand All @@ -43,8 +43,33 @@ jobs:
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.version }} main'
sudo apt update
sudo apt install -y clang-${{ matrix.version }} libc++-${{ matrix.version }}-dev libc++abi-${{ matrix.version }}-dev
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install -y g++-13 clang-${{ matrix.version }}
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 110 --slave /usr/bin/g++ g++ /usr/bin/g++-13

- name: Run test suite
env:
CXX: clang++-${{ matrix.version }}
run: make check DRIVEROPTS=-vvf

clang-libcxx:
strategy:
fail-fast: false
matrix:
version: [15, 17]

runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3

- name: Install Clang ${{ matrix.version }}
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.version }} main'
sudo apt-get update
sudo apt-get install -y clang-${{ matrix.version }} libc++-${{ matrix.version }}-dev libc++abi-${{ matrix.version }}-dev

- name: Run test suite
env:
Expand Down
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ build_dir := build-$(subst /,-,$(build_dir:/%=%))

triplet := $(shell $(CXX) -dumpmachine)

CXXFLAGS+=-Wno-attributes -Wno-unknown-pragmas -Wno-psabi
CXXFLAGS+=-Wall -Wextra -Wpedantic -Wno-attributes -Wno-unknown-pragmas -Wno-psabi
ChristianTackeGSI marked this conversation as resolved.
Show resolved Hide resolved
ifneq ($(findstring GCC,$(shell $(CXX) --version)),)
CXXFLAGS+=-static-libstdc++
else ifneq ($(findstring clang,$(shell $(CXX) --version)),)
# Avoid warning on self-assignment tests
CXXFLAGS+=-Wno-self-assign-overloaded
# Avoid warning about PCH inclusion method
CXXFLAGS+=-Wno-deprecated
endif
CXXFLAGS+=-I$(PWD)
prefix=/usr/local
Expand All @@ -25,7 +30,6 @@ ifneq ($(findstring 86,$(triplet)),)
testflags=-march=native
else ifneq ($(findstring wasm,$(triplet)),)
testflags=
CXXFLAGS+=-Wno-deprecated
endif

std=$(shell ./latest_std_flag.sh)
Expand Down
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,61 @@ defines the following functions:
elimination leading up to the results passed to this function.


### `constexpr_wrapper`: function arguments as constant expressions
mattkretz marked this conversation as resolved.
Show resolved Hide resolved

The header
```c++
#include <vir/constexpr_wrapper.h>
```
defines the following tools:

* `vir::constexpr_value` (concept): Satisfied by any type with a static
`::value` member that can be used in a constant expression.

* `vir::constexpr_wrapper<auto>` (class template): A type storing the value of
its NTTP (non-type template parameter) and overloading all operators to
return another `constexpr_wrapper`. `constexpr_wrapper` objects are
implicitly convertible to their value type (a `constexpr_wrapper`
automatically unwraps its constant expression).

* `vir::cw<auto>` (variable template): Shorthand for producing
`constexpr_wrapper` objects with the given value.
mattkretz marked this conversation as resolved.
Show resolved Hide resolved

* `vir::literals` (namespace with `_cw` UDL): Shorthand for producing
`constexpr_wrapper` objects of the integer literal in front of the `_cw`
suffix. The type will be deduced automatically from the value of the literal
to be the smallest signed integral type, or if the value is larger, `unsigned
long long`. If the value is too large for an `unsigned long long`, the
program is ill-formed.

`constexpr_wrapper` may appear unrelated to `simd`. However, it is an important
tool used in many places in the implementation and on interfaces of vir-simd
tools. `vir::constexpr_wrapper` is very similar to `std::integral_constant`,
which is used in the `simd` TS interface for generator constructors.

#### Example

```c++
#include <vir/constexpr_wrapper.h>

auto f(vir::constexpr_value auto N)
{
std::array<int, N> x = {};
return x;
}

std::array a = f(vir::cw<4>); // array<int, 4>

using namespace vir::literals;

std::array b = f(10_cw); // array<int, 10>
```

This example cannot work with a signature `constexpr auto f(int n)` (or
`consteval`) because `n` will never be considered a constant expression in the
body of the function.


## Debugging

Compile with `-D _GLIBCXX_DEBUG_UB` to get runtime checks for undefined
Expand Down
18 changes: 9 additions & 9 deletions testsuite/tests/bits/verify.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,18 +228,18 @@ template <typename T>
}

#define COMPARE(_a, _b) \
[&](auto&& _aa, auto&& _bb) { \
[&](const auto& fun, auto&& _aa, auto&& _bb) { \
return verify(std::experimental::all_of(_aa == _bb), __FILE__, __LINE__, \
__PRETTY_FUNCTION__, #_a " == " #_b, #_a " = ", _aa, \
fun, #_a " == " #_b, #_a " = ", _aa, \
"\n" #_b " = ", _bb); \
}(force_fp_truncation(_a), force_fp_truncation(_b))
}(__PRETTY_FUNCTION__, force_fp_truncation(_a), force_fp_truncation(_b))
#else
#define COMPARE(_a, _b) \
[&](auto&& _aa, auto&& _bb) { \
[&](const auto& fun, auto&& _aa, auto&& _bb) { \
return verify(std::experimental::all_of(_aa == _bb), __FILE__, __LINE__, \
__PRETTY_FUNCTION__, #_a " == " #_b, #_a " = ", _aa, \
fun, #_a " == " #_b, #_a " = ", _aa, \
"\n" #_b " = ", _bb); \
}((_a), (_b))
}(__PRETTY_FUNCTION__, (_a), (_b))
#endif

#define VERIFY(_test) \
Expand All @@ -248,14 +248,14 @@ template <typename T>
// 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 auto& fun, auto&& _aa, auto&& _bb) { \
const bool success = std::experimental::all_of( \
vir::test::ulp_distance(_aa, _bb) <= (_allowed_distance)); \
return verify(success, __FILE__, __LINE__, __PRETTY_FUNCTION__, \
return verify(success, __FILE__, __LINE__, fun, \
#_a " ~~ " #_b, #_a " = ", _aa, "\n" #_b " = ", _bb, \
"\ndistance = ", \
success ? 0 : vir::test::ulp_distance_signed(_aa, _bb)); \
}((_a), (_b))
}(__PRETTY_FUNCTION__, (_a), (_b))

namespace vir {
namespace test
Expand Down
4 changes: 3 additions & 1 deletion testsuite/tests/fpclassify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,16 @@ template <typename V>
{
using T = typename V::value_type;
using intv = std::experimental::fixed_size_simd<int, V::size()>;
#if COMPLETE_IEC559_SUPPORT
constexpr T inf = vir::infinity_v<T>;
constexpr T denorm_min = vir::infinity_v<T>;
constexpr T nan = vir::quiet_NaN_v<T>;
#endif
constexpr T max = vir::finite_max_v<T>;
constexpr T norm_min = vir::norm_min_v<T>;
test_values<V>(
{0., 1., -1.,
#if __GCC_IEC_559 >= 2
#if COMPLETE_IEC559_SUPPORT
-0., inf, -inf, denorm_min, -denorm_min, nan,
norm_min * 0.9, -norm_min * 0.9,
#endif
Expand Down
8 changes: 5 additions & 3 deletions testsuite/tests/frexp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@ template <typename V>
{
using int_v = std::experimental::fixed_size_simd<int, V::size()>;
using T = typename V::value_type;
#if COMPLETE_IEC559_SUPPORT
constexpr auto denorm_min = vir::denorm_min_v<T>;
constexpr auto norm_min = vir::norm_min_v<T>;
constexpr auto max = vir::finite_max_v<T>;
constexpr auto nan = vir::quiet_NaN_v<T>;
constexpr auto inf = vir::infinity_v<T>;
#endif
constexpr auto max = vir::finite_max_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
#if COMPLETE_IEC559_SUPPORT
denorm_min, -denorm_min, norm_min / 2, -norm_min / 2,
#endif
max, -max, max * 0.123f, -max * 0.123f},
Expand All @@ -53,7 +55,7 @@ template <typename V>
COMPARE(exponent, expectedExponent)
<< "\ninput: " << input << ", fraction: " << fraction;
});
#ifdef __STDC_IEC_559__
#if COMPLETE_IEC559_SUPPORT
test_values<V>(
// If x is a NaN, a NaN is returned, and the value of *exp is unspecified.
//
Expand Down
10 changes: 7 additions & 3 deletions testsuite/tests/transform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ template <typename V>
COMPARE(i, T(data0.size()));
COMPARE(data0, data1);

vir::transform(exec_simd.template unroll_by<2>(), data0, data1, [&i](auto v) {
vir::transform(exec_simd.template unroll_by<2>(), data0, data1, [](auto v) {
return v + 1;
});
vir::transform(exec_simd, data0, data1, data2, [&i](auto v0, auto v1) {
vir::transform(exec_simd, data0, data1, data2, [](auto v0, auto v1) {
return Point2D<decltype(v0)>{v0, v1 + 2};
});

Expand All @@ -65,7 +65,11 @@ template <typename V>
for (int x : dataInt)
COMPARE(x, 3);

#if __cpp_lib_ranges_zip >= 202110L
#if defined __clang_major__ and __clang_major__ <= 17
// Clang 17 fails to compile libstdc++ zip_view code
#define BAD_COMPILER 1
#endif
#if __cpp_lib_ranges_zip >= 202110L and not BAD_COMPILER
vir::transform(exec_simd, std::views::zip(data0, data1), dataInt, [](const auto& v) {
using IV = vir::simdize<int, std::remove_cvref_t<decltype(v.first)>::size()>;
const IV a = vir::cvt(v.first);
Expand Down
6 changes: 3 additions & 3 deletions vir/constexpr_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,11 @@ namespace vir
static_assert(valid_chars, "invalid characters in constexpr_wrapper literal");

// common values, freeing values for error conditions
if constexpr (arr == std::array {'0'})
if constexpr (arr.size() == 1 and arr[0] =='0')
return static_cast<signed char>(0);
else if constexpr (arr == std::array {'1'})
else if constexpr (arr.size() == 1 and arr[0] =='1')
return static_cast<signed char>(1);
else if constexpr (arr == std::array {'2'})
else if constexpr (arr.size() == 1 and arr[0] =='2')
return static_cast<signed char>(2);

constexpr unsigned long long x = [&]() {
Expand Down
19 changes: 14 additions & 5 deletions vir/detail.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,22 @@
#define VIR_GLIBCXX_STDX_SIMD 0
#endif

#ifdef __GNUC__
#if defined __GNUC__ and not defined __clang__
#define VIR_LAMBDA_ALWAYS_INLINE __attribute__((__always_inline__))
#else
#define VIR_LAMBDA_ALWAYS_INLINE
#endif

#ifdef __has_builtin
#if __has_builtin(__builtin_shufflevector)
#define VIR_HAVE_BUILTIN_SHUFFLEVECTOR 1
// Clang 17 miscompiles permuting loads and stores for simdized types. I was unable to pin down the
// cause, but it seems highly likely that some __builtin_shufflevector calls get miscompiled. So
// far, not using __builtin_shufflevector has resolved all failures.
#if __has_builtin(__builtin_shufflevector) and __clang_major__ != 17
#define VIR_HAVE_WORKING_SHUFFLEVECTOR 1
#endif
#endif
#ifndef VIR_HAVE_BUILTIN_SHUFFLEVECTOR
#define VIR_HAVE_BUILTIN_SHUFFLEVECTOR 0
#ifndef VIR_HAVE_WORKING_SHUFFLEVECTOR
#define VIR_HAVE_WORKING_SHUFFLEVECTOR 0
#endif


Expand Down Expand Up @@ -72,6 +75,8 @@ namespace vir::meta
struct as_int<T, short, false>
: as_int<T, signed char> {};

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
template <typename T>
struct as_int<T, signed char, false>
#ifdef __SIZEOF_INT128__
Expand All @@ -81,6 +86,7 @@ namespace vir::meta
struct as_int<T, __int128, false>
#endif // __SIZEOF_INT128__
{};
#pragma GCC diagnostic pop

template <typename T>
using as_int_t = typename as_int<T>::type;
Expand Down Expand Up @@ -108,6 +114,8 @@ namespace vir::meta
struct as_unsigned<T, unsigned short, false>
: as_unsigned<T, unsigned char> {};

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
template <typename T>
struct as_unsigned<T, unsigned char, false>
#ifdef __SIZEOF_INT128__
Expand All @@ -117,6 +125,7 @@ namespace vir::meta
struct as_unsigned<T, unsigned __int128, false>
#endif // __SIZEOF_INT128__
{};
#pragma GCC diagnostic pop

template <typename T>
using as_unsigned_t = typename as_unsigned<T>::type;
Expand Down
Loading