Skip to content

Commit

Permalink
Merge pull request #468 from wasmx/fp_div
Browse files Browse the repository at this point in the history
Implement f{32,64}.div instructions
  • Loading branch information
chfast authored Aug 12, 2020
2 parents a1f001d + 69fdd36 commit dc66074
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 10 deletions.
16 changes: 8 additions & 8 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
19 changes: 17 additions & 2 deletions lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,13 @@ inline uint64_t popcnt64(uint64_t value) noexcept
return static_cast<uint64_t>(__builtin_popcountll(value));
}

template <typename T>
__attribute__((no_sanitize("float-divide-by-zero"))) inline constexpr T fdiv(T a, T b) noexcept
{
static_assert(std::numeric_limits<T>::is_iec559);
return a / b; // For IEC 559 (IEEE 754) floating-point types division by 0 is defined.
}

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 @@ -1533,6 +1540,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
binary_op(stack, std::plus<float>{});
break;
}
case Instr::f32_div:
{
binary_op(stack, fdiv<float>);
break;
}

case Instr::f64_abs:
{
Expand All @@ -1546,6 +1558,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
binary_op(stack, std::plus<double>{});
break;
}
case Instr::f64_div:
{
binary_op(stack, fdiv<double>);
break;
}

case Instr::i32_wrap_i64:
{
Expand Down Expand Up @@ -1689,7 +1706,6 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
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:
Expand All @@ -1701,7 +1717,6 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
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:
Expand Down
64 changes: 64 additions & 0 deletions test/unittests/execute_floating_point_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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<TypeParam>;
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
Expand Down

0 comments on commit dc66074

Please sign in to comment.