Skip to content

Commit

Permalink
Use roundeven instead of rint for round(x)
Browse files Browse the repository at this point in the history
The `llvm.rint` intrinsic is sensitive to the floating-point
environment, so determined enough users can change the definition
of `round(x, RoundNearest)` to not be rount to even.

```
julia> round(2.5, RoundNearest)
2.0
julia> Base.Rounding.setrounding_raw(Float64, Base.Rounding.to_fenv(RoundUp))
julia> round(2.5, RoundNearest)
3.0
julia> round_even(x::Float64) = ccall("llvm.roundeven.f64", llvmcall, Float64, (Float64,), x)
round_even (generic function with 1 method)
julia> round_even(2.5)
2.0
```
  • Loading branch information
vchuravy committed Apr 17, 2021
1 parent 0b0e8e5 commit 044356c
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 3 deletions.
1 change: 1 addition & 0 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ add_tfunc(ceil_llvm, 1, 1, math_tfunc, 10)
add_tfunc(floor_llvm, 1, 1, math_tfunc, 10)
add_tfunc(trunc_llvm, 1, 1, math_tfunc, 10)
add_tfunc(rint_llvm, 1, 1, math_tfunc, 10)
add_tfunc(roundeven_llvm, 1, 1, math_tfunc, 10)
add_tfunc(sqrt_llvm, 1, 1, math_tfunc, 20)
add_tfunc(sqrt_llvm_fast, 1, 1, math_tfunc, 20)
## same-type comparisons ##
Expand Down
6 changes: 3 additions & 3 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,9 @@ round(x::Float16, r::RoundingMode{:Down}) = floor_llvm(x)
round(x::Float64, r::RoundingMode{:Up}) = ceil_llvm(x)
round(x::Float32, r::RoundingMode{:Up}) = ceil_llvm(x)
round(x::Float16, r::RoundingMode{:Up}) = ceil_llvm(x)
round(x::Float64, r::RoundingMode{:Nearest}) = rint_llvm(x)
round(x::Float32, r::RoundingMode{:Nearest}) = rint_llvm(x)
round(x::Float16, r::RoundingMode{:Nearest}) = rint_llvm(x)
round(x::Float64, r::RoundingMode{:Nearest}) = roundeven_llvm(x)
round(x::Float32, r::RoundingMode{:Nearest}) = roundeven_llvm(x)
round(x::Float16, r::RoundingMode{:Nearest}) = roundeven_llvm(x)

## floating point promotions ##
promote_rule(::Type{Float32}, ::Type{Float16}) = Float32
Expand Down
5 changes: 5 additions & 0 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static void jl_init_intrinsic_functions_codegen(void)
float_func[floor_llvm] = true;
float_func[trunc_llvm] = true;
float_func[rint_llvm] = true;
float_func[roundeven_llvm] = true;
float_func[sqrt_llvm] = true;
float_func[sqrt_llvm_fast] = true;
}
Expand Down Expand Up @@ -1286,6 +1287,10 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **arg
FunctionCallee rintintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::rint, makeArrayRef(t));
return ctx.builder.CreateCall(rintintr, x);
}
case roundeven_llvm: {
FunctionCallee roundevenintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::roundeven, makeArrayRef(t));
return ctx.builder.CreateCall(roundevenintr, x);
}
case sqrt_llvm: {
FunctionCallee sqrtintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::sqrt, makeArrayRef(t));
return ctx.builder.CreateCall(sqrtintr, x);
Expand Down
1 change: 1 addition & 0 deletions src/intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
ADD_I(floor_llvm, 1) \
ADD_I(trunc_llvm, 1) \
ADD_I(rint_llvm, 1) \
ADD_I(roundeven_llvm, 1) \
ADD_I(sqrt_llvm, 1) \
ADD_I(sqrt_llvm_fast, 1) \
/* pointer access */ \
Expand Down
1 change: 1 addition & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,7 @@ JL_DLLEXPORT jl_value_t *jl_ceil_llvm(jl_value_t *a);
JL_DLLEXPORT jl_value_t *jl_floor_llvm(jl_value_t *a);
JL_DLLEXPORT jl_value_t *jl_trunc_llvm(jl_value_t *a);
JL_DLLEXPORT jl_value_t *jl_rint_llvm(jl_value_t *a);
JL_DLLEXPORT jl_value_t *jl_roundeven_llvm(jl_value_t *a);
JL_DLLEXPORT jl_value_t *jl_sqrt_llvm(jl_value_t *a);
JL_DLLEXPORT jl_value_t *jl_sqrt_llvm_fast(jl_value_t *a);
JL_DLLEXPORT jl_value_t *jl_abs_float(jl_value_t *a);
Expand Down
1 change: 1 addition & 0 deletions src/runtime_intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,7 @@ un_fintrinsic(ceil_float,ceil_llvm)
un_fintrinsic(floor_float,floor_llvm)
un_fintrinsic(trunc_float,trunc_llvm)
un_fintrinsic(rint_float,rint_llvm)
un_fintrinsic(roundeven_float,roundeven_llvm)
un_fintrinsic(sqrt_float,sqrt_llvm)
un_fintrinsic(sqrt_float,sqrt_llvm_fast)

Expand Down

0 comments on commit 044356c

Please sign in to comment.