summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-04-01 16:02:06 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-04-01 16:02:06 -0700
commitdd3086a32e790c423c48bf2cfe6a7d8cc8754a15 (patch)
treec23f0fc33915b0b6fd6ddca056baa907994b62be
parentb22f29a4ee0858721278df7d9cea1a487bc7b543 (diff)
parent6daea13bd8e31bbf098a2c0bef92932f70a6f47f (diff)
downloadbinaryen-dd3086a32e790c423c48bf2cfe6a7d8cc8754a15.tar.gz
binaryen-dd3086a32e790c423c48bf2cfe6a7d8cc8754a15.tar.bz2
binaryen-dd3086a32e790c423c48bf2cfe6a7d8cc8754a15.zip
Merge pull request #286 from WebAssembly/asm2wasm-opts
asm2wasm opts
-rw-r--r--src/asm2wasm.h60
-rw-r--r--test/min.asm.js18
-rw-r--r--test/min.fromasm13
-rw-r--r--test/min.fromasm.imprecise13
-rw-r--r--test/unit.asm.js19
-rw-r--r--test/unit.fromasm13
-rw-r--r--test/unit.fromasm.imprecise13
7 files changed, 148 insertions, 1 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 4c37b7705..7d9b9652b 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -202,6 +202,8 @@ private:
IString Math_ceil;
IString Math_sqrt;
+ IString tempDoublePtr; // imported name of tempDoublePtr
+
// function types. we fill in this information as we see
// uses, in the first pass
@@ -483,6 +485,13 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
} else {
assert(module[0] == NAME);
moduleName = module[1]->getIString();
+ if (moduleName == ENV) {
+ if (imported[2] == TEMP_DOUBLE_PTR) {
+ assert(tempDoublePtr.isNull());
+ tempDoublePtr = name;
+ // we don't return here, as we can only optimize out some uses of tDP. So it remains imported
+ }
+ }
}
auto import = allocator.alloc<Import>();
import->name = name;
@@ -1404,6 +1413,57 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
ret->type = ret->ifTrue->type;
return ret;
} else if (what == SEQ) {
+ // Some (x, y) patterns can be optimized, like bitcasts,
+ // (HEAP32[tempDoublePtr >> 2] = i, Math_fround(HEAPF32[tempDoublePtr >> 2])); // i32->f32
+ // (HEAP32[tempDoublePtr >> 2] = i, +HEAPF32[tempDoublePtr >> 2]); // i32->f32, no fround
+ // (HEAPF32[tempDoublePtr >> 2] = f, HEAP32[tempDoublePtr >> 2] | 0); // f32->i32
+ if (ast[1][0] == ASSIGN && ast[1][2][0] == SUB && ast[1][2][1][0] == NAME && ast[1][2][2][0] == BINARY && ast[1][2][2][1] == RSHIFT &&
+ ast[1][2][2][2][0] == NAME && ast[1][2][2][2][1] == tempDoublePtr && ast[1][2][2][3][0] == NUM && ast[1][2][2][3][1]->getNumber() == 2) {
+ // (?[tempDoublePtr >> 2] = ?, ?) so far
+ auto heap = ast[1][2][1][1]->getIString();
+ if (views.find(heap) != views.end()) {
+ AsmType writeType = views[heap].type;
+ AsmType readType = ASM_NONE;
+ Ref readValue;
+ if (ast[2][0] == BINARY && ast[2][1] == OR && ast[2][3][0] == NUM && ast[2][3][1]->getNumber() == 0) {
+ readType = ASM_INT;
+ readValue = ast[2][2];
+ } else if (ast[2][0] == UNARY_PREFIX && ast[2][1] == PLUS) {
+ readType = ASM_DOUBLE;
+ readValue = ast[2][2];
+ } else if (ast[2][0] == CALL && ast[2][1][0] == NAME && ast[2][1][1] == Math_fround) {
+ readType = ASM_FLOAT;
+ readValue = ast[2][2][0];
+ }
+ if (readType != ASM_NONE) {
+ if (readValue[0] == SUB && readValue[1][0] == NAME && readValue[2][0] == BINARY && readValue[2][1] == RSHIFT &&
+ readValue[2][2][0] == NAME && readValue[2][2][1] == tempDoublePtr && readValue[2][3][0] == NUM && readValue[2][3][1]->getNumber() == 2) {
+ // pattern looks right!
+ Ref writtenValue = ast[1][3];
+ if (writeType == ASM_INT && (readType == ASM_FLOAT || readType == ASM_DOUBLE)) {
+ auto conv = allocator.alloc<Unary>();
+ conv->op = ReinterpretInt;
+ conv->value = process(writtenValue);
+ conv->type = WasmType::f32;
+ if (readType == ASM_DOUBLE) {
+ auto promote = allocator.alloc<Unary>();
+ promote->op = PromoteFloat32;
+ promote->value = conv;
+ promote->type = WasmType::f64;
+ return promote;
+ }
+ return conv;
+ } else if (writeType == ASM_FLOAT && readType == ASM_INT) {
+ auto conv = allocator.alloc<Unary>();
+ conv->op = ReinterpretFloat;
+ conv->value = process(writtenValue);
+ conv->type = WasmType::i32;
+ return conv;
+ }
+ }
+ }
+ }
+ }
auto ret = allocator.alloc<Block>();
ret->list.push_back(process(ast[1]));
ret->list.push_back(process(ast[2]));
diff --git a/test/min.asm.js b/test/min.asm.js
index 77e54caab..ed5d186f5 100644
--- a/test/min.asm.js
+++ b/test/min.asm.js
@@ -6,6 +6,17 @@ function (global, env, buffer) {
var fr = global.Math.fround;
+ var tDP = env.tempDoublePtr | 0;
+
+ var h8 = new global.Int8Array(buffer);
+ var h16 = new global.Int16Array(buffer);
+ var h32 = new global.Int32Array(buffer);
+ var hU8 = new global.Uint8Array(buffer);
+ var hU16 = new global.Uint16Array(buffer);
+ var hU32 = new global.Uint32Array(buffer);
+ var hF32 = new global.Float32Array(buffer);
+ var hF64 = new global.Float64Array(buffer);
+
function floats(f) {
f = fr(f);
var t = fr(0);
@@ -18,6 +29,13 @@ function (global, env, buffer) {
n = fr(-(c[k >> 2] = p, fr(g[k >> 2])));
return n;
}
+ function bitcasts(i, f) {
+ i = i | 0;
+ f = Math_fround(f);
+ (h32[tDP >> 2] = i, fr(hF32[tDP >> 2])); // i32->f32
+ (h32[tDP >> 2] = i, +hF32[tDP >> 2]); // i32->f32, no fround
+ (hF32[tDP >> 2] = f, h32[tDP >> 2] | 0); // f32->i32
+ }
return { floats: floats };
}
diff --git a/test/min.fromasm b/test/min.fromasm
index 839fd167c..564980a96 100644
--- a/test/min.fromasm
+++ b/test/min.fromasm
@@ -30,4 +30,17 @@
(get_local $n)
)
)
+ (func $bitcasts (param $i i32) (param $f f32)
+ (f32.reinterpret/i32
+ (get_local $i)
+ )
+ (f64.promote/f32
+ (f32.reinterpret/i32
+ (get_local $i)
+ )
+ )
+ (i32.reinterpret/f32
+ (get_local $f)
+ )
+ )
)
diff --git a/test/min.fromasm.imprecise b/test/min.fromasm.imprecise
index 839fd167c..564980a96 100644
--- a/test/min.fromasm.imprecise
+++ b/test/min.fromasm.imprecise
@@ -30,4 +30,17 @@
(get_local $n)
)
)
+ (func $bitcasts (param $i i32) (param $f f32)
+ (f32.reinterpret/i32
+ (get_local $i)
+ )
+ (f64.promote/f32
+ (f32.reinterpret/i32
+ (get_local $i)
+ )
+ )
+ (i32.reinterpret/f32
+ (get_local $f)
+ )
+ )
)
diff --git a/test/unit.asm.js b/test/unit.asm.js
index 5bb84bdcd..cd432da5c 100644
--- a/test/unit.asm.js
+++ b/test/unit.asm.js
@@ -1,4 +1,4 @@
-function asm() {
+function asm(global, env, buffer) {
"use asm";
var t = global.NaN, u = global.Infinity;
@@ -7,11 +7,21 @@ function asm() {
var Math_fround = global.Math.fround;
var Math_abs = global.Math.abs;
var Math_ceil = global.Math.ceil;
+ var tempDoublePtr = env.tempDoublePtr | 0;
var abort = env.abort;
var print = env.print;
var h = env.h;
+ var HEAP8 = new global.Int8Array(buffer);
+ var HEAP16 = new global.Int16Array(buffer);
+ var HEAP32 = new global.Int32Array(buffer);
+ var HEAPU8 = new global.Uint8Array(buffer);
+ var HEAPU16 = new global.Uint16Array(buffer);
+ var HEAPU32 = new global.Uint32Array(buffer);
+ var HEAPF32 = new global.Float32Array(buffer);
+ var HEAPF64 = new global.Float64Array(buffer);
+
function big_negative() {
var temp = 0.0;
temp = +-2147483648;
@@ -190,6 +200,13 @@ function asm() {
print(2);
}
}
+ function bitcasts(i, f) {
+ i = i | 0;
+ f = Math_fround(f);
+ (HEAP32[tempDoublePtr >> 2] = i, Math_fround(HEAPF32[tempDoublePtr >> 2])); // i32->f32
+ (HEAP32[tempDoublePtr >> 2] = i, +HEAPF32[tempDoublePtr >> 2]); // i32->f32, no fround
+ (HEAPF32[tempDoublePtr >> 2] = f, HEAP32[tempDoublePtr >> 2] | 0); // f32->i32
+ }
function z() {
}
diff --git a/test/unit.fromasm b/test/unit.fromasm
index 3db25c78b..d7fce8b8f 100644
--- a/test/unit.fromasm
+++ b/test/unit.fromasm
@@ -516,6 +516,19 @@
(br $while-in$1)
)
)
+ (func $bitcasts (param $i i32) (param $f f32)
+ (f32.reinterpret/i32
+ (get_local $i)
+ )
+ (f64.promote/f32
+ (f32.reinterpret/i32
+ (get_local $i)
+ )
+ )
+ (i32.reinterpret/f32
+ (get_local $f)
+ )
+ )
(func $z
(nop)
)
diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise
index ef9ccaa5d..6383d6e87 100644
--- a/test/unit.fromasm.imprecise
+++ b/test/unit.fromasm.imprecise
@@ -512,6 +512,19 @@
(br $while-in$1)
)
)
+ (func $bitcasts (param $i i32) (param $f f32)
+ (f32.reinterpret/i32
+ (get_local $i)
+ )
+ (f64.promote/f32
+ (f32.reinterpret/i32
+ (get_local $i)
+ )
+ )
+ (i32.reinterpret/f32
+ (get_local $f)
+ )
+ )
(func $z
(nop)
)