Skip to content

Commit

Permalink
Merge pull request #457 from wasmx/fp_promote
Browse files Browse the repository at this point in the history
Implement f64.promote_f32 instruction
  • Loading branch information
axic authored Aug 12, 2020
2 parents 85e4b84 + 6636ce0 commit 23d6a6a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 9 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: 10556
expected_passed: 10560
expected_failed: 3
expected_skipped: 1254
expected_skipped: 1250

sanitizers-macos:
executor: macos
Expand All @@ -289,9 +289,9 @@ jobs:
- benchmark:
min_time: "0.01"
- spectest:
expected_passed: 10556
expected_passed: 10560
expected_failed: 3
expected_skipped: 1254
expected_skipped: 1250

benchmark:
machine:
Expand Down Expand Up @@ -397,13 +397,13 @@ jobs:
at: ~/build
- spectest:
skip_validation: true
expected_passed: 9614
expected_passed: 9618
expected_failed: 3
expected_skipped: 2196
expected_skipped: 2192
- spectest:
expected_passed: 10556
expected_passed: 10560
expected_failed: 3
expected_skipped: 1254
expected_skipped: 1250
- collect_coverage_data

workflows:
Expand Down
6 changes: 5 additions & 1 deletion lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1661,6 +1661,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
convert<uint64_t, double>(stack);
break;
}
case Instr::f64_promote_f32:
{
stack.top() = double{stack.top().f32};
break;
}

case Instr::f32_abs:
case Instr::f32_neg:
Expand Down Expand Up @@ -1689,7 +1694,6 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
case Instr::f64_max:
case Instr::f64_copysign:
case Instr::f32_demote_f64:
case Instr::f64_promote_f32:
case Instr::i32_reinterpret_f32:
case Instr::i64_reinterpret_f64:
case Instr::f32_reinterpret_i32:
Expand Down
58 changes: 58 additions & 0 deletions test/unittests/execute_floating_point_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,64 @@ TYPED_TEST(execute_floating_point_types, add)
EXPECT_THAT(exec(TypeParam{0x0.287p2}, TypeParam{0x1.FFp4}), Result(TypeParam{0x1.048Ep5}));
}

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

const std::pair<float, double> test_cases[] = {
{0.0f, 0.0},
{-0.0f, -0.0},
{1.0f, 1.0},
{-1.0f, -1.0},
{FP32::Limits::lowest(), double{FP32::Limits::lowest()}},
{FP32::Limits::max(), double{FP32::Limits::max()}},
{FP32::Limits::min(), double{FP32::Limits::min()}},
{FP32::Limits::denorm_min(), double{FP32::Limits::denorm_min()}},
{FP32::Limits::infinity(), FP64::Limits::infinity()},
{-FP32::Limits::infinity(), -FP64::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;
}

// Check arithmetic NaNs (payload >= canonical payload).
// The following check expect arithmetic NaNs. Canonical NaNs are arithmetic NaNs
// and are allowed by the spec in these situations, but our checks are more restrictive

// An arithmetic NaN must result in any arithmetic NaN.
const auto res1 = execute(*instance, 0, {FP32::nan(FP32::canon + 1)});
ASSERT_TRUE(!res1.trapped && res1.has_value);
EXPECT_EQ(std::signbit(res1.value.f64), 0);
EXPECT_GT(FP{res1.value.f64}.nan_payload(), FP64::canon);
const auto res2 = execute(*instance, 0, {-FP32::nan(FP32::canon + 1)});
ASSERT_TRUE(!res2.trapped && res2.has_value);
EXPECT_EQ(std::signbit(res2.value.f64), 1);
EXPECT_GT(FP{res2.value.f64}.nan_payload(), FP64::canon);

// Other NaN must also result in arithmetic NaN.
const auto res3 = execute(*instance, 0, {FP32::nan(1)});
ASSERT_TRUE(!res3.trapped && res3.has_value);
EXPECT_EQ(std::signbit(res3.value.f64), 0);
EXPECT_GT(FP{res3.value.f64}.nan_payload(), FP64::canon);
const auto res4 = execute(*instance, 0, {-FP32::nan(1)});
ASSERT_TRUE(!res4.trapped && res4.has_value);
EXPECT_EQ(std::signbit(res4.value.f64), 1);
EXPECT_GT(FP{res4.value.f64}.nan_payload(), FP64::canon);
}


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

0 comments on commit 23d6a6a

Please sign in to comment.