From 9c0adfe910455f0481cc9b910256042fd1f51159 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Fri, 14 Aug 2026 21:34:32 +0900 Subject: [PATCH 01/10] Initial implementation of interface with mcalite --- runtime/ir/Mpfr.cpp | 98 +++++++++++++++++++++ runtime/obj/MonteCarloArithmetic.cpp | 125 +++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index 30ba26a9..84669031 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -87,15 +87,68 @@ #define __RAPTOR_USE_MCA true #define __RAPTOR_MCA_CONCAT(prefix, FROM_TY) __raptor_mca_##prefix##FROM_TY + #define __RAPTOR_MCA_STRINGIFY(x) #x #define __RAPTOR_MCA_INEXACT(FROM_TY, a, loc, rnd_mode, isOutbound) \ __RAPTOR_MCA_CONCAT(inexact_, FROM_TY)(a, \ __RAPTOR_MCA_CONCAT(get_virtural_prec_, FROM_TY)(a, loc), rnd_mode, \ isOutbound); + + #ifdef __RAPTOR_MCALITE_MODE + #define __RAPTOR_MCA_BYPASS_MPFR true + #include + #define __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + ...) /* LLVM_TYPE if it exists */ \ + __raptor_fprt_original_ ## FROM_TYPE ## _ ## OP_TYPE ## _ ## LLVM_OP_NAME\ + ## __VA_OPT__(_) ## __VA_ARGS__ + #define __RAPTOR_MCA_ORIGINAL_FUNC(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE, ...) \ + __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE)(__VA_ARGS__) + #define __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET_TYPE, FROM_TYPE, OP_TYPE, \ + LLVM_OP_NAME, LLVM_TYPE, ...) \ + __RAPTOR_MPFR_ORIGINAL_ATTRIBUTES \ + RET_TYPE __RAPTOR_MCA_ORIGINAL_FUNC(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE, __VA_ARGS__); + #define __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(FUNC_NAME, FROM_TYPE, ...) \ + __RAPTOR_MPFR_ATTRIBUTES \ + int __RAPTOR_MCA_CONCAT(FUNC_NAME##_, FROM_TYPE)(__VA_ARGS__); + #define __RAPTOR_MCA_BYPASS_MPFR_FUNC(FUNC_NAME, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE, FROM_TYPE, RET_TYPE, ...) \ + do { \ + using namespace std::literals::string_view_literals; \ + if constexpr((__RAPTOR_MCA_STRINGIFY(OP_TYPE) == "unaryop"sv && \ + __RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fneg"sv) || \ + (__RAPTOR_MCA_STRINGIFY(OP_TYPE) == "binop"sv && \ + (__RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fadd"sv || \ + __RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fsub"sv || \ + __RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fmul"sv || \ + __RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fdiv"sv)) \ + ) { \ + RET_TYPE res; \ + if (__RAPTOR_MCA_CONCAT(FUNC_NAME##_, FROM_TYPE)(res, __VA_ARGS__) \ + == 0 \ + ) { \ + return res; \ + } else { abort(); } \ + } else { \ + return __RAPTOR_MCA_ORIGINAL_FUNC(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE, __VA_ARGS__); \ + } \ + } while (0) + #endif #else #define __RAPTOR_USE_MCA false #define __RAPTOR_MCA_INEXACT(FROM_TY, a, loc, rnd_mode, isOutbound) #endif +#ifndef __RAPTOR_MCA_BYPASS_MPFR + #define __RAPTOR_MCA_BYPASS_MPFR false + #define __RAPTOR_MCA_ORIGINAL_FUNC_DECL(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE, ...) + #define __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(FUNC_NAME, FROM_TYPE, ...) + #define __RAPTOR_MCA_BYPASS_MPFR_FUNC(FUNC_NAME, ...) +#endif + __RAPTOR_MPFR_ATTRIBUTES void __raptor_fprt_trunc_change(int64_t is_push, int64_t to_e, int64_t to_m, int64_t mode, const char *loc, void *scratch) { @@ -554,11 +607,18 @@ void raptor_fprt_op_clear(); // this. We need to detect these patterns #define __RAPTOR_MPFR_LROUND(OP_TYPE, LLVM_OP_NAME, FROM_TYPE, RET, ARG1, \ MPFR_SET_ARG1, ROUNDING_MODE) \ + __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ + ARG1 a) \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(get_si, FROM_TYPE, RET & result, ARG1 a) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ + if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(get_si, OP_TYPE, LLVM_OP_NAME,, \ + FROM_TYPE, RET, a); \ + } \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ RET c = mpfr_get_si(scratch[0], ROUNDING_MODE); \ return c; \ @@ -570,11 +630,19 @@ void raptor_fprt_op_clear(); #define __RAPTOR_MPFR_SINGOP(OP_TYPE, LLVM_OP_NAME, MPFR_FUNC_NAME, FROM_TYPE, \ RET, MPFR_GET, ARG1, MPFR_SET_ARG1, \ ROUNDING_MODE) \ + __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ + ARG1 a) \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(MPFR_FUNC_NAME, FROM_TYPE, RET & result, \ + ARG1 a) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ + if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,, \ + FROM_TYPE, RET, a); \ + } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ @@ -612,11 +680,19 @@ void raptor_fprt_op_clear(); #define __RAPTOR_MPFR_BIN_INT(OP_TYPE, LLVM_OP_NAME, MPFR_FUNC_NAME, \ FROM_TYPE, RET, MPFR_GET, ARG1, MPFR_SET_ARG1, \ ARG2, ROUNDING_MODE) \ + __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ + ARG1 a, ARG2 b) \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(MPFR_FUNC_NAME, FROM_TYPE, RET & result, \ + ARG1 a, ARG2 b) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, ARG2 b, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ + if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,, \ + FROM_TYPE, RET, a, b); \ + } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ @@ -652,11 +728,19 @@ void raptor_fprt_op_clear(); #define __RAPTOR_MPFR_BIN(OP_TYPE, LLVM_OP_NAME, MPFR_FUNC_NAME, FROM_TYPE, \ RET, MPFR_GET, ARG1, MPFR_SET_ARG1, ARG2, \ MPFR_SET_ARG2, ROUNDING_MODE) \ + __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ + ARG1 a, ARG2 b) \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(MPFR_FUNC_NAME, FROM_TYPE, RET & result, \ + ARG1 a, ARG2 b) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, ARG2 b, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ + if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,, \ + FROM_TYPE, RET, a, b); \ + } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ mpfr_set_##MPFR_SET_ARG2(scratch[1], b, ROUNDING_MODE); \ @@ -699,11 +783,19 @@ void raptor_fprt_op_clear(); #define __RAPTOR_MPFR_FMULADD(OP_TYPE, LLVM_OP_NAME, FROM_TYPE, TYPE, \ MPFR_TYPE, LLVM_TYPE, ROUNDING_MODE) \ + __RAPTOR_MCA_ORIGINAL_FUNC_DECL(TYPE, FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE, TYPE a, TYPE b, TYPE c) \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(fma, FROM_TYPE, TYPE & result, TYPE a, \ + TYPE b, TYPE c) \ __RAPTOR_MPFR_ATTRIBUTES \ TYPE __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME##_##LLVM_TYPE( \ TYPE a, TYPE b, TYPE c, int64_t exponent, int64_t significand, \ int64_t mode, const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ + if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(fma, OP_TYPE, LLVM_OP_NAME, LLVM_TYPE, \ + FROM_TYPE, TYPE, a, b, c); \ + } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_TYPE(scratch[0], a, ROUNDING_MODE); \ mpfr_set_##MPFR_TYPE(scratch[1], b, ROUNDING_MODE); \ @@ -756,11 +848,17 @@ void raptor_fprt_op_clear(); // TODO This does not currently make distinctions between ordered/unordered. #define __RAPTOR_MPFR_FCMP_IMPL(NAME, ORDERED, CMP, FROM_TYPE, TYPE, MPFR_GET, \ ROUNDING_MODE) \ + __RAPTOR_MCA_ORIGINAL_FUNC_DECL(bool, FROM_TYPE, fcmp, NAME,, TYPE a, TYPE b)\ + __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(cmp, FROM_TYPE, bool & result, TYPE a, \ + TYPE b) \ __RAPTOR_MPFR_ATTRIBUTES \ bool __raptor_fprt_##FROM_TYPE##_fcmp_##NAME( \ TYPE a, TYPE b, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ + if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(cmp, fcmp, NAME,, FROM_TYPE, bool, a, b);\ + } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_GET(scratch[0], a, ROUNDING_MODE); \ mpfr_set_##MPFR_GET(scratch[1], b, ROUNDING_MODE); \ diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp index 83072f4f..14b144af 100644 --- a/runtime/obj/MonteCarloArithmetic.cpp +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -477,12 +477,137 @@ #endif // defined(__RAPTOR_VERIFICARLOMCA_QUAD_MODE) || // defined(__RAPTOR_VERIFICARLOMCA_INT_MODE) +#ifdef __RAPTOR_MCALITE_MODE + #define __RAPTOR_USE_MCALITE true + #include + #include + namespace { + enum mcalite_mode { // Comment copied from mca.h + RR, /* Random Rounding (RR): round(inexact(x op y)). */ + PB, /* Precision Bounding (PB): round(inexact(x) op inexact(y)). */ + FULL /* Full MCA: round(inexact(inexact(x) op inexact(y))). */ + }; + struct mcalite_context_t { + uint64_t rng_seed = 42; + int t = 24; // virtual precision + size_t ntrials = 5; // Number of repetition per operation + mcalite_mode mode = mcalite_mode::PB; + std::vector results; + mca_rng rng; + void parse_env() { + // Get the seed, t, ntrials and mode from env var. + char *env_val = getenv("MCA_SEED"); + if (env_val != nullptr) { + std::string env_str(env_val); + rng_seed = std::stoul(env_str); + } + env_val = getenv("MCA_T"); + if (env_val != nullptr) { + std::string env_str(env_val); + t = std::stoi(env_str); + } + env_val = getenv("MCA_NTRIALS"); + if (env_val != nullptr) { + std::string env_str(env_val); + ntrials = std::stoul(env_str); + } + env_val = getenv("MCA_MODE"); + if (env_val != nullptr) { + std::string env_str(env_val); + if (env_str == "RR") { mode = mcalite_mode::RR; } + else if (env_str == "PB") { mode = mcalite_mode::PB; } + else if (env_str == "FULL") { mode = mcalite_mode::FULL; } + else { + std::cerr << "Error: invalid MCA_MODE value " << env_str; + std::cerr << ", valid MCA_MODE options are RR, PB and FULL."; + std::cerr << std::endl; + abort(); + } + } + } + std::string mode_str() { + std::string str = "FULL"; + switch(mode) { + case mcalite_mode::RR: str = "RR"; break; + case mcalite_mode::PB: str = "PB"; break; + default: break; // mcalite_mode::FULL + } + return str; + } + void print() { + std::cout << "rng_seed = " << rng_seed << ", t = " << t << ", "; + std::cout << "ntrials = " << ntrials << ", mode = " << mode_str(); + } + mcalite_context_t(uint64_t rng_stream) { + parse_env(); + results.resize(ntrials); + mca_rng_seed(&rng, rng_seed, rng_stream); + print(); std::cout << ", rng_stream " << rng_stream << std::endl; + } + }; + mcalite_context_t mcalite_context{1}; + } + #define __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(OP, FROM_TY, ...) \ + int __raptor_mca_##OP##_##FROM_TY(__VA_ARGS__) + #define __RAPTOR_MCALITE_CALL(OP, MODE, ...) \ + mca_##OP##_##MODE(__VA_ARGS__, mcalite_context.t, mcalite_context.ntrials, \ + &(mcalite_context.rng), mcalite_context.results.data()) + #define __RAPTOR_MCALITE_OP_FUNC_BODY(OP, ...) \ + { \ + int err = 0; \ + switch (mcalite_context.mode) { \ + case mcalite_mode::RR: \ + err = __RAPTOR_MCALITE_CALL(OP, rr, __VA_ARGS__); \ + break; \ + case mcalite_mode::PB: \ + err = __RAPTOR_MCALITE_CALL(OP, pb, __VA_ARGS__); \ + break; \ + case mcalite_mode::FULL: \ + err = __RAPTOR_MCALITE_CALL(OP, full, __VA_ARGS__); \ + break; \ + default: err = -1; break; \ + } \ + if (err == 0) { result = mcalite_context.results[0]; } \ + else { \ + std::cerr << "Error in mode " << mcalite_context.mode; \ + std::cerr << " with op " << #OP << std::endl; \ + } \ + return err; \ + } + #define __RAPTOR_MCALITE_BINARY_OP(OP, FROM_TY, CPP_TY) \ + __RAPTOR_MPFR_ATTRIBUTES \ + __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(OP, FROM_TY, \ + CPP_TY & result, CPP_TY x, CPP_TY y) \ + __RAPTOR_MCALITE_OP_FUNC_BODY(OP, x, y) + #define __RAPTOR_MCALITE_UNARY_OP(OP, FROM_TY, CPP_TY) \ + __RAPTOR_MPFR_ATTRIBUTES \ + __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(OP, FROM_TY, CPP_TY & result, CPP_TY x) \ + __RAPTOR_MCALITE_OP_FUNC_BODY(OP, x) + + #define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ + __RAPTOR_MCALITE_BINARY_OP(add, FROM_TY, CPP_TY) \ + __RAPTOR_MCALITE_BINARY_OP(sub, FROM_TY, CPP_TY) \ + __RAPTOR_MCALITE_BINARY_OP(mul, FROM_TY, CPP_TY) \ + __RAPTOR_MCALITE_BINARY_OP(div, FROM_TY, CPP_TY) \ + __RAPTOR_MCALITE_UNARY_OP(neg, FROM_TY, CPP_TY) + #include "raptor/FloatTypes.def" + + #define __RAPTOR_MCALITE_get_virtual_prec \ + do { return mcalite_context.t; } while(0) + +#else + #define __RAPTOR_USE_MCALITE false + #define __RAPTOR_MCALITE_get_virtual_prec +#endif // __RAPTOR_USE_MCALITE + #define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ __RAPTOR_MPFR_ATTRIBUTES \ unsigned int __raptor_mca_get_virtural_prec_##FROM_TY(mpfr_t a, \ const char *loc) { \ if constexpr (__RAPTOR_USE_VERIFICARLOMCA) { \ __RAPTOR_VERIFICARLOMCA_get_virtual_prec(CPP_TY); \ + } else if constexpr (__RAPTOR_USE_MCALITE) { \ + __RAPTOR_MCALITE_get_virtual_prec; \ } else { \ std::cerr << "__raptor_mca_get_virtural_prec_" << #FROM_TY; \ std::cerr << " is not implemented." << std::endl; \ From bed69207203c9d67ededf4668508174a00acb140 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:25:52 +0900 Subject: [PATCH 02/10] Modified cmake files and link options for tests to add options to build RAPTOR with mcalite --- CMakeLists.txt | 36 ++++++++++++++++++++++++++++++++++++ runtime/CMakeLists.txt | 4 ++++ test/lit.site.cfg.py.in | 7 +++++++ 3 files changed, 47 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ebc045af..70b0cfba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -408,6 +408,42 @@ if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) target_compile_definitions(verificarlo_int INTERFACE __RAPTOR_VERIFICARLOMCA_INT_MODE) endif() endif() + +if (DEFINED __RAPTOR_MCALITE_SOURCE_DIR) + if (NOT __RAPTOR_MCALITE_SOURCE_DIR MATCHES "mcalite") + message(SEND_ERROR "__RAPTOR_MCALITE_SOURCE_DIR ${__RAPTOR_MCALITE_SOURCE_DIR} does not include the expected lib name") + elseif (NOT EXISTS "${__RAPTOR_MCALITE_SOURCE_DIR}") + message(SEND_ERROR "__RAPTOR_MCALITE_SOURCE_DIR ${__RAPTOR_MCALITE_SOURCE_DIR} does not exists") + elseif(NOT EXISTS "${__RAPTOR_MCALITE_SOURCE_DIR}/mca.h") + message(SEND_ERROR "mcalite header file ${__RAPTOR_MCALITE_SOURCE_DIR}/mca.h does not exists") + elseif(NOT EXISTS "${__RAPTOR_MCALITE_SOURCE_DIR}/mca.c") + message(SEND_ERROR "mcalite source file ${__RAPTOR_MCALITE_SOURCE_DIR}/mca.c does not exists") + else() + add_library(mcalite OBJECT "${__RAPTOR_MCALITE_SOURCE_DIR}/mca.h" "${__RAPTOR_MCALITE_SOURCE_DIR}/mca.c") + target_include_directories(mcalite PUBLIC ${__RAPTOR_MCALITE_SOURCE_DIR}) + target_compile_definitions(mcalite PUBLIC __RAPTOR_MCALITE_MODE) + endif() +elseif (DEFINED __RAPTOR_MCALITE_HEADER_PATH) + if (NOT __RAPTOR_MCALITE_HEADER_PATH MATCHES "mca.h") + message(SEND_ERROR "__RAPTOR_MCALITE_HEADER_PATH ${__RAPTOR_MCALITE_HEADER_PATH} does not include the expected header name") + elseif (NOT EXISTS "${__RAPTOR_MCALITE_HEADER_PATH}") + message(SEND_ERROR "__RAPTOR_MCALITE_HEADER_PATH ${__RAPTOR_MCALITE_HEADER_PATH} does not exists") + elseif (NOT DEFINED __RAPTOR_MCALITE_LIB_PATH) + message(SEND_ERROR "__RAPTOR_MCALITE_LIB_PATH not defined, this is required for tests") + elseif (NOT __RAPTOR_MCALITE_LIB_PATH MATCHES "libmcalite.so") + message(SEND_ERROR "__RAPTOR_MCALITE_LIB_PATH ${__RAPTOR_MCALITE_LIB_PATH} does not include the expected library name") + elseif (NOT EXISTS "${__RAPTOR_MCALITE_LIB_PATH}") + message(SEND_ERROR "__RAPTOR_MCALITE_LIB_PATH ${__RAPTOR_MCALITE_LIB_PATH} does not exists") + else() + get_filename_component(__RAPTOR_MCALITE_SOURCE_DIR "${__RAPTOR_MCALITE_HEADER_PATH}" DIRECTORY) + add_library(mcalite INTERFACE "${__RAPTOR_MCALITE_HEADER_PATH}") + target_include_directories(mcalite INTERFACE ${__RAPTOR_MCALITE_SOURCE_DIR}) + target_compile_definitions(mcalite INTERFACE __RAPTOR_MCALITE_MODE) + endif() +elseif (DEFINED __RAPTOR_MCALITE_LIB_PATH) + message(SEND_ERROR "__RAPTOR_MCALITE_LIB_PATH defined but __RAPTOR_MCALITE_HEADER_PATH not defined, the header is required to build the RAPTOR runtime") +endif() + add_subdirectory(runtime) add_subdirectory(test) add_subdirectory(wrappers) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 12601533..9566dc3d 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -53,6 +53,10 @@ if (DEFINED __RAPTOR_VERIFICARLOMCA_INT_LIB_PATH) target_link_libraries(Raptor-RT-${LLVM_VERSION_MAJOR} PRIVATE verificarlo_int) endif() +if (DEFINED __RAPTOR_MCALITE_SOURCE_DIR) + target_link_libraries(Raptor-RT-${LLVM_VERSION_MAJOR} PRIVATE mcalite) +endif() + install( DIRECTORY ${RAPTOR_PUBLIC_INCLUDE_DIR} DESTINATION include diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index 75e4c5d5..62a00328 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -118,6 +118,13 @@ if verificarlomca_lib_path != "": link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver + verificarlomca_link_options + +mcalite_lib_path = "@__RAPTOR_MCALITE_LIB_PATH@" +if mcalite_lib_path != "": + mcalite_lib_dir = "/".join(mcalite_lib_path.split("/")[:-1]) + mcalite_lib_name = mcalite_lib_path.split("/")[-1].split(".")[0][3:] + link = link + " -L" + mcalite_lib_dir + " -l" + mcalite_lib_name + " -Wl,-rpath=" + mcalite_lib_dir + config.substitutions.append(('%linkRaptorRT', link)) link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver From 08684d2ce4215b0408608e7f7b7df7c9557bc8f2 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Thu, 3 Sep 2026 18:40:49 +0900 Subject: [PATCH 03/10] Add MCAlite option to __raptor_mca_op_func --- pass/CMakeLists.txt | 3 +++ pass/RaptorLogic.cpp | 19 +++++++++++--- pass/RaptorLogic.h | 11 ++++++++ runtime/include/private/raptor/Common.h | 16 +++++++++++ runtime/ir/Mpfr.cpp | 35 +++++++++++++++++-------- 5 files changed, 70 insertions(+), 14 deletions(-) diff --git a/pass/CMakeLists.txt b/pass/CMakeLists.txt index 2f7c97c2..93e9a819 100644 --- a/pass/CMakeLists.txt +++ b/pass/CMakeLists.txt @@ -26,6 +26,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) add_compile_definitions(__RAPTOR_HAS_VERIFICARLOMCA) endif() +if (DEFINED __RAPTOR_MCALITE_SOURCE_DIR) + add_compile_definitions(__RAPTOR_HAS_MCALITE) +endif() # on windows `PLUGIN_TOOL` doesn't link against LLVM.dll if ((WIN32 OR CYGWIN) AND LLVM_LINK_LLVM_DYLIB) diff --git a/pass/RaptorLogic.cpp b/pass/RaptorLogic.cpp index 0ee30050..1e6b19b4 100644 --- a/pass/RaptorLogic.cpp +++ b/pass/RaptorLogic.cpp @@ -439,7 +439,8 @@ class TruncateGenerator : public llvm::InstVisitor, } }; if (TC.isToFPRT()) { - if (Mode == TruncOpMode || Mode == TruncOpMCAVerificarloMode) { + if (Mode == TruncOpMode || Mode == TruncOpMCAVerificarloMode || + Mode == TruncOpMCAMCAliteMode) { if (TC.NeedTruncChange || TC.NeedNewScratch) AllocScratch(); if (!TC.NeedNewScratch) { @@ -471,6 +472,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncOpMode: case TruncOpFullModuleMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: EmitWarning( "UnhandledTrunc", I, "Operation not handled - it will be executed in the original way.", @@ -502,6 +504,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncOpMode: case TruncOpFullModuleMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: return floatValTruncate(B, v, TC); } llvm_unreachable("Unknown trunc mode"); @@ -514,6 +517,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncOpMode: case TruncOpFullModuleMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: return floatValExpand(B, v, TC); } llvm_unreachable("Unknown trunc mode"); @@ -576,6 +580,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncOpMode: case TruncOpFullModuleMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: return; } } @@ -620,6 +625,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncOpMode: case TruncOpFullModuleMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: return; } } @@ -643,6 +649,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncOpMode: case TruncOpFullModuleMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: return; } llvm_unreachable(""); @@ -783,6 +790,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncOpMode: case TruncOpFullModuleMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: break; default: llvm_unreachable("Unknown trunc mode"); @@ -816,6 +824,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncOpMode: case TruncOpFullModuleMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: break; default: llvm_unreachable("Unknown trunc mode"); @@ -865,6 +874,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncMemMode: case TruncOpMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: EmitWarning("FPNoFollow", CI, "Will not follow FP through this indirect call.", CI); break; @@ -883,6 +893,7 @@ class TruncateGenerator : public llvm::InstVisitor, break; case TruncOpMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: EmitWarning("FPNoFollow", CI, "Will not truncate flops in this function call as the " "definition is not available.", @@ -933,14 +944,15 @@ class TruncateGenerator : public llvm::InstVisitor, IRBuilder<> BuilderZ(newCall); if (Mode != TruncOpMode && Mode != TruncMemMode && - Mode != TruncOpMCAVerificarloMode) + Mode != TruncOpMCAVerificarloMode && Mode != TruncOpMCAMCAliteMode) return; RequestContext ctx(&CI, &BuilderZ); auto FTTs = getFunctionToTruncate(CI); auto NeedDirectCall = [&](auto FTT) { return scratch && (Mode == TruncOpMode || - Mode == TruncOpMCAVerificarloMode) && + Mode == TruncOpMCAVerificarloMode || + Mode == TruncOpMCAMCAliteMode) && isa(&CI) && !FTT.isCallbackFunc(); }; @@ -1010,6 +1022,7 @@ class TruncateGenerator : public llvm::InstVisitor, case TruncOpMode: case TruncOpFullModuleMode: case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: break; default: llvm_unreachable("Unknown trunc mode"); diff --git a/pass/RaptorLogic.h b/pass/RaptorLogic.h index c6c3a1cc..414ee3ea 100644 --- a/pass/RaptorLogic.h +++ b/pass/RaptorLogic.h @@ -87,6 +87,7 @@ namespace MCAType { enum MCAType { NoMCAType, VerificarloMCA, + MCAlite, NumMCAType }; static constexpr int shift = 4; @@ -98,6 +99,7 @@ enum TruncateMode { TruncOpFullModuleMode = 0b0110, TruncOpMCAVerificarloMode = TruncOpMode + (MCAType::VerificarloMCA << MCAType::shift), + TruncOpMCAMCAliteMode = TruncOpMode + (MCAType::MCAlite << MCAType::shift), }; [[maybe_unused]] static const char *truncateModeStr(TruncateMode mode) { switch (mode) { @@ -109,6 +111,8 @@ enum TruncateMode { return "op_full_module"; case TruncOpMCAVerificarloMode: return "op_mca_verificarlo"; + case TruncOpMCAMCAliteMode: + return "op_mca_mcalite"; } llvm_unreachable("Invalid truncation mode"); } @@ -124,6 +128,8 @@ namespace MCAType { switch (Mode) { case TruncOpMCAVerificarloMode: return {TruncOpMode, VerificarloMCA}; break; + case TruncOpMCAMCAliteMode: + return {TruncOpMode, MCAlite}; break; default: return {Mode, NoMCAType}; break; } @@ -133,6 +139,9 @@ namespace MCAType { switch(mcaType) { #ifdef __RAPTOR_HAS_VERIFICARLOMCA case VerificarloMCA: return VerificarloMCA; break; +#endif +#ifdef __RAPTOR_HAS_MCALITE + case MCAlite: return MCAlite; break; #endif default: return NoMCAType; break; } @@ -142,6 +151,7 @@ namespace MCAType { switch(mcaType) { case NoMCAType: return ""; break; case VerificarloMCA: return "verificarlo"; break; + case MCAlite: return "mcalite"; break; default: return "invalid"; break; } } @@ -156,6 +166,7 @@ namespace MCAType { assert(!isMCA(Mode)); switch (Mode + (mcaType << shift)) { case TruncOpMCAVerificarloMode: + case TruncOpMCAMCAliteMode: return true; break; default: return false; break; diff --git a/runtime/include/private/raptor/Common.h b/runtime/include/private/raptor/Common.h index a7df3395..ac2a3bba 100644 --- a/runtime/include/private/raptor/Common.h +++ b/runtime/include/private/raptor/Common.h @@ -36,6 +36,17 @@ typedef struct __raptor_fp { // #endif } __raptor_fp; +// Should match definition in pass/RaptorLogic.h +namespace MCAType { + enum MCAType { + NoMCAType, + VerificarloMCA, + MCAlite, + NumMCAType + }; + static constexpr int shift = 4; +}; + static inline bool __raptor_fprt_is_mem_mode(int64_t mode) { return mode & 0b0001; } @@ -48,6 +59,11 @@ static inline bool __raptor_fprt_is_full_module_op_mode(int64_t mode) { static inline bool __raptor_fprt_is_mca_mode(int64_t mode) { return mode & 0b011110000; } +static inline bool __raptor_fprt_mca_type_is(int64_t mode, + MCAType::MCAType mcaType) +{ + return (mode & 0b011110000) == (mcaType << MCAType::shift); +} __RAPTOR_MPFR_DECL_ATTRIBUTES void raptor_fprt_gc_dump_status(); diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index 84669031..9a69b2cb 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -616,8 +616,10 @@ void raptor_fprt_op_clear(); const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(get_si, OP_TYPE, LLVM_OP_NAME,, \ - FROM_TYPE, RET, a); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(get_si, OP_TYPE, LLVM_OP_NAME,, \ + FROM_TYPE, RET, a); \ + } \ } \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ RET c = mpfr_get_si(scratch[0], ROUNDING_MODE); \ @@ -640,8 +642,10 @@ void raptor_fprt_op_clear(); const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,, \ - FROM_TYPE, RET, a); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,,\ + FROM_TYPE, RET, a); \ + } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ @@ -690,8 +694,10 @@ void raptor_fprt_op_clear(); const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,, \ - FROM_TYPE, RET, a, b); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,,\ + FROM_TYPE, RET, a, b); \ + } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ @@ -738,8 +744,10 @@ void raptor_fprt_op_clear(); const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,, \ - FROM_TYPE, RET, a, b); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,,\ + FROM_TYPE, RET, a, b); \ + } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ @@ -793,8 +801,10 @@ void raptor_fprt_op_clear(); int64_t mode, const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(fma, OP_TYPE, LLVM_OP_NAME, LLVM_TYPE, \ - FROM_TYPE, TYPE, a, b, c); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(fma, OP_TYPE, LLVM_OP_NAME, LLVM_TYPE, \ + FROM_TYPE, TYPE, a, b, c); \ + } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_TYPE(scratch[0], a, ROUNDING_MODE); \ @@ -857,7 +867,10 @@ void raptor_fprt_op_clear(); const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(cmp, fcmp, NAME,, FROM_TYPE, bool, a, b);\ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + __RAPTOR_MCA_BYPASS_MPFR_FUNC(cmp, fcmp, NAME,, FROM_TYPE, bool, a, \ + b); \ + } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_GET(scratch[0], a, ROUNDING_MODE); \ From 3a8154548b0ad2724a7df6553a2b4574c059c6f9 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Thu, 3 Sep 2026 18:48:09 +0900 Subject: [PATCH 04/10] Update lib name and link options to match MCAlite repo --- CMakeLists.txt | 6 +++--- test/lit.site.cfg.py.in | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70b0cfba..0c7e47c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -410,14 +410,14 @@ if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) endif() if (DEFINED __RAPTOR_MCALITE_SOURCE_DIR) - if (NOT __RAPTOR_MCALITE_SOURCE_DIR MATCHES "mcalite") + if (NOT __RAPTOR_MCALITE_SOURCE_DIR MATCHES "MCAlite") message(SEND_ERROR "__RAPTOR_MCALITE_SOURCE_DIR ${__RAPTOR_MCALITE_SOURCE_DIR} does not include the expected lib name") elseif (NOT EXISTS "${__RAPTOR_MCALITE_SOURCE_DIR}") message(SEND_ERROR "__RAPTOR_MCALITE_SOURCE_DIR ${__RAPTOR_MCALITE_SOURCE_DIR} does not exists") elseif(NOT EXISTS "${__RAPTOR_MCALITE_SOURCE_DIR}/mca.h") - message(SEND_ERROR "mcalite header file ${__RAPTOR_MCALITE_SOURCE_DIR}/mca.h does not exists") + message(SEND_ERROR "MCAlite header file ${__RAPTOR_MCALITE_SOURCE_DIR}/mca.h does not exists") elseif(NOT EXISTS "${__RAPTOR_MCALITE_SOURCE_DIR}/mca.c") - message(SEND_ERROR "mcalite source file ${__RAPTOR_MCALITE_SOURCE_DIR}/mca.c does not exists") + message(SEND_ERROR "MCAlite source file ${__RAPTOR_MCALITE_SOURCE_DIR}/mca.c does not exists") else() add_library(mcalite OBJECT "${__RAPTOR_MCALITE_SOURCE_DIR}/mca.h" "${__RAPTOR_MCALITE_SOURCE_DIR}/mca.c") target_include_directories(mcalite PUBLIC ${__RAPTOR_MCALITE_SOURCE_DIR}) diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index 62a00328..abb6f3ba 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -125,6 +125,10 @@ if mcalite_lib_path != "": mcalite_lib_name = mcalite_lib_path.split("/")[-1].split(".")[0][3:] link = link + " -L" + mcalite_lib_dir + " -l" + mcalite_lib_name + " -Wl,-rpath=" + mcalite_lib_dir +mcalite_src_dir = "@__RAPTOR_MCALITE_SOURCE_DIR@" +if mcalite_src_dir != "": + link = link + " -lm" + config.substitutions.append(('%linkRaptorRT', link)) link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver From b903997c5c314a8928bb2d083dfb22aa243533e1 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:29:52 +0900 Subject: [PATCH 05/10] Modify interface of MCAlite operations to keep return type and arguments the same as the original operation --- runtime/ir/Mpfr.cpp | 112 +++++++++++++-------------- runtime/obj/MonteCarloArithmetic.cpp | 15 ++-- 2 files changed, 62 insertions(+), 65 deletions(-) diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index 9a69b2cb..de284c4a 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -100,41 +100,51 @@ ...) /* LLVM_TYPE if it exists */ \ __raptor_fprt_original_ ## FROM_TYPE ## _ ## OP_TYPE ## _ ## LLVM_OP_NAME\ ## __VA_OPT__(_) ## __VA_ARGS__ - #define __RAPTOR_MCA_ORIGINAL_FUNC(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ - LLVM_TYPE, ...) \ - __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ - LLVM_TYPE)(__VA_ARGS__) #define __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET_TYPE, FROM_TYPE, OP_TYPE, \ LLVM_OP_NAME, LLVM_TYPE, ...) \ __RAPTOR_MPFR_ORIGINAL_ATTRIBUTES \ - RET_TYPE __RAPTOR_MCA_ORIGINAL_FUNC(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ - LLVM_TYPE, __VA_ARGS__); - #define __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(FUNC_NAME, FROM_TYPE, ...) \ + RET_TYPE __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,\ + LLVM_TYPE)(__VA_ARGS__); + #define __RAPTOR_MCA_OP_FUNC_DECL(RET_TYPE, OP_NAME, FROM_TYPE, ...) \ __RAPTOR_MPFR_ATTRIBUTES \ - int __RAPTOR_MCA_CONCAT(FUNC_NAME##_, FROM_TYPE)(__VA_ARGS__); - #define __RAPTOR_MCA_BYPASS_MPFR_FUNC(FUNC_NAME, OP_TYPE, LLVM_OP_NAME, \ - LLVM_TYPE, FROM_TYPE, RET_TYPE, ...) \ + RET_TYPE __RAPTOR_MCA_CONCAT(OP_NAME##_, FROM_TYPE)(__VA_ARGS__); + #define __RAPTOR_MCA_OP_FUNC_IF(OP_TYPE, OP_TYPE_REF, LLVM_OP_NAME, \ + LLVM_OP_NAME_REF, FUNC_NAME, FROM_TYPE,...)\ + if constexpr((__RAPTOR_MCA_STRINGIFY(OP_TYPE) == OP_TYPE_REF && \ + __RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == LLVM_OP_NAME_REF) \ + ) { return __RAPTOR_MCA_CONCAT(FUNC_NAME##_, FROM_TYPE)(__VA_ARGS__); } + #define __RAPTOR_MCA_BYPASS_MPFR_UNARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE, ...) \ do { \ using namespace std::literals::string_view_literals; \ - if constexpr((__RAPTOR_MCA_STRINGIFY(OP_TYPE) == "unaryop"sv && \ - __RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fneg"sv) || \ - (__RAPTOR_MCA_STRINGIFY(OP_TYPE) == "binop"sv && \ - (__RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fadd"sv || \ - __RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fsub"sv || \ - __RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fmul"sv || \ - __RAPTOR_MCA_STRINGIFY(LLVM_OP_NAME) == "fdiv"sv)) \ - ) { \ - RET_TYPE res; \ - if (__RAPTOR_MCA_CONCAT(FUNC_NAME##_, FROM_TYPE)(res, __VA_ARGS__) \ - == 0 \ - ) { \ - return res; \ - } else { abort(); } \ - } else { \ - return __RAPTOR_MCA_ORIGINAL_FUNC(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ - LLVM_TYPE, __VA_ARGS__); \ - } \ + __RAPTOR_MCA_OP_FUNC_IF(OP_TYPE, "unaryop"sv, LLVM_OP_NAME, "fneg"sv, \ + neg, FROM_TYPE, __VA_ARGS__); \ + return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,\ + LLVM_TYPE)(__VA_ARGS__); \ } while (0) + #define __RAPTOR_MCA_BYPASS_MPFR_BINARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE, ...) \ + do { \ + using namespace std::literals::string_view_literals; \ + __RAPTOR_MCA_OP_FUNC_IF(OP_TYPE, "binop"sv, LLVM_OP_NAME, "fadd"sv, \ + add, FROM_TYPE, __VA_ARGS__); \ + __RAPTOR_MCA_OP_FUNC_IF(OP_TYPE, "binop"sv, LLVM_OP_NAME, "fsub"sv, \ + sub, FROM_TYPE, __VA_ARGS__); \ + __RAPTOR_MCA_OP_FUNC_IF(OP_TYPE, "binop"sv, LLVM_OP_NAME, "fmul"sv, \ + mul, FROM_TYPE, __VA_ARGS__); \ + __RAPTOR_MCA_OP_FUNC_IF(OP_TYPE, "binop"sv, LLVM_OP_NAME, "fdiv"sv, \ + div, FROM_TYPE, __VA_ARGS__); \ + return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,\ + LLVM_TYPE)(__VA_ARGS__); \ + } while (0) + + #define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, neg, FROM_TY, CPP_TY x) \ + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, add, FROM_TY, CPP_TY x, CPP_TY y) \ + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, sub, FROM_TY, CPP_TY x, CPP_TY y) \ + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, mul, FROM_TY, CPP_TY x, CPP_TY y) \ + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, div, FROM_TY, CPP_TY x, CPP_TY y) + #include "raptor/FloatTypes.def" #endif #else #define __RAPTOR_USE_MCA false @@ -609,16 +619,15 @@ void raptor_fprt_op_clear(); MPFR_SET_ARG1, ROUNDING_MODE) \ __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ ARG1 a) \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(get_si, FROM_TYPE, RET & result, ARG1 a) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(get_si, OP_TYPE, LLVM_OP_NAME,, \ - FROM_TYPE, RET, a); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, \ + LLVM_OP_NAME)(a); \ } \ } \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ @@ -634,17 +643,14 @@ void raptor_fprt_op_clear(); ROUNDING_MODE) \ __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ ARG1 a) \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(MPFR_FUNC_NAME, FROM_TYPE, RET & result, \ - ARG1 a) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,,\ - FROM_TYPE, RET, a); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + __RAPTOR_MCA_BYPASS_MPFR_UNARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, a);\ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ @@ -686,17 +692,15 @@ void raptor_fprt_op_clear(); ARG2, ROUNDING_MODE) \ __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ ARG1 a, ARG2 b) \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(MPFR_FUNC_NAME, FROM_TYPE, RET & result, \ - ARG1 a, ARG2 b) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, ARG2 b, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,,\ - FROM_TYPE, RET, a, b); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, \ + LLVM_OP_NAME)(a, b); \ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ @@ -736,17 +740,15 @@ void raptor_fprt_op_clear(); MPFR_SET_ARG2, ROUNDING_MODE) \ __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ ARG1 a, ARG2 b) \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(MPFR_FUNC_NAME, FROM_TYPE, RET & result, \ - ARG1 a, ARG2 b) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, ARG2 b, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(MPFR_FUNC_NAME, OP_TYPE, LLVM_OP_NAME,,\ - FROM_TYPE, RET, a, b); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + __RAPTOR_MCA_BYPASS_MPFR_BINARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, a,\ + b); \ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ @@ -793,17 +795,16 @@ void raptor_fprt_op_clear(); MPFR_TYPE, LLVM_TYPE, ROUNDING_MODE) \ __RAPTOR_MCA_ORIGINAL_FUNC_DECL(TYPE, FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ LLVM_TYPE, TYPE a, TYPE b, TYPE c) \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(fma, FROM_TYPE, TYPE & result, TYPE a, \ - TYPE b, TYPE c) \ __RAPTOR_MPFR_ATTRIBUTES \ TYPE __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME##_##LLVM_TYPE( \ TYPE a, TYPE b, TYPE c, int64_t exponent, int64_t significand, \ int64_t mode, const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(fma, OP_TYPE, LLVM_OP_NAME, LLVM_TYPE, \ - FROM_TYPE, TYPE, a, b, c); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, \ + LLVM_OP_NAME, LLVM_TYPE)(a, b, \ + c); \ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ @@ -859,17 +860,14 @@ void raptor_fprt_op_clear(); #define __RAPTOR_MPFR_FCMP_IMPL(NAME, ORDERED, CMP, FROM_TYPE, TYPE, MPFR_GET, \ ROUNDING_MODE) \ __RAPTOR_MCA_ORIGINAL_FUNC_DECL(bool, FROM_TYPE, fcmp, NAME,, TYPE a, TYPE b)\ - __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(cmp, FROM_TYPE, bool & result, TYPE a, \ - TYPE b) \ __RAPTOR_MPFR_ATTRIBUTES \ bool __raptor_fprt_##FROM_TYPE##_fcmp_##NAME( \ TYPE a, TYPE b, int64_t exponent, int64_t significand, int64_t mode, \ const char *loc, mpfr_t *scratch) { \ if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ - if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - __RAPTOR_MCA_BYPASS_MPFR_FUNC(cmp, fcmp, NAME,, FROM_TYPE, bool, a, \ - b); \ + if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ + return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, fcmp, NAME)(a, b); \ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp index 14b144af..e9ce08c3 100644 --- a/runtime/obj/MonteCarloArithmetic.cpp +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -547,8 +547,8 @@ }; mcalite_context_t mcalite_context{1}; } - #define __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(OP, FROM_TY, ...) \ - int __raptor_mca_##OP##_##FROM_TY(__VA_ARGS__) + #define __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(CPP_TY, OP, FROM_TY, ...) \ + CPP_TY __raptor_mca_##OP##_##FROM_TY(__VA_ARGS__) #define __RAPTOR_MCALITE_CALL(OP, MODE, ...) \ mca_##OP##_##MODE(__VA_ARGS__, mcalite_context.t, mcalite_context.ntrials, \ &(mcalite_context.rng), mcalite_context.results.data()) @@ -567,21 +567,20 @@ break; \ default: err = -1; break; \ } \ - if (err == 0) { result = mcalite_context.results[0]; } \ - else { \ + if (err != 0) { \ std::cerr << "Error in mode " << mcalite_context.mode; \ std::cerr << " with op " << #OP << std::endl; \ + abort(); \ } \ - return err; \ + return mcalite_context.results[0]; \ } #define __RAPTOR_MCALITE_BINARY_OP(OP, FROM_TY, CPP_TY) \ __RAPTOR_MPFR_ATTRIBUTES \ - __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(OP, FROM_TY, \ - CPP_TY & result, CPP_TY x, CPP_TY y) \ + __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(CPP_TY, OP, FROM_TY, CPP_TY x, CPP_TY y)\ __RAPTOR_MCALITE_OP_FUNC_BODY(OP, x, y) #define __RAPTOR_MCALITE_UNARY_OP(OP, FROM_TY, CPP_TY) \ __RAPTOR_MPFR_ATTRIBUTES \ - __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(OP, FROM_TY, CPP_TY & result, CPP_TY x) \ + __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(CPP_TY, OP, FROM_TY, CPP_TY x) \ __RAPTOR_MCALITE_OP_FUNC_BODY(OP, x) #define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ From 24bb80cd5fb3ab9d5c256598149e511ce6475d73 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Fri, 4 Sep 2026 19:22:30 +0900 Subject: [PATCH 06/10] Modified pass to only instrument MCAlite supported ops, removed calls to original in runtime --- pass/RaptorLogic.cpp | 14 ++++++++++++++ runtime/ir/Mpfr.cpp | 46 ++++++++++++++------------------------------ 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/pass/RaptorLogic.cpp b/pass/RaptorLogic.cpp index 1e6b19b4..9b47498f 100644 --- a/pass/RaptorLogic.cpp +++ b/pass/RaptorLogic.cpp @@ -687,6 +687,17 @@ class TruncateGenerator : public llvm::InstVisitor, return; } + if (Mode == TruncOpMCAMCAliteMode) { + // MCAlite only performs fadd, fsub, fmul and fdiv binary operations + switch (BO.getOpcode()) { + case BinaryOperator::FAdd: + case BinaryOperator::FSub: + case BinaryOperator::FMul: + case BinaryOperator::FDiv: + break; + default: return; break; + } + } auto newI = getNewFromOriginal(&BO); IRBuilder<> B(newI); auto newLHS = truncate(B, getNewFromOriginal(oldLHS)); @@ -726,6 +737,9 @@ class TruncateGenerator : public llvm::InstVisitor, bool handleIntrinsic(llvm::CallBase &CI, Intrinsic::ID ID) { if (isDbgInfoIntrinsic(ID)) return true; + + // MCAlite do not support intrinsics + if (Mode == TruncOpMCAMCAliteMode) { return true; } auto newI = cast(getNewFromOriginal(&CI)); IRBuilder<> B(newI); diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index de284c4a..02c291b6 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -96,15 +96,6 @@ #ifdef __RAPTOR_MCALITE_MODE #define __RAPTOR_MCA_BYPASS_MPFR true #include - #define __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ - ...) /* LLVM_TYPE if it exists */ \ - __raptor_fprt_original_ ## FROM_TYPE ## _ ## OP_TYPE ## _ ## LLVM_OP_NAME\ - ## __VA_OPT__(_) ## __VA_ARGS__ - #define __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET_TYPE, FROM_TYPE, OP_TYPE, \ - LLVM_OP_NAME, LLVM_TYPE, ...) \ - __RAPTOR_MPFR_ORIGINAL_ATTRIBUTES \ - RET_TYPE __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,\ - LLVM_TYPE)(__VA_ARGS__); #define __RAPTOR_MCA_OP_FUNC_DECL(RET_TYPE, OP_NAME, FROM_TYPE, ...) \ __RAPTOR_MPFR_ATTRIBUTES \ RET_TYPE __RAPTOR_MCA_CONCAT(OP_NAME##_, FROM_TYPE)(__VA_ARGS__); @@ -119,8 +110,6 @@ using namespace std::literals::string_view_literals; \ __RAPTOR_MCA_OP_FUNC_IF(OP_TYPE, "unaryop"sv, LLVM_OP_NAME, "fneg"sv, \ neg, FROM_TYPE, __VA_ARGS__); \ - return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,\ - LLVM_TYPE)(__VA_ARGS__); \ } while (0) #define __RAPTOR_MCA_BYPASS_MPFR_BINARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ LLVM_TYPE, ...) \ @@ -134,9 +123,9 @@ mul, FROM_TYPE, __VA_ARGS__); \ __RAPTOR_MCA_OP_FUNC_IF(OP_TYPE, "binop"sv, LLVM_OP_NAME, "fdiv"sv, \ div, FROM_TYPE, __VA_ARGS__); \ - return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,\ - LLVM_TYPE)(__VA_ARGS__); \ } while (0) + #define __RAPTOR_MCA_BYPASS_MPFR_ERR(prefix, OP_TYPE, LLVM_OP_NAME) \ + fprintf(stderr, "%s %s %s\n", #prefix, #OP_TYPE, #LLVM_OP_NAME); abort(); #define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, neg, FROM_TY, CPP_TY x) \ @@ -617,8 +606,6 @@ void raptor_fprt_op_clear(); // this. We need to detect these patterns #define __RAPTOR_MPFR_LROUND(OP_TYPE, LLVM_OP_NAME, FROM_TYPE, RET, ARG1, \ MPFR_SET_ARG1, ROUNDING_MODE) \ - __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ - ARG1 a) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, int64_t exponent, int64_t significand, int64_t mode, \ @@ -626,8 +613,8 @@ void raptor_fprt_op_clear(); if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, \ - LLVM_OP_NAME)(a); \ + __RAPTOR_MCA_BYPASS_MPFR_ERR("Unsupported MCAlite op", OP_TYPE, \ + LLVM_OP_NAME); \ } \ } \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ @@ -641,8 +628,6 @@ void raptor_fprt_op_clear(); #define __RAPTOR_MPFR_SINGOP(OP_TYPE, LLVM_OP_NAME, MPFR_FUNC_NAME, FROM_TYPE, \ RET, MPFR_GET, ARG1, MPFR_SET_ARG1, \ ROUNDING_MODE) \ - __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ - ARG1 a) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, int64_t exponent, int64_t significand, int64_t mode, \ @@ -651,6 +636,8 @@ void raptor_fprt_op_clear(); if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ __RAPTOR_MCA_BYPASS_MPFR_UNARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, a);\ + __RAPTOR_MCA_BYPASS_MPFR_ERR("Unsupported MCAlite op", OP_TYPE, \ + LLVM_OP_NAME); \ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ @@ -690,8 +677,6 @@ void raptor_fprt_op_clear(); #define __RAPTOR_MPFR_BIN_INT(OP_TYPE, LLVM_OP_NAME, MPFR_FUNC_NAME, \ FROM_TYPE, RET, MPFR_GET, ARG1, MPFR_SET_ARG1, \ ARG2, ROUNDING_MODE) \ - __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ - ARG1 a, ARG2 b) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, ARG2 b, int64_t exponent, int64_t significand, int64_t mode, \ @@ -699,8 +684,8 @@ void raptor_fprt_op_clear(); if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, \ - LLVM_OP_NAME)(a, b); \ + __RAPTOR_MCA_BYPASS_MPFR_ERR("Unsupported MCAlite op", OP_TYPE, \ + LLVM_OP_NAME); \ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ @@ -738,8 +723,6 @@ void raptor_fprt_op_clear(); #define __RAPTOR_MPFR_BIN(OP_TYPE, LLVM_OP_NAME, MPFR_FUNC_NAME, FROM_TYPE, \ RET, MPFR_GET, ARG1, MPFR_SET_ARG1, ARG2, \ MPFR_SET_ARG2, ROUNDING_MODE) \ - __RAPTOR_MCA_ORIGINAL_FUNC_DECL(RET, FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, \ - ARG1 a, ARG2 b) \ __RAPTOR_MPFR_ATTRIBUTES \ RET __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME( \ ARG1 a, ARG2 b, int64_t exponent, int64_t significand, int64_t mode, \ @@ -749,6 +732,8 @@ void raptor_fprt_op_clear(); if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ __RAPTOR_MCA_BYPASS_MPFR_BINARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, a,\ b); \ + __RAPTOR_MCA_BYPASS_MPFR_ERR("Unsupported MCAlite op", OP_TYPE, \ + LLVM_OP_NAME); \ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ @@ -793,8 +778,6 @@ void raptor_fprt_op_clear(); #define __RAPTOR_MPFR_FMULADD(OP_TYPE, LLVM_OP_NAME, FROM_TYPE, TYPE, \ MPFR_TYPE, LLVM_TYPE, ROUNDING_MODE) \ - __RAPTOR_MCA_ORIGINAL_FUNC_DECL(TYPE, FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ - LLVM_TYPE, TYPE a, TYPE b, TYPE c) \ __RAPTOR_MPFR_ATTRIBUTES \ TYPE __raptor_fprt_##FROM_TYPE##_##OP_TYPE##_##LLVM_OP_NAME##_##LLVM_TYPE( \ TYPE a, TYPE b, TYPE c, int64_t exponent, int64_t significand, \ @@ -802,9 +785,8 @@ void raptor_fprt_op_clear(); if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, OP_TYPE, \ - LLVM_OP_NAME, LLVM_TYPE)(a, b, \ - c); \ + __RAPTOR_MCA_BYPASS_MPFR_ERR("Unsupported MCAlite op", OP_TYPE, \ + LLVM_OP_NAME); \ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ @@ -859,7 +841,6 @@ void raptor_fprt_op_clear(); // TODO This does not currently make distinctions between ordered/unordered. #define __RAPTOR_MPFR_FCMP_IMPL(NAME, ORDERED, CMP, FROM_TYPE, TYPE, MPFR_GET, \ ROUNDING_MODE) \ - __RAPTOR_MCA_ORIGINAL_FUNC_DECL(bool, FROM_TYPE, fcmp, NAME,, TYPE a, TYPE b)\ __RAPTOR_MPFR_ATTRIBUTES \ bool __raptor_fprt_##FROM_TYPE##_fcmp_##NAME( \ TYPE a, TYPE b, int64_t exponent, int64_t significand, int64_t mode, \ @@ -867,7 +848,8 @@ void raptor_fprt_op_clear(); if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - return __RAPTOR_MCA_ORIGINAL_FUNCNAME(FROM_TYPE, fcmp, NAME)(a, b); \ + __RAPTOR_MCA_BYPASS_MPFR_ERR("Unsupported MCAlite op", OP_TYPE, \ + LLVM_OP_NAME); \ } \ } \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ From f03d389c9d8802b3c9da3529dcf7e7c2890e9f73 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Mon, 7 Sep 2026 18:34:00 +0900 Subject: [PATCH 07/10] Use atomic to make stream to mca_rng_seed unique per thread. --- runtime/obj/MonteCarloArithmetic.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp index e9ce08c3..01d96c05 100644 --- a/runtime/obj/MonteCarloArithmetic.cpp +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -487,6 +487,7 @@ PB, /* Precision Bounding (PB): round(inexact(x) op inexact(y)). */ FULL /* Full MCA: round(inexact(inexact(x) op inexact(y))). */ }; + std::atomic rng_stream; struct mcalite_context_t { uint64_t rng_seed = 42; int t = 24; // virtual precision @@ -538,14 +539,14 @@ std::cout << "rng_seed = " << rng_seed << ", t = " << t << ", "; std::cout << "ntrials = " << ntrials << ", mode = " << mode_str(); } - mcalite_context_t(uint64_t rng_stream) { + mcalite_context_t() { parse_env(); results.resize(ntrials); - mca_rng_seed(&rng, rng_seed, rng_stream); - print(); std::cout << ", rng_stream " << rng_stream << std::endl; + auto stream_id = rng_stream++; + mca_rng_seed(&rng, rng_seed, stream_id); } }; - mcalite_context_t mcalite_context{1}; + thread_local mcalite_context_t mcalite_context; } #define __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(CPP_TY, OP, FROM_TY, ...) \ CPP_TY __raptor_mca_##OP##_##FROM_TY(__VA_ARGS__) From 0714fd3216c384fb541717379a57b09979ced1b1 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Mon, 7 Sep 2026 18:40:52 +0900 Subject: [PATCH 08/10] Add ability to suppress output when MCA_QUIET environment variable is set to anything but empty --- runtime/obj/MonteCarloArithmetic.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp index 01d96c05..72dde1f2 100644 --- a/runtime/obj/MonteCarloArithmetic.cpp +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -493,6 +493,7 @@ int t = 24; // virtual precision size_t ntrials = 5; // Number of repetition per operation mcalite_mode mode = mcalite_mode::PB; + bool quiet = false; std::vector results; mca_rng rng; void parse_env() { @@ -525,6 +526,10 @@ abort(); } } + env_val = getenv("MCA_QUIET"); + if (env_val != nullptr) { + quiet = true; + } } std::string mode_str() { std::string str = "FULL"; @@ -544,6 +549,9 @@ results.resize(ntrials); auto stream_id = rng_stream++; mca_rng_seed(&rng, rng_seed, stream_id); + if (!quiet) { + print(); std::cout << ", rng_stream " << stream_id << std::endl; + } } }; thread_local mcalite_context_t mcalite_context; From 49498d3e7625e0f55696e5b83b7699ed303cbaef Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Mon, 7 Sep 2026 18:49:09 +0900 Subject: [PATCH 09/10] Add calls to mca_compute_stats, accumulate stats per "loc" and print stats --- runtime/ir/Mpfr.cpp | 20 +++++---- runtime/obj/MonteCarloArithmetic.cpp | 61 ++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index 02c291b6..39227abb 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -128,11 +128,16 @@ fprintf(stderr, "%s %s %s\n", #prefix, #OP_TYPE, #LLVM_OP_NAME); abort(); #define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ - __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, neg, FROM_TY, CPP_TY x) \ - __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, add, FROM_TY, CPP_TY x, CPP_TY y) \ - __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, sub, FROM_TY, CPP_TY x, CPP_TY y) \ - __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, mul, FROM_TY, CPP_TY x, CPP_TY y) \ - __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, div, FROM_TY, CPP_TY x, CPP_TY y) + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, neg, FROM_TY, CPP_TY x, \ + const char * loc) \ + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, add, FROM_TY, CPP_TY x, CPP_TY y, \ + const char * loc) \ + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, sub, FROM_TY, CPP_TY x, CPP_TY y, \ + const char * loc) \ + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, mul, FROM_TY, CPP_TY x, CPP_TY y, \ + const char * loc) \ + __RAPTOR_MCA_OP_FUNC_DECL(CPP_TY, div, FROM_TY, CPP_TY x, CPP_TY y, \ + const char * loc) #include "raptor/FloatTypes.def" #endif #else @@ -635,7 +640,8 @@ void raptor_fprt_op_clear(); if (__raptor_fprt_is_op_mode(mode)) { \ if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ - __RAPTOR_MCA_BYPASS_MPFR_UNARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, a);\ + __RAPTOR_MCA_BYPASS_MPFR_UNARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, a, \ + loc); \ __RAPTOR_MCA_BYPASS_MPFR_ERR("Unsupported MCAlite op", OP_TYPE, \ LLVM_OP_NAME); \ } \ @@ -731,7 +737,7 @@ void raptor_fprt_op_clear(); if constexpr(__RAPTOR_MCA_BYPASS_MPFR) { \ if (__raptor_fprt_mca_type_is(mode, MCAType::MCAlite)) { \ __RAPTOR_MCA_BYPASS_MPFR_BINARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME,, a,\ - b); \ + b, loc); \ __RAPTOR_MCA_BYPASS_MPFR_ERR("Unsupported MCAlite op", OP_TYPE, \ LLVM_OP_NAME); \ } \ diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp index 72dde1f2..51febf11 100644 --- a/runtime/obj/MonteCarloArithmetic.cpp +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -479,6 +479,9 @@ #ifdef __RAPTOR_MCALITE_MODE #define __RAPTOR_USE_MCALITE true + #include + #include + #include #include #include namespace { @@ -488,6 +491,31 @@ FULL /* Full MCA: round(inexact(inexact(x) op inexact(y))). */ }; std::atomic rng_stream; + struct mcalite_accumulate_stats { + double mu = 0; + double variance = 0; + double sigma = 0; + double s = 0; + void accumulate_stats(double in_mu, double in_sigma) { + mu += in_mu; + variance += (in_sigma * in_sigma); + } + void calculate() { + sigma = std::sqrt(variance); + if (variance == 0.0) { + s = INFINITY; + } else if (mu == 0.0) { + s = -INFINITY; + } else { + s = -std::log2(sigma / std::fabs(mu)); + } + } + std::string str() { + std::stringstream ss; + ss << "mu = " << mu << ", sigma = " << sigma << ", s = " << s; + return ss.str(); + } + }; struct mcalite_context_t { uint64_t rng_seed = 42; int t = 24; // virtual precision @@ -495,7 +523,22 @@ mcalite_mode mode = mcalite_mode::PB; bool quiet = false; std::vector results; + mca_stats stats; + std::map acc_stats; mca_rng rng; + void print_stats(mca_stats * in) { + std::cout << "mu = " << in->mu << ", sigma = " << in->sigma; + std::cout << ", s = " << in->s << std::endl; + } + int calc_stats(const char *loc) { + int err = mca_compute_stats(results.data(), ntrials, &stats); + if (!quiet) { + std::cout << "MCAlite stats at " << loc << ": "; + print_stats(&stats); + } + acc_stats[loc].accumulate_stats(stats.mu, stats.sigma); + return err; + } void parse_env() { // Get the seed, t, ntrials and mode from env var. char *env_val = getenv("MCA_SEED"); @@ -553,6 +596,13 @@ print(); std::cout << ", rng_stream " << stream_id << std::endl; } } + ~mcalite_context_t() { + for (auto acc_stat : acc_stats) { + acc_stat.second.calculate(); + std::cout << "MCAlite accumulated stats at " << acc_stat.first; + std::cout << ": " << acc_stat.second.str() << std::endl; + } + } }; thread_local mcalite_context_t mcalite_context; } @@ -576,20 +626,25 @@ break; \ default: err = -1; break; \ } \ + if (err == 0 && mcalite_context.ntrials > 1) { \ + err = mcalite_context.calc_stats(loc); \ + } \ if (err != 0) { \ std::cerr << "Error in mode " << mcalite_context.mode; \ - std::cerr << " with op " << #OP << std::endl; \ + std::cerr << " with op " << #OP << " at " << loc << std::endl; \ abort(); \ } \ return mcalite_context.results[0]; \ } #define __RAPTOR_MCALITE_BINARY_OP(OP, FROM_TY, CPP_TY) \ __RAPTOR_MPFR_ATTRIBUTES \ - __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(CPP_TY, OP, FROM_TY, CPP_TY x, CPP_TY y)\ + __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(CPP_TY, OP, FROM_TY, CPP_TY x, CPP_TY y,\ + const char * loc) \ __RAPTOR_MCALITE_OP_FUNC_BODY(OP, x, y) #define __RAPTOR_MCALITE_UNARY_OP(OP, FROM_TY, CPP_TY) \ __RAPTOR_MPFR_ATTRIBUTES \ - __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(CPP_TY, OP, FROM_TY, CPP_TY x) \ + __RAPTOR_MCALITE_OP_FUNC_SIGNATURE(CPP_TY, OP, FROM_TY, CPP_TY x, \ + const char * loc) \ __RAPTOR_MCALITE_OP_FUNC_BODY(OP, x) #define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ From 092e0e6e9008178e7ed1779c4d88e26fed359873 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Thu, 10 Sep 2026 18:57:40 +0900 Subject: [PATCH 10/10] Fix build error when not building with MCAlite --- runtime/ir/Mpfr.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index 39227abb..645c58bc 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -147,10 +147,11 @@ #ifndef __RAPTOR_MCA_BYPASS_MPFR #define __RAPTOR_MCA_BYPASS_MPFR false - #define __RAPTOR_MCA_ORIGINAL_FUNC_DECL(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + #define __RAPTOR_MCA_BYPASS_MPFR_UNARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ + LLVM_TYPE, ...) + #define __RAPTOR_MCA_BYPASS_MPFR_BINARY(FROM_TYPE, OP_TYPE, LLVM_OP_NAME, \ LLVM_TYPE, ...) - #define __RAPTOR_MCA_BYPASS_MPFR_FUNC_DECL(FUNC_NAME, FROM_TYPE, ...) - #define __RAPTOR_MCA_BYPASS_MPFR_FUNC(FUNC_NAME, ...) + #define __RAPTOR_MCA_BYPASS_MPFR_ERR(prefix, OP_TYPE, LLVM_OP_NAME) #endif __RAPTOR_MPFR_ATTRIBUTES