Skip to content

Commit ad872cb

Browse files
committed
Replaces checked_fptosi/checked_fptoui intrinsics with Julia implementations. Fixes #14549.
1 parent b36141f commit ad872cb

File tree

7 files changed

+22
-103
lines changed

7 files changed

+22
-103
lines changed

base/float.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -602,16 +602,29 @@ for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UIn
602602
$(Tf(typemin(Ti))-one(Tf)) < x < $(Tf(typemax(Ti))+one(Tf)) || throw(InexactError())
603603
unsafe_trunc($Ti,x)
604604
end
605-
else
605+
@eval function convert(::Type{$Ti}, x::$Tf)
606+
if ($(Tf(typemin(Ti))) <= x <= $(Tf(typemax(Ti)))) && (trunc(x) == x)
607+
return unsafe_trunc($Ti,x)
608+
else
609+
throw(InexactError())
610+
end
611+
end
612+
else #
606613
@eval function trunc(::Type{$Ti},x::$Tf)
607614
$(Tf(typemin(Ti))) <= x < $(Tf(typemax(Ti))) || throw(InexactError())
608615
unsafe_trunc($Ti,x)
609616
end
617+
@eval function convert(::Type{$Ti}, x::$Tf)
618+
if ($(Tf(typemin(Ti))) <= x < $(Tf(typemax(Ti)))) && (trunc(x) == x)
619+
return unsafe_trunc($Ti,x)
620+
else
621+
throw(InexactError())
622+
end
623+
end
610624
end
611625
end
612626
end
613627

614-
615628
@eval begin
616629
issubnormal(x::Float32) = (abs(x) < $(box(Float32,unbox(UInt32,0x00800000)))) & (x!=0)
617630
issubnormal(x::Float64) = (abs(x) < $(box(Float64,unbox(UInt64,0x0010000000000000)))) & (x!=0)

base/int.jl

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -328,16 +328,6 @@ rem(x::Integer, ::Type{Bool}) = ((x&1)!=0)
328328
mod{T<:Integer}(x::Integer, ::Type{T}) = rem(x, T)
329329

330330
unsafe_trunc{T<:Integer}(::Type{T}, x::Integer) = rem(x, T)
331-
332-
convert{Tf<:Union{Float32,Float64}}(T::BitSigned64T, x::Tf) =
333-
box(T,checked_fptosi(T,unbox(Tf,x)))
334-
convert{Tf<:Union{Float32,Float64}}(T::BitUnsigned64T, x::Tf) =
335-
box(T,checked_fptoui(T,unbox(Tf,x)))
336-
337-
convert{Tf<:Union{Float32,Float64}}(T::Union{Type{Int128},Type{UInt128}}, x::Tf) =
338-
(isinteger(x) || throw(InexactError()) ; trunc(T,x))
339-
convert(T::Union{Type{Int128},Type{UInt128}}, x::Float16) = convert(T, Float32(x))
340-
341331
for (Ts, Tu) in ((Int8, UInt8), (Int16, UInt16), (Int32, UInt32), (Int64, UInt64), (Int128, UInt128))
342332
@eval convert(::Type{Signed}, x::$Tu) = convert($Ts, x)
343333
@eval convert(::Type{Unsigned}, x::$Ts) = convert($Tu, x)

src/intrinsics.cpp

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -653,80 +653,6 @@ static jl_cgval_t generic_zext(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ct
653653
return mark_julia_type(ans, false, jlto, ctx);
654654
}
655655

656-
static Value *emit_eqfsi(Value *x, Value *y)
657-
{
658-
Value *fy = JL_INT(y);
659-
660-
// using all 64-bit is slightly faster than using mixed sizes
661-
Value *xx = x, *vv = fy;
662-
if (x->getType() == T_float32)
663-
xx = builder.CreateFPExt(xx, T_float64);
664-
if (vv->getType()->getPrimitiveSizeInBits() < 64)
665-
vv = builder.CreateSExt(vv, T_int64);
666-
667-
Value *back = builder.CreateSIToFP(vv, xx->getType());
668-
return builder.CreateAnd
669-
(builder.CreateFCmpOEQ(xx, back),
670-
builder.CreateICmpEQ(vv, builder.CreateFPToSI(back, vv->getType())));
671-
}
672-
673-
static Value *emit_eqfui(Value *x, Value *y)
674-
{
675-
Value *fy = JL_INT(y);
676-
677-
// using all 64-bit is slightly faster than using mixed sizes
678-
Value *xx = x, *vv = fy;
679-
if (x->getType() == T_float32)
680-
xx = builder.CreateFPExt(xx, T_float64);
681-
if (vv->getType()->getPrimitiveSizeInBits() < 64)
682-
vv = builder.CreateZExt(vv, T_int64);
683-
684-
Value *back = builder.CreateUIToFP(vv, xx->getType());
685-
return builder.CreateAnd
686-
(builder.CreateFCmpOEQ(xx, back),
687-
builder.CreateICmpEQ(vv, builder.CreateFPToUI(back, vv->getType())));
688-
}
689-
690-
static jl_cgval_t emit_checked_fptosi(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx)
691-
{
692-
jl_value_t *jlto = staticeval_bitstype(targ, "checked_fptosi", ctx);
693-
if (!jlto) return jl_cgval_t();
694-
Type *to = staticeval_bitstype(jlto);
695-
Value *fx = FP(auto_unbox(x, ctx));
696-
if (fx->getType() == T_void) return jl_cgval_t(); // auto_unbox threw an error
697-
Value *ans = builder.CreateFPToSI(fx, to);
698-
if (fx->getType() == T_float32 && to == T_int32) {
699-
raise_exception_unless
700-
(builder.CreateFCmpOEQ(builder.CreateFPExt(fx, T_float64),
701-
builder.CreateSIToFP(ans, T_float64)),
702-
literal_pointer_val(jl_inexact_exception), ctx);
703-
}
704-
else {
705-
raise_exception_unless(emit_eqfsi(fx, ans), literal_pointer_val(jl_inexact_exception), ctx);
706-
}
707-
return mark_julia_type(ans, false, jlto, ctx);
708-
}
709-
710-
static jl_cgval_t emit_checked_fptoui(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx)
711-
{
712-
jl_value_t *jlto = staticeval_bitstype(targ, "checked_fptoui", ctx);
713-
if (!jlto) return jl_cgval_t();
714-
Type *to = staticeval_bitstype(jlto);
715-
Value *fx = FP(auto_unbox(x, ctx));
716-
if (fx->getType() == T_void) return jl_cgval_t(); // auto_unbox threw an error
717-
Value *ans = builder.CreateFPToUI(fx, to);
718-
if (fx->getType() == T_float32 && to == T_int32) {
719-
raise_exception_unless
720-
(builder.CreateFCmpOEQ(builder.CreateFPExt(fx, T_float64),
721-
builder.CreateUIToFP(ans, T_float64)),
722-
literal_pointer_val(jl_inexact_exception), ctx);
723-
}
724-
else {
725-
raise_exception_unless(emit_eqfui(fx, ans), literal_pointer_val(jl_inexact_exception), ctx);
726-
}
727-
return mark_julia_type(ans, false, jlto, ctx);
728-
}
729-
730656
static jl_cgval_t emit_runtime_pointerref(jl_value_t *e, jl_value_t *i, jl_value_t *align, jl_codectx_t *ctx)
731657
{
732658
jl_cgval_t parg = emit_expr(e, ctx);
@@ -992,10 +918,6 @@ static jl_cgval_t emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
992918
return generic_sext(args[1], args[2], ctx);
993919
case zext_int:
994920
return generic_zext(args[1], args[2], ctx);
995-
case checked_fptosi:
996-
return emit_checked_fptosi(args[1], args[2], ctx);
997-
case checked_fptoui:
998-
return emit_checked_fptoui(args[1], args[2], ctx);
999921

1000922
case uitofp: {
1001923
jl_value_t *bt = staticeval_bitstype(args[1], "uitofp", ctx);

src/intrinsics.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@
6868
ADD_I(fptrunc, 2) \
6969
ADD_I(fpext, 2) \
7070
/* checked conversion */ \
71-
ADD_I(checked_fptosi, 2) \
72-
ADD_I(checked_fptoui, 2) \
7371
ADD_I(checked_trunc_sint, 2) \
7472
ADD_I(checked_trunc_uint, 2) \
7573
ADD_I(check_top_bit, 1) \

src/julia_internal.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -647,8 +647,6 @@ JL_DLLEXPORT jl_value_t *jl_fpext(jl_value_t *ty, jl_value_t *a);
647647
JL_DLLEXPORT jl_value_t *jl_fptoui_auto(jl_value_t *a);
648648
JL_DLLEXPORT jl_value_t *jl_fptosi_auto(jl_value_t *a);
649649

650-
JL_DLLEXPORT jl_value_t *jl_checked_fptoui(jl_value_t *ty, jl_value_t *a);
651-
JL_DLLEXPORT jl_value_t *jl_checked_fptosi(jl_value_t *ty, jl_value_t *a);
652650
JL_DLLEXPORT jl_value_t *jl_checked_trunc_sint(jl_value_t *ty, jl_value_t *a);
653651
JL_DLLEXPORT jl_value_t *jl_checked_trunc_uint(jl_value_t *ty, jl_value_t *a);
654652

src/runtime_intrinsics.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -876,15 +876,6 @@ static unsigned check_trunc_uint(unsigned isize, unsigned osize, void *pa)
876876
}
877877
cvt_iintrinsic_checked(LLVMTrunc, check_trunc_uint, checked_trunc_uint)
878878

879-
#define checked_fptosi(pr, a) \
880-
if (!LLVMFPtoSI_exact(sizeof(a) * host_char_bit, pa, osize, pr)) \
881-
jl_throw(jl_inexact_exception);
882-
un_fintrinsic_withtype(checked_fptosi, checked_fptosi)
883-
#define checked_fptoui(pr, a) \
884-
if (!LLVMFPtoUI_exact(sizeof(a) * host_char_bit, pa, osize, pr)) \
885-
jl_throw(jl_inexact_exception);
886-
un_fintrinsic_withtype(checked_fptoui, checked_fptoui)
887-
888879
JL_DLLEXPORT jl_value_t *jl_check_top_bit(jl_value_t *a)
889880
{
890881
jl_value_t *ty = jl_typeof(a);

test/numbers.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,6 +2458,13 @@ end
24582458
@test_throws InexactError convert(Int16, typemax(UInt64))
24592459
@test_throws InexactError convert(Int, typemax(UInt64))
24602460

2461+
# issue #14549
2462+
for T in (Int8, Int16, UInt8, UInt16)
2463+
for F in (Float32,Float64)
2464+
@test_throws InexactError convert(T, F(200000.0))
2465+
end
2466+
end
2467+
24612468
let x = big(-0.0)
24622469
@test signbit(x) && !signbit(abs(x))
24632470
end

0 commit comments

Comments
 (0)