https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115458
--- Comment #6 from Jeffrey A. Law <law at gcc dot gnu.org> --- Heavily reduced testcase. -O2 -fpermissive -fno-exceptions -std=c++17 -march=rv64gcv -mabi=lp64d typedef char int8_t; typedef unsigned char uint8_t; template <typename> using MakeUnsigned = unsigned char; #pragma riscv intrinsic "vector" template <typename, long> struct Simd { using T = int; template <typename NewT> using Rebind = Simd<NewT, 0>; }; template <typename T> struct ClampNAndPow2 { using type = Simd<T, 1>; }; template <typename T> struct ScalableTagChecker { using type = typename ClampNAndPow2<T>::type; }; template <typename T> struct CappedTagChecker { using type = typename ClampNAndPow2<T>::type; }; template <typename T, int> using ScalableTag = typename ScalableTagChecker<T>::type; template <typename T, long, int> using CappedTag = typename CappedTagChecker<T>::type; template <class D> using TFromD = typename D::T; template <class T, class D> using Rebind = typename D::Rebind<T>; template <class D> using RebindToUnsigned = Rebind<MakeUnsigned<D>, D>; template <class> struct DFromV_t; template <class V> using DFromV = typename DFromV_t<V>::type; template <> struct DFromV_t<vint8m8_t> { using Lane = int8_t; using type = ScalableTag<Lane, 3>; }; template <long N> void Lanes(Simd<int8_t, N>); template <long N> vuint8m8_t Set(Simd<uint8_t, N>, uint8_t arg) { return __riscv_vmv_v_x_u8m8(arg, 0); } template <long N> vint8m8_t Set(Simd<int8_t, N>, int8_t); template <class D> using VFromD = decltype(Set(D(), TFromD<D>())); template <class D> VFromD<D> Zero(D d) { RebindToUnsigned<decltype(d)> du; return BitCast(d, Set(du, 0)); } template <long N> vint8m8_t BitCastFromByte(Simd<int8_t, N>, vuint8m8_t v) { return __riscv_vreinterpret_v_u8m8_i8m8(v); } template <class D, class FromV> VFromD<D> BitCast(D d, FromV v) { return BitCastFromByte(d, v); } vint8m8_t MaskedSubOr(vint8m8_t no, vbool1_t m, vint8m8_t a, vint8m8_t b) { return __riscv_vsub_vv_i8m8_mu(m, no, a, b, 0); } vbool1_t Lt(vint8m8_t a, vint8m8_t b) { return __riscv_vmslt_vv_i8m8_b1(a, b, 0); } template <class D, class V> V InterleaveUpper(D, V, V); template <class D> using Vec = decltype(Zero(D())); template <class V> V IfNegativeThenNegOrUndefIfZero(V mask, V v) { auto zero = Zero(DFromV<V>()); return MaskedSubOr(v, Lt(mask, zero), zero, v); } template <class D> Vec<D> PositiveIota(D); template <class D> void AssertVecEqual(D, Vec<D>, Vec<D>); template <typename T, int kMul, class Test, int kPow2> struct ForeachCappedR { static Do(long, long) { CappedTag<T, kMul, kPow2> d; Test()(T(), d); } }; template <class D> TestMoreThan1LaneIfNegativeThenNegOrUndefIfZero(D d, Vec<D> v2) { Vec<D> v1, v4; Lanes(d); Vec<D> v8 = InterleaveUpper(d, v2, v1); AssertVecEqual(d, v8, IfNegativeThenNegOrUndefIfZero(v4, v8)); Vec<D> zero(IfNegativeThenNegOrUndefIfZero(v4, zero)); AssertVecEqual(d, zero, IfNegativeThenNegOrUndefIfZero(v8, zero)); } struct TestIfNegativeThenNegOrUndefIfZero { template <typename T, class D> operator()(T, D d) { auto v1 = PositiveIota(d), v2(v1), zero = Zero(d), vmin = Set(d, 0), vmax(IfNegativeThenNegOrUndefIfZero(vmin, v1)); AssertVecEqual(d, zero, zero); AssertVecEqual(d, v2, IfNegativeThenNegOrUndefIfZero(vmax, v2)); TestMoreThan1LaneIfNegativeThenNegOrUndefIfZero(d, v2); } }; template <int kPow2> struct ForExtendableVectors { template <typename T> operator()(T) { constexpr kMaxCapped(sizeof(T)); long max_lanes; constexpr long kMul = kMaxCapped; ForeachCappedR<T, kMul, TestIfNegativeThenNegOrUndefIfZero, kPow2>::Do( 1, max_lanes); } }; struct { operator()(char t) { ForExtendableVectors<0>()(t); } } ForSignedTypes_func; ForSignedTypes() { ForSignedTypes_func(int8_t()); }