From 5aa9c9562ad077b3a5c814cda1b0fa206e35b91b Mon Sep 17 00:00:00 2001 From: velonica0 <47554626+velonica0@users.noreply.github.com> Date: Fri, 17 Jul 2026 16:47:03 +0800 Subject: [PATCH] Merge pull request #29541 from velonica0:rvv-fix-cvtabs-gcc-build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit core: fix RISC-V GCC build break in cvtabs_32f (#29369 follow-up) #29541 ### Summary `modules/core/src/convert_scale.simd.hpp` does not compile on RISC-V with GCC on current 5.x: ``` convert_scale.simd.hpp:44:13: error: 'useSIMD' was not declared in this scope convert_scale.simd.hpp:45:37: error: 'VECSZ' was not declared in this scope convert_scale.simd.hpp:55:28: error: 'va' was not declared in this scope convert_scale.simd.hpp:55:32: error: 'vb' was not declared in this scope ``` This breaks every RISC-V + GCC build of the core module. ### Root cause In #29369 `cvtabs_32f` ended up with a declaration guard and a usage guard that disagree: ```c #if (CV_SIMD || (CV_SIMD_SCALABLE && !(defined(__GNUC__) && !defined(__clang__)))) // decl v_float32 va = ..., vb = ...; const int VECSZ = ...; const bool useSIMD = ...; #endif ... #if (CV_SIMD || CV_SIMD_SCALABLE) // usage if( useSIMD ) for( ; j < size.width; j += VECSZ ) { ... v_fma(v0, va, vb) ... } ``` On RISC-V `CV_SIMD == 0` and `CV_SIMD_SCALABLE == 1`, so under GCC the first is false and the second is true: the declarations are dropped while the loop using them is still compiled. ### Second commit (independent, droppable) `useSIMD` asks "is this a 128-bit vector machine?" but tests `vlanes() != 8`. `vlanes()` is `VLEN/32 * LMUL`, so the literal `8` encodes both "VLEN == 128" **and** "LMUL == 2" — correct only while `v_float32` stays at LMUL=2. Under #29493 (LMUL=1) the same expression silently becomes "VLEN != 256": disabling SIMD on 256-bit machines and enabling it at VLEN=128, the exact case the workaround exists to avoid. CI cannot catch that regression, since the block is GCC-only. VLEN is not recoverable from the universal intrinsics (every type scales with LMUL, so the factor never cancels), so this asks the hardware: `__riscv_vlenb()*8 != 128`. Behaviour is unchanged today — with LMUL=2, `vlanes() == 8` iff `VLEN == 128`. ### Testing SpaceMIT K3, GCC 15.2, **unmodified LMUL=2 backend** (no #29493 changes involved): | configuration | result | | --- | --- | | 5.x as-is | `opencv_core` fails to build (errors above) | | + commit 1 | builds clean, 0 errors | | + commits 1&2 | builds clean, 0 errors | | `Core_ConvertScale*`, X100 @ VLEN=256 | 4/4 pass (incl. `Core_ConvertScaleAbs/ElemWiseTest.accuracy`) | | `Core_ConvertScale*`, A100 @ VLEN=1024 | 4/4 pass | | `useSIMD == false` path (temporary probe forcing it at VLEN=256) | passes | --- modules/core/src/convert_scale.simd.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/core/src/convert_scale.simd.hpp b/modules/core/src/convert_scale.simd.hpp index 9db95a50b5..9bf092f8af 100644 --- a/modules/core/src/convert_scale.simd.hpp +++ b/modules/core/src/convert_scale.simd.hpp @@ -22,14 +22,14 @@ template inline void cvtabs_32f( const _Ts* src, size_t sstep, _Td* dst, size_t dstep, Size size, float a, float b ) { -// Excluding GNU in CV_SIMD_SCALABLE because of "opencv/issues/26936" -#if (CV_SIMD || (CV_SIMD_SCALABLE && !(defined(__GNUC__) && !defined(__clang__))) ) +#if (CV_SIMD || CV_SIMD_SCALABLE) v_float32 va = vx_setall_f32(a), vb = vx_setall_f32(b); const int VECSZ = VTraits::vlanes()*2; - // GCC miscompiles this scalable block only on VLEN=128 RVV (opencv/issues/26936). - // v_float32 is LMUL=2, so vlanes()==8 means VLEN==128: use scalar there, keep SIMD elsewhere. -#if (CV_SIMD_SCALABLE && defined(__GNUC__) && !defined(__clang__)) - const bool useSIMD = VTraits::vlanes() != 8; + // GCC miscompiles this scalable block only on VLEN=128 RVV (opencv/issues/26936); + // use scalar there, keep SIMD on wider vectors. Ask the hardware for VLEN directly: + // vlanes() would depend on the LMUL the universal intrinsics happen to use. +#if (CV_RVV && CV_SIMD_SCALABLE && defined(__GNUC__) && !defined(__clang__)) + const bool useSIMD = __riscv_vlenb()*8 != 128; #else const bool useSIMD = true; #endif