diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2018-12-04 10:30:35 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-04 10:30:35 -0800 |
commit | bebbeb54f177bdc2cfdff71d6a256a35f2f2057b (patch) | |
tree | 80609eb177ddab4edae30323d42152e9ab59ba9b /src/wasm/literal.cpp | |
parent | b4badb815ec844e438a05d501eafb6bb99383bc6 (diff) | |
download | binaryen-bebbeb54f177bdc2cfdff71d6a256a35f2f2057b.tar.gz binaryen-bebbeb54f177bdc2cfdff71d6a256a35f2f2057b.tar.bz2 binaryen-bebbeb54f177bdc2cfdff71d6a256a35f2f2057b.zip |
Implement nontrapping float-to-int instructions (#1780)
Diffstat (limited to 'src/wasm/literal.cpp')
-rw-r--r-- | src/wasm/literal.cpp | 87 |
1 files changed, 83 insertions, 4 deletions
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<typename F> +struct AsInt { + using type = void; +}; +template<> struct AsInt<float> { using type = int32_t; }; +template<> struct AsInt<double> { using type = int64_t; }; + +template<typename F, typename I, bool (*RangeCheck)(typename AsInt<F>::type)> +static Literal saturating_trunc(typename AsInt<F>::type val) { + if (std::isnan(bit_cast<F>(val))) { + return Literal(I(0)); + } + if (!RangeCheck(val)) { + if (std::signbit(bit_cast<F>(val))) { + return Literal(std::numeric_limits<I>::min()); + } else { + return Literal(std::numeric_limits<I>::max()); + } + } + return Literal(I(std::trunc(bit_cast<F>(val)))); +} + +Literal Literal::truncSatToSI32() const { + if (type == Type::f32) { + return saturating_trunc<float, int32_t, isInRangeI32TruncS>( + Literal(*this).castToI32().geti32() + ); + } + if (type == Type::f64) { + return saturating_trunc<double, int32_t, isInRangeI32TruncS>( + Literal(*this).castToI64().geti64() + ); + } + WASM_UNREACHABLE(); +} + +Literal Literal::truncSatToSI64() const { + if (type == Type::f32) { + return saturating_trunc<float, int64_t, isInRangeI64TruncS>( + Literal(*this).castToI32().geti32() + ); + } + if (type == Type::f64) { + return saturating_trunc<double, int64_t, isInRangeI64TruncS>( + Literal(*this).castToI64().geti64() + ); + } + WASM_UNREACHABLE(); +} + +Literal Literal::truncSatToUI32() const { + if (type == Type::f32) { + return saturating_trunc<float, uint32_t, isInRangeI32TruncU>( + Literal(*this).castToI32().geti32() + ); + } + if (type == Type::f64) { + return saturating_trunc<double, uint32_t, isInRangeI32TruncU>( + Literal(*this).castToI64().geti64() + ); + } + WASM_UNREACHABLE(); +} + +Literal Literal::truncSatToUI64() const { + if (type == Type::f32) { + return saturating_trunc<float, uint64_t, isInRangeI64TruncU>( + Literal(*this).castToI32().geti32() + ); + } + if (type == Type::f64) { + return saturating_trunc<double, uint64_t, isInRangeI64TruncU>( + Literal(*this).castToI64().geti64() + ); + } + WASM_UNREACHABLE(); +} + Literal Literal::eqz() const { switch (type) { case Type::i32: return eq(Literal(int32_t(0))); |