diff --git a/CMakeLists.txt b/CMakeLists.txt index 06bb3f7d..ebc045af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -369,6 +369,45 @@ install(PROGRAMS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/raptor_plot_float_histogram.py" DESTINATION bin) +if (DEFINED __RAPTOR_VERIFICARLOMCA_LIB_PATH) + 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) + 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() +endif() add_subdirectory(runtime) add_subdirectory(test) add_subdirectory(wrappers) 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 1ca8ec81..f3cf1d3a 100644 --- a/pass/Raptor.cpp +++ b/pass/Raptor.cpp @@ -514,6 +514,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 +545,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 +575,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 +623,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 +648,43 @@ 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)); + 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(mcaTypeID + 1); + auto mcaName = MCAType::getName(mcaTypeID + 1); + if (mcaType == MCAType::NoMCAType) { + EmitFailure("Unsupported", CI->getDebugLoc(), CI, + "Unsupported MCA backend type ", mcaTypeID, "(", mcaName, + "), 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 +887,7 @@ class RaptorBase { SmallVector toTruncateFuncOp; SmallVector toTruncateValue; SmallVector toExpandValue; + SmallVector toMCAFuncOp; retry:; for (BasicBlock &BB : F) { for (Instruction &I : BB) { @@ -1062,6 +1116,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 +1133,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 +1187,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 +1213,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..c6c3a1cc 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,62 @@ enum TruncateMode { return "op"; case TruncOpFullModuleMode: return "op_full_module"; + case TruncOpMCAVerificarloMode: + return "op_mca_verificarlo"; } llvm_unreachable("Invalid truncation mode"); } +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) { + case TruncOpMCAVerificarloMode: + return {TruncOpMode, VerificarloMCA}; break; + default: + 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 { public: enum FloatRepresentationType { IEEE = 0, MPFR = 1 }; @@ -423,6 +486,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/CMakeLists.txt b/runtime/CMakeLists.txt index 62de130e..12601533 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 @@ -44,6 +45,14 @@ target_include_directories(Raptor-RT-${LLVM_VERSION_MAJOR} PUBLIC $ ) +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/include/private/raptor/Common.h b/runtime/include/private/raptor/Common.h index 3fdfa753..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(); @@ -131,4 +134,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, bool isOutbound); +#include "raptor/FloatTypes.def" + #endif // _RAPTOR_COMMON_H_ 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 3333faa6..30ba26a9 100644 --- a/runtime/ir/Mpfr.cpp +++ b/runtime/ir/Mpfr.cpp @@ -82,6 +82,20 @@ } while (0) #endif +#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 + #define __RAPTOR_MCA_INEXACT(FROM_TY, a, loc, rnd_mode, isOutbound) \ + __RAPTOR_MCA_CONCAT(inexact_, FROM_TY)(a, \ + __RAPTOR_MCA_CONCAT(get_virtural_prec_, FROM_TY)(a, loc), rnd_mode, \ + isOutbound); +#else + #define __RAPTOR_USE_MCA false + #define __RAPTOR_MCA_INEXACT(FROM_TY, a, loc, rnd_mode, isOutbound) +#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,7 +577,19 @@ 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) { \ + 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) { \ + 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; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ @@ -593,7 +619,19 @@ 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) { \ + 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) { \ + 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; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ @@ -622,8 +660,22 @@ 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) { \ + 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) { \ + 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; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ @@ -656,8 +708,24 @@ 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) { \ + 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) { \ + 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; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ @@ -696,6 +764,14 @@ 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) { \ + 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; \ } else if (__raptor_fprt_is_mem_mode(mode)) { \ diff --git a/runtime/obj/MonteCarloArithmetic.cpp b/runtime/obj/MonteCarloArithmetic.cpp new file mode 100644 index 00000000..83072f4f --- /dev/null +++ b/runtime/obj/MonteCarloArithmetic.cpp @@ -0,0 +1,504 @@ +#include +#include + +// verificarlo uses _Float128 that needs extra definition +#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 + #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 + +#if defined(__RAPTOR_VERIFICARLOMCA_QUAD_MODE) || \ + defined(__RAPTOR_VERIFICARLOMCA_INT_MODE) + #define __RAPTOR_USE_VERIFICARLOMCA true + // Includes needed to define interface to verificarlo + #include + #include + #include + #include + #include + #if defined(__cplusplus) + extern "C" { + #endif + #ifdef __RAPTOR_VERIFICARLOMCA_INT_MODE + #define __RAPTOR_VERIFICARLOMCA_HAS_INT true + #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, ...) \ + 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_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 + #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, ...) \ + 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) + } + #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 { + // 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_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 + 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>; + + // 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; + 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); + } + + // Context used for the _mca*_inexact_binary64 functions + void * context = nullptr; + // 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) { + if (is_mcaint) { + __RAPTOR_VERIFICARLOMCA_INT_INTERFLOP_CALL(configure, + configure, context); + } else { + __RAPTOR_VERIFICARLOMCA_INTERFLOP_CALL(configure, configure, 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) + 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> + 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" { + #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[verificarlo_mca_context_t::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'; + } + } + } + } + } + + verificarlo_mca_context_t::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); + // 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) { + 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 + 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 + 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 verificarlo_mca_context.get_virtual_prec(); \ + } while (0) + + #define __RAPTOR_VERIFICARLOMCA_inexact(CPP_TY, a, virtual_prec, rnd_mode, \ + isOutbound) \ + do { \ + 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() \ + ) { \ + verificarlo_mca_context.set_virtual_prec(virtual_prec); \ + } \ + 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) +#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, \ + isOutbound) +#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) { \ + __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(); \ + } \ + } \ + __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) { \ + __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; \ + abort(); \ + } \ + } +#include "raptor/FloatTypes.def" \ No newline at end of file diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index 48ec93a2..75e4c5d5 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -105,7 +105,19 @@ 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_link_options = "" +if verificarlomca_lib_path != "": + 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)) link = "-L@RAPTOR_BINARY_DIR@/runtime/ -lstdc++ -lmpfr -lRaptor-RT-" + config.llvm_ver