summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asm2wasm.h30
-rw-r--r--test/unit.asm.js9
-rw-r--r--test/unit.fromasm.imprecise.no-opts30
-rw-r--r--test/unit.fromasm.no-opts30
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