mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge pull request #29541 from velonica0:rvv-fix-cvtabs-gcc-build
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 |
This commit is contained in:
@@ -22,14 +22,14 @@ template<typename _Ts, typename _Td> 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<v_float32>::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<v_float32>::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
|
||||
|
||||
Reference in New Issue
Block a user