Skip to content

Commit adb6921

Browse files
bjacobElias Joseph
authored andcommitted
Fix floating point type conversions when the result is in the denormal range (#20242)
The condition for generating a denormal (which we just flush to zero) was incorrect. The new condition is very simple, checks that the biased converted exponent would be <= 0 which is the definition of a denormal. The added testcases show what is being fixed here. Prior to the fix, these cases converted to some large values as the exponent wrapped around! Signed-off-by: Benoit Jacob <[email protected]> Signed-off-by: Elias Joseph <[email protected]>
1 parent 51db978 commit adb6921

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

runtime/src/iree/base/internal/math.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ static inline uint32_t iree_math_truncate_f32_to_bits_rounding_to_nearest_even(
396396
// Generate NaN.
397397
generate_nan = true;
398398
}
399-
} else if (arithmetic_exp < -(1 << (dst_exp_bits - 1))) {
399+
} else if (arithmetic_exp + dst_exp_bias <= 0) {
400400
// Underflow. Generate zero. Leave zero mantissa.
401401
dst_exp = 0;
402402
} else {

runtime/src/iree/base/internal/math_test.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ TEST(F16ConversionTest, F32ToF16) {
192192
// Underflow
193193
EXPECT_EQ(0, iree_math_f32_to_f16(FLT_MIN));
194194
EXPECT_EQ(0x8000, iree_math_f32_to_f16(-FLT_MIN));
195+
EXPECT_EQ(0, iree_math_f32_to_f16(1.0e-05));
196+
EXPECT_EQ(0x8000, iree_math_f32_to_f16(-1.0e-05));
197+
EXPECT_EQ(0, iree_math_f32_to_f16(6.1e-05)); // Near largest denormal
198+
EXPECT_EQ(0x8000, iree_math_f32_to_f16(-6.1e-05));
199+
195200
// Denormals may or may not get flushed to zero. Accept both ways.
196201
uint16_t positive_denormal = iree_math_f32_to_f16(kF16Min / 2);
197202
EXPECT_TRUE(positive_denormal == 0 || positive_denormal == 0x0200);
@@ -357,6 +362,11 @@ TEST(F8E5M2ConversionTest, F32ToF8E5M2) {
357362
// Underflow
358363
EXPECT_EQ(0, iree_math_f32_to_f8e5m2(FLT_MIN));
359364
EXPECT_EQ(0x80, iree_math_f32_to_f8e5m2(-FLT_MIN));
365+
EXPECT_EQ(0, iree_math_f32_to_f8e5m2(kF8E5M2Min * 0.5f));
366+
EXPECT_EQ(0x80, iree_math_f32_to_f8e5m2(-kF8E5M2Min * 0.5f));
367+
EXPECT_EQ(0, iree_math_f32_to_f8e5m2(kF8E5M2Min * 0.75f));
368+
EXPECT_EQ(0x80, iree_math_f32_to_f8e5m2(-kF8E5M2Min * 0.75f));
369+
360370
// Denormals may or may not get flushed to zero. Accept both ways.
361371
uint16_t positive_denormal = iree_math_f32_to_f8e5m2(kF8E5M2Min / 2);
362372
EXPECT_TRUE(positive_denormal == 0 || positive_denormal == 0x02);

0 commit comments

Comments
 (0)