diff options
-rw-r--r-- | src/asm2wasm.h | 30 | ||||
-rw-r--r-- | test/unit.asm.js | 9 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise.no-opts | 30 | ||||
-rw-r--r-- | test/unit.fromasm.no-opts | 30 |
4 files changed, 98 insertions, 1 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 853cb84df..1df74456d 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -107,7 +107,9 @@ Name I32_CTTZ("i32_cttz"), STOREF("storef"), STORED("stored"), FTCALL("ftCall_"), - MFTCALL("mftCall_"); + MFTCALL("mftCall_"), + MAX_("max"), + MIN_("min"); // Utilities @@ -280,6 +282,8 @@ private: IString Math_floor; IString Math_ceil; IString Math_sqrt; + IString Math_max; + IString Math_min; IString llvm_cttz_i32; @@ -606,6 +610,14 @@ void Asm2WasmBuilder::processAsm(Ref ast) { assert(Math_sqrt.isNull()); Math_sqrt = name; return; + } else if (imported[2] == MAX_) { + assert(Math_max.isNull()); + Math_max = name; + return; + } else if (imported[2] == MIN_) { + assert(Math_min.isNull()); + Math_min = name; + return; } } std::string fullName = module[1][1]->getCString(); @@ -1596,6 +1608,22 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } return ret; } + if (name == Math_max || name == Math_min) { + // overloaded on type: f32 or f64 + assert(ast[2]->size() == 2); + auto ret = allocator.alloc<Binary>(); + ret->left = process(ast[2][0]); + ret->right = process(ast[2][1]); + if (ret->left->type == f32) { + ret->op = name == Math_max ? MaxFloat32 : MinFloat32; + } else if (ret->left->type == f64) { + ret->op = name == Math_max ? MaxFloat64 : MinFloat64; + } else { + abort(); + } + ret->type = ret->left->type; + return ret; + } bool tableCall = false; if (wasmOnly) { auto num = ast[2]->size(); diff --git a/test/unit.asm.js b/test/unit.asm.js index 385db859c..a865350f6 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -7,6 +7,8 @@ function asm(global, env, buffer) { var Math_fround = global.Math.fround; var Math_abs = global.Math.abs; var Math_ceil = global.Math.ceil; + var Math_max = global.Math.max; + var Math_min = global.Math.min; var tempDoublePtr = env.tempDoublePtr | 0; var n = env.gb | 0; var STACKTOP = env.STACKTOP | 0; @@ -158,6 +160,13 @@ function asm(global, env, buffer) { y = +Math_abs(0.0); z = Math_fround(Math_abs(Math_fround(0))); } + function minmax() { + var x = 0.0, y = 0.0, z = Math_fround(0), w = Math_fround(0); + x = +Math_min(+x, +y); + y = +Math_max(+x, +y); + z = Math_fround(Math_min(Math_fround(z), Math_fround(w))); + w = Math_fround(Math_max(Math_fround(z), Math_fround(w))); + } function neg() { var x = Math_fround(0); x = Math_fround(-x); diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts index b79ff2389..fe2e7edbd 100644 --- a/test/unit.fromasm.imprecise.no-opts +++ b/test/unit.fromasm.imprecise.no-opts @@ -456,6 +456,36 @@ ) ) ) + (func $minmax + (local $x f64) + (local $y f64) + (local $z f32) + (local $w f32) + (set_local $x + (f64.min + (get_local $x) + (get_local $y) + ) + ) + (set_local $y + (f64.max + (get_local $x) + (get_local $y) + ) + ) + (set_local $z + (f32.min + (get_local $z) + (get_local $w) + ) + ) + (set_local $w + (f32.max + (get_local $z) + (get_local $w) + ) + ) + ) (func $neg (local $x f32) (set_local $x diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts index 717b6a4c4..960ee6c5f 100644 --- a/test/unit.fromasm.no-opts +++ b/test/unit.fromasm.no-opts @@ -462,6 +462,36 @@ ) ) ) + (func $minmax + (local $x f64) + (local $y f64) + (local $z f32) + (local $w f32) + (set_local $x + (f64.min + (get_local $x) + (get_local $y) + ) + ) + (set_local $y + (f64.max + (get_local $x) + (get_local $y) + ) + ) + (set_local $z + (f32.min + (get_local $z) + (get_local $w) + ) + ) + (set_local $w + (f32.max + (get_local $z) + (get_local $w) + ) + ) + ) (func $neg (local $x f32) (set_local $x |