From bebbeb54f177bdc2cfdff71d6a256a35f2f2057b Mon Sep 17 00:00:00 2001 From: Thomas Lively <7121787+tlively@users.noreply.github.com> Date: Tue, 4 Dec 2018 10:30:35 -0800 Subject: Implement nontrapping float-to-int instructions (#1780) --- src/wasm/literal.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 4 deletions(-) (limited to 'src/wasm/literal.cpp') diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 7b248010e..ece92c6ee 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -22,6 +22,7 @@ #include "emscripten-optimizer/simple_ast.h" #include "pretty_printing.h" #include "support/bits.h" +#include "support/utilities.h" #include "ir/bits.h" @@ -232,30 +233,108 @@ Literal Literal::truncateToF32() const { return Literal(float(getf64())); } -Literal Literal::convertSToF32() const { +Literal Literal::truncSIToF32() const { if (type == Type::i32) return Literal(float(i32)); if (type == Type::i64) return Literal(float(i64)); WASM_UNREACHABLE(); } -Literal Literal::convertUToF32() const { +Literal Literal::truncUIToF32() const { if (type == Type::i32) return Literal(float(uint32_t(i32))); if (type == Type::i64) return Literal(float(uint64_t(i64))); WASM_UNREACHABLE(); } -Literal Literal::convertSToF64() const { +Literal Literal::truncSIToF64() const { if (type == Type::i32) return Literal(double(i32)); if (type == Type::i64) return Literal(double(i64)); WASM_UNREACHABLE(); } -Literal Literal::convertUToF64() const { +Literal Literal::truncUIToF64() const { if (type == Type::i32) return Literal(double(uint32_t(i32))); if (type == Type::i64) return Literal(double(uint64_t(i64))); WASM_UNREACHABLE(); } +template +struct AsInt { + using type = void; +}; +template<> struct AsInt { using type = int32_t; }; +template<> struct AsInt { using type = int64_t; }; + +template::type)> +static Literal saturating_trunc(typename AsInt::type val) { + if (std::isnan(bit_cast(val))) { + return Literal(I(0)); + } + if (!RangeCheck(val)) { + if (std::signbit(bit_cast(val))) { + return Literal(std::numeric_limits::min()); + } else { + return Literal(std::numeric_limits::max()); + } + } + return Literal(I(std::trunc(bit_cast(val)))); +} + +Literal Literal::truncSatToSI32() const { + if (type == Type::f32) { + return saturating_trunc( + Literal(*this).castToI32().geti32() + ); + } + if (type == Type::f64) { + return saturating_trunc( + Literal(*this).castToI64().geti64() + ); + } + WASM_UNREACHABLE(); +} + +Literal Literal::truncSatToSI64() const { + if (type == Type::f32) { + return saturating_trunc( + Literal(*this).castToI32().geti32() + ); + } + if (type == Type::f64) { + return saturating_trunc( + Literal(*this).castToI64().geti64() + ); + } + WASM_UNREACHABLE(); +} + +Literal Literal::truncSatToUI32() const { + if (type == Type::f32) { + return saturating_trunc( + Literal(*this).castToI32().geti32() + ); + } + if (type == Type::f64) { + return saturating_trunc( + Literal(*this).castToI64().geti64() + ); + } + WASM_UNREACHABLE(); +} + +Literal Literal::truncSatToUI64() const { + if (type == Type::f32) { + return saturating_trunc( + Literal(*this).castToI32().geti32() + ); + } + if (type == Type::f64) { + return saturating_trunc( + Literal(*this).castToI64().geti64() + ); + } + WASM_UNREACHABLE(); +} + Literal Literal::eqz() const { switch (type) { case Type::i32: return eq(Literal(int32_t(0))); -- cgit v1.2.3