Skip to content

Commit

Permalink
Add tests for fptrunc on NaNs, fix float_to_half NaN handling
Browse files Browse the repository at this point in the history
double_to_half, float/double_to_bfloat TODO
  • Loading branch information
xal-0 committed Jan 30, 2025
1 parent 31ecec5 commit d604e8e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/runtime_intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,11 @@ static inline uint16_t float_to_half(float param) JL_NOTSAFEPOINT
uint32_t f;
memcpy(&f, &param, sizeof(float));
if (isnan(param)) {
uint32_t t = 0x8000 ^ (0x8000 & ((uint16_t)(f >> 0x10)));
return t ^ ((uint16_t)(f >> 0xd));
// Match the behaviour of arm64's fcvt or x86's vcvtps2ph by quieting
// all NaNs (avoids creating infinities), preserving the sign, and using
// the upper bits of the payload.
// sign exp quiet payload
return (f>>16 & 0x8000) | 0x7c00 | 0x0200 | (f>>13 & 0x03ff);
}
int i = ((f & ~0x007fffff) >> 23);
uint8_t sh = shifttable[i];
Expand Down
56 changes: 56 additions & 0 deletions test/intrinsics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,18 @@ macro test_intrinsic(intr, args...)
end
end

macro test_intrinsic_pred(intr, args...)
p = args[end]
inputs = args[1:end-1]
quote
function f()
$intr($(inputs...))
end
@test $(p)(Base.invokelatest($intr, $(inputs...)))
@test $(p)(f())
end
end

@testset "Float64 intrinsics" begin
# unary
@test_intrinsic Core.Intrinsics.abs_float Float64(-3.3) Float64(3.3)
Expand Down Expand Up @@ -269,6 +281,19 @@ end
@test_intrinsic Core.Intrinsics.fptoui UInt Float32(3.3) UInt(3)
end

function f16(sign, exp, sig)
x = (sign&1)<<15 | (exp&((1<<5)-1))<<10 | sig&((1<<10)-1)
return reinterpret(Float16, UInt16(x))
end
function f32(sign, exp, sig)
x = (sign&1)<<31 | (exp&((1<<8)-1))<<23 | sig&((1<<23)-1)
return reinterpret(Float32, UInt32(x))
end
function f64(sign, exp, sig)
x = (sign&1)<<31 | (exp&((1<<11)-1))<<52 | sig&((1<<52)-1)
return reinterpret(Float64, UInt64(x))
end

@testset "Float16 intrinsics" begin
# unary
@test_intrinsic Core.Intrinsics.abs_float Float16(-3.3) Float16(3.3)
Expand All @@ -279,6 +304,37 @@ end
@test_intrinsic Core.Intrinsics.fptrunc Float16 Float32(3.3) Float16(3.3)
@test_intrinsic Core.Intrinsics.fptrunc Float16 Float64(3.3) Float16(3.3)

# float_to_half/bfloat_to_float special cases
@test_intrinsic Core.Intrinsics.fptrunc Float16 Inf32 Inf16
@test_intrinsic Core.Intrinsics.fptrunc Float16 -Inf32 -Inf16
@test_intrinsic Core.Intrinsics.fptrunc Float16 Inf64 Inf16
@test_intrinsic Core.Intrinsics.fptrunc Float16 -Inf64 -Inf16

# LLVM gives us three things that may happen to NaNs in an fptrunc on
# "normal" platforms (x86, ARM):
# - Return a canonical NaN (quiet, all-zero payload)
# - Copy high bits of payload to output, and:
# - Set the quiet bit
# - Leave the quiet bit as-is. This option isn't possible if doing so
# would result in an infinity (all-zero payload and quiet bit clear)
#
# We'll just test a NaN is returned at all.
#
# Refer to #49353 and https://llvm.org/docs/LangRef.html#floatnan

# Canonical NaN
@test_intrinsic_pred Core.Intrinsics.fptrunc Float16 NaN32 isnan
@test_intrinsic_pred Core.Intrinsics.fptrunc Float16 NaN isnan
# Quiet NaN
@test_intrinsic_pred Core.Intrinsics.fptrunc Float16 f32(0, 0xff, 1<<22 | 1<<13) isnan
@test_intrinsic_pred Core.Intrinsics.fptrunc Float16 f64(0, 0x7ff, 1<<51 | 1<<42) isnan
# Signalling NaN that can be propagated to Float16
@test_intrinsic_pred Core.Intrinsics.fptrunc Float16 f32(0, 0xff, 1<<13) isnan
@test_intrinsic_pred Core.Intrinsics.fptrunc Float16 f64(0, 0x7ff, 1<<42) isnan
# Signalling NaN that cannot be propagated to Float16
@test_intrinsic_pred Core.Intrinsics.fptrunc Float16 f32(0, 0xff, 1) isnan
@test_intrinsic_pred Core.Intrinsics.fptrunc Float16 f64(0, 0x7ff, 1) isnan

# binary
@test_intrinsic Core.Intrinsics.add_float Float16(3.3) Float16(2) Float16(5.3)
@test_intrinsic Core.Intrinsics.sub_float Float16(3.3) Float16(2) Float16(1.301)
Expand Down

0 comments on commit d604e8e

Please sign in to comment.