Skip to content

Commit

Permalink
Add more FP-rounding LLVM intrinsics (ldc-developers#4756)
Browse files Browse the repository at this point in the history
  • Loading branch information
kinke authored Oct 7, 2024
1 parent c0bb238 commit 495578b
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 11 deletions.
18 changes: 18 additions & 0 deletions dmd/builtin.d
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions dmd/func.d
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ enum BUILTIN : ubyte
llvm_rint,
llvm_nearbyint,
llvm_round,
llvm_lround,
llvm_llround,
llvm_lrint,
llvm_llrint,
llvm_fma,
llvm_copysign,
llvm_bswap,
Expand Down
5 changes: 5 additions & 0 deletions dmd/root/ctfloat.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions dmd/root/ctfloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 3 additions & 10 deletions runtime/druntime/src/core/math.d
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
29 changes: 29 additions & 0 deletions runtime/druntime/src/ldc/intrinsics.di
Original file line number Diff line number Diff line change
Expand Up @@ -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.llround.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.
Expand Down
2 changes: 1 addition & 1 deletion runtime/phobos
Submodule phobos updated 1 files
+28 −0 std/math/rounding.d

0 comments on commit 495578b

Please sign in to comment.