From 2d433050d9a893692c156cd085f5e24119d4fd7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 10 Aug 2020 16:14:11 +0200 Subject: [PATCH 1/2] Implement f{32,64}.div instructions --- lib/fizzy/execute.cpp | 19 +++++- .../unittests/execute_floating_point_test.cpp | 64 +++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index e8e403c16..70a1bdccb 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -510,6 +510,13 @@ inline uint64_t popcnt64(uint64_t value) noexcept return static_cast(__builtin_popcountll(value)); } +template +__attribute__((no_sanitize("float-divide-by-zero"))) inline constexpr T fdiv(T a, T b) noexcept +{ + static_assert(std::numeric_limits::is_iec559); + return a / b; // For IEC 559 (IEEE 754) floating-point types division by 0 is defined. +} + std::optional find_export(const Module& module, ExternalKind kind, std::string_view name) { const auto it = std::find_if(module.exportsec.begin(), module.exportsec.end(), @@ -1533,6 +1540,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span binary_op(stack, std::plus{}); break; } + case Instr::f32_div: + { + binary_op(stack, fdiv); + break; + } case Instr::f64_abs: { @@ -1546,6 +1558,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span binary_op(stack, std::plus{}); break; } + case Instr::f64_div: + { + binary_op(stack, fdiv); + break; + } case Instr::i32_wrap_i64: { @@ -1689,7 +1706,6 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span case Instr::f32_sqrt: case Instr::f32_sub: case Instr::f32_mul: - case Instr::f32_div: case Instr::f32_min: case Instr::f32_max: case Instr::f32_copysign: @@ -1701,7 +1717,6 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span case Instr::f64_sqrt: case Instr::f64_sub: case Instr::f64_mul: - case Instr::f64_div: case Instr::f64_min: case Instr::f64_max: case Instr::f64_copysign: diff --git a/test/unittests/execute_floating_point_test.cpp b/test/unittests/execute_floating_point_test.cpp index 20982df59..f6400ce75 100644 --- a/test/unittests/execute_floating_point_test.cpp +++ b/test/unittests/execute_floating_point_test.cpp @@ -224,6 +224,7 @@ TYPED_TEST(execute_floating_point_types, binop_nan_propagation) // Only f32 variants, but f64 variants are going to be covered as well. constexpr Instr opcodes[] = { Instr::f32_add, + Instr::f32_div, }; for (const auto op : opcodes) @@ -407,6 +408,69 @@ TYPED_TEST(execute_floating_point_types, add) EXPECT_THAT(exec(TypeParam{0x0.287p2}, TypeParam{0x1.FFp4}), Result(TypeParam{0x1.048Ep5})); } +TYPED_TEST(execute_floating_point_types, div) +{ + using FP = FP; + using Limits = typename FP::Limits; + + auto instance = instantiate(parse(this->get_binop_code(Instr::f32_div))); + const auto exec = [&](auto arg1, auto arg2) { return execute(*instance, 0, {arg1, arg2}); }; + + // fdiv(+-inf, +-inf) = nan:canonical + EXPECT_THAT(exec(Limits::infinity(), Limits::infinity()), CanonicalNaN(TypeParam{})); + EXPECT_THAT(exec(-Limits::infinity(), -Limits::infinity()), CanonicalNaN(TypeParam{})); + + // fdiv(+-inf, -+inf) = nan:canonical + EXPECT_THAT(exec(Limits::infinity(), -Limits::infinity()), CanonicalNaN(TypeParam{})); + EXPECT_THAT(exec(-Limits::infinity(), Limits::infinity()), CanonicalNaN(TypeParam{})); + + // fdiv(+-0, +-0) = nan:canonical + EXPECT_THAT(exec(TypeParam{0.0}, TypeParam{0.0}), CanonicalNaN(TypeParam{})); + EXPECT_THAT(exec(-TypeParam{0.0}, -TypeParam{0.0}), CanonicalNaN(TypeParam{})); + + // fdiv(+-0, -+0) = nan:canonical + EXPECT_THAT(exec(TypeParam{0.0}, -TypeParam{0.0}), CanonicalNaN(TypeParam{})); + EXPECT_THAT(exec(-TypeParam{0.0}, TypeParam{0.0}), CanonicalNaN(TypeParam{})); + + for (const auto q : this->positive_special_values) + { + // fdiv(+-inf, +-q2) = +inf + EXPECT_THAT(exec(Limits::infinity(), q), Result(Limits::infinity())); + EXPECT_THAT(exec(-Limits::infinity(), -q), Result(Limits::infinity())); + + // fdiv(+-inf, -+q2) = -inf + EXPECT_THAT(exec(Limits::infinity(), -q), Result(-Limits::infinity())); + EXPECT_THAT(exec(-Limits::infinity(), q), Result(-Limits::infinity())); + + // fdiv(+-q1 +-inf) = +0 + EXPECT_THAT(exec(q, Limits::infinity()), Result(TypeParam{0.0})); + EXPECT_THAT(exec(-q, -Limits::infinity()), Result(TypeParam{0.0})); + + // fdiv(+-q1 -+inf) = -0 + EXPECT_THAT(exec(-q, Limits::infinity()), Result(-TypeParam{0.0})); + EXPECT_THAT(exec(q, -Limits::infinity()), Result(-TypeParam{0.0})); + + // fdiv(+-0, +-q2) = +0 + EXPECT_THAT(exec(TypeParam{0.0}, q), Result(TypeParam{0.0})); + EXPECT_THAT(exec(-TypeParam{0.0}, -q), Result(TypeParam{0.0})); + + // fdiv(+-0, -+q2) = -0 + EXPECT_THAT(exec(-TypeParam{0.0}, q), Result(-TypeParam{0.0})); + EXPECT_THAT(exec(TypeParam{0.0}, -q), Result(-TypeParam{0.0})); + + // fdiv(+-q1, +-0) = +inf + EXPECT_THAT(exec(q, TypeParam{0.0}), Result(Limits::infinity())); + EXPECT_THAT(exec(-q, -TypeParam{0.0}), Result(Limits::infinity())); + + // fdiv(+-q1, -+0) = -inf + EXPECT_THAT(exec(q, -TypeParam{0.0}), Result(-Limits::infinity())); + EXPECT_THAT(exec(-q, TypeParam{0.0}), Result(-Limits::infinity())); + } + + EXPECT_THAT(exec(TypeParam{0xABCD.01p7}, TypeParam{4}), Result(TypeParam{0x1.579A02p20})); +} + + TEST(execute_floating_point, f64_promote_f32) { /* wat2wasm From 69fdd3631c81c3825650350d79b7d524219cb20f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 12 Aug 2020 09:35:38 +0200 Subject: [PATCH 2/2] ci: Update spectests expectations --- circle.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/circle.yml b/circle.yml index 3cfa9a9db..71ed306bc 100644 --- a/circle.yml +++ b/circle.yml @@ -271,9 +271,9 @@ jobs: - benchmark: min_time: "0.01" - spectest: - expected_passed: 10596 + expected_passed: 10598 expected_failed: 3 - expected_skipped: 1214 + expected_skipped: 1212 sanitizers-macos: executor: macos @@ -289,9 +289,9 @@ jobs: - benchmark: min_time: "0.01" - spectest: - expected_passed: 10596 + expected_passed: 10598 expected_failed: 3 - expected_skipped: 1214 + expected_skipped: 1212 benchmark: machine: @@ -397,13 +397,13 @@ jobs: at: ~/build - spectest: skip_validation: true - expected_passed: 9654 + expected_passed: 9656 expected_failed: 3 - expected_skipped: 2156 + expected_skipped: 2154 - spectest: - expected_passed: 10596 + expected_passed: 10598 expected_failed: 3 - expected_skipped: 1214 + expected_skipped: 1212 - collect_coverage_data workflows: