From ede5ce93913e4f20f6112e251fab6a470bade1ea Mon Sep 17 00:00:00 2001 From: Marcin Juszkiewicz Date: Thu, 30 Jul 2026 10:46:45 +0200 Subject: [PATCH] Handle FMA on RISC-V MathCore, Matrix tests fail on RISC-V: 266 - gtest-math-mathcore-stressMathCoreUnit (Failed) Discrepancy in PtEtaPhiMVector operations() : 62919.12458590859 != 62919.124585843325 discr = 5 (Allowed discrepancy is 1.7763568394002505e-13) 300 - gtest-math-matrix-testMatrixTSparse (Failed) Expected equality of these values: m1 Which is: 80-byte object <90-0A 9E-93 FF-FF 00-00 00-00 00-00 00-00 00-02 04-00 00-00 05-00 00-00 01-00 00-00 00-00 00-00 14-00 00-00 05-00 00-00 00-00 00-00 00-00 B0-3C 01-E2 1E-94 FF-FF 00-00 30-26 61-55 55-55 00-00 00-62 60-55 55-55 00-00 A0-2B 61-55 55-55 00-00> m2 Which is: 264-byte object <48-76 56-55 55-55 00-00 00-00 00-00 00-00 00-02 04-00 00-00 05-00 00-00 01-00 00-00 00-00 00-00 14-00 00-00 00-00 00-00 00-00 00-00 00-00 B0-3C 01-00 00-00 03-00 00-00 18-2D 44-54 FB-21 09-40 ... 53-B7 49-9E A1-B8 34-40 40-42 AC-EF 82-70 37-40 E0-09 61-55 55-55 00-00 60-E2 1E-94 FF-FF 00-00 50-2A 61-55 55-55 00-00 20-0A 61-55 55-55 00-00 30-E3 1E-94 FF-FF 00-00 60-E1 1E-94 FF-FF 00-00> 422 - test-stressmathcore (Failed) longtest Based on my experience with similar failures on AArch64 (years ago) I suspected FMA handling. Looked through code and found some places where disabling/handling FMA was needed. --- math/mathcore/CMakeLists.txt | 7 +++++++ math/mathcore/test/stress/testGenVector.cxx | 3 ++- math/matrix/CMakeLists.txt | 7 +++++++ math/matrix/test/CMakeLists.txt | 6 ++++++ test/stressMathCore.cxx | 3 ++- 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/math/mathcore/CMakeLists.txt b/math/mathcore/CMakeLists.txt index 6d88a65284ddc..319051e35335c 100644 --- a/math/mathcore/CMakeLists.txt +++ b/math/mathcore/CMakeLists.txt @@ -190,4 +190,11 @@ ROOT_STANDARD_LIBRARY_PACKAGE(MathCore target_link_libraries(MathCore PRIVATE ${CMAKE_THREAD_LIBS_INIT}) +# Force remove FMA on RISC-V +if(CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64|riscv") + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(MathCore PRIVATE -ffp-contract=off) + endif() +endif() + ROOT_ADD_TEST_SUBDIRECTORY(test) diff --git a/math/mathcore/test/stress/testGenVector.cxx b/math/mathcore/test/stress/testGenVector.cxx index f8b65a09444cd..1d3577dd75e29 100644 --- a/math/mathcore/test/stress/testGenVector.cxx +++ b/math/mathcore/test/stress/testGenVector.cxx @@ -79,7 +79,8 @@ TYPED_TEST_P(GenVectorTest, TestGenVectors) scale = this->fDim * 20; if (this->fDim == 3 && this->V2Name() == "RhoEtaPhiVector") scale *= 12; // for problem with RhoEtaPhi if (this->fDim == 4 && ( this->V2Name() == "PtEtaPhiMVector" || this->V2Name() == "PxPyPzMVector")) { -#if (defined(__arm__) || defined(__arm64__) || defined(__aarch64__) || defined(__s390x__) || defined(__FMA__)) +#if (defined(__arm__) || defined(__arm64__) || defined(__aarch64__) || defined(__s390x__) || defined(__FMA__)) || \ + defined(__riscv) scale *= 1.E7; #else scale *= 10; diff --git a/math/matrix/CMakeLists.txt b/math/matrix/CMakeLists.txt index 64d7e20a6d135..e7ab970408d96 100644 --- a/math/matrix/CMakeLists.txt +++ b/math/matrix/CMakeLists.txt @@ -82,5 +82,12 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Matrix -writeEmptyRootPCM ) +# Force remove FMA on RISC-V +if(CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64|riscv") + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(Matrix PRIVATE -ffp-contract=off) + endif() +endif() + ROOT_ADD_TEST_SUBDIRECTORY(test) diff --git a/math/matrix/test/CMakeLists.txt b/math/matrix/test/CMakeLists.txt index ec88d5deb9579..13a21be919d8c 100644 --- a/math/matrix/test/CMakeLists.txt +++ b/math/matrix/test/CMakeLists.txt @@ -5,5 +5,11 @@ #For the list of contributors see $ROOTSYS / README / CREDITS. ROOT_ADD_GTEST(testMatrixTSparse testMatrixTSparse.cxx LIBRARIES Matrix) +# Disable FMA on RISC-V to avoid 1-ULP differences between sparse and dense paths +if(CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64|riscv") + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(testMatrixTSparse PRIVATE -ffp-contract=off) + endif() +endif() ROOT_ADD_GTEST(testMatrixTDecomp testMatrixTDecomp.cxx LIBRARIES Matrix) ROOT_ADD_GTEST(testMatrixT testMatrixT.cxx LIBRARIES Matrix) \ No newline at end of file diff --git a/test/stressMathCore.cxx b/test/stressMathCore.cxx index 67b9d26dcb67d..467eb0c2ee8f8 100644 --- a/test/stressMathCore.cxx +++ b/test/stressMathCore.cxx @@ -1113,7 +1113,8 @@ int testVector(int ngen, bool testio=false) { scale = Dim*20; if (Dim==3 && VecType::name() == "RhoEtaPhiVector") scale *= 12; // for problem with RhoEtaPhi if (Dim==4 && ( VecType::name() == "PtEtaPhiMVector" || VecType::name() == "PxPyPzMVector")) { -#if (defined(__arm__) || defined(__arm64__) || defined(__aarch64__) || defined(__s390x__) || defined(__FMA__)) +#if (defined(__arm__) || defined(__arm64__) || defined(__aarch64__) || defined(__s390x__) || defined(__FMA__)) || \ + defined(__riscv) scale *= 1.E7; #else scale *= 10;