Sven Tennie pushed to branch wip/supersven/riscv-vectors at Glasgow Haskell Compiler / GHC Commits: 696d1213 by Sven Tennie at 2025-07-04T18:34:51+02:00 Adjust vector check in all.T - - - - - d00766d6 by Sven Tennie at 2025-07-04T19:10:44+02:00 Print vectors to show that the stack is intact - - - - - 897fd7be by Sven Tennie at 2025-07-05T15:56:24+02:00 Check for GCC >= 14 in autoconf - - - - - 6a40bf19 by Sven Tennie at 2025-07-05T19:51:24+02:00 VectorCCallConv test: Test doubles as well - - - - - 8 changed files: - configure.ac - distrib/configure.ac.in - + m4/fp_riscv_check_gcc_version.m4 - testsuite/driver/testlib.py - testsuite/tests/simd/should_run/VectorCCallConv.hs - testsuite/tests/simd/should_run/VectorCCallConv.stdout - testsuite/tests/simd/should_run/VectorCCallConv_c.c - testsuite/tests/simd/should_run/all.T Changes: ===================================== configure.ac ===================================== @@ -612,9 +612,10 @@ AC_SYS_INTERPRETER() dnl ** look for GCC and find out which version dnl Figure out which C compiler to use. Gcc is preferred. -dnl If gcc, make sure it's at least 4.7 +dnl If gcc, make sure it's at least 4.7 (14 for RISC-V 64bit) dnl FP_GCC_VERSION +FP_RISCV_CHECK_GCC_VERSION dnl ** Check support for the extra flags passed by GHC when compiling via C ===================================== distrib/configure.ac.in ===================================== @@ -225,6 +225,7 @@ dnl ** Check gcc version and flags we need to pass it ** FP_GCC_VERSION FP_GCC_SUPPORTS_NO_PIE FP_GCC_SUPPORTS_VIA_C_FLAGS +FP_RISCV_CHECK_GCC_VERSION FPTOOLS_SET_C_LD_FLAGS([target],[CFLAGS],[LDFLAGS],[IGNORE_LINKER_LD_FLAGS],[CPPFLAGS]) FPTOOLS_SET_C_LD_FLAGS([build],[CONF_CC_OPTS_STAGE0],[CONF_GCC_LINKER_OPTS_STAGE0],[CONF_LD_LINKER_OPTS_STAGE0],[CONF_CPP_OPTS_STAGE0]) ===================================== m4/fp_riscv_check_gcc_version.m4 ===================================== @@ -0,0 +1,37 @@ +# FP_RISCV_CHECK_GCC_VERSION +# +# We cannot use all GCC versions that are generally supported: Up to +# (including) GCC 13, GCC does not support the expected C calling convention +# for vectors. Thus, we require at least GCC 14. +# +# Details: GCC 13 expects vector arguments to be passed on stack / by +# reference, though the "Standard Vector Calling Convention Variant" +# (https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.ad...) +# - which is the new default (e.g. for GCC 14) - expects vector arguments in +# registers v8 to v23. I guess, this is due to the "Standard Vector Calling +# Convention Variant" being pretty new. And, the GCC implementors had to make +# up design decissions before this part of the standard has been ratified. +# As long as the calling convention is consistently used for all code, this +# isn't an issue. But, we have to be able to call C functions compiled by GCC +# with code emitted by GHC. + +AC_DEFUN([FP_RISCV_CHECK_GCC_VERSION], [ + AC_REQUIRE([FP_GCC_VERSION]) + AC_REQUIRE([AC_CANONICAL_TARGET]) + # + # Check if target is RISC-V + case "$target" in + riscv64*-*-*) + AC_MSG_NOTICE([Assert GCC version for RISC-V. Detected version is $GccVersion]) + if test -n "$GccVersion"; then + AC_CACHE_CHECK([risc-v version of gcc], [fp_riscv_check_gcc_version], [ + FP_COMPARE_VERSIONS([$GccVersion], [-lt], [14.0], + [AC_MSG_ERROR([Need at least GCC version 14 for RISC-V])], + [AC_MSG_RESULT([good])] + ) + ]) + fi + ;; + # Ignore riscv32*-*-* as we don't have a NCG for RISC-V 32bit targets + esac +]) ===================================== testsuite/driver/testlib.py ===================================== @@ -416,7 +416,7 @@ def req_basic_simd_cpu( name, opts ): - PowerPC with AltiVec (not currently supported) """ - if not (arch('aarch64') or have_cpu_feature('sse2') or have_cpu_feature('zvl128b')): + if not (arch('aarch64') or have_cpu_feature('sse2') or have_cpu_feature('zvl128b')): opts.skip = True def req_fma_cpu( name, opts ): ===================================== testsuite/tests/simd/should_run/VectorCCallConv.hs ===================================== @@ -7,6 +7,7 @@ module Main where import Data.Int +import GHC.Float import GHC.Int import GHC.Prim import System.IO @@ -38,46 +39,151 @@ unpackInt64X2 :: Int64X2# -> (Int64, Int64) unpackInt64X2 v = case unpackInt64X2# v of (# x0, x1 #) -> (I64# x0, I64# x1) +foreign import ccall "printVecs_doublex2_c" + printVecs_doublex2# :: + DoubleX2# -> -- v8 + DoubleX2# -> -- v9 + DoubleX2# -> -- v10 + DoubleX2# -> -- v11 + DoubleX2# -> -- v12 + DoubleX2# -> -- v13 + DoubleX2# -> -- v14 + DoubleX2# -> -- v15 + DoubleX2# -> -- v16 + DoubleX2# -> -- v17 + DoubleX2# -> -- v18 + DoubleX2# -> -- v19 + DoubleX2# -> -- v20 + DoubleX2# -> -- v21 + DoubleX2# -> -- v22 + DoubleX2# -> -- v23 + IO () + +foreign import ccall "return_doubleX2" + return_doubleX2# :: (# #) -> DoubleX2# + +unpackDoubleX2 :: DoubleX2# -> (Double, Double) +unpackDoubleX2 v = case unpackDoubleX2# v of + (# x0, x1 #) -> (D# x0, D# x1) + main :: IO () main = do -- Use some negative values to fill more bits and discover possible overlaps. - let v8 = packInt64X2# (# 0#Int64, -1#Int64 #) - v9 = packInt64X2# (# -2#Int64, 3#Int64 #) - v10 = packInt64X2# (# -4#Int64, 5#Int64 #) - v11 = packInt64X2# (# -6#Int64, 7#Int64 #) - v12 = packInt64X2# (# -8#Int64, 9#Int64 #) - v13 = packInt64X2# (# -10#Int64, 11#Int64 #) - v14 = packInt64X2# (# -12#Int64, 13#Int64 #) - v15 = packInt64X2# (# -14#Int64, 15#Int64 #) - v16 = packInt64X2# (# -16#Int64, 17#Int64 #) - v17 = packInt64X2# (# -18#Int64, 19#Int64 #) - v18 = packInt64X2# (# -20#Int64, 21#Int64 #) - v19 = packInt64X2# (# -22#Int64, 23#Int64 #) - v20 = packInt64X2# (# -24#Int64, 25#Int64 #) - v21 = packInt64X2# (# -26#Int64, 27#Int64 #) - v22 = packInt64X2# (# -28#Int64, 29#Int64 #) - v23 = packInt64X2# (# -30#Int64, 31#Int64 #) - - print "Arguments" + let int_v8 = packInt64X2# (# 0#Int64, -1#Int64 #) + int_v9 = packInt64X2# (# -2#Int64, 3#Int64 #) + int_v10 = packInt64X2# (# -4#Int64, 5#Int64 #) + int_v11 = packInt64X2# (# -6#Int64, 7#Int64 #) + int_v12 = packInt64X2# (# -8#Int64, 9#Int64 #) + int_v13 = packInt64X2# (# -10#Int64, 11#Int64 #) + int_v14 = packInt64X2# (# -12#Int64, 13#Int64 #) + int_v15 = packInt64X2# (# -14#Int64, 15#Int64 #) + int_v16 = packInt64X2# (# -16#Int64, 17#Int64 #) + int_v17 = packInt64X2# (# -18#Int64, 19#Int64 #) + int_v18 = packInt64X2# (# -20#Int64, 21#Int64 #) + int_v19 = packInt64X2# (# -22#Int64, 23#Int64 #) + int_v20 = packInt64X2# (# -24#Int64, 25#Int64 #) + int_v21 = packInt64X2# (# -26#Int64, 27#Int64 #) + int_v22 = packInt64X2# (# -28#Int64, 29#Int64 #) + int_v23 = packInt64X2# (# -30#Int64, 31#Int64 #) + + double_v8 = packDoubleX2# (# 0.0##, -1.0## #) + double_v9 = packDoubleX2# (# -2.0##, 3.0## #) + double_v10 = packDoubleX2# (# -4.0##, 5.0## #) + double_v11 = packDoubleX2# (# -6.0##, 7.0## #) + double_v12 = packDoubleX2# (# -8.0##, 9.0## #) + double_v13 = packDoubleX2# (# -10.0##, 11.0## #) + double_v14 = packDoubleX2# (# -12.0##, 13.0## #) + double_v15 = packDoubleX2# (# -14.0##, 15.0## #) + double_v16 = packDoubleX2# (# -16.0##, 17.0## #) + double_v17 = packDoubleX2# (# -18.0##, 19.0## #) + double_v18 = packDoubleX2# (# -20.0##, 21.0## #) + double_v19 = packDoubleX2# (# -22.0##, 23.0## #) + double_v20 = packDoubleX2# (# -24.0##, 25.0## #) + double_v21 = packDoubleX2# (# -26.0##, 27.0## #) + double_v22 = packDoubleX2# (# -28.0##, 29.0## #) + double_v23 = packDoubleX2# (# -30.0##, 31.0## #) + + print "Arguments (int)" hFlush stdout printVecs_int64x2# - v8 - v9 - v10 - v11 - v12 - v13 - v14 - v15 - v16 - v17 - v18 - v19 - v20 - v21 - v22 - v23 - - print "Return values" + int_v8 + int_v9 + int_v10 + int_v11 + int_v12 + int_v13 + int_v14 + int_v15 + int_v16 + int_v17 + int_v18 + int_v19 + int_v20 + int_v21 + int_v22 + int_v23 + + print "Arguments (double)" + hFlush stdout + printVecs_doublex2# + double_v8 + double_v9 + double_v10 + double_v11 + double_v12 + double_v13 + double_v14 + double_v15 + double_v16 + double_v17 + double_v18 + double_v19 + double_v20 + double_v21 + double_v22 + double_v23 + + print "Return values (int)" let v = return_int64X2# (# #) print $ unpackInt64X2 v + + print "Return values (double)" + let v = return_doubleX2# (# #) + print $ unpackDoubleX2 v + + -- Check that these registers weren't messed up + print "Initial vectors (int)" + print $ unpackInt64X2 int_v8 + print $ unpackInt64X2 int_v9 + print $ unpackInt64X2 int_v10 + print $ unpackInt64X2 int_v11 + print $ unpackInt64X2 int_v12 + print $ unpackInt64X2 int_v13 + print $ unpackInt64X2 int_v14 + print $ unpackInt64X2 int_v15 + print $ unpackInt64X2 int_v16 + print $ unpackInt64X2 int_v17 + print $ unpackInt64X2 int_v18 + print $ unpackInt64X2 int_v19 + print $ unpackInt64X2 int_v20 + print $ unpackInt64X2 int_v21 + print $ unpackInt64X2 int_v22 + print $ unpackInt64X2 int_v23 + + print "Initial vectors (double)" + print $ unpackDoubleX2 double_v8 + print $ unpackDoubleX2 double_v9 + print $ unpackDoubleX2 double_v10 + print $ unpackDoubleX2 double_v11 + print $ unpackDoubleX2 double_v12 + print $ unpackDoubleX2 double_v13 + print $ unpackDoubleX2 double_v14 + print $ unpackDoubleX2 double_v15 + print $ unpackDoubleX2 double_v16 + print $ unpackDoubleX2 double_v17 + print $ unpackDoubleX2 double_v18 + print $ unpackDoubleX2 double_v19 + print $ unpackDoubleX2 double_v20 + print $ unpackDoubleX2 double_v21 + print $ unpackDoubleX2 double_v22 + print $ unpackDoubleX2 double_v23 ===================================== testsuite/tests/simd/should_run/VectorCCallConv.stdout ===================================== @@ -1,4 +1,4 @@ -"Arguments" +"Arguments (int)" [0, -1] [-2, 3] [-4, 5] @@ -15,5 +15,58 @@ [-26, 27] [-28, 29] [-30, 31] -"Return values" +"Arguments (double)" +[0.000000, -1.000000] +[-2.000000, 3.000000] +[-4.000000, 5.000000] +[-6.000000, 7.000000] +[-8.000000, 9.000000] +[-10.000000, 11.000000] +[-12.000000, 13.000000] +[-14.000000, 15.000000] +[-16.000000, 17.000000] +[-18.000000, 19.000000] +[-20.000000, 21.000000] +[-22.000000, 23.000000] +[-24.000000, 25.000000] +[-26.000000, 27.000000] +[-28.000000, 29.000000] +[-30.000000, 31.000000] +"Return values (int)" (-9223372036854775808,9223372036854775807) +"Return values (double)" +(2.2250738585072014e-308,1.7976931348623157e308) +"Initial vectors (int)" +(0,-1) +(-2,3) +(-4,5) +(-6,7) +(-8,9) +(-10,11) +(-12,13) +(-14,15) +(-16,17) +(-18,19) +(-20,21) +(-22,23) +(-24,25) +(-26,27) +(-28,29) +(-30,31) +"Initial vectors (double)" +(0.0,-1.0) +(-2.0,3.0) +(-4.0,5.0) +(-6.0,7.0) +(-8.0,9.0) +(-10.0,11.0) +(-12.0,13.0) +(-14.0,15.0) +(-16.0,17.0) +(-18.0,19.0) +(-20.0,21.0) +(-22.0,23.0) +(-24.0,25.0) +(-26.0,27.0) +(-28.0,29.0) +(-30.0,31.0) ===================================== testsuite/tests/simd/should_run/VectorCCallConv_c.c ===================================== @@ -1,4 +1,5 @@ #include "riscv_vector.h" +#include <float.h> #include <stdio.h> static void printVec_int64(vint64m1_t v, int length) { @@ -44,3 +45,47 @@ vint64m1_t return_int64X2() { int64_t v[] = {INT64_MIN, INT64_MAX}; return __riscv_vle64_v_i64m1(v, 2); } + +static void printVec_double(vfloat64m1_t v, int length) { + // Extract and print elements from the vector register + double temp[length]; // Temporary array to hold vector elements + __riscv_vse64_v_f64m1(temp, v, length); // Store vector to memory + + printf("[%f", temp[0]); + for (int i = 1; i < length; i++) { + printf(", %f", temp[i]); + } + printf("]\n"); + fflush(stdout); +} +// Provide many vectors to enforce stack usage +void printVecs_doublex2_c(vfloat64m1_t v8, vfloat64m1_t v9, vfloat64m1_t v10, + vfloat64m1_t v11, vfloat64m1_t v12, vfloat64m1_t v13, + vfloat64m1_t v14, vfloat64m1_t v15, vfloat64m1_t v16, + vfloat64m1_t v17, vfloat64m1_t v18, vfloat64m1_t v19, + vfloat64m1_t v20, vfloat64m1_t v21, vfloat64m1_t v22, + vfloat64m1_t v23) { + printVec_double(v8, 2); + printVec_double(v9, 2); + printVec_double(v10, 2); + printVec_double(v11, 2); + printVec_double(v12, 2); + printVec_double(v13, 2); + printVec_double(v14, 2); + printVec_double(v15, 2); + printVec_double(v16, 2); + printVec_double(v17, 2); + printVec_double(v18, 2); + printVec_double(v19, 2); + printVec_double(v20, 2); + printVec_double(v21, 2); + printVec_double(v22, 2); + printVec_double(v23, 2); + + fflush(stdout); +} + +vfloat64m1_t return_doubleX2() { + double v[] = {DBL_MIN, DBL_MAX}; + return __riscv_vle64_v_f64m1(v, 2); +} ===================================== testsuite/tests/simd/should_run/all.T ===================================== @@ -26,7 +26,7 @@ def riscvVlen(): elif have_cpu_feature('zvl512b'): return 512 else: - raise Exception("Vector extension not supported by CPU or VLEN too small.") + return 0 # Ensure we set the CPU features we have available. # @@ -35,7 +35,7 @@ def riscvVlen(): # with or without -mavx2. setTestOpts([ # TODO: -optc and -opta should not be required, but provided by the GHC pipeline - when(arch('riscv64'), extra_hc_opts('-mriscv-vlen' + str(riscvVlen()) + " -optc=-march=rv64gv -opta=-march=rv64gv")) + when(arch('riscv64') and (riscvVlen() > 0), extra_hc_opts('-mriscv-vlen' + str(riscvVlen()) + " -optc=-march=rv64gv -opta=-march=rv64gv")) ]) test('simd_insert_baseline', [], compile_and_run, ['']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/80263d354b4743a66c458587ff8d173... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/80263d354b4743a66c458587ff8d173... You're receiving this email because of your account on gitlab.haskell.org.