From 68b7250f40aa8eacd28c9addddb071bc6e02514f Mon Sep 17 00:00:00 2001 From: Katherine Whitlock Date: Sun, 13 Apr 2025 22:53:36 -0400 Subject: [PATCH] Small Fixes --- arm | 3 + include/argon.hpp | 21 +++++ include/argon/argon_full.hpp | 129 ++++++++++++++++------------- include/argon/lane.hpp | 19 +++-- include/argon/vector.hpp | 6 +- include/argon/vectorize/load.hpp | 3 +- test/specs/vectorize/load_spec.cpp | 2 +- 7 files changed, 111 insertions(+), 72 deletions(-) create mode 100644 arm diff --git a/arm b/arm new file mode 100644 index 0000000..dc1da4c --- /dev/null +++ b/arm @@ -0,0 +1,3 @@ +CC=arm-none-eabi-gcc CXX=arm-none-eabi-g++ cmake -B build-m55 -DARGON_ENABLE_TESTING=ON -DARGON_TEST_CPU=M55 -DFETCHCONTENT_SOURCE_DIR_C++SPEC=../cppspec + +cmake --build build-m55 --target gather_spec && sudo qemu-arm -cpu cortex-m55 build-m55/test/specs/gather_spec diff --git a/include/argon.hpp b/include/argon.hpp index f2dd6be..fb41c61 100644 --- a/include/argon.hpp +++ b/include/argon.hpp @@ -6,6 +6,7 @@ #include #include "argon/argon_full.hpp" #include "argon/argon_half.hpp" +#include "argon/helpers/argon_for.hpp" #include "argon/store.hpp" #include "argon/vector.hpp" #include "arm_simd/helpers/multivector.hpp" @@ -52,6 +53,16 @@ ace argon_type reinterpret(V in) { return argon_type{simd::reinterpret(in)}; } +/// @brief Reinterpret a vector of one type to another +/// @tparam argon_type The type to reinterpret to +/// @tparam V The type to reinterpret from +/// @param in The vector to reinterpret +/// @return The reinterpreted vector +template +ace ScalarType bit_cast(ArgonType in) { + return in.template As(); +} + /// @brief Load data to a set of vector lanes from a pointer with interleaving /// @tparam lane The lane to load to /// @tparam stride The stride @@ -162,6 +173,16 @@ ace Argon ternary(Argon condition, Argon true_ } } +template + requires(sizeof(CondType) == sizeof(BranchType)) +ace BranchType ternary(CondType condition, BranchType true_value, BranchType false_value) { + if constexpr (ARGON_USE_COMPILER_EXTENSIONS) { + return condition ? true_value.vec() : false_value.vec(); + } else { + return helpers::ArgonFor_t{condition}.Select(true_value, false_value); + } +} + /// @copydoc ternary template requires std::is_arithmetic_v && diff --git a/include/argon/argon_full.hpp b/include/argon/argon_full.hpp index 3d445f8..ff3064d 100644 --- a/include/argon/argon_full.hpp +++ b/include/argon/argon_full.hpp @@ -19,23 +19,28 @@ #define ace [[nodiscard]] [[gnu::always_inline]] inline #endif -template -class Argon : public argon::Vector> { - using T = argon::Vector>; +template +class Argon : public argon::Vector> { + using T = argon::Vector>; public: - using vector_type = simd::Vec128_t; + using vector_type = simd::Vec128_t; using lane_type = const argon::Lane; static_assert(simd::is_quadword_v); static constexpr size_t bytes = 16; - static constexpr size_t lanes = bytes / sizeof(scalar_type); + static constexpr size_t lanes = bytes / sizeof(ScalarType); - using T::T; + using argon::Vector::Vector; ace Argon(argon::Vector vec) : T{std::move(vec)} {}; - ace Argon(std::array value_list) : T{T::Load(value_list.data())} {}; - ace Argon(ArgonHalf low, ArgonHalf high) : T{Combine(low, high)} {}; + ace Argon(std::array value_list) : T{T::Load(value_list.data())} {}; + ace Argon(ArgonHalf low, ArgonHalf high) : T{Combine(low, high)} {}; + +#ifndef ARGON_PLATFORM_MVE + ace Argon(argon::Lane b) : T{b} {}; + ace Argon(argon::ConstLane<0, vector_type> b) : T{b} {}; +#endif template ace Argon(argon::Lane b) : T{b} {}; @@ -46,142 +51,142 @@ class Argon : public argon::Vector> { } #ifndef ARGON_PLATFORM_MVE - ace static Argon Combine(ArgonHalf low, ArgonHalf high) { + ace static Argon Combine(ArgonHalf low, ArgonHalf high) { return simd::combine(low, high); } - ace Argon Reverse() { + ace Argon Reverse() { auto rev_half = this->Reverse64bit(); return Combine(rev_half.GetHigh(), rev_half.GetLow()); } template - requires argon::helpers::has_smaller_v && - std::is_same_v::type> - ace Argon MultiplyAddLong(ArgonHalf b, ArgonHalf c) { + requires argon::helpers::has_smaller_v && + std::is_same_v::type> + ace Argon MultiplyAddLong(ArgonHalf b, ArgonHalf c) { return simd::multiply_add_long(this->vec_, b, c); } template - requires argon::helpers::has_smaller_v && - std::is_same_v>> - ace Argon MultiplyAddLong(ArgonHalf b, C c) { + requires argon::helpers::has_smaller_v && + std::is_same_v>> + ace Argon MultiplyAddLong(ArgonHalf b, C c) { return simd::multiply_add_long(this->vec_, b, c); } template - requires argon::helpers::has_smaller_v && - std::is_same_v::type> - ace Argon MultiplyAddLong(ArgonHalf b, U c) { + requires argon::helpers::has_smaller_v && + std::is_same_v::type> + ace Argon MultiplyAddLong(ArgonHalf b, U c) { return simd::multiply_add_long(this->vec_, b, c); } template - requires argon::helpers::has_smaller_v && - std::is_same_v::type> - ace Argon MultiplyAddLong(ArgonHalf b, typename ArgonHalf::lane_type c) { + requires argon::helpers::has_smaller_v && + std::is_same_v::type> + ace Argon MultiplyAddLong(ArgonHalf b, typename ArgonHalf::lane_type c) { return simd::multiply_add_long(this->vec_, b, c.vec(), c.lane()); } template - requires argon::helpers::has_smaller_v && - std::is_same_v::type> - ace Argon MultiplySubtractLong(ArgonHalf b, ArgonHalf c) { + requires argon::helpers::has_smaller_v && + std::is_same_v::type> + ace Argon MultiplySubtractLong(ArgonHalf b, ArgonHalf c) { return simd::multiply_subtract_long(this->vec_, b, c); } template - requires argon::helpers::has_smaller_v && - std::is_same_v::type> - ace Argon MultiplySubtractLong(ArgonHalf b, U c) { + requires argon::helpers::has_smaller_v && + std::is_same_v::type> + ace Argon MultiplySubtractLong(ArgonHalf b, U c) { return simd::multiply_subtract_long(this->vec_, b, c); } template - requires argon::helpers::has_smaller_v && - std::is_same_v::type> - ace Argon MultiplySubtractLong(ArgonHalf b, typename ArgonHalf::lane_type c) { + requires argon::helpers::has_smaller_v && + std::is_same_v::type> + ace Argon MultiplySubtractLong(ArgonHalf b, typename ArgonHalf::lane_type c) { return simd::multiply_subtract_long(this->vec_, b, c.vec(), c.lane()); } - ace auto AddNarrow(Argon b) const - requires argon::helpers::has_smaller_v + ace auto AddNarrow(Argon b) const + requires argon::helpers::has_smaller_v { auto result = simd::add_narrow(this->vec_, b); return argon::helpers::ArgonFor_t{result}; } - ace auto AddRoundNarrow(Argon b) const - requires argon::helpers::has_smaller_v + ace auto AddRoundNarrow(Argon b) const + requires argon::helpers::has_smaller_v { auto result = simd::add_round_narrow(this->vec_, b); return argon::helpers::ArgonFor_t{result}; } - ace auto SubtractNarrow(Argon b) const - requires argon::helpers::has_smaller_v + ace auto SubtractNarrow(Argon b) const + requires argon::helpers::has_smaller_v { auto result = simd::subtract_narrow(this->vec_, b); return argon::helpers::ArgonFor_t{result}; } - ace auto SubtractRoundNarrow(Argon b) const - requires argon::helpers::has_smaller_v + ace auto SubtractRoundNarrow(Argon b) const + requires argon::helpers::has_smaller_v { auto result = simd::subtract_round_narrow(this->vec_, b); return argon::helpers::ArgonFor_t{result}; } template - requires argon::helpers::has_smaller_v + requires argon::helpers::has_smaller_v ace auto ShiftRightNarrow() const { auto result = simd::shift_right_narrow(this->vec_); return argon::helpers::ArgonFor_t{result}; } template - requires argon::helpers::has_smaller_v + requires argon::helpers::has_smaller_v ace auto ShiftRightSaturateNarrow() const { auto result = simd::shift_right_saturate_narrow(this->vec_); return argon::helpers::ArgonFor_t{result}; } template - requires argon::helpers::has_smaller_v + requires argon::helpers::has_smaller_v ace auto ShiftRightRoundSaturateNarrow() const { auto result = simd::shift_right_round_saturate_narrow(this->vec_); return argon::helpers::ArgonFor_t{result}; } template - requires argon::helpers::has_smaller_v + requires argon::helpers::has_smaller_v ace auto ShiftRightRoundNarrow() const { auto result = simd::shift_right_round_narrow(this->vec_); return argon::helpers::ArgonFor_t{result}; } ace auto Narrow() const - requires argon::helpers::has_smaller_v + requires argon::helpers::has_smaller_v { auto result = simd::move_narrow(this->vec_); return argon::helpers::ArgonFor_t{result}; } ace auto SaturateNarrow() const - requires argon::helpers::has_smaller_v + requires argon::helpers::has_smaller_v { auto result = simd::move_saturate_narrow(this->vec_); return argon::helpers::ArgonFor_t{result}; } template - requires argon::helpers::has_smaller_v && - std::is_same_v> - ace Argon MultiplyDoubleAddSaturateLong(ArgonHalf b, ArgonHalf c) { + requires argon::helpers::has_smaller_v && + std::is_same_v> + ace Argon MultiplyDoubleAddSaturateLong(ArgonHalf b, ArgonHalf c) { return neon::multiply_double_add_saturate_long(this->vec_, b, c); } - ace ArgonHalf GetHigh() const { return simd::get_high(this->vec_); } - ace ArgonHalf GetLow() const { return simd::get_low(this->vec_); } + ace ArgonHalf GetHigh() const { return simd::get_high(this->vec_); } + ace ArgonHalf GetLow() const { return simd::get_low(this->vec_); } #endif template @@ -201,13 +206,13 @@ class Argon : public argon::Vector> { } } - ace Argon Reverse() const { - Argon rev = this->Reverse64bit(); // rev within dword - return Argon{rev.GetHigh(), rev.GetLow()}; // swap dwords + ace Argon Reverse() const { + Argon rev = this->Reverse64bit(); // rev within dword + return Argon{rev.GetHigh(), rev.GetLow()}; // swap dwords } template - scalar_type Reduce(CommutableOpType op) { + ScalarType Reduce(CommutableOpType op) { auto rev = this->SwapDoublewords(); auto sum = op(*this, rev); if constexpr (lanes == 16) { @@ -222,7 +227,7 @@ class Argon : public argon::Vector> { return sum[0]; } - scalar_type ReduceAdd() { + ScalarType ReduceAdd() { #ifdef __aarch64__ return simd::reduce_add(this->vec_); #else @@ -230,7 +235,7 @@ class Argon : public argon::Vector> { #endif } - scalar_type ReduceMax() { + ScalarType ReduceMax() { #ifdef __aarch64__ return simd::reduce_max(this->vec_); #else @@ -238,7 +243,7 @@ class Argon : public argon::Vector> { #endif } - scalar_type ReduceMin() { + ScalarType ReduceMin() { #ifdef __aarch64__ return simd::reduce_min(this->vec_); #else @@ -248,7 +253,7 @@ class Argon : public argon::Vector> { } #ifndef ARGON_PLATFORM_MVE - ace Argon SwapDoublewords() { return Combine(GetHigh(), GetLow()); } + ace Argon SwapDoublewords() { return Combine(GetHigh(), GetLow()); } #endif }; @@ -257,6 +262,14 @@ template // Argon(arg_types...) -> Argon; Argon(arg_types...) -> Argon>>; +#ifndef ARGON_PLATFORM_MVE +template +Argon(argon::Lane) -> Argon>; + +template +Argon(argon::ConstLane<0, VectorType>) -> Argon>; +#endif + template requires std::is_scalar_v Argon(ScalarType) -> Argon; diff --git a/include/argon/lane.hpp b/include/argon/lane.hpp index acc477f..f27f896 100644 --- a/include/argon/lane.hpp +++ b/include/argon/lane.hpp @@ -1,6 +1,7 @@ #pragma once #include "arm_simd.hpp" #include "arm_simd/helpers/scalar.hpp" +#include "arm_simd/helpers/vec64.hpp" #include "features.h" #include "helpers/argon_for.hpp" @@ -64,17 +65,17 @@ class ConstLane { ace scalar_type Get() const { return simd::get_lane(vec_); } #if __ARM_ARCH >= 8 - ace VectorType& vec() { return vec_; } + ace VectorType vec() { return vec_; } ace const int lane() { return LaneIndex; } #else - ace VectorType& vec() { + ace neon::Vec64_t vec() { if constexpr (simd::is_doubleword_v) { return vec_; } else if constexpr (simd::is_quadword_v) { - if (LaneIndex >= ArgonHalf::lanes) { - return simd::get_high(vec()); + if constexpr (LaneIndex >= ArgonHalf::lanes) { + return simd::get_high(vec_); } else { - return simd::get_low(vec()); + return simd::get_low(vec_); } } } @@ -118,17 +119,17 @@ class Lane { ace operator scalar_type() const { return Get(); } #if __ARM_ARCH >= 8 - ace VectorType& vec() { return vec_; } + ace VectorType vec() { return vec_; } ace const int lane() { return lane_; } #else - ace VectorType& vec() { + ace neon::Vec64_t vec() { if constexpr (simd::is_doubleword_v) { return vec_; } else if constexpr (simd::is_quadword_v) { if (lane_ >= ArgonHalf::lanes) { - return simd::get_high(vec()); + return simd::get_high(vec_); } else { - return simd::get_low(vec()); + return simd::get_low(vec_); } } } diff --git a/include/argon/vector.hpp b/include/argon/vector.hpp index 5459744..3e89053 100644 --- a/include/argon/vector.hpp +++ b/include/argon/vector.hpp @@ -124,7 +124,7 @@ class Vector { #ifdef ARGON_PLATFORM_MVE return simd::duplicate(lane.Get()); #else - return simd::duplicate_lane(lane.vec(), lane.lane()); + return simd::duplicate_lane(lane.vec(), lane.lane()); #endif } @@ -138,9 +138,9 @@ class Vector { return simd::duplicate(lane.Get()); #else if constexpr (simd::is_quadword_v) { - return simd::duplicate_lane_quad(lane.vec()); + return simd::duplicate_lane_quad(lane.vec()); } else { - return simd::duplicate_lane(lane.vec()); + return simd::duplicate_lane(lane.vec()); } #endif } diff --git a/include/argon/vectorize/load.hpp b/include/argon/vectorize/load.hpp index ae86afc..4f2d2ee 100644 --- a/include/argon/vectorize/load.hpp +++ b/include/argon/vectorize/load.hpp @@ -160,7 +160,8 @@ struct load : std::ranges::view_interface> { static_assert(std::bidirectional_iterator); static_assert(std::input_iterator); - using iterator = LoadIterator; ///< The iterator type for the range. + using iterator = LoadIterator; ///< The iterator type for the range. + using sentinel = const ScalarType*; ///< The sentinel type for the range. /// @brief Returns an iterator to the beginning of the range. /// @return An iterator to the beginning of the range. diff --git a/test/specs/vectorize/load_spec.cpp b/test/specs/vectorize/load_spec.cpp index 09d6318..bda6fb2 100644 --- a/test/specs/vectorize/load_spec.cpp +++ b/test/specs/vectorize/load_spec.cpp @@ -16,7 +16,7 @@ auto vectorize_load = describe("vectorize_load", ${ using element_type = int16_t; std::array vals; auto vec = argon::vectorize::load(vals); - expect(std::is_same_v).to_be_true(); + expect(std::is_same_v::sentinel>).to_be_true(); }); it("can access all elements of vals", _{