diff --git a/dmd/builtin.d b/dmd/builtin.d index 600d42d92a9..4acad88ed9e 100644 --- a/dmd/builtin.d +++ b/dmd/builtin.d @@ -706,6 +706,24 @@ Expression eval_llvmround(Loc loc, FuncDeclaration fd, Expression[] arguments) return new RealExp(loc, CTFloat.round(arg0.toReal()), type); } +alias eval_llvmlrint = eval_llvmllrint; // difference: int return type, not long +Expression eval_llvmllrint(Loc loc, FuncDeclaration fd, Expression[] arguments) +{ + Type type = fd.type.isTypeFunction().next; // int or long + Expression arg0 = arguments[0]; + assert(arg0.op == EXP.float64); + return new IntegerExp(loc, CTFloat.llrint(arg0.toReal()), type); +} + +alias eval_llvmlround = eval_llvmllround; // difference: int return type, not long +Expression eval_llvmllround(Loc loc, FuncDeclaration fd, Expression[] arguments) +{ + Type type = fd.type.isTypeFunction().next; // int or long + Expression arg0 = arguments[0]; + assert(arg0.op == EXP.float64); + return new IntegerExp(loc, CTFloat.llround(arg0.toReal()), type); +} + Expression eval_llvmfma(Loc loc, FuncDeclaration fd, Expression[] arguments) { Type type = getTypeOfOverloadedIntrinsic(fd); diff --git a/dmd/func.d b/dmd/func.d index 434c6b1202f..8a3cf1b24ff 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -130,6 +130,8 @@ enum BUILTIN : ubyte llvm_rint, llvm_nearbyint, llvm_round, + llvm_llround, + llvm_llrint, llvm_fma, llvm_copysign, llvm_bswap, diff --git a/dmd/root/ctfloat.d b/dmd/root/ctfloat.d index 521a9eabd26..1aac24a66f7 100644 --- a/dmd/root/ctfloat.d +++ b/dmd/root/ctfloat.d @@ -13,6 +13,7 @@ module dmd.root.ctfloat; static import core.math, core.stdc.math; import core.stdc.errno; +import core.stdc.stdint; import core.stdc.stdio; import core.stdc.stdlib; import core.stdc.string; @@ -136,11 +137,15 @@ extern (C++) struct CTFloat { static real_t rint(real_t x) { return real_t(cast(double)std.math.rint(cast(double)x)); } static real_t nearbyint(real_t x) { return real_t(cast(double)std.math.nearbyint(cast(double)x)); } + static int64_t llround(real_t x) { return core.math.rndtol(cast(double)x)); } + static int64_t llrint(real_t x) { return core.stdc.math.llrint(cast(double)x)); } } else { static real_t rint(real_t x) { return std.math.rint(x); } static real_t nearbyint(real_t x) { return std.math.nearbyint(x); } + static int64_t llround(real_t x) { return core.math.rndtol(x); } + static int64_t llrint(real_t x) { return core.stdc.math.llrintl(x); } } static bool isFloat32LiteralOutOfRange(const(char)* literal) @nogc; diff --git a/dmd/root/ctfloat.h b/dmd/root/ctfloat.h index 23f7dd04d1b..e672ac78b04 100644 --- a/dmd/root/ctfloat.h +++ b/dmd/root/ctfloat.h @@ -53,6 +53,8 @@ struct CTFloat #if IN_LLVM static real_t rint(real_t x); static real_t nearbyint(real_t x); + static int64_t llround(real_t x); + static int64_t llrint(real_t x); // implemented in gen/ctfloat.cpp static void toAPFloat(real_t src, llvm::APFloat &dst); diff --git a/runtime/druntime/src/core/math.d b/runtime/druntime/src/core/math.d index 947bcdd3dce..ff0a5f00541 100644 --- a/runtime/druntime/src/core/math.d +++ b/runtime/druntime/src/core/math.d @@ -98,16 +98,9 @@ else version (LDC) { - private extern(C) - { - long llroundf(float x); - long llround(double x); - long llroundl(real x); - } - - alias rndtol = llroundf; - alias rndtol = llround; - alias rndtol = llroundl; + alias rndtol = llvm_llround!float; + alias rndtol = llvm_llround!double; + alias rndtol = llvm_llround!real; } else { diff --git a/runtime/druntime/src/ldc/intrinsics.di b/runtime/druntime/src/ldc/intrinsics.di index 485ffc8c473..04c6b9e958b 100644 --- a/runtime/druntime/src/ldc/intrinsics.di +++ b/runtime/druntime/src/ldc/intrinsics.di @@ -300,6 +300,35 @@ pragma(LDC_intrinsic, "llvm.round.f#") T llvm_round(T)(T val) if (__traits(isFloating, T)); +/// The 'llvm.roundeven.*' intrinsics returns the operand rounded to the nearest +/// integer in floating-point format rounding halfway cases to even (that is, to +/// the nearest value that is an even integer). +pragma(LDC_intrinsic, "llvm.roundeven.f#") + T llvm_roundeven(T)(T val) + if (__traits(isFloating, T)); + +/// The 'llvm.lround.*' intrinsics return the operand rounded to the nearest +/// integer with ties away from zero. +pragma(LDC_intrinsic, "llvm.lround.i32.f#") + int llvm_lround(T)(T val) + if (__traits(isFloating, T)); + +/// The 'llvm.llround.*' intrinsics return the operand rounded to the nearest +/// integer with ties away from zero. +pragma(LDC_intrinsic, "llvm.lround.i64.f#") + long llvm_llround(T)(T val) + if (__traits(isFloating, T)); + +/// The 'llvm.lrint.*' intrinsics return the operand rounded to the nearest integer. +pragma(LDC_intrinsic, "llvm.lrint.i32.f#") + int llvm_lrint(T)(T val) + if (__traits(isFloating, T)); + +/// The 'llvm.llrint.*' intrinsics return the operand rounded to the nearest integer. +pragma(LDC_intrinsic, "llvm.llrint.i64.f#") + long llvm_llrint(T)(T val) + if (__traits(isFloating, T)); + /// The 'llvm.fmuladd.*' intrinsic functions represent multiply-add expressions /// that can be fused if the code generator determines that the fused expression /// would be legal and efficient. diff --git a/runtime/phobos b/runtime/phobos index 788d4b0fed3..05f2638c7f7 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 788d4b0fed3c7ba46654a5548d1e7401586471c3 +Subproject commit 05f2638c7f70b2d83455e717236fdfd16ab6b9d9