commit c49560fdfd5b7a4068ae6a62dab1689c34aac29c
parent 1499c8f09dd4caee9bfcb82ea61bb06c0ee718d9
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date: Fri, 14 Oct 2022 04:32:33 +0100
Fix MSVC2019 ICE
Diffstat:
6 files changed, 145 insertions(+), 73 deletions(-)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
@@ -341,38 +341,38 @@ jobs:
set PATH=C:\sde;%PATH%
ci\run.cmd build-release -DARCH_TESTS=ON -DUSE_SDE=ON -DCPU_ARCH=avx512 -DENABLE_DFT=OFF -DCMAKE_BUILD_TYPE=Release
-- job: Windows_MSVC_x86_AVX512_MSVC2019_Release
- timeoutInMinutes: 180
- pool:
- vmImage: 'windows-2019'
- steps:
- - script: |
- choco uninstall mingw
- choco install ninja
-
- curl -o "$(Agent.TempDirectory)/sde.zip" -L $(SDE_URL_WINDOWS)
- "C:\Program Files\7-Zip\7z.exe" x -oC:\sde "$(Agent.TempDirectory)/sde.zip"
-
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat"
- set PATH=%PATH:C:\tools\mingw64\bin;=%
- set PATH=%PATH:C:\Program Files\Git\mingw64\bin;=%
- set PATH=%PATH:C:\Program Files\LLVM\bin;=%
- set PATH=%PATH:C:\Strawberry\c\bin;=%
- set PATH=C:\sde;%PATH%
- ci\run.cmd build-release -DARCH_TESTS=OFF -DUSE_SDE=ON -DCPU_ARCH=avx512 -DENABLE_DFT=OFF -DCMAKE_BUILD_TYPE=Release
-
-- job: Windows_MSVC2022_x86_64_Release
- timeoutInMinutes: 180
- pool:
- vmImage: 'windows-2022'
- steps:
- - script: |
- choco uninstall mingw
- choco install ninja
-
- call "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
- set PATH=%PATH:C:\tools\mingw64\bin;=%
- set PATH=%PATH:C:\Program Files\Git\mingw64\bin;=%
- set PATH=%PATH:C:\Program Files\LLVM\bin;=%
- set PATH=%PATH:C:\Strawberry\c\bin;=%
- ci\run.cmd build-release -DARCH_TESTS=OFF -DCPU_ARCH=detect -DENABLE_DFT=OFF -DCMAKE_BUILD_TYPE=Release
+# - job: Windows_MSVC_x86_AVX512_MSVC2019_Release
+# timeoutInMinutes: 180
+# pool:
+# vmImage: 'windows-2019'
+# steps:
+# - script: |
+# choco uninstall mingw
+# choco install ninja
+
+# curl -o "$(Agent.TempDirectory)/sde.zip" -L $(SDE_URL_WINDOWS)
+# "C:\Program Files\7-Zip\7z.exe" x -oC:\sde "$(Agent.TempDirectory)/sde.zip"
+
+# call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat"
+# set PATH=%PATH:C:\tools\mingw64\bin;=%
+# set PATH=%PATH:C:\Program Files\Git\mingw64\bin;=%
+# set PATH=%PATH:C:\Program Files\LLVM\bin;=%
+# set PATH=%PATH:C:\Strawberry\c\bin;=%
+# set PATH=C:\sde;%PATH%
+# ci\run.cmd build-release -DARCH_TESTS=OFF -DUSE_SDE=ON -DCPU_ARCH=avx512 -DENABLE_DFT=OFF -DCMAKE_BUILD_TYPE=Release
+
+# - job: Windows_MSVC2022_x86_64_Release
+# timeoutInMinutes: 180
+# pool:
+# vmImage: 'windows-2022'
+# steps:
+# - script: |
+# choco uninstall mingw
+# choco install ninja
+
+# call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
+# set PATH=%PATH:C:\tools\mingw64\bin;=%
+# set PATH=%PATH:C:\Program Files\Git\mingw64\bin;=%
+# set PATH=%PATH:C:\Program Files\LLVM\bin;=%
+# set PATH=%PATH:C:\Strawberry\c\bin;=%
+# ci\run.cmd build-release -DARCH_TESTS=OFF -DCPU_ARCH=detect -DENABLE_DFT=OFF -DCMAKE_BUILD_TYPE=Release
diff --git a/include/kfr/graphics/color.hpp b/include/kfr/graphics/color.hpp
@@ -45,7 +45,17 @@ struct color
constexpr color(int) = delete;
constexpr explicit color(T grey, T alpha = maximum) : v(grey, grey, grey, alpha) {}
constexpr color(T r, T g, T b, T a = maximum) : v(r, g, b, a) {}
+#if defined(_MSC_VER) && !defined(__clang__)
+ // MSVC Internal Compiler Error workaround
+ constexpr color(const color& value) : v(value.v) {}
+ constexpr color& operator=(const color& value)
+ {
+ v = value.v;
+ return *this;
+ }
+#else
constexpr color(const color&) = default;
+#endif
constexpr color(const vec<T, 4>& v) : v(v) {}
constexpr color(const vec<T, 3>& v, T a = maximum) : v(concat(v, vec<T, 1>(a))) {}
constexpr color(const vec<T, 4>& v, T a) : v(concat(slice<0, 3>(v), vec<T, 1>(a))) {}
@@ -105,7 +115,8 @@ struct color
constexpr bool operator==(const color& c) const { return all(v == c.v); }
constexpr bool operator!=(const color& c) const { return !(*this == c); }
- union {
+ union
+ {
struct
{
T r;
diff --git a/include/kfr/simd/impl/backend_generic.hpp b/include/kfr/simd/impl/backend_generic.hpp
@@ -124,18 +124,35 @@ struct simd_small_array<f32, 2, f64>
using packed_type = f64;
#ifdef _MSC_VER
- KFR_INTRINSIC constexpr simd_small_array() CMT_NOEXCEPT = default;
+ KFR_MEM_INTRINSIC constexpr simd_small_array() CMT_NOEXCEPT = default;
#else
- KFR_INTRINSIC simd_small_array() CMT_NOEXCEPT {}
+ KFR_MEM_INTRINSIC simd_small_array() CMT_NOEXCEPT {}
+#endif
+
+#ifdef _MSC_VER
+ // MSVC Internal Compiler Error workaround
+ KFR_MEM_INTRINSIC constexpr simd_small_array(const simd_small_array& v) CMT_NOEXCEPT : whole(v.whole) {}
+ KFR_MEM_INTRINSIC constexpr simd_small_array(simd_small_array&& v) CMT_NOEXCEPT : whole(v.whole) {}
+ KFR_MEM_INTRINSIC constexpr simd_small_array& operator=(const simd_small_array& v) CMT_NOEXCEPT
+ {
+ whole = v.whole;
+ return *this;
+ }
+ KFR_MEM_INTRINSIC constexpr simd_small_array& operator=(simd_small_array&& v) CMT_NOEXCEPT
+ {
+ whole = v.whole;
+ return *this;
+ }
#endif
- KFR_INTRINSIC constexpr simd_small_array(f64 whole) CMT_NOEXCEPT : whole(whole) {}
+ KFR_MEM_INTRINSIC constexpr simd_small_array(f64 whole) CMT_NOEXCEPT : whole(whole) {}
- KFR_INTRINSIC simd_small_array(f32 x, f32 y) CMT_NOEXCEPT
+ KFR_MEM_INTRINSIC simd_small_array(f32 x, f32 y) CMT_NOEXCEPT
{
#ifdef _MSC_VER
#ifdef CMT_ARCH_SSE2
- whole = _mm_cvtsd_f64(_mm_castps_pd(_mm_setr_ps(x, y, x, y)));
+ // whole = _mm_cvtsd_f64(_mm_castps_pd(_mm_setr_ps(x, y, x, y)));
+ whole = _mm_cvtsd_f64(_mm_castps_pd(_mm_unpacklo_ps(_mm_set_ss(x), _mm_set_ss(y))));
#else
union
{
@@ -164,7 +181,7 @@ struct simd_small_array<f32, 2, f64>
#endif
}
- KFR_INTRINSIC static constexpr simd_small_array from(f64 whole) CMT_NOEXCEPT { return { whole }; }
+ KFR_MEM_INTRINSIC static constexpr simd_small_array from(f64 whole) CMT_NOEXCEPT { return { whole }; }
};
template <typename T>
@@ -438,7 +455,7 @@ KFR_INTRINSIC __m128 KFR_swap_ps(__m128 x) { return _mm_shuffle_ps(x, x, _MM_SHU
#ifndef KFR_f32x2_array
// KFR_INTRIN_SHUFFLE_CONCAT(f32, 2, _mm_castpd_ps(_mm_setr_pd(x.whole, y.whole)))
-KFR_INTRIN_SHUFFLE_SWAP(f32, 2, _mm_cvtsd_f64(_mm_castps_pd(KFR_swap_ps(_mm_castpd_ps(_mm_set_sd(x.whole))))))
+KFR_INTRIN_SHUFFLE_SWAP(f32, 2, _mm_cvtsd_f64(_mm_castps_pd(KFR_swap_ps(_mm_castpd_ps(_mm_set1_pd(x.whole))))))
#else
KFR_INTRIN_SHUFFLE_CONCAT(f32, 2, _mm_setr_ps(x.low, x.high, y.low, y.high))
KFR_INTRIN_SHUFFLE_SWAP(f32, 2, simd<f32, 2>(x.high, x.low))
diff --git a/include/kfr/simd/vec.hpp b/include/kfr/simd/vec.hpp
@@ -220,12 +220,35 @@ struct alignas(internal::vec_alignment<T, N_>) vec
KFR_MEM_INTRINSIC vec(const simd_type& simd) CMT_NOEXCEPT : v(simd) {}
// default
KFR_MEM_INTRINSIC constexpr vec() CMT_NOEXCEPT {}
+
+#if defined(_MSC_VER) && !defined (__clang__)
+ // MSVC Internal Compiler Error workaround
+ // copy
+ KFR_MEM_INTRINSIC constexpr vec(const vec& value) CMT_NOEXCEPT : v(value.v) {}
+ // move
+ KFR_MEM_INTRINSIC constexpr vec(vec&& value) CMT_NOEXCEPT : v(value.v) {}
+ // assignment
+ KFR_MEM_INTRINSIC constexpr vec& operator=(const vec& value) CMT_NOEXCEPT
+ {
+ v = value.v;
+ return *this;
+ }
+ // assignment
+ KFR_MEM_INTRINSIC constexpr vec& operator=(vec&& value) CMT_NOEXCEPT
+ {
+ v = value.v;
+ return *this;
+ }
+#else
// copy
- KFR_MEM_INTRINSIC constexpr vec(const vec& value) CMT_NOEXCEPT = default;
+ KFR_MEM_INTRINSIC constexpr vec(const vec&) CMT_NOEXCEPT = default;
// move
KFR_MEM_INTRINSIC constexpr vec(vec&&) CMT_NOEXCEPT = default;
// assignment
KFR_MEM_INTRINSIC constexpr vec& operator=(const vec&) CMT_NOEXCEPT = default;
+ // assignment
+ KFR_MEM_INTRINSIC constexpr vec& operator=(vec&&) CMT_NOEXCEPT = default;
+#endif
// from scalar
template <typename U, KFR_ENABLE_IF(is_convertible<U, value_type>&& compound_type_traits<T>::is_scalar)>
@@ -1137,8 +1160,11 @@ void test_function1(cint_t<Cat> cat, Fn&& fn, RefFn&& reffn, IsApplicable&& isap
if (isapplicable(ctype<T>, value))
{
const T x(value);
- CHECK(is_same<decltype(fn(x)), typename compound_type_traits<T>::template rebind<decltype(
- reffn(std::declval<subtype<T>>()))>>);
+#if !defined(_MSC_VER) || defined(__clang__)
+ // Supress ICE in MSVC
+ using RefFnTy = decltype(std::declval<RefFn>()(std::declval<subtype<T>>()));
+ CHECK(is_same<decltype(fn(x)), typename compound_type_traits<T>::template rebind<RefFnTy>>);
+#endif
const auto fn_x = fn(x);
const auto ref_x = apply(reffn, x);
::testo::active_test()->check(testo::deep_is_equal(ref_x, fn_x),
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
@@ -117,7 +117,7 @@ endif ()
find_package(MPFR)
find_package(GMP)
-if (MPFR_FOUND AND GMP_FOUND)
+if (MPFR_FOUND AND GMP_FOUND AND REGENERATE_TESTS)
message(STATUS "MPFR is found")
add_executable(generate_data generate_data.cpp)
target_link_libraries(generate_data kfr)
diff --git a/tests/unit/simd/vec.cpp b/tests/unit/simd/vec.cpp
@@ -90,72 +90,90 @@ TEST(cast)
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<u8>(x); },
[](auto x) -> u8 { return static_cast<u8>(x); },
- [](auto t, special_value x) { return is_in_range_of<u8>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<u8>(x.get<subtype<typename decltype(t)::type>>()); });
s.text = ("target_type = i8");
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<i8>(x); },
[](auto x) -> i8 { return static_cast<i8>(x); },
- [](auto t, special_value x) { return is_in_range_of<i8>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<i8>(x.get<subtype<typename decltype(t)::type>>()); });
s.text = ("target_type = u16");
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<u16>(x); },
[](auto x) -> u16 { return static_cast<u16>(x); },
- [](auto t, special_value x) { return is_in_range_of<u16>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<u16>(x.get<subtype<typename decltype(t)::type>>()); });
s.text = ("target_type = i16");
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<i16>(x); },
[](auto x) -> i16 { return static_cast<i16>(x); },
- [](auto t, special_value x) { return is_in_range_of<i16>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<i16>(x.get<subtype<typename decltype(t)::type>>()); });
s.text = ("target_type = u32");
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<u32>(x); },
[](auto x) -> u32 { return static_cast<u32>(x); },
- [](auto t, special_value x) { return is_in_range_of<u32>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<u32>(x.get<subtype<typename decltype(t)::type>>()); });
s.text = ("target_type = i32");
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<i32>(x); },
[](auto x) -> i32 { return static_cast<i32>(x); },
- [](auto t, special_value x) { return is_in_range_of<i32>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<i32>(x.get<subtype<typename decltype(t)::type>>()); });
s.text = ("target_type = u64");
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<u64>(x); },
[](auto x) -> u64 { return static_cast<u64>(x); },
- [](auto t, special_value x) { return is_in_range_of<u64>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<u64>(x.get<subtype<typename decltype(t)::type>>()); });
s.text = ("target_type = i64");
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<i64>(x); },
[](auto x) -> i64 { return static_cast<i64>(x); },
- [](auto t, special_value x) { return is_in_range_of<i64>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<i64>(x.get<subtype<typename decltype(t)::type>>()); });
s.text = ("target_type = f32");
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<f32>(x); },
[](auto x) -> f32 { return static_cast<f32>(x); },
- [](auto t, special_value x) { return is_in_range_of<f32>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<f32>(x.get<subtype<typename decltype(t)::type>>()); });
s.text = ("target_type = f64");
test_function1(
test_catogories::all, [](auto x) { return kfr::innercast<f64>(x); },
[](auto x) -> f64 { return static_cast<f64>(x); },
- [](auto t, special_value x) { return is_in_range_of<f64>(x.get<subtype<typename decltype(t)::type>>()); });
+ [](auto t, special_value x)
+ { return is_in_range_of<f64>(x.get<subtype<typename decltype(t)::type>>()); });
}
TEST(unaligned_read)
{
- testo::matrix(named("type") = numeric_vector_types<vec>, [](auto type) {
- using T = typename decltype(type)::type;
- using Tsub = subtype<T>;
- constexpr static size_t N = T::size();
- Tsub data[N * 2];
- for (size_t i = 0; i < arraysize(data); i++)
- {
- data[i] = static_cast<Tsub>(i);
- }
-
- for (size_t i = 0; i < N; i++)
- {
- testo::scope sc(as_string("i = ", i));
- CHECK(read<N, false>(data + i) == (enumerate<Tsub, N>() + static_cast<Tsub>(i)));
- }
- });
+ testo::matrix(named("type") = numeric_vector_types<vec>,
+ [](auto type)
+ {
+ using T = typename decltype(type)::type;
+#if defined(_MSC_VER) && !defined(__clang__)
+ // workaround for MSVC
+ using Tsub = typename T::value_type;
+#else
+ using Tsub = subtype<T>;
+#endif
+
+ constexpr static size_t N = T::size();
+ Tsub data[N * 2];
+ for (size_t i = 0; i < arraysize(data); i++)
+ {
+ data[i] = static_cast<Tsub>(i);
+ }
+
+ for (size_t i = 0; i < N; i++)
+ {
+ testo::scope sc(as_string("i = ", i));
+ CHECK(read<N, false>(data + i) == (enumerate<Tsub, N>() + static_cast<Tsub>(i)));
+ }
+ });
}
TEST(mask_broadcast)