From 80af92f806bdc6bf048d40f9e4bc297687fbe969 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Wed, 22 Jul 2026 20:15:44 +0900 Subject: [PATCH 01/14] Initial implementation of interface with verificarlo mca backend --- runtime/obj/MonteCarloArithmetic.cpp | 466 +++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 runtime/obj/MonteCarloArithmetic.cpp diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp new file mode 100644 index 00000000..ab42c8e1 --- /dev/null +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -0,0 +1,466 @@ +#include +#include + +#ifndef __RAPTOR_VERIFICARLOMCA_MODE + #ifdef __RAPTOR_VERIFICARLOMCA_INT_MODE + #define __RAPTOR_VERIFICARLOMCA_MODE + #endif +#endif + +// verificarlo uses _Float128 that needs extra definition +#ifdef __RAPTOR_VERIFICARLOMCA_MODE + // Clang has "unknown type name" error for _Float128 on x86 + #if defined(__clang__) && (defined(__i386) || defined(__x86_64)) + #define _Float128 __float128 + #endif + // Need to be defined before including mpfr.h to enable binary128 support + #define MPFR_WANT_FLOAT128 +#endif +// mpfr.h is included in Common.h +#include + +#ifdef __RAPTOR_VERIFICARLOMCA_MODE + #define __RAPTOR_USE_VERIFICARLOMCA true + // Includes needed to define interface to verificarlo + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + // Macros to help get function names of the corresponding backend + #define __RAPTOR_VERIFICARLOMCA_CONCAT(prefix,name,suffix) \ + prefix##name##suffix + #define __RAPTOR_VERIFICARLOMCA_INTERFLOP_API(BACKENDNAME, name) \ + __RAPTOR_VERIFICARLOMCA_CONCAT(INTERFLOP_, BACKENDNAME, _API)(name) + #define __RAPTOR_VERIFICARLOMCA_INEXACT(backendname, bits) \ + __RAPTOR_VERIFICARLOMCA_CONCAT(_, backendname, _inexact_binary##bits) + #define __RAPTOR_VERIFICARLOMCA_CONTEXT_T(backendname) \ + __RAPTOR_VERIFICARLOMCA_CONCAT(, backendname, _context_t) + #if defined(__cplusplus) + extern "C" { + #endif + // Typedefs copied from verificarlo repo file + // src/interflop-stdlib/interflop_stdlib.h + typedef void (*interflop_panic_t)(const char *msg); + typedef void File; + // Function signature copied from verificarlo repo file + // src/interflop-stdlib/interflop_stdlib.c + extern void interflop_set_handler(const char *name, void *function_ptr); + #ifdef __RAPTOR_VERIFICARLOMCA_INT_MODE + #define __RAPTOR_VERIFICARLOMCA_BACKENDNAME MCAINT + #define __RAPTOR_VERIFICARLOMCA_backendname mcaint + // Macro copied from verificarlo repo backends files + // src/backends/interflop-backend-mcaint/interflop_mca.h + #define INTERFLOP_MCAINT_API(name) interflop_mcaint_##name + // Function signatures copied from verificarlo repo backends files + // src/backends/interflop-backend-mcaint/interflop_mca.c + extern void INTERFLOP_MCAINT_API(pre_init)(interflop_panic_t panic, + File *stream, void **context); + extern void INTERFLOP_MCAINT_API(cli)(int argc, char **argv, + void *context); + extern void INTERFLOP_MCAINT_API(configure)(void *configure, + void *context); + extern void _mcaint_inexact_binary64(double *da, void *context); + extern void _mcaint_inexact_binary128(_Float128 *qa, void *context); + #else + #define __RAPTOR_VERIFICARLOMCA_BACKENDNAME MCAQUAD + #define __RAPTOR_VERIFICARLOMCA_backendname mcaquad + // Macro copied from verificarlo repo backends files + // src/backends/interflop-backend-mcaint/interflop_mca_int.h + #define INTERFLOP_MCAQUAD_API(name) interflop_mcaquad_##name + // Function signatures copied from verificarlo repo backends files + // src/backends/interflop-backend-mcaint/interflop_mca_int.c + extern void INTERFLOP_MCAQUAD_API(pre_init)(interflop_panic_t panic, + File *stream, void **context); + extern void INTERFLOP_MCAQUAD_API(cli)(int argc, char **argv, + void *context); + extern void INTERFLOP_MCAQUAD_API(configure)(void *configure, + void *context); + extern void _mcaquad_inexact_binary64(double *da, void *context); + extern void _mcaquad_inexact_binary128(_Float128 *qa, void *context); + #endif + #if defined(__cplusplus) + } + #endif + + // Enclose types/functions to interface with verificarlo in unnamed namespace + namespace { + // Typedef copied from verificarlo repo file + // src/interflop-stdlib/interflop_stdlib.h + typedef unsigned int IUint32_t; + typedef long int IInt64_t; + typedef unsigned long int IUint64_t; + typedef int IBool; + + // Definitions adapted from verificarlo repo backends files + // src/backends/interflop-backend-mcaint/interflop_mca_int.h and + // src/backends/interflop-backend-mcaquad/interflop_mca.h + // These definitions from mcaint and mcaquad are compatible so defining + // only once here. + /* define the available MCA modes of operation */ + typedef enum { + mca_mode_ieee, + mca_mode_mca, + mca_mode_pb, + mca_mode_rr, + _mca_mode_end_ + } mca_mode; + + /* define the available error modes */ + typedef enum { + mca_err_mode_rel, + mca_err_mode_abs, + mca_err_mode_all, + _mca_err_mode_end_ + } mca_err_mode; + + /* Interflop context */ + typedef struct { + IUint64_t seed; + float sparsity; + int binary32_precision; + int binary64_precision; + int absErr_exp; + IBool relErr; + IBool absErr; + IBool daz; + IBool ftz; + IBool choose_seed; + mca_mode mode; + } mcaquad_context_t; + + /* Interflop context */ + typedef struct { + IBool relErr; + IBool absErr; + IBool daz; + IBool ftz; + IBool choose_seed; + mca_mode mode; + int binary32_precision; + int binary64_precision; + int absErr_exp; + float sparsity; + IUint64_t seed; + } mcaint_context_t; + + using mca_context_t = __RAPTOR_VERIFICARLOMCA_CONTEXT_T( + __RAPTOR_VERIFICARLOMCA_backendname); + + typedef struct { + IUint64_t seed; + float sparsity; + IUint32_t precision_binary32; + IUint32_t precision_binary64; + mca_mode mode; + mca_err_mode err_mode; + IInt64_t max_abs_err_exponent; + IUint32_t daz; + IUint32_t ftz; + } mca_conf_t; + + // Helper type for compile time type check + template + using is_float_t = std::enable_if_t, bool>; + template + using is_double_t = std::enable_if_t, bool>; + template + using is__Float128_t = std::enable_if_t, + bool>; + template + using is_float_or_double_t = std::enable_if_t< + std::is_same_v || std::is_same_v, bool>; + template + using is_double_or__Float128_t = std::enable_if_t< + std::is_same_v || std::is_same_v, bool>; + template = true> + using inexact_t = std::conditional_t, double, + _Float128>; + // Using a struct because the context needs initialization + struct verificarlo_mca_context_t { + // Context used for the _mca*_inexact_binary64 functions + void * context = nullptr; + verificarlo_mca_context_t(); + }; + // Global so that it gets automatically initialized through construction + verificarlo_mca_context_t verificarlo_mca_context; + + // Set the context with configure + void set_verificarlo_mca_context(void *configure, void *context) { + __RAPTOR_VERIFICARLOMCA_INTERFLOP_API( + __RAPTOR_VERIFICARLOMCA_BACKENDNAME, configure)(configure, context); + } + void set_verificarlo_mca_context(int argc, char **argv, void *context) { + __RAPTOR_VERIFICARLOMCA_INTERFLOP_API( + __RAPTOR_VERIFICARLOMCA_BACKENDNAME, cli)(argc, argv, context); + } + // Returns the virtual precision used for MCA of floating point type T + template = true> + IUint32_t get_virtual_prec(void * context) { + return ((mca_context_t *)context)->binary32_precision; + } + template = true> + IUint32_t get_virtual_prec(void * context) { + return ((mca_context_t *)context)->binary64_precision; + } + // Function and definition adapted from verificarlo repo file + // src/vfcwrapper/main.c.in + static constexpr int MAX_ARGS=256; + void get_args_from_str(char *str, const char *err_msg_prefix, int &argc, + char *argv[MAX_ARGS]){ + if (str != NULL) { + char *spaceptr; + char *arg = strtok_r(str, " ", &spaceptr); + while (arg) { + if (argc >= MAX_ARGS) { + fprintf(stderr, "%s syntax error: too many arguments", + err_msg_prefix); + } + argv[argc++] = arg; + arg = strtok_r(NULL, " ", &spaceptr); + } + argv[argc] = NULL; + } + } + // Set the virtual precision used for MCA of floating point type T + template = true> + void set_virtual_prec(void * context, IUint32_t virtual_prec) { + int argc; + char *argv[MAX_ARGS]; + std::string str = "dummy --precision-binary32=" + + std::to_string(virtual_prec); + get_args_from_str(str.data(), "set_virtual_prec 32", argc, argv); + set_verificarlo_mca_context(argc, argv, context); + } + template = true> + void set_virtual_prec(void * context, IUint32_t virtual_prec) { + int argc; + char *argv[MAX_ARGS]; + std::string str = "dummy --precision-binary64=" + + std::to_string(virtual_prec); + get_args_from_str(str.data(), "set_virtual_prec 64", argc, argv); + set_verificarlo_mca_context(argc, argv, context); + } + // Return the high precision type used for MCA calculation from mpfr_t a, + // with the rounding mode rnd_mode + template = true> + inexact_t get_inexact_t_from(mpfr_t a, mpfr_rnd_t rnd_mode) { + return mpfr_get_d(a, rnd_mode); + } + template = true> + inexact_t get_inexact_t_from(mpfr_t a, mpfr_rnd_t rnd_mode) { + return mpfr_get_float128(a, rnd_mode); + } + // Assigns mpfr_t a with the value of val with rnd_mode rounding mode, + // where val is of the high precision type used for MCA calculation. + // Returns the return value from mpfr_set_* used underneath. + template = true> + int assign_inexact_t_to(mpfr_t a, inexact_t val, mpfr_rnd_t rnd_mode) { + return mpfr_set_d(a, val, rnd_mode); + } + template = true> + int assign_inexact_t_to(mpfr_t a, inexact_t val, mpfr_rnd_t rnd_mode) { + return mpfr_set_float128(a, val, rnd_mode); + } + // Apply MCA random perturbation to a of type T, with the parameters for + // MCA defined in context + template = true> + void mca_inexact(T &a, void *context) { + __RAPTOR_VERIFICARLOMCA_INEXACT(__RAPTOR_VERIFICARLOMCA_backendname, + 64)(&a, context); + } + template = true> + void mca_inexact(T &a, void *context) { + __RAPTOR_VERIFICARLOMCA_INEXACT(__RAPTOR_VERIFICARLOMCA_backendname, + 128)(&a, context); + } + + #if defined(__cplusplus) + extern "C" { + #endif + // Function definitions copied from verificarlo repo file + // src/vfcwrapper/main.c.in + void _vfc_panic(const char *msg) { fprintf(stderr, "%s", msg); exit(1);} + pid_t get_tid() { return syscall(__NR_gettid); } + long _vfc_strtol(const char *nptr, char **endptr, int *error) { + *error = 0; + errno = 0; + long val = strtoll(nptr, endptr, 10); + if (errno != 0) { + *error = 1; + } + return val; + } + double _vfc_strtod(const char *nptr, char **endptr, int *error) { + *error = 0; + errno = 0; + double val = strtod(nptr, endptr); + if (errno != 0) { + *error = 1; + } + return val; + } + // Function adapted from verificarlo repo file + // src/vfcwrapper/main.c.in + /* Parse the different VFC_BACKENDS variables per priorty order */ + /* 1- VFC_BACKENDS */ + /* 2- VFC_BACKENDS_FROM_FILE */ + /* Set the backends read in vfc_backends */ + /* Set the name of the environment variable read in vfc_backends_env */ + void parse_vfc_backends_env(int &backend_argc, char *backend_argv[MAX_ARGS]) { + char *vfc_backends_v = NULL; + const char *vfc_backends_env_v = NULL; + char ** vfc_backends = &vfc_backends_v; + const char ** vfc_backends_env = &vfc_backends_env_v; + + /* Parse VFC_BACKENDS */ + *vfc_backends_env = "VFC_BACKENDS"; + char *env_val = getenv(*vfc_backends_env); + if (env_val != NULL) { + size_t env_len = strlen(env_val); + *vfc_backends = (char *)malloc(env_len + 1); + if (*vfc_backends == NULL) { + fprintf(stderr, "Memory allocation failed for %s", *vfc_backends_env); + } + strcpy(*vfc_backends, env_val); + } else { + *vfc_backends = NULL; + } + + /* Parse VFC_BACKENDS_FROM_FILE if VFC_BACKENDS is empty*/ + if (*vfc_backends == NULL) { + *vfc_backends_env = "VFC_BACKENDS_FROM_FILE"; + char *vfc_backends_fromfile_file = getenv(*vfc_backends_env); + if (vfc_backends_fromfile_file != NULL) { + FILE *fi = fopen(vfc_backends_fromfile_file, "r"); + if (fi == NULL) { + fprintf(stderr, "Error while opening file pointed by %s: %s", + *vfc_backends_env, strerror(errno)); + } else { + size_t len = 0; + ssize_t nread; + nread = getline(vfc_backends, &len, fi); + if (nread == -1) { + fprintf(stderr, "Error while reading file pointed by %s: %s", + *vfc_backends_env, strerror(errno)); + } else { + if ((*vfc_backends)[nread - 1] == '\n') { + (*vfc_backends)[nread - 1] = '\0'; + } + } + } + } + } + + get_args_from_str(vfc_backends_v, vfc_backends_env_v, backend_argc, + backend_argv); + } + #if defined(__cplusplus) + } + #endif + + // Interflop needs some set up, then allocate and set context + verificarlo_mca_context_t::verificarlo_mca_context_t() { + interflop_set_handler("argp_parse", (void *)argp_parse); + interflop_set_handler("panic", (void *)_vfc_panic); + interflop_set_handler("exit", (void *)exit); + interflop_set_handler("fopen", (void *)fopen); + interflop_set_handler("fprintf", (void *)fprintf); + interflop_set_handler("getenv", (void *)getenv); + interflop_set_handler("gettid", (void *)get_tid); + interflop_set_handler("malloc", (void *)malloc); + interflop_set_handler("sprintf", (void *)sprintf); + interflop_set_handler("strcasecmp", (void *)strcasecmp); + interflop_set_handler("strerror", (void *)strerror); + interflop_set_handler("strtol", (void *)_vfc_strtol); + interflop_set_handler("strtod", (void *)_vfc_strtod); + interflop_set_handler("vfprintf", (void *)vfprintf); + interflop_set_handler("vwarnx", (void *)vwarnx); + interflop_set_handler("gettimeofday", (void *)gettimeofday); + // pre_init also allocates and initialize the context + __RAPTOR_VERIFICARLOMCA_INTERFLOP_API( + __RAPTOR_VERIFICARLOMCA_BACKENDNAME, pre_init)( + _vfc_panic, stderr, &context); + // Skipping interflop init since it is mostly registering hooked function + // for instrumentation (and we are doing it in RAPTOR instead) + int backend_argc = 0; + char *backend_argv[MAX_ARGS]; + parse_vfc_backends_env(backend_argc, backend_argv); + if (backend_argc > 0) { + set_verificarlo_mca_context(backend_argc, backend_argv, context); + } else { + // Default configuration used to initialize the context + // Also used to set the context when configuration changes + mca_conf_t mca_conf = { + .seed = 0ULL, // Default to 0, but always sets the seed to chosen + // If random (0,1) num > sparsity, MCA is not applied. + .sparsity = 1.0f, // Always apply MCA + // Between 1 and double precision pseudo-mantissa encoding size (52) + .precision_binary32 = 24, // default to float mantissa size (23+1) + // Between 1 and quad precision pseudo mantissa encoding size (112) + .precision_binary64 = 53, // default to double mantissa size (52+1) + // Only add inexact to input operands. + .mode = mca_mode::mca_mode_pb, // Irrelevant for inexact. + // The mode matching formula (1) in Verificarlo + .err_mode = mca_err_mode::mca_err_mode_rel, + // Unused for relative error mode mca_err_mode_rel + .max_abs_err_exponent = 112, // default from verificarlo set to 112 + // Default to false, not dealing with this now + .daz = 0, // 0 for false, 1 for true + .ftz = 0 // 0 for false, 1 for true + }; + set_verificarlo_mca_context(&mca_conf, context); + } + } + } // end of unnamed namespace + + // verificarlo does not change virtual precision mid run, just get from conf + #define __RAPTOR_VERIFICARLOMCA_get_virtual_prec(CPP_TY) \ + do { \ + return get_virtual_prec(verificarlo_mca_context.context); \ + } while (0) + + #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode) \ + do { \ + if (virtual_prec != \ + get_virtual_prec(verificarlo_mca_context.context) \ + ) { \ + set_virtual_prec(verificarlo_mca_context.context,virtual_prec);\ + } \ + inexact_t high_prec_a = get_inexact_t_from(a, rnd_mode); \ + mca_inexact(high_prec_a, verificarlo_mca_context.context); \ + assign_inexact_t_to(a, high_prec_a, rnd_mode); \ + } while (0) +#else + #define __RAPTOR_USE_VERIFICARLOMCA false + #define __RAPTOR_VERIFICARLOMCA_get_virtual_prec(CPP_TY) + #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode) +#endif // __RAPTOR_VERIFICARLOMCA_MODE + +#define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ + 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 { \ + std::cerr << "__raptor_mca_get_virtural_prec_" << #FROM_TY; \ + std::cerr << " is not implemented." << std::endl; \ + abort(); \ + } \ + } \ + void __raptor_mca_inexact_##FROM_TY(mpfr_t a, unsigned int virtual_prec, \ + mpfr_rnd_t rnd_mode) { \ + if constexpr (__RAPTOR_USE_VERIFICARLOMCA) { \ + __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode); \ + } else { \ + std::cerr << "__raptor_mca_inexact_" << #FROM_TY; \ + std::cerr << " is not implemented." << std::endl; \ + abort(); \ + } \ + } +#include "raptor/FloatTypes.def" \ No newline at end of file From 22bfae4984dc5c5f40103060615d86412732788a Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Wed, 22 Jul 2026 20:17:10 +0900 Subject: [PATCH 02/14] Add use of MCA pb mode (inexact on inbound operand) in op-mode --- runtime/include/private/raptor/Common.h | 9 ++++++ runtime/ir/Mpfr.cpp | 41 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/runtime/include/private/raptor/Common.h b/runtime/include/private/raptor/Common.h index 3fdfa753..2e941726 100644 --- a/runtime/include/private/raptor/Common.h +++ b/runtime/include/private/raptor/Common.h @@ -131,4 +131,13 @@ template To checked_raptor_bitcast(From from) { #include "raptor/FloatTypes.def" +#define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ + __RAPTOR_MPFR_DECL_ATTRIBUTES \ + unsigned int __raptor_mca_get_virtural_prec_##FROM_TY(mpfr_t a, \ + const char *loc); \ + __RAPTOR_MPFR_DECL_ATTRIBUTES \ + void __raptor_mca_inexact_##FROM_TY(mpfr_t a, unsigned int virtual_prec, \ + mpfr_rnd_t rnd_mode); +#include "raptor/FloatTypes.def" + #endif // _RAPTOR_COMMON_H_ diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index 3333faa6..f6bea64c 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -82,6 +82,28 @@ } while (0) #endif +#ifndef __RAPTOR_MCA_MODE + #ifdef __RAPTOR_VERIFICARLOMCA_MODE + #define __RAPTOR_MCA_MODE + #else + #ifdef __RAPTOR_VERIFICARLOMCA_INT_MODE + #define __RAPTOR_MCA_MODE + #endif + #endif +#endif + +#ifdef __RAPTOR_MCA_MODE + #define __RAPTOR_USE_MCA true + + #define __RAPTOR_MCA_CONCAT(prefix, FROM_TY) __raptor_mca_##prefix##FROM_TY + #define __RAPTOR_MCA_INEXACT(FROM_TY, a, loc, rnd_mode) \ + __RAPTOR_MCA_CONCAT(inexact_, FROM_TY)(a, \ + __RAPTOR_MCA_CONCAT(get_virtural_prec_, FROM_TY)(a, loc), rnd_mode); +#else + #define __RAPTOR_USE_MCA false + #define __RAPTOR_MCA_INEXACT(FROM_TY, a, loc, rnd_mode) +#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) { @@ -563,6 +585,9 @@ void raptor_fprt_op_clear(); if (__raptor_fprt_is_op_mode(mode)) { \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ + if constexpr (__RAPTOR_USE_MCA) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ + } \ mpfr_##MPFR_FUNC_NAME(scratch[2], scratch[0], ROUNDING_MODE); \ RET c = mpfr_get_##MPFR_GET(scratch[2], ROUNDING_MODE); \ return c; \ @@ -593,6 +618,9 @@ void raptor_fprt_op_clear(); if (__raptor_fprt_is_op_mode(mode)) { \ __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ + if constexpr (__RAPTOR_USE_MCA) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ + } \ mpfr_##MPFR_FUNC_NAME(scratch[2], scratch[0], b, ROUNDING_MODE); \ RET c = mpfr_get_##MPFR_GET(scratch[2], ROUNDING_MODE); \ return c; \ @@ -622,6 +650,10 @@ void raptor_fprt_op_clear(); __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); \ + if constexpr (__RAPTOR_USE_MCA) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE); \ + } \ mpfr_##MPFR_FUNC_NAME(scratch[2], scratch[0], scratch[1], \ ROUNDING_MODE); \ RET c = mpfr_get_##MPFR_GET(scratch[2], ROUNDING_MODE); \ @@ -656,6 +688,11 @@ void raptor_fprt_op_clear(); mpfr_set_##MPFR_TYPE(scratch[0], a, ROUNDING_MODE); \ mpfr_set_##MPFR_TYPE(scratch[1], b, ROUNDING_MODE); \ mpfr_set_##MPFR_TYPE(scratch[2], c, ROUNDING_MODE); \ + if constexpr (__RAPTOR_USE_MCA) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE); \ + } \ mpfr_mul(scratch[0], scratch[0], scratch[1], ROUNDING_MODE); \ mpfr_add(scratch[0], scratch[0], scratch[2], ROUNDING_MODE); \ TYPE res = mpfr_get_##MPFR_TYPE(scratch[0], ROUNDING_MODE); \ @@ -696,6 +733,10 @@ void raptor_fprt_op_clear(); __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); \ + if constexpr (__RAPTOR_USE_MCA) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE); \ + } \ int ret = mpfr_cmp(scratch[0], scratch[1]); \ return ret CMP; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ From 383c507d2d9797a6bc12608e9a1ae7ef6a0d389e Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Wed, 22 Jul 2026 20:18:39 +0900 Subject: [PATCH 03/14] Modified cmake files to compile with MCA when __RAPTOR_VERIFICARLOMCA_LIB_PATH is defined --- CMakeLists.txt | 17 +++++++++++++++++ runtime/CMakeLists.txt | 1 + 2 files changed, 18 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06bb3f7d..c4971e6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -369,6 +369,23 @@ install(PROGRAMS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/raptor_plot_float_histogram.py" DESTINATION bin) +if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) + if (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca.so") + string(APPEND CMAKE_CXX_FLAGS " -D__RAPTOR_VERIFICARLOMCA_MODE") + elseif (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca_int.so") + string(APPEND CMAKE_CXX_FLAGS " -D__RAPTOR_VERIFICARLOMCA_INT_MODE") + else() + message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH} does not include the expected library name") + if (NOT EXISTS "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}") + message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH} does not exists") + endif() + endif() + + add_library(verificarlo SHARED IMPORTED) + set_target_properties(verificarlo PROPERTIES + IMPORTED_LOCATION "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}" + ) +endif() add_subdirectory(runtime) add_subdirectory(test) add_subdirectory(wrappers) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 62de130e..ced63956 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -3,6 +3,7 @@ add_library( Raptor-RT-${LLVM_VERSION_MAJOR} obj/Counting.cpp obj/GarbageCollection.cpp + obj/MonteCarloArithmetic.cpp ir/Mpfr.cpp ir/Fprt.cpp ir/Log.cpp From 055a7834246eb3580fd35bcb73f8a2fafe9c5696 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Wed, 22 Jul 2026 20:19:55 +0900 Subject: [PATCH 04/14] Modified link options for tests to link in the verificarlo MCA when compiling tests --- test/lit.site.cfg.py.in | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index 48ec93a2..f9dc959e 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -105,7 +105,13 @@ config.substitutions.append(('%loadFlangRaptor', passPlugin)) newPM = ('-Wl,--load-pass-plugin=@RAPTOR_BINARY_DIR@/pass/LLDRaptor-' + config.llvm_ver + config.llvm_shlib_ext) config.substitutions.append(('%loadLLDRaptor', newPM)) -link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver + +verificarlomca_lib_path = "@__RAPTOR_VERIFICARLOMCA_LIB_PATH@" +verificarlomca_lib_dir = "/".join(verificarlomca_lib_path.split("/")[:-1]) +verificarlomca_lib_name = verificarlomca_lib_path.split("/")[-1].split(".")[0][3:] +verificarlomca_link_options = " -L" + verificarlomca_lib_dir + " -l" + verificarlomca_lib_name + " -linterflop_stdlib" + +link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver + verificarlomca_link_options config.substitutions.append(('%linkRaptorRT', link)) link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver From c50838ae598e2ecfc78892d974a10f2bb9c98cd6 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Thu, 23 Jul 2026 11:14:34 +0900 Subject: [PATCH 05/14] Fix build check linkage failure when __RAPTOR_VERIFICARLOMCA_LIB_PATH is not defined --- test/lit.site.cfg.py.in | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index f9dc959e..fed5b72f 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -107,9 +107,11 @@ config.substitutions.append(('%loadLLDRaptor', newPM)) verificarlomca_lib_path = "@__RAPTOR_VERIFICARLOMCA_LIB_PATH@" -verificarlomca_lib_dir = "/".join(verificarlomca_lib_path.split("/")[:-1]) -verificarlomca_lib_name = verificarlomca_lib_path.split("/")[-1].split(".")[0][3:] -verificarlomca_link_options = " -L" + verificarlomca_lib_dir + " -l" + verificarlomca_lib_name + " -linterflop_stdlib" +verificarlomca_link_options = "" +if verificarlomca_lib_path != "": + verificarlomca_lib_dir = "/".join(verificarlomca_lib_path.split("/")[:-1]) + verificarlomca_lib_name = verificarlomca_lib_path.split("/")[-1].split(".")[0][3:] + verificarlomca_link_options = " -L" + verificarlomca_lib_dir + " -l" + verificarlomca_lib_name + " -linterflop_stdlib" link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver + verificarlomca_link_options config.substitutions.append(('%linkRaptorRT', link)) From 8fa26c9db31b3706d071ddc858d93acec5c7dba9 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:30:42 +0900 Subject: [PATCH 06/14] Modified link options for tests to add rpath for verificarlo MCA when compiling tests --- test/lit.site.cfg.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index fed5b72f..091378e1 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -111,7 +111,7 @@ verificarlomca_link_options = "" if verificarlomca_lib_path != "": verificarlomca_lib_dir = "/".join(verificarlomca_lib_path.split("/")[:-1]) verificarlomca_lib_name = verificarlomca_lib_path.split("/")[-1].split(".")[0][3:] - verificarlomca_link_options = " -L" + verificarlomca_lib_dir + " -l" + verificarlomca_lib_name + " -linterflop_stdlib" + verificarlomca_link_options = " -L" + verificarlomca_lib_dir + " -l" + verificarlomca_lib_name + " -linterflop_stdlib" + " -Wl,-rpath=" + verificarlomca_lib_dir link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver + verificarlomca_link_options config.substitutions.append(('%linkRaptorRT', link)) From 957bb537a45d9977fe43c267225f59770490329b Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:44:39 +0900 Subject: [PATCH 07/14] Make MCA mode runtime controllable through VFC_BACKENDS_OPTIONS environment variable (same as verificarlo) --- runtime/include/private/raptor/Common.h | 2 +- runtime/ir/Mpfr.cpp | 37 ++++++++++++++++-------- runtime/obj/MonteCarloArithmetic.cpp | 38 +++++++++++++++++-------- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/runtime/include/private/raptor/Common.h b/runtime/include/private/raptor/Common.h index 2e941726..708614a3 100644 --- a/runtime/include/private/raptor/Common.h +++ b/runtime/include/private/raptor/Common.h @@ -137,7 +137,7 @@ template To checked_raptor_bitcast(From from) { const char *loc); \ __RAPTOR_MPFR_DECL_ATTRIBUTES \ void __raptor_mca_inexact_##FROM_TY(mpfr_t a, unsigned int virtual_prec, \ - mpfr_rnd_t rnd_mode); + mpfr_rnd_t rnd_mode, bool isOutbound); #include "raptor/FloatTypes.def" #endif // _RAPTOR_COMMON_H_ diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index f6bea64c..a5e4895a 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -96,12 +96,13 @@ #define __RAPTOR_USE_MCA true #define __RAPTOR_MCA_CONCAT(prefix, FROM_TY) __raptor_mca_##prefix##FROM_TY - #define __RAPTOR_MCA_INEXACT(FROM_TY, a, loc, rnd_mode) \ + #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); + __RAPTOR_MCA_CONCAT(get_virtural_prec_, FROM_TY)(a, loc), rnd_mode, \ + isOutbound); #else #define __RAPTOR_USE_MCA false - #define __RAPTOR_MCA_INEXACT(FROM_TY, a, loc, rnd_mode) + #define __RAPTOR_MCA_INEXACT(FROM_TY, a, loc, rnd_mode, isOutbound) #endif __RAPTOR_MPFR_ATTRIBUTES @@ -586,9 +587,12 @@ void raptor_fprt_op_clear(); __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ } \ mpfr_##MPFR_FUNC_NAME(scratch[2], scratch[0], ROUNDING_MODE); \ + if constexpr (__RAPTOR_USE_MCA) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, true); \ + } \ RET c = mpfr_get_##MPFR_GET(scratch[2], ROUNDING_MODE); \ return c; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ @@ -619,9 +623,12 @@ void raptor_fprt_op_clear(); __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ } \ mpfr_##MPFR_FUNC_NAME(scratch[2], scratch[0], b, ROUNDING_MODE); \ + if constexpr (__RAPTOR_USE_MCA) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, true); \ + } \ RET c = mpfr_get_##MPFR_GET(scratch[2], ROUNDING_MODE); \ return c; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ @@ -651,11 +658,14 @@ void raptor_fprt_op_clear(); mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ mpfr_set_##MPFR_SET_ARG2(scratch[1], b, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE, false);\ } \ mpfr_##MPFR_FUNC_NAME(scratch[2], scratch[0], scratch[1], \ ROUNDING_MODE); \ + if constexpr (__RAPTOR_USE_MCA) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, true); \ + } \ RET c = mpfr_get_##MPFR_GET(scratch[2], ROUNDING_MODE); \ return c; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ @@ -689,12 +699,15 @@ void raptor_fprt_op_clear(); mpfr_set_##MPFR_TYPE(scratch[1], b, ROUNDING_MODE); \ mpfr_set_##MPFR_TYPE(scratch[2], c, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE); \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE, false);\ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, false);\ } \ mpfr_mul(scratch[0], scratch[0], scratch[1], ROUNDING_MODE); \ mpfr_add(scratch[0], scratch[0], scratch[2], ROUNDING_MODE); \ + if constexpr (__RAPTOR_USE_MCA) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, true); \ + } \ TYPE res = mpfr_get_##MPFR_TYPE(scratch[0], ROUNDING_MODE); \ return res; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ @@ -734,8 +747,8 @@ void raptor_fprt_op_clear(); mpfr_set_##MPFR_GET(scratch[0], a, ROUNDING_MODE); \ mpfr_set_##MPFR_GET(scratch[1], b, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE); \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE, false);\ } \ int ret = mpfr_cmp(scratch[0], scratch[1]); \ return ret CMP; \ diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp index ab42c8e1..e4badb5d 100644 --- a/runtime/obj/MonteCarloArithmetic.cpp +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -208,6 +208,9 @@ IUint32_t get_virtual_prec(void * context) { return ((mca_context_t *)context)->binary64_precision; } + mca_mode get_mode(void * context) { + return ((mca_context_t *)context)->mode; + } // Function and definition adapted from verificarlo repo file // src/vfcwrapper/main.c.in static constexpr int MAX_ARGS=256; @@ -405,7 +408,7 @@ // Between 1 and quad precision pseudo mantissa encoding size (112) .precision_binary64 = 53, // default to double mantissa size (52+1) // Only add inexact to input operands. - .mode = mca_mode::mca_mode_pb, // Irrelevant for inexact. + .mode = mca_mode::mca_mode_pb, // default to only perturb inbound // The mode matching formula (1) in Verificarlo .err_mode = mca_err_mode::mca_err_mode_rel, // Unused for relative error mode mca_err_mode_rel @@ -425,21 +428,31 @@ return get_virtual_prec(verificarlo_mca_context.context); \ } while (0) - #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode) \ + #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode, \ + isOutbound) \ do { \ - if (virtual_prec != \ - get_virtual_prec(verificarlo_mca_context.context) \ - ) { \ - set_virtual_prec(verificarlo_mca_context.context,virtual_prec);\ + mca_mode mode = get_mode(verificarlo_mca_context.context); \ + bool addInexact = isOutbound ? \ + (mode == mca_mode::mca_mode_rr || mode == mca_mode::mca_mode_mca) \ + : (mode == mca_mode::mca_mode_pb || mode == mca_mode::mca_mode_mca); \ + if (addInexact) { \ + if (virtual_prec != \ + get_virtual_prec(verificarlo_mca_context.context) \ + ) { \ + set_virtual_prec(verificarlo_mca_context.context, \ + virtual_prec); \ + } \ + inexact_t high_prec_a = get_inexact_t_from(a, \ + rnd_mode); \ + mca_inexact(high_prec_a, verificarlo_mca_context.context); \ + assign_inexact_t_to(a, high_prec_a, rnd_mode); \ } \ - inexact_t high_prec_a = get_inexact_t_from(a, rnd_mode); \ - mca_inexact(high_prec_a, verificarlo_mca_context.context); \ - assign_inexact_t_to(a, high_prec_a, rnd_mode); \ } while (0) #else #define __RAPTOR_USE_VERIFICARLOMCA false #define __RAPTOR_VERIFICARLOMCA_get_virtual_prec(CPP_TY) - #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode) + #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode, \ + isOutbound) #endif // __RAPTOR_VERIFICARLOMCA_MODE #define RAPTOR_FLOAT_TYPE(CPP_TY, FROM_TY) \ @@ -454,9 +467,10 @@ } \ } \ void __raptor_mca_inexact_##FROM_TY(mpfr_t a, unsigned int virtual_prec, \ - mpfr_rnd_t rnd_mode) { \ + mpfr_rnd_t rnd_mode, bool isOutbound) { \ if constexpr (__RAPTOR_USE_VERIFICARLOMCA) { \ - __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode); \ + __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode, \ + isOutbound); \ } else { \ std::cerr << "__raptor_mca_inexact_" << #FROM_TY; \ std::cerr << " is not implemented." << std::endl; \ From 20f91b92d4e1541607d3dea0332a02a0e88b7e6d Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:20:09 +0900 Subject: [PATCH 08/14] Fix cmake check verificarlo lib path existence --- CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4971e6f..019e9b10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -376,9 +376,10 @@ if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) string(APPEND CMAKE_CXX_FLAGS " -D__RAPTOR_VERIFICARLOMCA_INT_MODE") else() message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH} does not include the expected library name") - if (NOT EXISTS "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}") - message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH} does not exists") - endif() + endif() + + if (NOT EXISTS "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}") + message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH} does not exists") endif() add_library(verificarlo SHARED IMPORTED) From d841554deaaf656820bc7790194fe2fab6511ea2 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Thu, 20 Aug 2026 19:28:32 +0900 Subject: [PATCH 09/14] Properly use target_link_libraries for defines --- CMakeLists.txt | 25 ++++++++++++------------- runtime/CMakeLists.txt | 4 ++++ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 019e9b10..11235db4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -370,22 +370,21 @@ install(PROGRAMS DESTINATION bin) if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) - if (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca.so") - string(APPEND CMAKE_CXX_FLAGS " -D__RAPTOR_VERIFICARLOMCA_MODE") - elseif (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca_int.so") - string(APPEND CMAKE_CXX_FLAGS " -D__RAPTOR_VERIFICARLOMCA_INT_MODE") - else() + if (NOT (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca.so" OR __RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca_int.so")) message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH} does not include the expected library name") - endif() - - if (NOT EXISTS "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}") + elseif (NOT EXISTS "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}") message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH} does not exists") + else() + add_library(verificarlo SHARED IMPORTED) + set_target_properties(verificarlo PROPERTIES + IMPORTED_LOCATION "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}" + ) + if (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca.so") + target_compile_definitions(verificarlo INTERFACE __RAPTOR_VERIFICARLOMCA_MODE) + elseif (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca_int.so") + target_compile_definitions(verificarlo INTERFACE __RAPTOR_VERIFICARLOMCA_INT_MODE) + endif() endif() - - add_library(verificarlo SHARED IMPORTED) - set_target_properties(verificarlo PROPERTIES - IMPORTED_LOCATION "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}" - ) endif() add_subdirectory(runtime) add_subdirectory(test) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index ced63956..e59e3ec8 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -45,6 +45,10 @@ target_include_directories(Raptor-RT-${LLVM_VERSION_MAJOR} PUBLIC $ ) +if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) + target_link_libraries(Raptor-RT-${LLVM_VERSION_MAJOR} PRIVATE verificarlo) +endif() + install( DIRECTORY ${RAPTOR_PUBLIC_INCLUDE_DIR} DESTINATION include From 80b1ec3060d80285006fbab72a2ee2d7f150063f Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:13:25 +0900 Subject: [PATCH 10/14] Make verificarlo mca backend runtime selectable through VFC_BACKENDS --- CMakeLists.txt | 40 ++- runtime/CMakeLists.txt | 6 +- runtime/ir/Mpfr.cpp | 8 +- runtime/obj/MonteCarloArithmetic.cpp | 491 +++++++++++++++------------ test/lit.site.cfg.py.in | 8 +- 5 files changed, 322 insertions(+), 231 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11235db4..f63c4db1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -370,20 +370,38 @@ install(PROGRAMS DESTINATION bin) if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) - if (NOT (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca.so" OR __RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca_int.so")) - message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH} does not include the expected library name") - elseif (NOT EXISTS "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}") - message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH} does not exists") - else() + foreach (LIB_PATH IN LISTS __RAPTOR_VERIFICARLOMCA_LIB_PATH) + if (NOT (LIB_PATH MATCHES "libinterflop_mca.so" OR LIB_PATH MATCHES "libinterflop_mca_int.so")) + message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${LIB_PATH} does not include the expected library name") + elseif (NOT EXISTS "${LIB_PATH}") + message(SEND_ERROR "__RAPTOR_VERIFICARLOMCA_LIB_PATH ${LIB_PATH} does not exists") + else() + if (LIB_PATH MATCHES "libinterflop_mca.so") + if (DEFINED __RAPTOR_VERIFICARLOMCA_QUAD_LIB_PATH) + message(SEND_ERROR "Redefining __RAPTOR_VERIFICARLOMCA_QUAD_LIB_PATH ${LIB_PATH}, __RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH}") + endif() + set(__RAPTOR_VERIFICARLOMCA_QUAD_LIB_PATH ${LIB_PATH}) + elseif (LIB_PATH MATCHES "libinterflop_mca_int.so") + if (DEFINED __RAPTOR_VERIFICARLOMCA_INT_LIB_PATH) + message(SEND_ERROR "Redefining __RAPTOR_VERIFICARLOMCA_INT_LIB_PATH ${LIB_PATH}, __RAPTOR_VERIFICARLOMCA_LIB_PATH ${__RAPTOR_VERIFICARLOMCA_LIB_PATH}") + endif() + set(__RAPTOR_VERIFICARLOMCA_INT_LIB_PATH ${LIB_PATH}) + endif() + endif() + endforeach() + if (DEFINED __RAPTOR_VERIFICARLOMCA_QUAD_LIB_PATH) add_library(verificarlo SHARED IMPORTED) set_target_properties(verificarlo PROPERTIES - IMPORTED_LOCATION "${__RAPTOR_VERIFICARLOMCA_LIB_PATH}" + IMPORTED_LOCATION "${__RAPTOR_VERIFICARLOMCA_QUAD_LIB_PATH}" ) - if (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca.so") - target_compile_definitions(verificarlo INTERFACE __RAPTOR_VERIFICARLOMCA_MODE) - elseif (__RAPTOR_VERIFICARLOMCA_LIB_PATH MATCHES "libinterflop_mca_int.so") - target_compile_definitions(verificarlo INTERFACE __RAPTOR_VERIFICARLOMCA_INT_MODE) - endif() + target_compile_definitions(verificarlo INTERFACE __RAPTOR_VERIFICARLOMCA_QUAD_MODE) + endif() + if (DEFINED __RAPTOR_VERIFICARLOMCA_INT_LIB_PATH) + add_library(verificarlo_int SHARED IMPORTED) + set_target_properties(verificarlo_int PROPERTIES + IMPORTED_LOCATION "${__RAPTOR_VERIFICARLOMCA_INT_LIB_PATH}" + ) + target_compile_definitions(verificarlo_int INTERFACE __RAPTOR_VERIFICARLOMCA_INT_MODE) endif() endif() add_subdirectory(runtime) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index e59e3ec8..12601533 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -45,10 +45,14 @@ target_include_directories(Raptor-RT-${LLVM_VERSION_MAJOR} PUBLIC $ ) -if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) +if (DEFINED __RAPTOR_VERIFICARLOMCA_QUAD_LIB_PATH) target_link_libraries(Raptor-RT-${LLVM_VERSION_MAJOR} PRIVATE verificarlo) endif() +if (DEFINED __RAPTOR_VERIFICARLOMCA_INT_LIB_PATH) + target_link_libraries(Raptor-RT-${LLVM_VERSION_MAJOR} PRIVATE verificarlo_int) +endif() + install( DIRECTORY ${RAPTOR_PUBLIC_INCLUDE_DIR} DESTINATION include diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index a5e4895a..e60bf1c4 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -85,10 +85,10 @@ #ifndef __RAPTOR_MCA_MODE #ifdef __RAPTOR_VERIFICARLOMCA_MODE #define __RAPTOR_MCA_MODE - #else - #ifdef __RAPTOR_VERIFICARLOMCA_INT_MODE - #define __RAPTOR_MCA_MODE - #endif + #elif (defined __RAPTOR_VERIFICARLOMCA_QUAD_MODE) + #define __RAPTOR_MCA_MODE + #elif (defined __RAPTOR_VERIFICARLOMCA_INT_MODE) + #define __RAPTOR_MCA_MODE #endif #endif diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp index e4badb5d..64d024b9 100644 --- a/runtime/obj/MonteCarloArithmetic.cpp +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -2,7 +2,9 @@ #include #ifndef __RAPTOR_VERIFICARLOMCA_MODE - #ifdef __RAPTOR_VERIFICARLOMCA_INT_MODE + #ifdef __RAPTOR_VERIFICARLOMCA_QUAD_MODE + #define __RAPTOR_VERIFICARLOMCA_MODE + #elif (defined __RAPTOR_VERIFICARLOMCA_INT_MODE) #define __RAPTOR_VERIFICARLOMCA_MODE #endif #endif @@ -32,15 +34,6 @@ #include #include #include - // Macros to help get function names of the corresponding backend - #define __RAPTOR_VERIFICARLOMCA_CONCAT(prefix,name,suffix) \ - prefix##name##suffix - #define __RAPTOR_VERIFICARLOMCA_INTERFLOP_API(BACKENDNAME, name) \ - __RAPTOR_VERIFICARLOMCA_CONCAT(INTERFLOP_, BACKENDNAME, _API)(name) - #define __RAPTOR_VERIFICARLOMCA_INEXACT(backendname, bits) \ - __RAPTOR_VERIFICARLOMCA_CONCAT(_, backendname, _inexact_binary##bits) - #define __RAPTOR_VERIFICARLOMCA_CONTEXT_T(backendname) \ - __RAPTOR_VERIFICARLOMCA_CONCAT(, backendname, _context_t) #if defined(__cplusplus) extern "C" { #endif @@ -52,8 +45,7 @@ // src/interflop-stdlib/interflop_stdlib.c extern void interflop_set_handler(const char *name, void *function_ptr); #ifdef __RAPTOR_VERIFICARLOMCA_INT_MODE - #define __RAPTOR_VERIFICARLOMCA_BACKENDNAME MCAINT - #define __RAPTOR_VERIFICARLOMCA_backendname mcaint + #define __RAPTOR_VERIFICARLOMCA_HAS_INT true // Macro copied from verificarlo repo backends files // src/backends/interflop-backend-mcaint/interflop_mca.h #define INTERFLOP_MCAINT_API(name) interflop_mcaint_##name @@ -67,9 +59,17 @@ void *context); extern void _mcaint_inexact_binary64(double *da, void *context); extern void _mcaint_inexact_binary128(_Float128 *qa, void *context); + #define __RAPTOR_VERIFICARLOMCA_INT_INTERFLOP_CALL(name, ...) \ + do { INTERFLOP_MCAINT_API(name)(__VA_ARGS__); } while (0) + #define __RAPTOR_VERIFICARLOMCA_INT_INEXACT_CALL(bits, ...) \ + do { _mcaint_inexact_binary##bits(__VA_ARGS__); } while (0) #else - #define __RAPTOR_VERIFICARLOMCA_BACKENDNAME MCAQUAD - #define __RAPTOR_VERIFICARLOMCA_backendname mcaquad + #define __RAPTOR_VERIFICARLOMCA_HAS_INT false + #define __RAPTOR_VERIFICARLOMCA_INT_INTERFLOP_CALL(name, ...) + #define __RAPTOR_VERIFICARLOMCA_INT_INEXACT_CALL(bits, ...) + #endif + #ifdef __RAPTOR_VERIFICARLOMCA_QUAD_MODE + #define __RAPTOR_VERIFICARLOMCA_HAS_QUAD true // Macro copied from verificarlo repo backends files // src/backends/interflop-backend-mcaint/interflop_mca_int.h #define INTERFLOP_MCAQUAD_API(name) interflop_mcaquad_##name @@ -83,6 +83,14 @@ void *context); extern void _mcaquad_inexact_binary64(double *da, void *context); extern void _mcaquad_inexact_binary128(_Float128 *qa, void *context); + #define __RAPTOR_VERIFICARLOMCA_INTERFLOP_CALL(name, ...) \ + do { INTERFLOP_MCAQUAD_API(name)(__VA_ARGS__); } while (0) + #define __RAPTOR_VERIFICARLOMCA_INEXACT_CALL(bits, ...) \ + do { _mcaquad_inexact_binary##bits(__VA_ARGS__); } while (0) + #else + #define __RAPTOR_VERIFICARLOMCA_HAS_QUAD false + #define __RAPTOR_VERIFICARLOMCA_INTERFLOP_CALL(name, ...) + #define __RAPTOR_VERIFICARLOMCA_INEXACT_CALL(bits, ...) #endif #if defined(__cplusplus) } @@ -90,198 +98,223 @@ // Enclose types/functions to interface with verificarlo in unnamed namespace namespace { - // Typedef copied from verificarlo repo file - // src/interflop-stdlib/interflop_stdlib.h - typedef unsigned int IUint32_t; - typedef long int IInt64_t; - typedef unsigned long int IUint64_t; - typedef int IBool; + // Using a struct because the context needs initialization + struct verificarlo_mca_context_t { + // Typedef copied from verificarlo repo file + // src/interflop-stdlib/interflop_stdlib.h + typedef unsigned int IUint32_t; + typedef long int IInt64_t; + typedef unsigned long int IUint64_t; + typedef int IBool; - // Definitions adapted from verificarlo repo backends files - // src/backends/interflop-backend-mcaint/interflop_mca_int.h and - // src/backends/interflop-backend-mcaquad/interflop_mca.h - // These definitions from mcaint and mcaquad are compatible so defining - // only once here. - /* define the available MCA modes of operation */ - typedef enum { - mca_mode_ieee, - mca_mode_mca, - mca_mode_pb, - mca_mode_rr, - _mca_mode_end_ - } mca_mode; + // Definitions adapted from verificarlo repo backends files + // src/backends/interflop-backend-mcaint/interflop_mca_int.h and + // src/backends/interflop-backend-mcaquad/interflop_mca.h + // These definitions from mcaint and mcaquad are compatible so defining + // only once here. + /* define the available MCA modes of operation */ + typedef enum { + mca_mode_ieee, + mca_mode_mca, + mca_mode_pb, + mca_mode_rr, + _mca_mode_end_ + } mca_mode; - /* define the available error modes */ - typedef enum { - mca_err_mode_rel, - mca_err_mode_abs, - mca_err_mode_all, - _mca_err_mode_end_ - } mca_err_mode; + /* define the available error modes */ + typedef enum { + mca_err_mode_rel, + mca_err_mode_abs, + mca_err_mode_all, + _mca_err_mode_end_ + } mca_err_mode; - /* Interflop context */ - typedef struct { - IUint64_t seed; - float sparsity; - int binary32_precision; - int binary64_precision; - int absErr_exp; - IBool relErr; - IBool absErr; - IBool daz; - IBool ftz; - IBool choose_seed; - mca_mode mode; - } mcaquad_context_t; + /* Interflop context */ + typedef struct { + IUint64_t seed; + float sparsity; + int binary32_precision; + int binary64_precision; + int absErr_exp; + IBool relErr; + IBool absErr; + IBool daz; + IBool ftz; + IBool choose_seed; + mca_mode mode; + } mcaquad_context_t; - /* Interflop context */ - typedef struct { - IBool relErr; - IBool absErr; - IBool daz; - IBool ftz; - IBool choose_seed; - mca_mode mode; - int binary32_precision; - int binary64_precision; - int absErr_exp; - float sparsity; - IUint64_t seed; - } mcaint_context_t; + /* Interflop context */ + typedef struct { + IBool relErr; + IBool absErr; + IBool daz; + IBool ftz; + IBool choose_seed; + mca_mode mode; + int binary32_precision; + int binary64_precision; + int absErr_exp; + float sparsity; + IUint64_t seed; + } mcaint_context_t; - using mca_context_t = __RAPTOR_VERIFICARLOMCA_CONTEXT_T( - __RAPTOR_VERIFICARLOMCA_backendname); + template + using mca_context_t = std::conditional_t; + typedef struct { + IUint64_t seed; + float sparsity; + IUint32_t precision_binary32; + IUint32_t precision_binary64; + mca_mode mode; + mca_err_mode err_mode; + IInt64_t max_abs_err_exponent; + IUint32_t daz; + IUint32_t ftz; + } mca_conf_t; - typedef struct { - IUint64_t seed; - float sparsity; - IUint32_t precision_binary32; - IUint32_t precision_binary64; - mca_mode mode; - mca_err_mode err_mode; - IInt64_t max_abs_err_exponent; - IUint32_t daz; - IUint32_t ftz; - } mca_conf_t; + // Helper type for compile time type check + template + using is_float_t = std::enable_if_t, bool>; + template + using is_double_t = std::enable_if_t, bool>; + template + using is__Float128_t = std::enable_if_t, + bool>; + template + using is_float_or_double_t = std::enable_if_t< + std::is_same_v || std::is_same_v, bool>; + template + using is_double_or__Float128_t = std::enable_if_t< + std::is_same_v || std::is_same_v, bool>; + template = true> + using inexact_t = std::conditional_t, double, + _Float128>; + + + // Function and definition adapted from verificarlo repo file + // src/vfcwrapper/main.c.in + static constexpr int MAX_ARGS=256; + static void get_args_from_str(char *str, const char *err_msg_prefix, + int &argc, char *argv[MAX_ARGS]) + { + if (str != NULL) { + char *spaceptr; + char *arg = strtok_r(str, " ", &spaceptr); + while (arg) { + if (argc >= MAX_ARGS) { + fprintf(stderr, "%s syntax error: too many arguments", + err_msg_prefix); + } + argv[argc++] = arg; + arg = strtok_r(NULL, " ", &spaceptr); + } + argv[argc] = NULL; + } + } + // Return the high precision type used for MCA calculation from mpfr_t a, + // with the rounding mode rnd_mode + template = true> + static inexact_t get_inexact_t_from(mpfr_t a, mpfr_rnd_t rnd_mode) { + return mpfr_get_d(a, rnd_mode); + } + template = true> + static inexact_t get_inexact_t_from(mpfr_t a, mpfr_rnd_t rnd_mode) { + return mpfr_get_float128(a, rnd_mode); + } + // Assigns mpfr_t a with the value of val with rnd_mode rounding mode, + // where val is of the high precision type used for MCA calculation. + // Returns the return value from mpfr_set_* used underneath. + template = true> + static int assign_inexact_t_to(mpfr_t a, inexact_t val, + mpfr_rnd_t rnd_mode) + { + return mpfr_set_d(a, val, rnd_mode); + } + template = true> + static int assign_inexact_t_to(mpfr_t a, inexact_t val, + mpfr_rnd_t rnd_mode) + { + return mpfr_set_float128(a, val, rnd_mode); + } - // Helper type for compile time type check - template - using is_float_t = std::enable_if_t, bool>; - template - using is_double_t = std::enable_if_t, bool>; - template - using is__Float128_t = std::enable_if_t, - bool>; - template - using is_float_or_double_t = std::enable_if_t< - std::is_same_v || std::is_same_v, bool>; - template - using is_double_or__Float128_t = std::enable_if_t< - std::is_same_v || std::is_same_v, bool>; - template = true> - using inexact_t = std::conditional_t, double, - _Float128>; - // Using a struct because the context needs initialization - struct verificarlo_mca_context_t { // Context used for the _mca*_inexact_binary64 functions void * context = nullptr; - verificarlo_mca_context_t(); - }; - // Global so that it gets automatically initialized through construction - verificarlo_mca_context_t verificarlo_mca_context; + // Flag indicating whether context is mcaint_context_t or not + bool is_mcaint = __RAPTOR_VERIFICARLOMCA_HAS_INT; - // Set the context with configure - void set_verificarlo_mca_context(void *configure, void *context) { - __RAPTOR_VERIFICARLOMCA_INTERFLOP_API( - __RAPTOR_VERIFICARLOMCA_BACKENDNAME, configure)(configure, context); - } - void set_verificarlo_mca_context(int argc, char **argv, void *context) { - __RAPTOR_VERIFICARLOMCA_INTERFLOP_API( - __RAPTOR_VERIFICARLOMCA_BACKENDNAME, cli)(argc, argv, context); - } - // Returns the virtual precision used for MCA of floating point type T - template = true> - IUint32_t get_virtual_prec(void * context) { - return ((mca_context_t *)context)->binary32_precision; - } - template = true> - IUint32_t get_virtual_prec(void * context) { - return ((mca_context_t *)context)->binary64_precision; - } - mca_mode get_mode(void * context) { - return ((mca_context_t *)context)->mode; - } - // Function and definition adapted from verificarlo repo file - // src/vfcwrapper/main.c.in - static constexpr int MAX_ARGS=256; - void get_args_from_str(char *str, const char *err_msg_prefix, int &argc, - char *argv[MAX_ARGS]){ - if (str != NULL) { - char *spaceptr; - char *arg = strtok_r(str, " ", &spaceptr); - while (arg) { - if (argc >= MAX_ARGS) { - fprintf(stderr, "%s syntax error: too many arguments", - err_msg_prefix); - } - argv[argc++] = arg; - arg = strtok_r(NULL, " ", &spaceptr); + // Set the context with configure + void set_verificarlo_mca_context(void *configure) { + if (is_mcaint) { + __RAPTOR_VERIFICARLOMCA_INT_INTERFLOP_CALL(configure, + configure, context); + } else { + __RAPTOR_VERIFICARLOMCA_INTERFLOP_CALL(configure, configure, context); } - argv[argc] = NULL; } - } - // Set the virtual precision used for MCA of floating point type T - template = true> - void set_virtual_prec(void * context, IUint32_t virtual_prec) { - int argc; - char *argv[MAX_ARGS]; - std::string str = "dummy --precision-binary32=" + - std::to_string(virtual_prec); - get_args_from_str(str.data(), "set_virtual_prec 32", argc, argv); - set_verificarlo_mca_context(argc, argv, context); - } - template = true> - void set_virtual_prec(void * context, IUint32_t virtual_prec) { - int argc; - char *argv[MAX_ARGS]; - std::string str = "dummy --precision-binary64=" + - std::to_string(virtual_prec); - get_args_from_str(str.data(), "set_virtual_prec 64", argc, argv); - set_verificarlo_mca_context(argc, argv, context); - } - // Return the high precision type used for MCA calculation from mpfr_t a, - // with the rounding mode rnd_mode - template = true> - inexact_t get_inexact_t_from(mpfr_t a, mpfr_rnd_t rnd_mode) { - return mpfr_get_d(a, rnd_mode); - } - template = true> - inexact_t get_inexact_t_from(mpfr_t a, mpfr_rnd_t rnd_mode) { - return mpfr_get_float128(a, rnd_mode); - } - // Assigns mpfr_t a with the value of val with rnd_mode rounding mode, - // where val is of the high precision type used for MCA calculation. - // Returns the return value from mpfr_set_* used underneath. - template = true> - int assign_inexact_t_to(mpfr_t a, inexact_t val, mpfr_rnd_t rnd_mode) { - return mpfr_set_d(a, val, rnd_mode); - } - template = true> - int assign_inexact_t_to(mpfr_t a, inexact_t val, mpfr_rnd_t rnd_mode) { - return mpfr_set_float128(a, val, rnd_mode); - } - // Apply MCA random perturbation to a of type T, with the parameters for - // MCA defined in context - template = true> - void mca_inexact(T &a, void *context) { - __RAPTOR_VERIFICARLOMCA_INEXACT(__RAPTOR_VERIFICARLOMCA_backendname, - 64)(&a, context); - } - template = true> - void mca_inexact(T &a, void *context) { - __RAPTOR_VERIFICARLOMCA_INEXACT(__RAPTOR_VERIFICARLOMCA_backendname, - 128)(&a, context); - } + void set_verificarlo_mca_context(int argc, char **argv) { + if (is_mcaint) { + __RAPTOR_VERIFICARLOMCA_INT_INTERFLOP_CALL(cli, argc, argv, context); + } else { + __RAPTOR_VERIFICARLOMCA_INTERFLOP_CALL(cli, argc, argv, context); + } + } + // Returns the virtual precision used for MCA of floating point type T + template = true> + IUint32_t _get_virtual_prec() { + return ((mca_context_t *)context)->binary32_precision; + } + template = true> + IUint32_t _get_virtual_prec() { + return ((mca_context_t *)context)->binary64_precision; + } + template = true> + IUint32_t get_virtual_prec() { + if (is_mcaint) { return _get_virtual_prec(); } + else { return _get_virtual_prec(); } + } + // Returns the MCA mode (ieee, rr, pb, or mca) + mca_mode get_mode() { + if (is_mcaint) { return ((mca_context_t *)context)->mode; } + else { return ((mca_context_t *)context)->mode; } + } + // Set the virtual precision used for MCA of floating point type T + template = true> + void set_virtual_prec(IUint32_t virtual_prec) { + int argc; + char *argv[MAX_ARGS]; + std::string str = is_mcaint? "libinterflop_mca_int.so" : + "libinterflop_mca.so"; + constexpr std::string_view nbits = std::is_same_v? + " --precision-binary32" : " --precision-binary64"; + str += nbits; + str += "=" + std::to_string(virtual_prec); + get_args_from_str(str.data(), ("set_virtual_prec " + str).c_str(), + argc, argv); + set_verificarlo_mca_context(argc, argv); + } + // Apply MCA random perturbation to a of type T, with the parameters for + // MCA defined in context + template = true> + void mca_inexact(T &a) { + if (is_mcaint) { + __RAPTOR_VERIFICARLOMCA_INT_INEXACT_CALL(64, &a, context); + } else { + __RAPTOR_VERIFICARLOMCA_INEXACT_CALL(64, &a, context); + } + } + template = true> + void mca_inexact(T &a) { + if (is_mcaint) { + __RAPTOR_VERIFICARLOMCA_INT_INEXACT_CALL(128, &a, context); + } else { + __RAPTOR_VERIFICARLOMCA_INEXACT_CALL(128, &a, context); + } + } + + verificarlo_mca_context_t(); + }; #if defined(__cplusplus) extern "C" { @@ -315,7 +348,9 @@ /* 2- VFC_BACKENDS_FROM_FILE */ /* Set the backends read in vfc_backends */ /* Set the name of the environment variable read in vfc_backends_env */ - void parse_vfc_backends_env(int &backend_argc, char *backend_argv[MAX_ARGS]) { + void parse_vfc_backends_env(int &backend_argc, + char *backend_argv[verificarlo_mca_context_t::MAX_ARGS]) + { char *vfc_backends_v = NULL; const char *vfc_backends_env_v = NULL; char ** vfc_backends = &vfc_backends_v; @@ -360,8 +395,8 @@ } } - get_args_from_str(vfc_backends_v, vfc_backends_env_v, backend_argc, - backend_argv); + verificarlo_mca_context_t::get_args_from_str( + vfc_backends_v, vfc_backends_env_v, backend_argc, backend_argv); } #if defined(__cplusplus) } @@ -385,17 +420,44 @@ interflop_set_handler("vfprintf", (void *)vfprintf); interflop_set_handler("vwarnx", (void *)vwarnx); interflop_set_handler("gettimeofday", (void *)gettimeofday); - // pre_init also allocates and initialize the context - __RAPTOR_VERIFICARLOMCA_INTERFLOP_API( - __RAPTOR_VERIFICARLOMCA_BACKENDNAME, pre_init)( - _vfc_panic, stderr, &context); // Skipping interflop init since it is mostly registering hooked function // for instrumentation (and we are doing it in RAPTOR instead) int backend_argc = 0; char *backend_argv[MAX_ARGS]; parse_vfc_backends_env(backend_argc, backend_argv); + // Setup which library is used and assign is_mcaint if (backend_argc > 0) { - set_verificarlo_mca_context(backend_argc, backend_argv, context); + std::string libname = backend_argv[0]; + if (libname == "libinterflop_mca_int.so") { + is_mcaint = __RAPTOR_VERIFICARLOMCA_HAS_INT; + if (!is_mcaint) { + std::cerr << "Error: " << libname << " selected through "; + std::cerr << "VFC_BACKENDS but not included in RAPTOR build. "; + std::cerr << std::endl; abort(); + } + } else if (libname == "libinterflop_mca.so") { + is_mcaint = !__RAPTOR_VERIFICARLOMCA_HAS_QUAD; + if (is_mcaint) { + std::cerr << "Error: " << libname << " selected through "; + std::cerr << "VFC_BACKENDS but not included in RAPTOR build. "; + std::cerr << std::endl; abort(); + } + } else { + std::cerr << "Error: " << libname << " is not a valid backend."; + std::cerr << std::endl; abort(); + } + } + // pre_init also allocates and initialize the context + if (is_mcaint) { + __RAPTOR_VERIFICARLOMCA_INT_INTERFLOP_CALL(pre_init, + _vfc_panic, stderr, + &context); + } else { + __RAPTOR_VERIFICARLOMCA_INTERFLOP_CALL(pre_init, + _vfc_panic, stderr, &context); + } + if (backend_argc > 0) { + set_verificarlo_mca_context(backend_argc, backend_argv); } else { // Default configuration used to initialize the context // Also used to set the context when configuration changes @@ -417,37 +479,40 @@ .daz = 0, // 0 for false, 1 for true .ftz = 0 // 0 for false, 1 for true }; - set_verificarlo_mca_context(&mca_conf, context); + set_verificarlo_mca_context(&mca_conf); } } + // Global so that it gets automatically initialized through construction + verificarlo_mca_context_t verificarlo_mca_context; } // end of unnamed namespace // verificarlo does not change virtual precision mid run, just get from conf #define __RAPTOR_VERIFICARLOMCA_get_virtual_prec(CPP_TY) \ do { \ - return get_virtual_prec(verificarlo_mca_context.context); \ + return verificarlo_mca_context.get_virtual_prec(); \ } while (0) #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode, \ isOutbound) \ do { \ - mca_mode mode = get_mode(verificarlo_mca_context.context); \ + using mca_mode = verificarlo_mca_context_t::mca_mode; \ + mca_mode mode = verificarlo_mca_context.get_mode(); \ bool addInexact = isOutbound ? \ (mode == mca_mode::mca_mode_rr || mode == mca_mode::mca_mode_mca) \ : (mode == mca_mode::mca_mode_pb || mode == mca_mode::mca_mode_mca); \ if (addInexact) { \ if (virtual_prec != \ - get_virtual_prec(verificarlo_mca_context.context) \ + verificarlo_mca_context.get_virtual_prec() \ ) { \ - set_virtual_prec(verificarlo_mca_context.context, \ - virtual_prec); \ + verificarlo_mca_context.set_virtual_prec(virtual_prec); \ } \ - inexact_t high_prec_a = get_inexact_t_from(a, \ - rnd_mode); \ - mca_inexact(high_prec_a, verificarlo_mca_context.context); \ - assign_inexact_t_to(a, high_prec_a, rnd_mode); \ + verificarlo_mca_context_t::inexact_t high_prec_a = \ + verificarlo_mca_context_t::get_inexact_t_from(a, rnd_mode); \ + verificarlo_mca_context.mca_inexact(high_prec_a); \ + verificarlo_mca_context_t::assign_inexact_t_to(a, high_prec_a, \ + rnd_mode); \ } \ - } while (0) + } while (0) #else #define __RAPTOR_USE_VERIFICARLOMCA false #define __RAPTOR_VERIFICARLOMCA_get_virtual_prec(CPP_TY) diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index 091378e1..75e4c5d5 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -109,9 +109,13 @@ config.substitutions.append(('%loadLLDRaptor', newPM)) verificarlomca_lib_path = "@__RAPTOR_VERIFICARLOMCA_LIB_PATH@" verificarlomca_link_options = "" if verificarlomca_lib_path != "": - verificarlomca_lib_dir = "/".join(verificarlomca_lib_path.split("/")[:-1]) - verificarlomca_lib_name = verificarlomca_lib_path.split("/")[-1].split(".")[0][3:] + verificarlomca_lib_dir = "/".join(verificarlomca_lib_path.split(";")[0].split("/")[:-1]) + verificarlomca_lib_name = verificarlomca_lib_path.split(";")[0].split("/")[-1].split(".")[0][3:] verificarlomca_link_options = " -L" + verificarlomca_lib_dir + " -l" + verificarlomca_lib_name + " -linterflop_stdlib" + " -Wl,-rpath=" + verificarlomca_lib_dir + if len(verificarlomca_lib_path.split(";")) > 1: + verificarlomca_lib_name = verificarlomca_lib_path.split(";")[1].split("/")[-1].split(".")[0][3:] + verificarlomca_link_options += " -l" + verificarlomca_lib_name + link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver + verificarlomca_link_options config.substitutions.append(('%linkRaptorRT', link)) From 46401587a4b7d3ebe4105fe9768f444be9b5110d Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Fri, 28 Aug 2026 21:41:51 +0900 Subject: [PATCH 11/14] Add new API __raptor_mca_op_func(func, mcaType, fromWidth, toType, toExponent, toSignificand), where mcaType=0 selects verificarlo MCA --- pass/Raptor.cpp | 88 ++++++++++++++++++++++++- pass/RaptorLogic.cpp | 20 +++++- pass/RaptorLogic.h | 45 +++++++++++++ runtime/include/private/raptor/Common.h | 3 + runtime/include/public/raptor/raptor.h | 2 + runtime/ir/Mpfr.cpp | 57 ++++++++++++---- 6 files changed, 198 insertions(+), 17 deletions(-) diff --git a/pass/Raptor.cpp b/pass/Raptor.cpp index 1ca8ec81..60619e9c 100644 --- a/pass/Raptor.cpp +++ b/pass/Raptor.cpp @@ -127,6 +127,32 @@ void addNoCapture(llvm::Function *F, unsigned ArgNo) { #endif } +namespace MCAType { + // Get MCAType from int input + constexpr MCAType get(int mcaType) { + switch(mcaType) { + case VerificarloMCA: return VerificarloMCA; break; + default: return NoMCAType; break; + } + } + // Add mcaType to TruncateMode + constexpr TruncateMode addToTruncateMode(TruncateMode Mode, + MCAType mcaType) { + assert(!isMCA(Mode)); + return TruncateMode(Mode + (mcaType << shift)); + } + // Check that the TruncateMode and mcaType combo is supported + constexpr bool isValidTruncMCAMode(TruncateMode Mode, MCAType mcaType) { + assert(!isMCA(Mode)); + switch (Mode + (mcaType << shift)) { + case TruncOpMCAVerificarloMode: + return true; break; + default: + return false; break; + } + } +}; + #define addAttribute addAttributeAtIndex #define getAttribute getAttributeAtIndex bool attributeKnownFunctions(llvm::Function &F) { @@ -514,6 +540,11 @@ class RaptorBase { std::pair parseTruncation(CallInst *CI, TruncateMode Mode, unsigned ArgOffset) { unsigned ArgNum = CI->arg_size(); + // Adjust ArgNum and ArgOffset for MCA which has an extra arg in the front + if (MCAType::isMCA(Mode)) { + ArgNum = ArgNum - 1; + ArgOffset = ArgOffset + 1; + } auto Cfrom = cast(CI->getArgOperand(ArgOffset)); if (!Cfrom) EmitFailure("NotConstant", CI->getDebugLoc(), CI, @@ -540,6 +571,12 @@ class RaptorBase { "Mem mode truncation to IEEE not supported, switching to " "equivalent MPFR."); } + if (MCAType::isMCA(Mode)) { + Constructor = FloatRepresentation::getMPFR; + EmitWarning("UnsupportedTruncation", *CI, + "MCA mode truncation to IEEE not supported, switching to " + "equivalent MPFR."); + } FloatRepresentation FRTo = Constructor((unsigned)Cto->getValue().getZExtValue()); return {FloatTruncation(FRFrom, FRTo, Mode), 3}; @@ -564,7 +601,8 @@ class RaptorBase { 4}; } - EmitFailure("NotConstant", CI->getDebugLoc(), CI, "Unknown float type"); + auto float_type = Cty->getValue().getZExtValue(); + EmitFailure("NotConstant", CI->getDebugLoc(), CI, "Unknown float type", float_type); llvm_unreachable("Unknown float type"); } @@ -611,6 +649,10 @@ class RaptorBase { if (!F) return false; unsigned ArgNum = CI->arg_size(); + // Adjust ArgNum for MCA which has an extra arg in the front + if (MCAType::isMCA(Mode)) { + ArgNum = ArgNum - 1; + } if (ArgNum != 4 && ArgNum != 5) { EmitFailure("TooManyArgs", CI->getDebugLoc(), CI, "Had incorrect number of args to __raptor_truncate_func", *CI, @@ -632,6 +674,41 @@ class RaptorBase { return true; } + bool HandleMCAFunc(CallInst *CI, TruncateMode Mode) { + IRBuilder<> Builder(CI); + Function *F = parseFunctionParameter(CI); + if (!F) + return false; + unsigned ArgNum = CI->arg_size(); + if (ArgNum != 5 && ArgNum != 6) { + EmitFailure("TooManyArgs", CI->getDebugLoc(), CI, + "Had incorrect number of args to __raptor_mca_func", *CI, + " - expected 5 or 6"); + return false; + } + auto Cmca = cast(CI->getArgOperand(1)); + if (Cmca->getValue().getZExtValue()+1 >= MCAType::NumMCAType) { + EmitFailure("WrongArgVal", CI->getDebugLoc(), CI, + "Invalid input for MCA backend type."); + return false; + } + MCAType::MCAType mcaType = MCAType::get(Cmca->getValue().getZExtValue()+1); + if (mcaType == MCAType::NoMCAType) { + EmitFailure("Unsupported", CI->getDebugLoc(), CI, + "Unsupported MCA backend type ", mcaType, + ", please build raptor with selected backend type."); + return false; + } + if (!isValidTruncMCAMode(TruncOpMode, mcaType)) { + EmitFailure("Unsupported", CI->getDebugLoc(), CI, + "Unsupported truncate mode for the chosen MCA backend."); + return false; + } + // Add MCAType to TruncateMode to propagate it to the runtime library + TruncateMode truncMCAMode = MCAType::addToTruncateMode(Mode, mcaType); + return HandleTruncateFunc(CI, truncMCAMode); + } + bool HandleTruncateValue(CallInst *CI, bool isTruncate) { IRBuilder<> Builder(CI); unsigned ArgSize = CI->arg_size(); @@ -834,6 +911,7 @@ class RaptorBase { SmallVector toTruncateFuncOp; SmallVector toTruncateValue; SmallVector toExpandValue; + SmallVector toMCAFuncOp; retry:; for (BasicBlock &BB : F) { for (Instruction &I : BB) { @@ -1062,6 +1140,7 @@ class RaptorBase { bool truncateFuncMem = false; bool truncateValue = false; bool expandValue = false; + bool mcaFuncOp = false; if (false) { } else if (Fn->getName().contains("__raptor_log_flops")) { enableRaptor = true; @@ -1078,6 +1157,9 @@ class RaptorBase { } else if (Fn->getName().contains("__raptor_expand_mem_value")) { enableRaptor = true; expandValue = true; + } else if (Fn->getName().contains("__raptor_mca_op_func")) { + enableRaptor = true; + mcaFuncOp = true; } if (enableRaptor) { @@ -1129,6 +1211,8 @@ class RaptorBase { toTruncateValue.push_back(CI); else if (expandValue) toExpandValue.push_back(CI); + else if (mcaFuncOp) + toMCAFuncOp.push_back(CI); // TODO do we leave this? if (auto dc = dyn_cast(fn)) { @@ -1153,6 +1237,8 @@ class RaptorBase { HandleTruncateValue(call, true); for (auto call : toExpandValue) HandleTruncateValue(call, false); + for (auto call : toMCAFuncOp) + HandleMCAFunc(call, TruncOpMode); return Changed; } diff --git a/pass/RaptorLogic.cpp b/pass/RaptorLogic.cpp index 86dfd4cf..0ee30050 100644 --- a/pass/RaptorLogic.cpp +++ b/pass/RaptorLogic.cpp @@ -439,7 +439,7 @@ class TruncateGenerator : public llvm::InstVisitor, } }; if (TC.isToFPRT()) { - if (Mode == TruncOpMode) { + if (Mode == TruncOpMode || Mode == TruncOpMCAVerificarloMode) { if (TC.NeedTruncChange || TC.NeedNewScratch) AllocScratch(); if (!TC.NeedNewScratch) { @@ -470,6 +470,7 @@ class TruncateGenerator : public llvm::InstVisitor, break; case TruncOpMode: case TruncOpFullModuleMode: + case TruncOpMCAVerificarloMode: EmitWarning( "UnhandledTrunc", I, "Operation not handled - it will be executed in the original way.", @@ -500,6 +501,7 @@ class TruncateGenerator : public llvm::InstVisitor, return floatMemTruncate(B, v, TC); case TruncOpMode: case TruncOpFullModuleMode: + case TruncOpMCAVerificarloMode: return floatValTruncate(B, v, TC); } llvm_unreachable("Unknown trunc mode"); @@ -511,6 +513,7 @@ class TruncateGenerator : public llvm::InstVisitor, return floatMemExpand(B, v, TC); case TruncOpMode: case TruncOpFullModuleMode: + case TruncOpMCAVerificarloMode: return floatValExpand(B, v, TC); } llvm_unreachable("Unknown trunc mode"); @@ -572,6 +575,7 @@ class TruncateGenerator : public llvm::InstVisitor, } case TruncOpMode: case TruncOpFullModuleMode: + case TruncOpMCAVerificarloMode: return; } } @@ -615,6 +619,7 @@ class TruncateGenerator : public llvm::InstVisitor, } case TruncOpMode: case TruncOpFullModuleMode: + case TruncOpMCAVerificarloMode: return; } } @@ -637,6 +642,7 @@ class TruncateGenerator : public llvm::InstVisitor, } case TruncOpMode: case TruncOpFullModuleMode: + case TruncOpMCAVerificarloMode: return; } llvm_unreachable(""); @@ -776,6 +782,7 @@ class TruncateGenerator : public llvm::InstVisitor, } case TruncOpMode: case TruncOpFullModuleMode: + case TruncOpMCAVerificarloMode: break; default: llvm_unreachable("Unknown trunc mode"); @@ -808,6 +815,7 @@ class TruncateGenerator : public llvm::InstVisitor, } case TruncOpMode: case TruncOpFullModuleMode: + case TruncOpMCAVerificarloMode: break; default: llvm_unreachable("Unknown trunc mode"); @@ -856,6 +864,7 @@ class TruncateGenerator : public llvm::InstVisitor, switch (Mode) { case TruncMemMode: case TruncOpMode: + case TruncOpMCAVerificarloMode: EmitWarning("FPNoFollow", CI, "Will not follow FP through this indirect call.", CI); break; @@ -873,6 +882,7 @@ class TruncateGenerator : public llvm::InstVisitor, CI); break; case TruncOpMode: + case TruncOpMCAVerificarloMode: EmitWarning("FPNoFollow", CI, "Will not truncate flops in this function call as the " "definition is not available.", @@ -922,13 +932,16 @@ class TruncateGenerator : public llvm::InstVisitor, CallBase *const newCall = cast(getNewFromOriginal(&CI)); IRBuilder<> BuilderZ(newCall); - if (Mode != TruncOpMode && Mode != TruncMemMode) + if (Mode != TruncOpMode && Mode != TruncMemMode && + Mode != TruncOpMCAVerificarloMode) return; RequestContext ctx(&CI, &BuilderZ); auto FTTs = getFunctionToTruncate(CI); auto NeedDirectCall = [&](auto FTT) { - return scratch && Mode == TruncOpMode && isa(&CI) && + return scratch && (Mode == TruncOpMode || + Mode == TruncOpMCAVerificarloMode) && + isa(&CI) && !FTT.isCallbackFunc(); }; for (auto &FTT : FTTs) { @@ -996,6 +1009,7 @@ class TruncateGenerator : public llvm::InstVisitor, } case TruncOpMode: case TruncOpFullModuleMode: + case TruncOpMCAVerificarloMode: break; default: llvm_unreachable("Unknown trunc mode"); diff --git a/pass/RaptorLogic.h b/pass/RaptorLogic.h index a4efa5d0..fe98ac8b 100644 --- a/pass/RaptorLogic.h +++ b/pass/RaptorLogic.h @@ -83,10 +83,21 @@ getTypeForWidth(llvm::LLVMContext &ctx, unsigned width, bool builtinFloat) { } } +namespace MCAType { + enum MCAType { + NoMCAType, + VerificarloMCA, + NumMCAType + }; + static constexpr int shift = 4; +}; + enum TruncateMode { TruncMemMode = 0b0001, TruncOpMode = 0b0010, TruncOpFullModuleMode = 0b0110, + TruncOpMCAVerificarloMode = TruncOpMode + + (MCAType::VerificarloMCA << MCAType::shift), }; [[maybe_unused]] static const char *truncateModeStr(TruncateMode mode) { switch (mode) { @@ -96,10 +107,27 @@ enum TruncateMode { return "op"; case TruncOpFullModuleMode: return "op_full_module"; + case TruncOpMCAVerificarloMode: + return "op_mca_verificarlo"; } llvm_unreachable("Invalid truncation mode"); } +namespace MCAType { + constexpr bool isMCA(TruncateMode Mode) { + return (Mode >> shift) > 0; + } + constexpr + std::pair splitTruncMCAMode(TruncateMode Mode) { + switch (Mode) { + case TruncOpMCAVerificarloMode: + return {TruncOpMode, VerificarloMCA}; break; + default: + return {Mode, NoMCAType}; break; + } + } +}; + struct FloatRepresentation { public: enum FloatRepresentationType { IEEE = 0, MPFR = 1 }; @@ -423,6 +451,23 @@ class TruncationConfiguration { "", false, Truncation.getTo()}; + } else if (MCAType::isMCA(Truncation.getMode())) { + // toFPRT is required to insert code throug the runtime library + assert(Truncation.isToFPRT()); + auto [truncateMode, mcaType] = + MCAType::splitTruncMCAMode(Truncation.getMode()); + // Currently only works with op-mode + assert(truncateMode == TruncOpMode); + return TruncationConfiguration{Truncation.getFrom(), // FromRepr + Truncation.getMode(), // Mode + true, // NeedNewScratch + true, // NeedTruncChange + false, // ScratchFromArgs + Args, // CustomArgs + Mangle, // CustomMangle + "fprt", // RTName + true, // IsToFPRT + std::nullopt}; // ToRepr } else { llvm_unreachable(""); } diff --git a/runtime/include/private/raptor/Common.h b/runtime/include/private/raptor/Common.h index 708614a3..a7df3395 100644 --- a/runtime/include/private/raptor/Common.h +++ b/runtime/include/private/raptor/Common.h @@ -45,6 +45,9 @@ static inline bool __raptor_fprt_is_op_mode(int64_t mode) { static inline bool __raptor_fprt_is_full_module_op_mode(int64_t mode) { return mode & 0b0100; } +static inline bool __raptor_fprt_is_mca_mode(int64_t mode) { + return mode & 0b011110000; +} __RAPTOR_MPFR_DECL_ATTRIBUTES void raptor_fprt_gc_dump_status(); diff --git a/runtime/include/public/raptor/raptor.h b/runtime/include/public/raptor/raptor.h index 321e8614..48ec09ac 100644 --- a/runtime/include/public/raptor/raptor.h +++ b/runtime/include/public/raptor/raptor.h @@ -42,6 +42,8 @@ template fty *__raptor_truncate_mem_func(fty *, int, int, int, int); template fty *__raptor_truncate_op_func(fty *, int, int, int, int); +template +fty *__raptor_mca_op_func(fty *, int, int, int, int, int); template double __raptor_truncate_mem_value(Tys...); template double __raptor_expand_mem_value(Tys...); #endif diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index e60bf1c4..4da82a2b 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -587,11 +587,17 @@ void raptor_fprt_op_clear(); __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ + if (__raptor_fprt_is_mca_mode(mode)) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, \ + false); \ + } \ } \ mpfr_##MPFR_FUNC_NAME(scratch[2], scratch[0], ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, true); \ + if (__raptor_fprt_is_mca_mode(mode)) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, \ + true); \ + } \ } \ RET c = mpfr_get_##MPFR_GET(scratch[2], ROUNDING_MODE); \ return c; \ @@ -623,11 +629,17 @@ void raptor_fprt_op_clear(); __raptor_fprt_trunc_count(exponent, significand, mode, loc, scratch); \ mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ + if (__raptor_fprt_is_mca_mode(mode)) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, \ + false); \ + } \ } \ mpfr_##MPFR_FUNC_NAME(scratch[2], scratch[0], b, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, true); \ + if (__raptor_fprt_is_mca_mode(mode)) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, \ + true); \ + } \ } \ RET c = mpfr_get_##MPFR_GET(scratch[2], ROUNDING_MODE); \ return c; \ @@ -658,13 +670,20 @@ void raptor_fprt_op_clear(); mpfr_set_##MPFR_SET_ARG1(scratch[0], a, ROUNDING_MODE); \ mpfr_set_##MPFR_SET_ARG2(scratch[1], b, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE, false);\ + if (__raptor_fprt_is_mca_mode(mode)) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, \ + false); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE, \ + false); \ + } \ } \ mpfr_##MPFR_FUNC_NAME(scratch[2], scratch[0], scratch[1], \ ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, true); \ + if (__raptor_fprt_is_mca_mode(mode)) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, \ + true); \ + } \ } \ RET c = mpfr_get_##MPFR_GET(scratch[2], ROUNDING_MODE); \ return c; \ @@ -699,14 +718,22 @@ void raptor_fprt_op_clear(); mpfr_set_##MPFR_TYPE(scratch[1], b, ROUNDING_MODE); \ mpfr_set_##MPFR_TYPE(scratch[2], c, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE, false);\ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, false);\ + if (__raptor_fprt_is_mca_mode(mode)) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, \ + false); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE, \ + false); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[2], loc, ROUNDING_MODE, \ + false); \ + } \ } \ mpfr_mul(scratch[0], scratch[0], scratch[1], ROUNDING_MODE); \ mpfr_add(scratch[0], scratch[0], scratch[2], ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, true); \ + if (__raptor_fprt_is_mca_mode(mode)) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, \ + true); \ + } \ } \ TYPE res = mpfr_get_##MPFR_TYPE(scratch[0], ROUNDING_MODE); \ return res; \ @@ -747,8 +774,12 @@ void raptor_fprt_op_clear(); mpfr_set_##MPFR_GET(scratch[0], a, ROUNDING_MODE); \ mpfr_set_##MPFR_GET(scratch[1], b, ROUNDING_MODE); \ if constexpr (__RAPTOR_USE_MCA) { \ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, false);\ - __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE, false);\ + if (__raptor_fprt_is_mca_mode(mode)) { \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[0], loc, ROUNDING_MODE, \ + false); \ + __RAPTOR_MCA_INEXACT(FROM_TYPE, scratch[1], loc, ROUNDING_MODE, \ + false); \ + } \ } \ int ret = mpfr_cmp(scratch[0], scratch[1]); \ return ret CMP; \ From 181e5ab13e41c348a6082d91bcd517ba044c45e6 Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Tue, 1 Sep 2026 19:05:08 +0900 Subject: [PATCH 12/14] Simplify macros --- runtime/ir/Mpfr.cpp | 13 ++----------- runtime/obj/MonteCarloArithmetic.cpp | 19 ++++++++----------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/runtime/ir/Mpfr.cpp b/runtime/ir/Mpfr.cpp index 4da82a2b..30ba26a9 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -82,17 +82,8 @@ } while (0) #endif -#ifndef __RAPTOR_MCA_MODE - #ifdef __RAPTOR_VERIFICARLOMCA_MODE - #define __RAPTOR_MCA_MODE - #elif (defined __RAPTOR_VERIFICARLOMCA_QUAD_MODE) - #define __RAPTOR_MCA_MODE - #elif (defined __RAPTOR_VERIFICARLOMCA_INT_MODE) - #define __RAPTOR_MCA_MODE - #endif -#endif - -#ifdef __RAPTOR_MCA_MODE +#if defined(__RAPTOR_VERIFICARLOMCA_QUAD_MODE) || \ + defined(__RAPTOR_VERIFICARLOMCA_INT_MODE) #define __RAPTOR_USE_MCA true #define __RAPTOR_MCA_CONCAT(prefix, FROM_TY) __raptor_mca_##prefix##FROM_TY diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp index 64d024b9..356307a6 100644 --- a/runtime/obj/MonteCarloArithmetic.cpp +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -1,16 +1,9 @@ #include #include -#ifndef __RAPTOR_VERIFICARLOMCA_MODE - #ifdef __RAPTOR_VERIFICARLOMCA_QUAD_MODE - #define __RAPTOR_VERIFICARLOMCA_MODE - #elif (defined __RAPTOR_VERIFICARLOMCA_INT_MODE) - #define __RAPTOR_VERIFICARLOMCA_MODE - #endif -#endif - // verificarlo uses _Float128 that needs extra definition -#ifdef __RAPTOR_VERIFICARLOMCA_MODE +#if defined(__RAPTOR_VERIFICARLOMCA_QUAD_MODE) || \ + defined(__RAPTOR_VERIFICARLOMCA_INT_MODE) // Clang has "unknown type name" error for _Float128 on x86 #if defined(__clang__) && (defined(__i386) || defined(__x86_64)) #define _Float128 __float128 @@ -21,7 +14,8 @@ // mpfr.h is included in Common.h #include -#ifdef __RAPTOR_VERIFICARLOMCA_MODE +#if defined(__RAPTOR_VERIFICARLOMCA_QUAD_MODE) || \ + defined(__RAPTOR_VERIFICARLOMCA_INT_MODE) #define __RAPTOR_USE_VERIFICARLOMCA true // Includes needed to define interface to verificarlo #include @@ -518,9 +512,11 @@ #define __RAPTOR_VERIFICARLOMCA_get_virtual_prec(CPP_TY) #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode, \ isOutbound) -#endif // __RAPTOR_VERIFICARLOMCA_MODE +#endif // defined(__RAPTOR_VERIFICARLOMCA_QUAD_MODE) || + // defined(__RAPTOR_VERIFICARLOMCA_INT_MODE) #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) { \ @@ -531,6 +527,7 @@ abort(); \ } \ } \ + __RAPTOR_MPFR_ATTRIBUTES \ void __raptor_mca_inexact_##FROM_TY(mpfr_t a, unsigned int virtual_prec, \ mpfr_rnd_t rnd_mode, bool isOutbound) { \ if constexpr (__RAPTOR_USE_VERIFICARLOMCA) { \ From f2edb222b589ff45b30e3658a4e223e0db2dec9a Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Tue, 1 Sep 2026 19:09:03 +0900 Subject: [PATCH 13/14] Improve error message when __raptor_mca_op_func is used without verificarlo in the raptor build --- pass/CMakeLists.txt | 4 ++++ pass/Raptor.cpp | 36 ++++++------------------------------ pass/RaptorLogic.h | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/pass/CMakeLists.txt b/pass/CMakeLists.txt index 5f77049b..2f7c97c2 100644 --- a/pass/CMakeLists.txt +++ b/pass/CMakeLists.txt @@ -23,6 +23,10 @@ set(RAPTOR_SRC set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) + add_compile_definitions(__RAPTOR_HAS_VERIFICARLOMCA) +endif() + # on windows `PLUGIN_TOOL` doesn't link against LLVM.dll if ((WIN32 OR CYGWIN) AND LLVM_LINK_LLVM_DYLIB) add_llvm_library( LLVMRaptor-${LLVM_VERSION_MAJOR} diff --git a/pass/Raptor.cpp b/pass/Raptor.cpp index 60619e9c..f3cf1d3a 100644 --- a/pass/Raptor.cpp +++ b/pass/Raptor.cpp @@ -127,32 +127,6 @@ void addNoCapture(llvm::Function *F, unsigned ArgNo) { #endif } -namespace MCAType { - // Get MCAType from int input - constexpr MCAType get(int mcaType) { - switch(mcaType) { - case VerificarloMCA: return VerificarloMCA; break; - default: return NoMCAType; break; - } - } - // Add mcaType to TruncateMode - constexpr TruncateMode addToTruncateMode(TruncateMode Mode, - MCAType mcaType) { - assert(!isMCA(Mode)); - return TruncateMode(Mode + (mcaType << shift)); - } - // Check that the TruncateMode and mcaType combo is supported - constexpr bool isValidTruncMCAMode(TruncateMode Mode, MCAType mcaType) { - assert(!isMCA(Mode)); - switch (Mode + (mcaType << shift)) { - case TruncOpMCAVerificarloMode: - return true; break; - default: - return false; break; - } - } -}; - #define addAttribute addAttributeAtIndex #define getAttribute getAttributeAtIndex bool attributeKnownFunctions(llvm::Function &F) { @@ -687,16 +661,18 @@ class RaptorBase { return false; } auto Cmca = cast(CI->getArgOperand(1)); - if (Cmca->getValue().getZExtValue()+1 >= MCAType::NumMCAType) { + auto mcaTypeID = Cmca->getValue().getZExtValue(); + if (mcaTypeID + 1 >= MCAType::NumMCAType) { EmitFailure("WrongArgVal", CI->getDebugLoc(), CI, "Invalid input for MCA backend type."); return false; } - MCAType::MCAType mcaType = MCAType::get(Cmca->getValue().getZExtValue()+1); + MCAType::MCAType mcaType = MCAType::get(mcaTypeID + 1); + auto mcaName = MCAType::getName(mcaTypeID + 1); if (mcaType == MCAType::NoMCAType) { EmitFailure("Unsupported", CI->getDebugLoc(), CI, - "Unsupported MCA backend type ", mcaType, - ", please build raptor with selected backend type."); + "Unsupported MCA backend type ", mcaTypeID, "(", mcaName, + "), please build raptor with selected backend type."); return false; } if (!isValidTruncMCAMode(TruncOpMode, mcaType)) { diff --git a/pass/RaptorLogic.h b/pass/RaptorLogic.h index fe98ac8b..c6c3a1cc 100644 --- a/pass/RaptorLogic.h +++ b/pass/RaptorLogic.h @@ -114,9 +114,11 @@ enum TruncateMode { } namespace MCAType { + // Check if a TruncateMode has an MCATYpe added constexpr bool isMCA(TruncateMode Mode) { return (Mode >> shift) > 0; } + // Split out the MCAType from the TruncateMode constexpr std::pair splitTruncMCAMode(TruncateMode Mode) { switch (Mode) { @@ -126,6 +128,39 @@ namespace MCAType { return {Mode, NoMCAType}; break; } } + // Get MCAType from int input + constexpr MCAType get(int mcaType) { + switch(mcaType) { +#ifdef __RAPTOR_HAS_VERIFICARLOMCA + case VerificarloMCA: return VerificarloMCA; break; +#endif + default: return NoMCAType; break; + } + } + // Get name of MCAType from int input + constexpr std::string_view getName(int mcaType) { + switch(mcaType) { + case NoMCAType: return ""; break; + case VerificarloMCA: return "verificarlo"; break; + default: return "invalid"; break; + } + } + // Add mcaType to TruncateMode + constexpr TruncateMode addToTruncateMode(TruncateMode Mode, + MCAType mcaType) { + assert(!isMCA(Mode)); + return TruncateMode(Mode + (mcaType << shift)); + } + // Check that the TruncateMode and mcaType combo is supported + constexpr bool isValidTruncMCAMode(TruncateMode Mode, MCAType mcaType) { + assert(!isMCA(Mode)); + switch (Mode + (mcaType << shift)) { + case TruncOpMCAVerificarloMode: + return true; break; + default: + return false; break; + } + } }; struct FloatRepresentation { From 73f6ccabad8c938f95170348c1a77093ffa60f8b Mon Sep 17 00:00:00 2001 From: Minli Liao <166613619+MinliLiao@users.noreply.github.com> Date: Wed, 2 Sep 2026 18:44:53 +0900 Subject: [PATCH 14/14] Move to including interflop_mca*.h instead of copying used declaration --- CMakeLists.txt | 4 + runtime/obj/MonteCarloArithmetic.cpp | 236 +++++++++++---------------- 2 files changed, 103 insertions(+), 137 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f63c4db1..ebc045af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -390,16 +390,20 @@ if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) endif() endforeach() if (DEFINED __RAPTOR_VERIFICARLOMCA_QUAD_LIB_PATH) + get_filename_component(__RAPTOR_VERIFICARLOMCA_QUAD_LIB_DIR "${__RAPTOR_VERIFICARLOMCA_QUAD_LIB_PATH}" DIRECTORY) add_library(verificarlo SHARED IMPORTED) set_target_properties(verificarlo PROPERTIES IMPORTED_LOCATION "${__RAPTOR_VERIFICARLOMCA_QUAD_LIB_PATH}" + INTERFACE_INCLUDE_DIRECTORIES "${__RAPTOR_VERIFICARLOMCA_QUAD_LIB_DIR}/../include" ) target_compile_definitions(verificarlo INTERFACE __RAPTOR_VERIFICARLOMCA_QUAD_MODE) endif() if (DEFINED __RAPTOR_VERIFICARLOMCA_INT_LIB_PATH) + get_filename_component(__RAPTOR_VERIFICARLOMCA_INT_LIB_DIR "${__RAPTOR_VERIFICARLOMCA_INT_LIB_PATH}" DIRECTORY) add_library(verificarlo_int SHARED IMPORTED) set_target_properties(verificarlo_int PROPERTIES IMPORTED_LOCATION "${__RAPTOR_VERIFICARLOMCA_INT_LIB_PATH}" + INTERFACE_INCLUDE_DIRECTORIES "${__RAPTOR_VERIFICARLOMCA_QUAD_LIB_DIR}/../include" ) target_compile_definitions(verificarlo_int INTERFACE __RAPTOR_VERIFICARLOMCA_INT_MODE) endif() diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp index 356307a6..83072f4f 100644 --- a/runtime/obj/MonteCarloArithmetic.cpp +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -20,37 +20,15 @@ // Includes needed to define interface to verificarlo #include #include - #include - #include - #include - #include #include #include - #include #include #if defined(__cplusplus) extern "C" { #endif - // Typedefs copied from verificarlo repo file - // src/interflop-stdlib/interflop_stdlib.h - typedef void (*interflop_panic_t)(const char *msg); - typedef void File; - // Function signature copied from verificarlo repo file - // src/interflop-stdlib/interflop_stdlib.c - extern void interflop_set_handler(const char *name, void *function_ptr); #ifdef __RAPTOR_VERIFICARLOMCA_INT_MODE #define __RAPTOR_VERIFICARLOMCA_HAS_INT true - // Macro copied from verificarlo repo backends files - // src/backends/interflop-backend-mcaint/interflop_mca.h - #define INTERFLOP_MCAINT_API(name) interflop_mcaint_##name - // Function signatures copied from verificarlo repo backends files - // src/backends/interflop-backend-mcaint/interflop_mca.c - extern void INTERFLOP_MCAINT_API(pre_init)(interflop_panic_t panic, - File *stream, void **context); - extern void INTERFLOP_MCAINT_API(cli)(int argc, char **argv, - void *context); - extern void INTERFLOP_MCAINT_API(configure)(void *configure, - void *context); + #include extern void _mcaint_inexact_binary64(double *da, void *context); extern void _mcaint_inexact_binary128(_Float128 *qa, void *context); #define __RAPTOR_VERIFICARLOMCA_INT_INTERFLOP_CALL(name, ...) \ @@ -64,17 +42,7 @@ #endif #ifdef __RAPTOR_VERIFICARLOMCA_QUAD_MODE #define __RAPTOR_VERIFICARLOMCA_HAS_QUAD true - // Macro copied from verificarlo repo backends files - // src/backends/interflop-backend-mcaint/interflop_mca_int.h - #define INTERFLOP_MCAQUAD_API(name) interflop_mcaquad_##name - // Function signatures copied from verificarlo repo backends files - // src/backends/interflop-backend-mcaint/interflop_mca_int.c - extern void INTERFLOP_MCAQUAD_API(pre_init)(interflop_panic_t panic, - File *stream, void **context); - extern void INTERFLOP_MCAQUAD_API(cli)(int argc, char **argv, - void *context); - extern void INTERFLOP_MCAQUAD_API(configure)(void *configure, - void *context); + #include extern void _mcaquad_inexact_binary64(double *da, void *context); extern void _mcaquad_inexact_binary128(_Float128 *qa, void *context); #define __RAPTOR_VERIFICARLOMCA_INTERFLOP_CALL(name, ...) \ @@ -89,84 +57,38 @@ #if defined(__cplusplus) } #endif + #if __RAPTOR_VERIFICARLOMCA_HAS_INT && __RAPTOR_VERIFICARLOMCA_HAS_QUAD + #define __RAPTOR_VERIFICARLO_MCA_TYPE(name) \ + std::conditional_t + #define __RAPTOR_VERIFICARLO_MCA_ENUM(type, name) \ + mca_##type(IS_MCAINT? mcaint_##type::mcaint_##name : \ + mcaquad_##type::mcaquad_##name) + #elif __RAPTOR_VERIFICARLOMCA_HAS_INT + #define __RAPTOR_VERIFICARLO_MCA_TYPE(name) mcaint_##name + #define __RAPTOR_VERIFICARLO_MCA_ENUM(type, name) \ + mcaint_##type::mcaint_##name + #else // __RAPTOR_VERIFICARLOMCA_HAS_QUAD + #define __RAPTOR_VERIFICARLO_MCA_TYPE(name) mcaquad_##name + #define __RAPTOR_VERIFICARLO_MCA_ENUM(type, name) \ + mcaquad_##type::mcaquad_##name + #endif // Enclose types/functions to interface with verificarlo in unnamed namespace namespace { // Using a struct because the context needs initialization struct verificarlo_mca_context_t { - // Typedef copied from verificarlo repo file - // src/interflop-stdlib/interflop_stdlib.h - typedef unsigned int IUint32_t; - typedef long int IInt64_t; - typedef unsigned long int IUint64_t; - typedef int IBool; - - // Definitions adapted from verificarlo repo backends files - // src/backends/interflop-backend-mcaint/interflop_mca_int.h and - // src/backends/interflop-backend-mcaquad/interflop_mca.h - // These definitions from mcaint and mcaquad are compatible so defining - // only once here. - /* define the available MCA modes of operation */ - typedef enum { - mca_mode_ieee, - mca_mode_mca, - mca_mode_pb, - mca_mode_rr, - _mca_mode_end_ - } mca_mode; - - /* define the available error modes */ - typedef enum { - mca_err_mode_rel, - mca_err_mode_abs, - mca_err_mode_all, - _mca_err_mode_end_ - } mca_err_mode; - - /* Interflop context */ - typedef struct { - IUint64_t seed; - float sparsity; - int binary32_precision; - int binary64_precision; - int absErr_exp; - IBool relErr; - IBool absErr; - IBool daz; - IBool ftz; - IBool choose_seed; - mca_mode mode; - } mcaquad_context_t; - - /* Interflop context */ - typedef struct { - IBool relErr; - IBool absErr; - IBool daz; - IBool ftz; - IBool choose_seed; - mca_mode mode; - int binary32_precision; - int binary64_precision; - int absErr_exp; - float sparsity; - IUint64_t seed; - } mcaint_context_t; - + // Helper type for getting the correct mca context type + template + using mca_context_t = __RAPTOR_VERIFICARLO_MCA_TYPE(context_t); + // Helper type for getting the correct mca configure type template - using mca_context_t = std::conditional_t; - typedef struct { - IUint64_t seed; - float sparsity; - IUint32_t precision_binary32; - IUint32_t precision_binary64; - mca_mode mode; - mca_err_mode err_mode; - IInt64_t max_abs_err_exponent; - IUint32_t daz; - IUint32_t ftz; - } mca_conf_t; + using mca_conf_t = __RAPTOR_VERIFICARLO_MCA_TYPE(conf_t); + // Helper type for getting the correct mca mode type + template + using mca_mode = __RAPTOR_VERIFICARLO_MCA_TYPE(mode); + // Helper type for getting the correct mca error mode type + template + using mca_err_mode = __RAPTOR_VERIFICARLO_MCA_TYPE(err_mode); // Helper type for compile time type check template @@ -185,8 +107,53 @@ template = true> using inexact_t = std::conditional_t, double, _Float128>; - + // Helper variable template to get the correct mca mode enum value + template + static constexpr mca_mode mca_mode_ieee = + __RAPTOR_VERIFICARLO_MCA_ENUM(mode, mode_ieee); + template + static constexpr mca_mode mca_mode_rr = + __RAPTOR_VERIFICARLO_MCA_ENUM(mode, mode_rr); + template + static constexpr mca_mode mca_mode_pb = + __RAPTOR_VERIFICARLO_MCA_ENUM(mode, mode_pb); + template + static constexpr mca_mode mca_mode_mca = + __RAPTOR_VERIFICARLO_MCA_ENUM(mode, mode_mca); + + // Helper variable template to get the correct mca error mode enum value + template + static constexpr mca_err_mode mca_err_mode_rel = + __RAPTOR_VERIFICARLO_MCA_ENUM(err_mode, err_mode_rel); + template + static constexpr mca_err_mode mca_err_mode_abs = + __RAPTOR_VERIFICARLO_MCA_ENUM(err_mode, err_mode_abs); + template + static constexpr mca_err_mode mca_err_mode_all = + __RAPTOR_VERIFICARLO_MCA_ENUM(err_mode, err_mode_all); + + // Helper variable template to get mca_conf_t with default values + template + static constexpr mca_conf_t default_mca_conf = { + .seed = 0ULL, // Default to 0, but always sets the seed to chosen + // If random (0,1) num > sparsity, MCA is not applied. + .sparsity = 1.0f, // Always apply MCA + // Between 1 and double precision pseudo-mantissa encoding size (52) + .precision_binary32 = 24, // default to float mantissa size (23+1) + // Between 1 and quad precision pseudo mantissa encoding size (112) + .precision_binary64 = 53, // default to double mantissa size (52+1) + // Only add inexact to input operands. + .mode = mca_mode_pb, // default to only perturb inbound + // The mode matching formula (1) in Verificarlo + .err_mode = mca_err_mode_rel, + // Unused for relative error mode mca_err_mode_rel + .max_abs_err_exponent = 112, // default from verificarlo set to 112 + // Default to false, not dealing with this now + .daz = 0, // 0 for false, 1 for true + .ftz = 0 // 0 for false, 1 for true + }; + // Function and definition adapted from verificarlo repo file // src/vfcwrapper/main.c.in static constexpr int MAX_ARGS=256; @@ -207,7 +174,7 @@ argv[argc] = NULL; } } - // Return the high precision type used for MCA calculation from mpfr_t a, + // Return the high precision type used for MCA calculation from mpfr_t a, // with the rounding mode rnd_mode template = true> static inexact_t get_inexact_t_from(mpfr_t a, mpfr_rnd_t rnd_mode) { @@ -269,9 +236,17 @@ else { return _get_virtual_prec(); } } // Returns the MCA mode (ieee, rr, pb, or mca) - mca_mode get_mode() { - if (is_mcaint) { return ((mca_context_t *)context)->mode; } - else { return ((mca_context_t *)context)->mode; } + template + mca_mode get_mode() { + return ((mca_context_t *)context)->mode; + } + // Returns if MCA random perturbation should be added based on mode + template + bool should_inexact(bool isOutbound) { + auto mode = get_mode(); + return isOutbound ? + (mode == mca_mode_rr || mode == mca_mode_mca) : + (mode == mca_mode_pb || mode == mca_mode_mca); } // Set the virtual precision used for MCA of floating point type T template = true> @@ -315,7 +290,7 @@ #endif // Function definitions copied from verificarlo repo file // src/vfcwrapper/main.c.in - void _vfc_panic(const char *msg) { fprintf(stderr, "%s", msg); exit(1);} + void _vfc_panic(const char *msg) { fprintf(stderr, "%s", msg); exit(1); } pid_t get_tid() { return syscall(__NR_gettid); } long _vfc_strtol(const char *nptr, char **endptr, int *error) { *error = 0; @@ -357,7 +332,8 @@ size_t env_len = strlen(env_val); *vfc_backends = (char *)malloc(env_len + 1); if (*vfc_backends == NULL) { - fprintf(stderr, "Memory allocation failed for %s", *vfc_backends_env); + fprintf(stderr, "Memory allocation failed for %s", + *vfc_backends_env); } strcpy(*vfc_backends, env_val); } else { @@ -455,25 +431,13 @@ } else { // Default configuration used to initialize the context // Also used to set the context when configuration changes - mca_conf_t mca_conf = { - .seed = 0ULL, // Default to 0, but always sets the seed to chosen - // If random (0,1) num > sparsity, MCA is not applied. - .sparsity = 1.0f, // Always apply MCA - // Between 1 and double precision pseudo-mantissa encoding size (52) - .precision_binary32 = 24, // default to float mantissa size (23+1) - // Between 1 and quad precision pseudo mantissa encoding size (112) - .precision_binary64 = 53, // default to double mantissa size (52+1) - // Only add inexact to input operands. - .mode = mca_mode::mca_mode_pb, // default to only perturb inbound - // The mode matching formula (1) in Verificarlo - .err_mode = mca_err_mode::mca_err_mode_rel, - // Unused for relative error mode mca_err_mode_rel - .max_abs_err_exponent = 112, // default from verificarlo set to 112 - // Default to false, not dealing with this now - .daz = 0, // 0 for false, 1 for true - .ftz = 0 // 0 for false, 1 for true - }; - set_verificarlo_mca_context(&mca_conf); + if (is_mcaint) { + mca_conf_t mca_conf = default_mca_conf; + set_verificarlo_mca_context(&mca_conf); + } else { + mca_conf_t mca_conf = default_mca_conf; + set_verificarlo_mca_context(&mca_conf); + } } } // Global so that it gets automatically initialized through construction @@ -489,11 +453,9 @@ #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode, \ isOutbound) \ do { \ - using mca_mode = verificarlo_mca_context_t::mca_mode; \ - mca_mode mode = verificarlo_mca_context.get_mode(); \ - bool addInexact = isOutbound ? \ - (mode == mca_mode::mca_mode_rr || mode == mca_mode::mca_mode_mca) \ - : (mode == mca_mode::mca_mode_pb || mode == mca_mode::mca_mode_mca); \ + bool addInexact = verificarlo_mca_context.is_mcaint? \ + verificarlo_mca_context.should_inexact(isOutbound) : \ + verificarlo_mca_context.should_inexact(isOutbound); \ if (addInexact) { \ if (virtual_prec != \ verificarlo_mca_context.get_virtual_prec() \