Skip to content

Commit 9734e5d

Browse files
committed
Replaces checked_fptosi/checked_fptoui intrinsics with Julia implementations. Fixes #14549.
1 parent 1667a95 commit 9734e5d

File tree

8 files changed

+22
-98
lines changed

8 files changed

+22
-98
lines changed

base/boot.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,13 @@ export
160160
# intrinsics module
161161
Intrinsics
162162
#ccall, cglobal, llvmcall, abs_float, add_float, add_int, and_int, ashr_int,
163-
#box, bswap_int, checked_fptosi, checked_fptoui,
163+
#box, bswap_int,
164164
#checked_sadd_int, checked_ssub_int, checked_smul_int, checked_sdiv_int,
165165
#checked_srem_int, checked_uadd_int, checked_usub_int, checked_umul_int,
166166
#checked_udiv_int, checked_urem_int,
167167
#checked_trunc_sint, checked_trunc_uint, check_top_bit,
168168
#nan_dom_err, copysign_float, ctlz_int, ctpop_int, cttz_int,
169-
#div_float, eq_float, eq_int, eqfsi64, eqfui64, flipsign_int, select_value,
169+
#div_float, eq_float, eq_int, flipsign_int, select_value,
170170
#sqrt_llvm, powi_llvm,
171171
#sqrt_llvm_fast,
172172
#fpext, fpiseq, fpislt, fpsiround, fpuiround, fptosi, fptoui,

base/float.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,19 @@ function unsafe_trunc(::Type{Int128}, x::Float32)
165165
copysign(unsafe_trunc(UInt128,x) % Int128, x)
166166
end
167167

168+
# convert methods
169+
@inline function convert{T<:Union{Int32,Int64,UInt32,UInt64},Tf<:Union{Float32,Float64}}(::Type{T}, x::Tf)
170+
i = unsafe_trunc(T,x)
171+
convert(Tf,i) == x || throw(InexactError())
172+
i
173+
end
174+
# avoid undefined behaviour on ARM, cf #14549
175+
@inline function convert{T<:Union{Int8,Int16,UInt8,UInt16},Tf<:Union{Float32,Float64}}(::Type{T}, x::Tf)
176+
i = unsafe_trunc(Int32,x) % T
177+
convert(Tf,i) == x || throw(InexactError())
178+
i
179+
end
180+
168181

169182
# matches convert methods
170183
# also determines floor, ceil, round

base/int.jl

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,6 @@ rem{T<:Integer}(x::T, ::Type{T}) = x
204204
rem(x::Integer, ::Type{Bool}) = ((x&1)!=0)
205205
mod{T<:Integer}(x::Integer, ::Type{T}) = rem(x, T)
206206

207-
convert{T<:UnionS64Types,Tf<:Union{Float32,Float64}}(::Type{T}, x::Tf) =
208-
box(T,checked_fptosi(T,unbox(Tf,x)))
209-
convert{T<:UnionU64Types,Tf<:Union{Float32,Float64}}(::Type{T}, x::Tf) =
210-
box(T,checked_fptoui(T,unbox(Tf,x)))
211-
212207
convert{T<:Union{Int128,UInt128},Tf<:Union{Float32,Float64}}(::Type{T},x::Tf) =
213208
(isinteger(x) || throw(InexactError()) ; trunc(T,x))
214209

src/intrinsics.cpp

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

624-
static Value *emit_eqfsi(Value *x, Value *y)
625-
{
626-
Value *fy = JL_INT(y);
627-
628-
// using all 64-bit is slightly faster than using mixed sizes
629-
Value *xx = x, *vv = fy;
630-
if (x->getType() == T_float32)
631-
xx = builder.CreateFPExt(xx, T_float64);
632-
if (vv->getType()->getPrimitiveSizeInBits() < 64)
633-
vv = builder.CreateSExt(vv, T_int64);
634-
635-
Value *back = builder.CreateSIToFP(vv, xx->getType());
636-
return builder.CreateAnd
637-
(builder.CreateFCmpOEQ(xx, back),
638-
builder.CreateICmpEQ(vv, builder.CreateFPToSI(back, vv->getType())));
639-
}
640-
641-
static Value *emit_eqfui(Value *x, Value *y)
642-
{
643-
Value *fy = JL_INT(y);
644-
645-
// using all 64-bit is slightly faster than using mixed sizes
646-
Value *xx = x, *vv = fy;
647-
if (x->getType() == T_float32)
648-
xx = builder.CreateFPExt(xx, T_float64);
649-
if (vv->getType()->getPrimitiveSizeInBits() < 64)
650-
vv = builder.CreateZExt(vv, T_int64);
651-
652-
Value *back = builder.CreateUIToFP(vv, xx->getType());
653-
return builder.CreateAnd
654-
(builder.CreateFCmpOEQ(xx, back),
655-
builder.CreateICmpEQ(vv, builder.CreateFPToUI(back, vv->getType())));
656-
}
657-
658-
static jl_cgval_t emit_checked_fptosi(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx)
659-
{
660-
jl_value_t *jlto = staticeval_bitstype(targ, "checked_fptosi", ctx);
661-
if (!jlto) return jl_cgval_t();
662-
Type *to = staticeval_bitstype(jlto);
663-
Value *fx = FP(auto_unbox(x, ctx));
664-
if (fx->getType() == T_void) return jl_cgval_t(); // auto_unbox threw an error
665-
Value *ans = builder.CreateFPToSI(fx, to);
666-
if (fx->getType() == T_float32 && to == T_int32) {
667-
raise_exception_unless
668-
(builder.CreateFCmpOEQ(builder.CreateFPExt(fx, T_float64),
669-
builder.CreateSIToFP(ans, T_float64)),
670-
prepare_global(jlinexacterr_var), ctx);
671-
}
672-
else {
673-
raise_exception_unless(emit_eqfsi(fx, ans), prepare_global(jlinexacterr_var), ctx);
674-
}
675-
return mark_julia_type(ans, false, jlto);
676-
}
677-
678-
static jl_cgval_t emit_checked_fptoui(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx)
679-
{
680-
jl_value_t *jlto = staticeval_bitstype(targ, "checked_fptoui", ctx);
681-
if (!jlto) return jl_cgval_t();
682-
Type *to = staticeval_bitstype(jlto);
683-
Value *fx = FP(auto_unbox(x, ctx));
684-
if (fx->getType() == T_void) return jl_cgval_t(); // auto_unbox threw an error
685-
Value *ans = builder.CreateFPToUI(fx, to);
686-
if (fx->getType() == T_float32 && to == T_int32) {
687-
raise_exception_unless
688-
(builder.CreateFCmpOEQ(builder.CreateFPExt(fx, T_float64),
689-
builder.CreateUIToFP(ans, T_float64)),
690-
prepare_global(jlinexacterr_var), ctx);
691-
}
692-
else {
693-
raise_exception_unless(emit_eqfui(fx, ans), prepare_global(jlinexacterr_var), ctx);
694-
}
695-
return mark_julia_type(ans, false, jlto);
696-
}
697-
698624
static jl_cgval_t emit_runtime_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ctx)
699625
{
700626
int ldepth = ctx->gc.argDepth;
@@ -958,10 +884,6 @@ static jl_cgval_t emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
958884
return generic_sext(args[1], args[2], ctx);
959885
case zext_int:
960886
return generic_zext(args[1], args[2], ctx);
961-
case checked_fptosi:
962-
return emit_checked_fptosi(args[1], args[2], ctx);
963-
case checked_fptoui:
964-
return emit_checked_fptoui(args[1], args[2], ctx);
965887

966888
case uitofp: {
967889
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
@@ -403,8 +403,6 @@ JL_DLLEXPORT jl_value_t *jl_fpext(jl_value_t *ty, jl_value_t *a);
403403
JL_DLLEXPORT jl_value_t *jl_fptoui_auto(jl_value_t *a);
404404
JL_DLLEXPORT jl_value_t *jl_fptosi_auto(jl_value_t *a);
405405

406-
JL_DLLEXPORT jl_value_t *jl_checked_fptoui(jl_value_t *ty, jl_value_t *a);
407-
JL_DLLEXPORT jl_value_t *jl_checked_fptosi(jl_value_t *ty, jl_value_t *a);
408406
JL_DLLEXPORT jl_value_t *jl_checked_trunc_sint(jl_value_t *ty, jl_value_t *a);
409407
JL_DLLEXPORT jl_value_t *jl_checked_trunc_uint(jl_value_t *ty, jl_value_t *a);
410408

src/runtime_intrinsics.c

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

821-
#define checked_fptosi(pr, a) \
822-
if (!LLVMFPtoSI_exact(sizeof(a) * host_char_bit, pa, osize, pr)) \
823-
jl_throw(jl_inexact_exception);
824-
un_fintrinsic_withtype(checked_fptosi, checked_fptosi)
825-
#define checked_fptoui(pr, a) \
826-
if (!LLVMFPtoUI_exact(sizeof(a) * host_char_bit, pa, osize, pr)) \
827-
jl_throw(jl_inexact_exception);
828-
un_fintrinsic_withtype(checked_fptoui, checked_fptoui)
829-
830821
JL_DLLEXPORT jl_value_t *jl_check_top_bit(jl_value_t *a)
831822
{
832823
jl_value_t *ty = jl_typeof(a);

test/numbers.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2562,6 +2562,13 @@ end
25622562
@test_throws InexactError convert(Int16, typemax(UInt64))
25632563
@test_throws InexactError convert(Int, typemax(UInt64))
25642564

2565+
# issue #14549
2566+
for T in (Int8, Int16, UInt8, UInt16)
2567+
for F in (Float32,Float64)
2568+
@test_throws InexactError convert(T, F(200000.0))
2569+
end
2570+
end
2571+
25652572
let x = big(-0.0)
25662573
@test signbit(x) && !signbit(abs(x))
25672574
end

0 commit comments

Comments
 (0)