google / highway

Performance-portable, length-agnostic SIMD with runtime dispatch
Apache License 2.0
3.97k stars 308 forks source link

no matching function for call to 'IfThenElse' #2269

Closed xiaozhuai closed 1 week ago

xiaozhuai commented 1 week ago

Hi there, my code compile failed on arm64 android, but it can compile on x64 android and arm android. And here is the error message and code. BTW, it can compile on 1.1.0

/Users/xiaozhuai/work/ailive/src/ailive/utils/imgproc.cpp:234:13: error: no matching function for call to 'IfThenElse'
        r = hn::IfThenElse(mask, r, r / a);
            ^~~~~~~~~~~~~~
/Users/xiaozhuai/work/ailive/src/ailive/utils/imgproc.cpp:244:17: note: in instantiation of function template specialization 'ailive::imgproc::N_SVE2::unpremultiply_f32_hwy(float *__restrict, const float *__restrict, int, int)::(anonymous class)::operator()<hwy::N_SVE2::Simd<float, 64, 0>>' requested here
            loop(d, dst_ptr, src_ptr);
                ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:1326:39: note: candidate function not viable: no known conversion from '__SVInt32_t' to 'svbool_t' (aka '__SVBool_t') for 1st argument
HWY_SVE_FOREACH(HWY_SVE_IF_THEN_ELSE, IfThenElse, sel)
                                      ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:185:30: note: expanded from macro 'HWY_SVE_FOREACH'
  HWY_SVE_FOREACH_F(X_MACRO, NAME, OP)
                             ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:149:34: note: expanded from macro 'HWY_SVE_FOREACH_F'
  HWY_SVE_FOREACH_F3264(X_MACRO, NAME, OP)
                                 ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:141:32: note: expanded from macro 'HWY_SVE_FOREACH_F3264'
  HWY_SVE_FOREACH_F32(X_MACRO, NAME, OP)         \
                               ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:102:29: note: expanded from macro 'HWY_SVE_FOREACH_F32'
  X_MACRO(float, f, 32, 16, NAME, OP)
                            ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:1322:7: note: expanded from macro 'HWY_SVE_IF_THEN_ELSE'
      NAME(svbool_t m, HWY_SVE_V(BASE, BITS) yes, HWY_SVE_V(BASE, BITS) no) { \
      ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:1326:39: note: candidate function not viable: no known conversion from '__SVInt32_t' to 'svbool_t' (aka '__SVBool_t') for 1st argument
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:183:30: note: expanded from macro 'HWY_SVE_FOREACH'
  HWY_SVE_FOREACH_U(X_MACRO, NAME, OP)     \
                             ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:129:32: note: expanded from macro 'HWY_SVE_FOREACH_U'
  HWY_SVE_FOREACH_U08(X_MACRO, NAME, OP)     \
                               ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:85:71: note: expanded from macro 'HWY_SVE_FOREACH_U08'
#define HWY_SVE_FOREACH_U08(X_MACRO, NAME, OP) X_MACRO(uint, u, 8, 8, NAME, OP)
                                                                      ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:1322:7: note: expanded from macro 'HWY_SVE_IF_THEN_ELSE'
      NAME(svbool_t m, HWY_SVE_V(BASE, BITS) yes, HWY_SVE_V(BASE, BITS) no) { \
      ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:1326:39: note: candidate function not viable: no known conversion from '__SVInt32_t' to 'svbool_t' (aka '__SVBool_t') for 1st argument
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:183:30: note: expanded from macro 'HWY_SVE_FOREACH'
  HWY_SVE_FOREACH_U(X_MACRO, NAME, OP)     \
                             ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:130:32: note: expanded from macro 'HWY_SVE_FOREACH_U'
  HWY_SVE_FOREACH_U16(X_MACRO, NAME, OP)     \
                               ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:86:72: note: expanded from macro 'HWY_SVE_FOREACH_U16'
#define HWY_SVE_FOREACH_U16(X_MACRO, NAME, OP) X_MACRO(uint, u, 16, 8, NAME, OP)
                                                                       ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:1322:7: note: expanded from macro 'HWY_SVE_IF_THEN_ELSE'
      NAME(svbool_t m, HWY_SVE_V(BASE, BITS) yes, HWY_SVE_V(BASE, BITS) no) { \
      ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:1326:39: note: candidate function not viable: no known conversion from '__SVInt32_t' to 'svbool_t' (aka '__SVBool_t') for 1st argument
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:183:30: note: expanded from macro 'HWY_SVE_FOREACH'
  HWY_SVE_FOREACH_U(X_MACRO, NAME, OP)     \
                             ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:131:32: note: expanded from macro 'HWY_SVE_FOREACH_U'
  HWY_SVE_FOREACH_U32(X_MACRO, NAME, OP)     \
                               ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:88:28: note: expanded from macro 'HWY_SVE_FOREACH_U32'
  X_MACRO(uint, u, 32, 16, NAME, OP)
                           ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:1322:7: note: expanded from macro 'HWY_SVE_IF_THEN_ELSE'
      NAME(svbool_t m, HWY_SVE_V(BASE, BITS) yes, HWY_SVE_V(BASE, BITS) no) { \
      ^
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:1326:39: note: candidate function not viable: no known conversion from '__SVInt32_t' to 'svbool_t' (aka '__SVBool_t') for 1st argument
/opt/vcpkg/installed/arm64-android/include/hwy/ops/arm_sve-inl.h:183:30: note: expanded from macro 'HWY_SVE_FOREACH'
  HWY_SVE_FOREACH_U(X_MACRO, NAME, OP)     \
                             ^
void unpremultiply_f32_hwy(float *HWY_RESTRICT dst, const float *HWY_RESTRICT src,  //
                           int width, int height) {
    // c / a
    constexpr int channels = 4;
    auto *dst_ptr = dst;
    const auto *src_ptr = src;
    const auto *const dst_end = dst_ptr + width * height * channels;
    auto loop = [](const auto d, float *HWY_RESTRICT dst_ptr, const float *HWY_RESTRICT src_ptr) {
        using D = decltype(d);
        hn::Vec<D> r, g, b, a;
        hn::LoadInterleaved4(d, src_ptr, r, g, b, a);

        auto mask = a == hn::Set(d, 0.0f);
        r = hn::IfThenElse(mask, r, r / a);
        g = hn::IfThenElse(mask, g, g / a);
        b = hn::IfThenElse(mask, b, b / a);

        hn::StoreInterleaved4(r, g, b, a, d, dst_ptr);
    };
    {
        constexpr hn::ScalableTag<float> d;
        const size_t N = hn::Lanes(d);
        for (; dst_ptr + N * channels <= dst_end; dst_ptr += N * channels, src_ptr += N * channels) {
            loop(d, dst_ptr, src_ptr);
        }
    }
    {
        constexpr hn::CappedTag<float, 1> d;
        for (; dst_ptr + channels <= dst_end; dst_ptr += channels, src_ptr += channels) {
            loop(d, dst_ptr, src_ptr);
        }
    }
}
jan-wassenberg commented 1 week ago

Hi, your code looks reasonable. The issue is that SVE does not properly support operators; until recently == did not even work at all. It seems they return a vector type instead of the expected svbool_t type. Thus we recommend using Eq() instead. BTW you might want to compute 1.0f/a once and then multiply by that three times?

xiaozhuai commented 1 week ago

Thus we recommend using Eq() instead.

Thanks @jan-wassenberg It works now.

Should I also replace other operators, such as * with hn::Mul and / with hn::Div? Is it recommended to do so?

jan-wassenberg commented 1 week ago

Glad to hear :) Yes, I'd recommend Mul etc. because RVV compilers still did not support operators, last time I checked. But if you never intend to run on RVV, at least the arithmetic operators are probably OK.