blob: 99ae451ffd897bf757c0dcfa40878405340a2650 [file] [log] [blame]
// { dg-do run { target c++26 } }
// { dg-require-effective-target x86 }
#include "test_setup.h"
template <typename V>
requires (V::size() * sizeof(typename V::value_type) <= 70 * 4) // avoid exploding RAM usage
struct Tests<V>
{
using T = typename V::value_type;
using M = typename V::mask_type;
static constexpr int max = sizeof(T) == 8 ? 64 : 32;
ADD_TEST_N(known_shift, 4, std::is_integral_v<T>) {
std::tuple {test_iota<V>},
[]<int N>(auto& t, const V x) {
constexpr int shift = max * (N + 1) / 4 - 1;
constexpr T tmax = std::numeric_limits<T>::max();
constexpr V vshift = T(shift);
const V vshiftx = vshift ^ (x & std::cw<1>);
t.verify(__is_const_known(vshift));
V ref([&](int i) -> T { return x[i] >> shift; });
V refx([&](int i) -> T { return x[i] >> (shift ^ (i & 1)); });
t.verify_equal(x >> shift, ref)("{:d} >> {:d}", x, shift);
t.verify_equal(x >> vshift, ref)("{:d} >> {:d}", x, vshift);
t.verify_equal(x >> vshiftx, refx)("{:d} >> {:d}", x, vshiftx);
const V y = ~x;
ref = V([&](int i) -> T { return T(~x[i]) >> shift; });
refx = V([&](int i) -> T { return T(~x[i]) >> (shift ^ (i & 1)); });
t.verify_equal(y >> shift, ref)("{:d} >> {:d}", y, shift);
t.verify_equal(y >> vshift, ref)("{:d} >> {:d}", y, vshift);
t.verify_equal(y >> vshiftx, refx)("{:d} >> {:d}", y, vshiftx);
const V z = tmax - x;
ref = V([&](int i) -> T { return T(tmax - x[i]) >> shift; });
refx = V([&](int i) -> T { return T(tmax - x[i]) >> (shift ^ (i & 1)); });
t.verify_equal(z >> shift, ref)("{:d} >> {:d}", z, shift);
t.verify_equal(z >> vshift, ref)("{:d} >> {:d}", z, vshift);
t.verify_equal(z >> vshiftx, refx)("{:d} >> {:d}", z, vshiftx);
}
};
ADD_TEST(unknown_shift, std::is_integral_v<T>) {
std::tuple {test_iota<V>},
[](auto& t, const V x) {
for (int shift = 0; shift < max; ++shift)
{
constexpr T tmax = std::numeric_limits<T>::max();
const V vshift = T(shift);
const V vshiftx = vshift ^ (x & std::cw<1>);
t.verify(std::is_constant_evaluated()
|| (!is_const_known(vshift) && !is_const_known(shift)));
V ref([&](int i) -> T { return x[i] >> shift; });
V refx([&](int i) -> T { return x[i] >> (shift ^ (i & 1)); });
t.verify_equal(x >> shift, ref)("{:d} >> {:d}", x, shift);
t.verify_equal(x >> vshift, ref)("{:d} >> {:d}", x, vshift);
t.verify_equal(x >> vshiftx, refx)("{:d} >> {:d}", x, vshiftx);
const V y = ~x;
ref = V([&](int i) -> T { return T(~x[i]) >> shift; });
refx = V([&](int i) -> T { return T(~x[i]) >> (shift ^ (i & 1)); });
t.verify_equal(y >> shift, ref)("{:d} >> {:d}", y, shift);
t.verify_equal(y >> vshift, ref)("{:d} >> {:d}", y, vshift);
t.verify_equal(y >> vshiftx, refx)("{:d} >> {:d}", y, vshiftx);
const V z = tmax - x;
ref = V([&](int i) -> T { return T(tmax - x[i]) >> shift; });
refx = V([&](int i) -> T { return T(tmax - x[i]) >> (shift ^ (i & 1)); });
t.verify_equal(z >> shift, ref)("{:d} >> {:d}", z, shift);
t.verify_equal(z >> vshift, ref)("{:d} >> {:d}", z, vshift);
t.verify_equal(z >> vshiftx, refx)("{:d} >> {:d}", z, vshiftx);
}
}
};
};
template <typename V>
struct Tests
{};
void create_tests()
{
template for (auto t : {char(), short(), unsigned(), 0l, 0ull})
[[maybe_unused]] Tests<simd::vec<decltype(t)>> test;
template for (constexpr int n : {1, 3, 17})
[[maybe_unused]] Tests<simd::vec<int, n>> test;
}