Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement {f32,f64}.sqrt instructions #480

Merged
merged 4 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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: 10639
expected_passed: 10641
expected_failed: 3
expected_skipped: 1171
expected_skipped: 1169

sanitizers-macos:
executor: macos
Expand All @@ -289,9 +289,9 @@ jobs:
- benchmark:
min_time: "0.01"
- spectest:
expected_passed: 10639
expected_passed: 10641
expected_failed: 3
expected_skipped: 1171
expected_skipped: 1169

benchmark:
machine:
Expand Down Expand Up @@ -397,13 +397,13 @@ jobs:
at: ~/build
- spectest:
skip_validation: true
expected_passed: 9697
expected_passed: 9699
expected_failed: 3
expected_skipped: 2113
expected_skipped: 2111
- spectest:
expected_passed: 10639
expected_passed: 10641
expected_failed: 3
expected_skipped: 1171
expected_skipped: 1169
- collect_coverage_data

workflows:
Expand Down
16 changes: 10 additions & 6 deletions lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1534,13 +1534,16 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
unary_op(stack, static_cast<float (*)(float)>(std::fabs));
break;
}

case Instr::f32_neg:
{
unary_op(stack, std::negate<float>{});
break;
}

case Instr::f32_sqrt:
{
unary_op(stack, static_cast<float (*)(float)>(std::sqrt));
break;
}
case Instr::f32_add:
{
binary_op(stack, std::plus<float>{});
Expand All @@ -1558,13 +1561,16 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
unary_op(stack, static_cast<double (*)(double)>(std::fabs));
break;
}

case Instr::f64_neg:
{
unary_op(stack, std::negate<double>{});
break;
}

case Instr::f64_sqrt:
{
unary_op(stack, static_cast<double (*)(double)>(std::sqrt));
break;
}
case Instr::f64_add:
{
binary_op(stack, std::plus<double>{});
Expand Down Expand Up @@ -1714,7 +1720,6 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
case Instr::f32_floor:
case Instr::f32_trunc:
case Instr::f32_nearest:
case Instr::f32_sqrt:
case Instr::f32_sub:
case Instr::f32_mul:
case Instr::f32_min:
Expand All @@ -1724,7 +1729,6 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
case Instr::f64_floor:
case Instr::f64_trunc:
case Instr::f64_nearest:
case Instr::f64_sqrt:
case Instr::f64_sub:
case Instr::f64_mul:
case Instr::f64_min:
Expand Down
59 changes: 59 additions & 0 deletions test/unittests/execute_floating_point_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,36 @@ TYPED_TEST(execute_floating_point_types, nan_matchers)
EXPECT_THAT(ExecutionResult{Value{-FP::nan(1)}}, Not(ArithmeticNaN(TypeParam{})));
}

TYPED_TEST(execute_floating_point_types, unop_nan_propagation)
{
// Tests NaN propagation in unary instructions (unop).
// If NaN input is canonical NN, the result must be the canonical NaN.
// Otherwise, the result must be an arithmetic NaN.

// The list of instructions to be tested.
// Only f32 variants, but f64 variants are going to be covered as well.
constexpr Instr opcodes[] = {
Instr::f32_sqrt,
};

for (const auto op : opcodes)
{
auto instance = instantiate(parse(this->get_unop_code(op)));

const auto cnan = FP<TypeParam>::nan(FP<TypeParam>::canon);
EXPECT_THAT(execute(*instance, 0, {cnan}), CanonicalNaN(TypeParam{}));
EXPECT_THAT(execute(*instance, 0, {-cnan}), CanonicalNaN(TypeParam{}));

const auto anan = FP<TypeParam>::nan(FP<TypeParam>::canon + 1);
EXPECT_THAT(execute(*instance, 0, {anan}), ArithmeticNaN(TypeParam{}));
EXPECT_THAT(execute(*instance, 0, {-anan}), ArithmeticNaN(TypeParam{}));

const auto snan = FP<TypeParam>::nan(1);
EXPECT_THAT(execute(*instance, 0, {snan}), ArithmeticNaN(TypeParam{}));
EXPECT_THAT(execute(*instance, 0, {-snan}), ArithmeticNaN(TypeParam{}));
}
}

TYPED_TEST(execute_floating_point_types, binop_nan_propagation)
{
// Tests NaN propagation in binary instructions (binop).
Expand Down Expand Up @@ -390,6 +420,35 @@ TYPED_TEST(execute_floating_point_types, neg)
}
}

TYPED_TEST(execute_floating_point_types, sqrt)
{
using FP = FP<TypeParam>;
using Limits = typename FP::Limits;

auto instance = instantiate(parse(this->get_unop_code(Instr::f32_sqrt)));
const auto exec = [&](auto arg) { return execute(*instance, 0, {arg}); };

// fsqrt(-inf) = nan:canonical
EXPECT_THAT(exec(-Limits::infinity()), CanonicalNaN(TypeParam{}));

// fsqrt(+inf) = +inf
EXPECT_THAT(exec(Limits::infinity()), Result(Limits::infinity()));

// fsqrt(+-0) = +-0
EXPECT_THAT(exec(TypeParam{0.0}), Result(TypeParam{0.0}));
EXPECT_THAT(exec(-TypeParam{0.0}), Result(-TypeParam{0.0}));

for (const auto p : this->positive_special_values)
{
// fsqrt(-p) = nan:canonical
EXPECT_THAT(exec(-p), CanonicalNaN(TypeParam{}));
}

EXPECT_THAT(exec(TypeParam{1}), Result(TypeParam{1}));
EXPECT_THAT(exec(TypeParam{4}), Result(TypeParam{2}));
EXPECT_THAT(exec(TypeParam{0x1.21p6}), Result(TypeParam{0x1.1p3}));
}

TYPED_TEST(execute_floating_point_types, add)
{
using FP = FP<TypeParam>;
Expand Down