Skip to content

Commit

Permalink
Implement f32.demote_f64
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Aug 12, 2020
1 parent a1f001d commit 0fa4519
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 2 deletions.
12 changes: 11 additions & 1 deletion lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,12 @@ inline uint64_t popcnt64(uint64_t value) noexcept
return static_cast<uint64_t>(__builtin_popcountll(value));
}

__attribute__((no_sanitize("float-cast-overflow"))) inline constexpr float demote(
double value) noexcept
{
return static_cast<float>(value);
}

std::optional<uint32_t> find_export(const Module& module, ExternalKind kind, std::string_view name)
{
const auto it = std::find_if(module.exportsec.begin(), module.exportsec.end(),
Expand Down Expand Up @@ -1655,6 +1661,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
convert<uint64_t, float>(stack);
break;
}
case Instr::f32_demote_f64:
{
stack.top() = demote(stack.top().f64);
break;
}
case Instr::f64_convert_i32_s:
{
convert<int32_t, double>(stack);
Expand Down Expand Up @@ -1705,7 +1716,6 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
case Instr::f64_min:
case Instr::f64_max:
case Instr::f64_copysign:
case Instr::f32_demote_f64:
case Instr::i32_reinterpret_f32:
case Instr::i64_reinterpret_f64:
case Instr::f32_reinterpret_i32:
Expand Down
54 changes: 53 additions & 1 deletion test/unittests/execute_floating_point_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ TEST(execute_floating_point, f64_promote_f32)
f64.promote_f32
)
*/
auto wasm = from_hex("0061736d0100000001060160017d017c030201000a070105002000bb0b");
const auto wasm = from_hex("0061736d0100000001060160017d017c030201000a070105002000bb0b");
auto instance = instantiate(parse(wasm));

const std::pair<float, double> test_cases[] = {
Expand Down Expand Up @@ -465,6 +465,58 @@ TEST(execute_floating_point, f64_promote_f32)
EXPECT_GT(FP{res4.value.f64}.nan_payload(), FP64::canon);
}

TEST(execute_floating_point, f32_demote_f64)
{
/* wat2wasm
(func (param f64) (result f32)
local.get 0
f32.demote_f64
)
*/
const auto wasm = from_hex("0061736d0100000001060160017c017d030201000a070105002000b60b");
auto instance = instantiate(parse(wasm));

const std::pair<double, float> test_cases[] = {
{0.0, 0.0f},
{-0.0, -0.0f},
{1.0, 1.0f},
{-1.0, -1.0f},
{double{FP32::Limits::lowest()}, FP32::Limits::lowest()},
{double{FP32::Limits::max()}, FP32::Limits::max()},
{double{FP32::Limits::min()}, FP32::Limits::min()},
{double{FP32::Limits::denorm_min()}, FP32::Limits::denorm_min()},

// Out of range values rounded to max/lowest.
{std::nextafter(double{FP32::Limits::max()}, FP64::Limits::infinity()),
FP32::Limits::max()},
{std::nextafter(double{FP32::Limits::lowest()}, -FP64::Limits::infinity()),
FP32::Limits::lowest()},
{double{FP32::Limits::max()} * 0x1.0000008000007p0, FP32::Limits::max()},
{double{FP32::Limits::lowest()} * 0x1.0000008000007p0, FP32::Limits::lowest()},

// The smallest of range values rounded to infinity.
{double{FP32::Limits::max()} * 0x1.0000008000008p0, FP32::Limits::infinity()},
{double{FP32::Limits::lowest()} * 0x1.0000008000008p0, -FP32::Limits::infinity()},

{FP64::Limits::infinity(), FP32::Limits::infinity()},
{-FP64::Limits::infinity(), -FP32::Limits::infinity()},

// The canonical NaN must result in canonical NaN (only the top bit set).
{FP32::nan(FP32::canon), FP64::nan(FP64::canon)},
{-FP32::nan(FP32::canon), -FP64::nan(FP64::canon)},
};

for (const auto& [arg, expected] : test_cases)
{
EXPECT_THAT(execute(*instance, 0, {arg}), Result(expected)) << arg << " -> " << expected;
}

EXPECT_THAT(execute(*instance, 0, {FP64::nan(FP64::canon + 1)}), ArithmeticNaN(float{}));
EXPECT_THAT(execute(*instance, 0, {-FP64::nan(FP64::canon + 1)}), ArithmeticNaN(float{}));
EXPECT_THAT(execute(*instance, 0, {FP64::nan(1)}), ArithmeticNaN(float{}));
EXPECT_THAT(execute(*instance, 0, {-FP64::nan(1)}), ArithmeticNaN(float{}));
}


template <typename SrcT, typename DstT>
struct ConversionPairWasmTraits;
Expand Down

0 comments on commit 0fa4519

Please sign in to comment.