SPU LLVM: Use ARM USHL for masked infinite shifts
- LLVM can't handle the select pattern we use to avoid poison values for large shifts - So let's just use the intrinsic to avoid poison values altogether for now - https://github.com/llvm/llvm-project/issues/200698
This commit is contained in:
@@ -3694,11 +3694,22 @@ public:
|
|||||||
|
|
||||||
// Infinite-precision shift left
|
// Infinite-precision shift left
|
||||||
template <typename T, typename U, typename CT = llvm_common_t<T, U>>
|
template <typename T, typename U, typename CT = llvm_common_t<T, U>>
|
||||||
auto inf_shl(T&& a, U&& b)
|
value_t<CT> inf_shl(T&& a, U&& b)
|
||||||
{
|
{
|
||||||
static constexpr u32 esz = llvm_value_t<CT>::esize;
|
static constexpr u32 esz = llvm_value_t<CT>::esize;
|
||||||
|
|
||||||
return expr(select(b < esz, a << b, splat<CT>(0)), [](llvm::Value*& value, llvm::Module* _m) -> llvm_match_tuple<T, U>
|
#ifdef ARCH_ARM64
|
||||||
|
auto sh = eval(std::forward<U>(b));
|
||||||
|
auto k = get_known_bits(sh);
|
||||||
|
const auto max_shift = llvm::APInt(k.Zero.getBitWidth(), esz * 2 - 1);
|
||||||
|
|
||||||
|
if ((k.Zero | max_shift).isAllOnes())
|
||||||
|
{
|
||||||
|
return ushl(std::forward<T>(a), sh);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto result = expr(select(b < esz, a << b, splat<CT>(0)), [](llvm::Value*& value, llvm::Module* _m) -> llvm_match_tuple<T, U>
|
||||||
{
|
{
|
||||||
static const auto M = match<CT>();
|
static const auto M = match<CT>();
|
||||||
|
|
||||||
@@ -3716,15 +3727,28 @@ public:
|
|||||||
value = nullptr;
|
value = nullptr;
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return eval(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infinite-precision logical shift right (unsigned)
|
// Infinite-precision logical shift right (unsigned)
|
||||||
template <typename T, typename U, typename CT = llvm_common_t<T, U>>
|
template <typename T, typename U, typename CT = llvm_common_t<T, U>>
|
||||||
auto inf_lshr(T&& a, U&& b)
|
value_t<CT> inf_lshr(T&& a, U&& b)
|
||||||
{
|
{
|
||||||
static constexpr u32 esz = llvm_value_t<CT>::esize;
|
static constexpr u32 esz = llvm_value_t<CT>::esize;
|
||||||
|
|
||||||
return expr(select(b < esz, a >> b, splat<CT>(0)), [](llvm::Value*& value, llvm::Module* _m) -> llvm_match_tuple<T, U>
|
#ifdef ARCH_ARM64
|
||||||
|
auto sh = eval(std::forward<U>(b));
|
||||||
|
auto k = get_known_bits(sh);
|
||||||
|
const auto max_shift = llvm::APInt(k.Zero.getBitWidth(), esz * 2 - 1);
|
||||||
|
|
||||||
|
if ((k.Zero | max_shift).isAllOnes())
|
||||||
|
{
|
||||||
|
return ushl(std::forward<T>(a), -sh);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto result = expr(select(b < esz, a >> b, splat<CT>(0)), [](llvm::Value*& value, llvm::Module* _m) -> llvm_match_tuple<T, U>
|
||||||
{
|
{
|
||||||
static const auto M = match<CT>();
|
static const auto M = match<CT>();
|
||||||
|
|
||||||
@@ -3742,6 +3766,8 @@ public:
|
|||||||
value = nullptr;
|
value = nullptr;
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return eval(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infinite-precision arithmetic shift right (signed)
|
// Infinite-precision arithmetic shift right (signed)
|
||||||
@@ -4021,6 +4047,18 @@ template <typename T1, typename T2, typename T3>
|
|||||||
return sve_mlal<u32[4]>(llvm::Intrinsic::aarch64_sve_umlalt, acc, a, b);
|
return sve_mlal<u32[4]>(llvm::Intrinsic::aarch64_sve_umlalt, acc, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T = llvm_common_t<T1, T2>>
|
||||||
|
value_t<T> ushl(T1 a, T2 b)
|
||||||
|
{
|
||||||
|
value_t<T> result;
|
||||||
|
|
||||||
|
const auto data0 = a.eval(m_ir);
|
||||||
|
const auto data1 = b.eval(m_ir);
|
||||||
|
|
||||||
|
result.value = m_ir->CreateCall(get_intrinsic<T>(llvm::Intrinsic::aarch64_neon_ushl), {data0, data1});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
auto addp(T1 a, T2 b)
|
auto addp(T1 a, T2 b)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user