@@ -161,8 +161,11 @@ static inline uint16_t float_to_half(float param) JL_NOTSAFEPOINT
161
161
uint32_t f ;
162
162
memcpy (& f , & param , sizeof (float ));
163
163
if (isnan (param )) {
164
- uint32_t t = 0x8000 ^ (0x8000 & ((uint16_t )(f >> 0x10 )));
165
- return t ^ ((uint16_t )(f >> 0xd ));
164
+ // Match the behaviour of arm64's fcvt or x86's vcvtps2ph by quieting
165
+ // all NaNs (avoids creating infinities), preserving the sign, and using
166
+ // the upper bits of the payload.
167
+ // sign exp quiet payload
168
+ return (f >>16 & 0x8000 ) | 0x7c00 | 0x0200 | (f >>13 & 0x03ff );
166
169
}
167
170
int i = ((f & ~0x007fffff ) >> 23 );
168
171
uint8_t sh = shifttable [i ];
@@ -761,33 +764,25 @@ static inline void name(unsigned osize, jl_value_t *ty, void *pa, void *pr) JL_N
761
764
OP(ty, (c_type*)pr, a); \
762
765
}
763
766
764
- #define un_fintrinsic_half (OP , name ) \
765
- static inline void name(unsigned osize, jl_value_t *ty, void *pa, void *pr) JL_NOTSAFEPOINT \
766
- { \
767
- uint16_t a = *(uint16_t*)pa; \
768
- float A = half_to_float(a); \
769
- if (osize == 16) { \
770
- float R; \
771
- OP(ty, &R, A); \
772
- *(uint16_t*)pr = float_to_half(R); \
773
- } else { \
774
- OP(ty, (uint16_t*)pr, A); \
775
- } \
776
- }
767
+ #define un_fintrinsic_half (OP , name ) \
768
+ static inline void name(unsigned osize, jl_value_t *ty, void *pa, void *pr) \
769
+ JL_NOTSAFEPOINT \
770
+ { \
771
+ uint16_t a = *(uint16_t *)pa; \
772
+ float R, A = half_to_float(a); \
773
+ OP(ty, &R, A); \
774
+ *(uint16_t *)pr = float_to_half(R); \
775
+ }
777
776
778
- #define un_fintrinsic_bfloat (OP , name ) \
779
- static inline void name(unsigned osize, jl_value_t *ty, void *pa, void *pr) JL_NOTSAFEPOINT \
780
- { \
781
- uint16_t a = *(uint16_t*)pa; \
782
- float A = bfloat_to_float(a); \
783
- if (osize == 16) { \
784
- float R; \
785
- OP(ty, &R, A); \
786
- *(uint16_t*)pr = float_to_bfloat(R); \
787
- } else { \
788
- OP(ty, (uint16_t*)pr, A); \
789
- } \
790
- }
777
+ #define un_fintrinsic_bfloat (OP , name ) \
778
+ static inline void name(unsigned osize, jl_value_t *ty, void *pa, void *pr) \
779
+ JL_NOTSAFEPOINT \
780
+ { \
781
+ uint16_t a = *(uint16_t *)pa; \
782
+ float R, A = bfloat_to_float(a); \
783
+ OP(ty, &R, A); \
784
+ *(uint16_t *)pr = float_to_bfloat(R); \
785
+ }
791
786
792
787
// float or integer inputs
793
788
// OP::Function macro(inputa, inputb)
@@ -1629,32 +1624,74 @@ cvt_iintrinsic(LLVMUItoFP, uitofp)
1629
1624
cvt_iintrinsic (LLVMFPtoSI , fptosi )
1630
1625
cvt_iintrinsic (LLVMFPtoUI , fptoui )
1631
1626
1632
- #define fptrunc (tr , pr , a ) \
1633
- if (!(osize < 8 * sizeof(a))) \
1634
- jl_error("fptrunc: output bitsize must be < input bitsize"); \
1635
- else if (osize == 16) { \
1636
- if ((jl_datatype_t*)tr == jl_float16_type) \
1637
- *(uint16_t*)pr = float_to_half(a); \
1638
- else /*if ((jl_datatype_t*)tr == jl_bfloat16_type)*/ \
1639
- * (uint16_t * )pr = float_to_bfloat (a ); \
1640
- } \
1641
- else if (osize == 32 ) \
1642
- * (float * )pr = a ; \
1643
- else if (osize == 64 ) \
1644
- * (double * )pr = a ; \
1645
- else \
1646
- jl_error ("fptrunc: runtime floating point intrinsics are not implemented for bit sizes other than 16, 32 and 64" );
1647
- #define fpext (tr , pr , a ) \
1648
- if (!(osize >= 8 * sizeof(a))) \
1649
- jl_error("fpext: output bitsize must be >= input bitsize"); \
1650
- if (osize == 32) \
1651
- *(float*)pr = a; \
1652
- else if (osize == 64) \
1653
- *(double*)pr = a; \
1654
- else \
1655
- jl_error("fpext: runtime floating point intrinsics are not implemented for bit sizes other than 32 and 64");
1656
- un_fintrinsic_withtype (fptrunc ,fptrunc )
1657
- un_fintrinsic_withtype (fpext ,fpext )
1627
+ #define fintrinsic_read_float16 (p ) half_to_float(*(uint16_t *)p)
1628
+ #define fintrinsic_read_bfloat16 (p ) bfloat_to_float(*(uint16_t *)p)
1629
+ #define fintrinsic_read_float32 (p ) *(float *)p
1630
+ #define fintrinsic_read_float64 (p ) *(double *)p
1631
+
1632
+ #define fintrinsic_write_float16 (p , x ) *(uint16_t *)p = float_to_half(x)
1633
+ #define fintrinsic_write_bfloat16 (p , x ) *(uint16_t *)p = float_to_bfloat(x)
1634
+ #define fintrinsic_write_float32 (p , x ) *(float *)p = x
1635
+ #define fintrinsic_write_float64 (p , x ) *(double *)p = x
1636
+
1637
+ /*
1638
+ * aty: Type of value argument (input)
1639
+ * pa: Pointer to value argument data
1640
+ * ty: Type argument (output)
1641
+ * pr: Pointer to result data
1642
+ */
1643
+
1644
+ static inline void fptrunc (jl_datatype_t * aty , void * pa , jl_datatype_t * ty , void * pr )
1645
+ {
1646
+ unsigned isize = jl_datatype_size (aty ), osize = jl_datatype_size (ty );
1647
+ if (!(osize < isize )) {
1648
+ jl_error ("fptrunc: output bitsize must be < input bitsize" );
1649
+ return ;
1650
+ }
1651
+
1652
+ #define fptrunc_convert (in , out ) \
1653
+ else if (aty == jl_##in##_type && ty == jl_##out##_type) \
1654
+ fintrinsic_write_##out(pr, fintrinsic_read_##in(pa))
1655
+
1656
+ if (0 )
1657
+ ;
1658
+ fptrunc_convert (float32 , float16 );
1659
+ fptrunc_convert (float64 , float16 );
1660
+ fptrunc_convert (float32 , bfloat16 );
1661
+ fptrunc_convert (float64 , bfloat16 );
1662
+ fptrunc_convert (float64 , float32 );
1663
+ else
1664
+ jl_error ("fptrunc: runtime floating point intrinsics are not implemented for bit sizes other than 16, 32 and 64" );
1665
+ #undef fptrunc_convert
1666
+ }
1667
+
1668
+ static inline void fpext (jl_datatype_t * aty , void * pa , jl_datatype_t * ty , void * pr )
1669
+ {
1670
+ unsigned isize = jl_datatype_size (aty ), osize = jl_datatype_size (ty );
1671
+ if (!(osize > isize )) {
1672
+ jl_error ("fpext: output bitsize must be > input bitsize" );
1673
+ return ;
1674
+ }
1675
+
1676
+ #define fpext_convert (in , out ) \
1677
+ else if (aty == jl_##in##_type && ty == jl_##out##_type) \
1678
+ fintrinsic_write_##out(pr, fintrinsic_read_##in(pa))
1679
+
1680
+ if (0 )
1681
+ ;
1682
+ fpext_convert (float16 , float32 );
1683
+ fpext_convert (float16 , float64 );
1684
+ fpext_convert (bfloat16 , float32 );
1685
+ fpext_convert (bfloat16 , float64 );
1686
+ fpext_convert (float32 , float64 );
1687
+ else
1688
+ jl_error ("fptrunc: runtime floating point intrinsics are not implemented for bit sizes other than 16, 32 and 64" );
1689
+ #undef fpext_convert
1690
+ }
1691
+
1692
+ cvt_iintrinsic (fptrunc , fptrunc )
1693
+ cvt_iintrinsic (fpext , fpext )
1694
+
1658
1695
1659
1696
// checked arithmetic
1660
1697
/**
0 commit comments