diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a23e1258b..7f0116012f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,10 @@ option(BUILD_ENABLE_AVX512 "Enable build with AVX512 at compile time" OFF) +option(BUILD_ENABLE_RVV + "Enable build with RISC-V Vector Extension at compile time" + OFF) + option(ORC_PACKAGE_KIND "Arbitrary string that identifies the kind of package" "") @@ -133,7 +137,13 @@ if (BUILD_ENABLE_AVX512 AND NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64|X86|x86|i set (BUILD_ENABLE_AVX512 "OFF") endif () +if (BUILD_ENABLE_RVV AND NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64|riscv")) + message(WARNING "Only RISC-V platform support RVV") + set (BUILD_ENABLE_RVV "OFF") +endif () + message(STATUS "BUILD_ENABLE_AVX512: ${BUILD_ENABLE_AVX512}") +message(STATUS "BUILD_ENABLE_RVV: ${BUILD_ENABLE_RVV}") # # macOS doesn't fully support AVX512, it has a different way dealing with AVX512 than Windows and Linux. # @@ -143,6 +153,10 @@ if (BUILD_ENABLE_AVX512 AND NOT APPLE) INCLUDE(ConfigSimdLevel) endif () +if (BUILD_ENABLE_RVV) + INCLUDE(ConfigSimdLevel) +endif () + set (EXAMPLE_DIRECTORY ${PROJECT_SOURCE_DIR}/examples) add_subdirectory(c++) diff --git a/c++/src/CpuInfoUtil.cc b/c++/src/CpuInfoUtil.cc index 588f8dc96a..86d8361ee1 100644 --- a/c++/src/CpuInfoUtil.cc +++ b/c++/src/CpuInfoUtil.cc @@ -30,6 +30,10 @@ #include #endif +#if defined(__linux__) && defined(__riscv) +#include +#endif + #ifdef _WIN32 #define NOMINMAX #include @@ -62,6 +66,11 @@ #define CPUINFO_ARCH_ARM #elif defined(__PPC64__) || defined(__PPC64LE__) || defined(__ppc64__) || defined(__powerpc64__) #define CPUINFO_ARCH_PPC +#elif defined(__riscv) +#define CPUINFO_ARCH_RISCV +#ifndef ORC_HAVE_RUNTIME_RVV +#define UNUSED(x) (void)(x) +#endif #endif namespace orc { @@ -374,6 +383,23 @@ namespace orc { return flags; } +#if defined(CPUINFO_ARCH_RISCV) + int64_t LinuxParseRiscvIsa(const std::string& values) { + (void)values; + int64_t flags = 0; +#if defined(__linux__) +#if !defined(HWCAP_RISCV_RVV) +#define HWCAP_RISCV_RVV (1UL << ('v' - 'a')) +#endif + unsigned long hwcap = getauxval(AT_HWCAP); + if (hwcap & HWCAP_RISCV_RVV) { + flags |= CpuInfo::RVV; + } +#endif + return flags; + } +#endif + void OsRetrieveCacheSize(std::array* cacheSizes) { for (int i = 0; i < kCacheLevels; ++i) { const int64_t cache_size = LinuxGetCacheSize(i); @@ -414,7 +440,13 @@ namespace orc { const std::string value = TrimString(line.substr(colon + 1, std::string::npos)); if (name.compare("flags") == 0 || name.compare("Features") == 0) { *hardwareFlags |= LinuxParseCpuFlags(value); - } else if (name.compare("model name") == 0) { + } +#if defined(CPUINFO_ARCH_RISCV) + else if (name.compare("isa") == 0) { + *hardwareFlags |= LinuxParseRiscvIsa(value); + } +#endif + else if (name.compare("model name") == 0) { *modelName = value; } else if (name.compare("vendor_id") == 0) { if (value.compare("GenuineIntel") == 0) { @@ -482,6 +514,40 @@ namespace orc { } } +#elif defined(CPUINFO_ARCH_RISCV) + //------------------------------ RISC-V ------------------------------// + bool ArchParseUserSimdLevel(const std::string& simdLevel, int64_t* hardwareFlags) { + enum { + USER_SIMD_NONE, + USER_SIMD_RVV, + USER_SIMD_MAX, + }; + + int level = USER_SIMD_MAX; + if (simdLevel == "RVV") { + level = USER_SIMD_RVV; + } else if (simdLevel == "NONE") { + level = USER_SIMD_NONE; + } else { + return false; + } + + if (level < USER_SIMD_RVV) { + *hardwareFlags &= ~CpuInfo::RVV; + } + return true; + } + + void ArchVerifyCpuRequirements(const CpuInfo* ci) { +#if defined(ORC_HAVE_RUNTIME_RVV) + if (!ci->isDetected(CpuInfo::RVV)) { + throw ParseError("CPU does not support the RISC-V Vector instruction set"); + } +#else + UNUSED(ci); +#endif + } + #else //------------------------------ PPC, ... ------------------------------// bool ArchParseUserSimdLevel(const std::string& simdLevel, int64_t* hardwareFlags) { @@ -490,7 +556,7 @@ namespace orc { void ArchVerifyCpuRequirements(const CpuInfo* ci) {} -#endif // X86, ARM, PPC +#endif // X86, ARM, RISCV, PPC } // namespace diff --git a/c++/src/CpuInfoUtil.hh b/c++/src/CpuInfoUtil.hh index 5637053e6d..28b14cbe18 100644 --- a/c++/src/CpuInfoUtil.hh +++ b/c++/src/CpuInfoUtil.hh @@ -58,6 +58,9 @@ namespace orc { /// Arm features static constexpr int64_t ASIMD = (1LL << 32); + /// RISC-V features + static constexpr int64_t RVV = (1LL << 33); + // Cache enums for L1 (data), L2 and L3 enum class CacheLevel { L1 = 0, L2, L3, Last = L3 }; diff --git a/cmake_modules/ConfigSimdLevel.cmake b/cmake_modules/ConfigSimdLevel.cmake index 86608e63b5..56d5e72e56 100644 --- a/cmake_modules/ConfigSimdLevel.cmake +++ b/cmake_modules/ConfigSimdLevel.cmake @@ -28,8 +28,10 @@ endif() if(NOT DEFINED ORC_CPU_FLAG) if(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64|X86|x86|i[3456]86|x64") set(ORC_CPU_FLAG "x86") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64|riscv") + set(ORC_CPU_FLAG "riscv") else() - message(STATUS "Unsupported system processor for SIMD optimization") + message(STATUS "Unsupported system processor for SIMD optimization: ${CMAKE_SYSTEM_PROCESSOR}") endif() endif() @@ -102,3 +104,44 @@ if(ORC_CPU_FLAG STREQUAL "x86") endif() endif() +if(ORC_CPU_FLAG STREQUAL "riscv") + # RISC-V compiler flags for RVV + set(ORC_RVV_FLAG "-march=rv64gcv") + check_cxx_compiler_flag(${ORC_RVV_FLAG} COMPILER_SUPPORT_RVV) + + if(COMPILER_SUPPORT_RVV) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${ORC_RVV_FLAG}") + CHECK_CXX_SOURCE_COMPILES(" + #include + int main() { + vuint8m1_t vec = __riscv_vmv_v_x_u8m1(0, __riscv_vsetvl_e8m1(64)); + return 0; + }" + CXX_SUPPORTS_RVV) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) + endif() + + if(CXX_SUPPORTS_RVV) + message(STATUS "Enabled the RVV for RLE bit-unpacking") + set(ORC_SIMD_LEVEL "RVV") + add_definitions(-DORC_HAVE_RUNTIME_RVV) + else() + if(ORC_SIMD_LEVEL STREQUAL "RVV") + message(STATUS "WARNING: RVV required but compiler doesn't support it, failed to enable RVV.") + endif() + set(BUILD_ENABLE_RVV OFF) + endif() + + if(ORC_SIMD_LEVEL STREQUAL "DEFAULT") + set(ORC_SIMD_LEVEL "NONE") + endif() + + if(ORC_SIMD_LEVEL STREQUAL "RVV") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ORC_RVV_FLAG}") + message(STATUS "ORC_HAVE_RUNTIME_RVV defined, ORC_SIMD_LEVEL: ${ORC_SIMD_LEVEL}") + else() + message(STATUS "ORC_HAVE_RUNTIME_RVV not defined, ORC_SIMD_LEVEL: ${ORC_SIMD_LEVEL}") + endif() +endif() +