diff --git a/src/Functions/DivisionUtils.h b/src/Functions/DivisionUtils.h index 7fd5b7476e1..f5767b01bc4 100644 --- a/src/Functions/DivisionUtils.h +++ b/src/Functions/DivisionUtils.h @@ -8,6 +8,10 @@ #include "config.h" +#if USE_EMBEDDED_COMPILER +# include +#endif + namespace DB { @@ -15,6 +19,7 @@ namespace DB namespace ErrorCodes { extern const int ILLEGAL_DIVISION; + extern const int LOGICAL_ERROR; } template @@ -158,7 +163,20 @@ struct ModuloImpl } #if USE_EMBEDDED_COMPILER - static constexpr bool compilable = false; /// don't know how to throw from LLVM IR + static constexpr bool compilable = true; /// Ignore exceptions in LLVM IR + + static llvm::Value * compile(llvm::IRBuilder<> & b, llvm::Value * left, llvm::Value * right, bool is_signed) + { + if (left->getType()->isFloatingPointTy()) + { + auto * func_frem = llvm::Intrinsic::getDeclaration(b.GetInsertBlock()->getModule(), llvm::Intrinsic::vp_frem, left->getType()); + return b.CreateCall(func_frem, {left, right}); + } + else if (left->getType()->isIntegerTy()) + return is_signed ? b.CreateSRem(left, right) : b.CreateURem(left, right); + else + throw Exception(ErrorCodes::LOGICAL_ERROR, "ModuloImpl compilation expected native integer or floating point type"); + } #endif }; diff --git a/src/Functions/FunctionBinaryArithmetic.h b/src/Functions/FunctionBinaryArithmetic.h index df239b820af..500eb471a13 100644 --- a/src/Functions/FunctionBinaryArithmetic.h +++ b/src/Functions/FunctionBinaryArithmetic.h @@ -2368,7 +2368,18 @@ ColumnPtr executeStringInteger(const ColumnsWithTypeAndName & arguments, const A using ResultDataType = typename BinaryOperationTraits::ResultDataType; using OpSpec = Op; if constexpr (!std::is_same_v && !IsDataTypeDecimal && OpSpec::compilable) - return true; + { + if constexpr (is_modulo) + { + using PromotedType = std::conditional_t< + std::is_floating_point_v, + Float64, + NumberTraits::ResultOfIf>; + return std::is_integral_v || std::is_floating_point_v; + } + else + return true; + } } return false; }); @@ -2393,10 +2404,23 @@ ColumnPtr executeStringInteger(const ColumnsWithTypeAndName & arguments, const A if constexpr (!std::is_same_v && !IsDataTypeDecimal && OpSpec::compilable) { auto & b = static_cast &>(builder); - auto * lval = nativeCast(b, arguments[0], result_type); - auto * rval = nativeCast(b, arguments[1], result_type); - result = OpSpec::compile(b, lval, rval, std::is_signed_v); - + if constexpr (is_modulo) + { + using PromotedType = std::conditional_t< + std::is_floating_point_v, + Float64, + NumberTraits::ResultOfIf>; + auto promoted_type = std::make_shared>(); + auto * lval = nativeCast(b, arguments[0], promoted_type); + auto * rval = nativeCast(b, arguments[1], promoted_type); + result = OpSpec::compile(b, lval, rval, std::is_signed_v); + } + else + { + auto * lval = nativeCast(b, arguments[0], result_type); + auto * rval = nativeCast(b, arguments[1], result_type); + result = OpSpec::compile(b, lval, rval, std::is_signed_v); + } return true; } }