Skip to content

Commit a360a68

Browse files
authored
wasm2js: optimize away casts going into a suitable store (#2069)
1 parent 06f659c commit a360a68

4 files changed

Lines changed: 128 additions & 15 deletions

File tree

src/tools/wasm2js.cpp

Lines changed: 97 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ static void traversePost(Ref node, std::function<void(Ref)> visit) {
129129
}
130130

131131
static void optimizeJS(Ref ast) {
132-
// helpers
132+
// Helpers
133133

134134
auto isOrZero = [](Ref node) {
135135
return node->isArray() && !node->empty() && node[0] == BINARY &&
@@ -141,6 +141,11 @@ static void optimizeJS(Ref ast) {
141141
node[1] == PLUS;
142142
};
143143

144+
auto isFround = [](Ref node) {
145+
return node->isArray() && !node->empty() && node[0] == cashew::CALL &&
146+
node[1] == MATH_FROUND;
147+
};
148+
144149
auto isBitwise = [](Ref node) {
145150
if (node->isArray() && !node->empty() && node[0] == BINARY) {
146151
auto op = node[1];
@@ -150,6 +155,60 @@ static void optimizeJS(Ref ast) {
150155
return false;
151156
};
152157

158+
auto isConstantAnd = [](Ref node, int num) {
159+
return node->isArray() && !node->empty() && node[0] == BINARY &&
160+
node[1] == AND && node[3]->isNumber() && node[3]->getNumber() == num;
161+
};
162+
163+
auto removeOrZero = [&](Ref node) {
164+
while (isOrZero(node)) {
165+
node = node[2];
166+
}
167+
return node;
168+
};
169+
170+
auto removePlus = [&](Ref node) {
171+
while (isPlus(node)) {
172+
node = node[2];
173+
}
174+
return node;
175+
};
176+
177+
auto removePlusAndFround = [&](Ref node) {
178+
while (1) {
179+
if (isFround(node)) {
180+
node = node[2][0];
181+
} else if (isPlus(node)) {
182+
node = node[2];
183+
} else {
184+
break;
185+
}
186+
}
187+
return node;
188+
};
189+
190+
auto getHeapFromAccess = [](Ref node) { return node[1]->getIString(); };
191+
192+
auto isIntegerHeap = [](IString heap) {
193+
return heap == HEAP8 || heap == HEAPU8 || heap == HEAP16 ||
194+
heap == HEAPU16 || heap == HEAP32 || heap == HEAPU32;
195+
};
196+
197+
auto isFloatHeap = [](IString heap) {
198+
return heap == HEAPF32 || heap == HEAPF64;
199+
};
200+
201+
auto isHeapAccess = [&](Ref node) {
202+
if (node->isArray() && !node->empty() && node[0] == SUB &&
203+
node[1]->isString()) {
204+
auto heap = getHeapFromAccess(node);
205+
return isIntegerHeap(heap) || isFloatHeap(heap);
206+
}
207+
return false;
208+
};
209+
210+
// Optimizations
211+
153212
// x >> 0 => x | 0
154213
traversePost(ast, [](Ref node) {
155214
if (node->isArray() && !node->empty() && node[0] == BINARY &&
@@ -175,17 +234,46 @@ static void optimizeJS(Ref ast) {
175234
}
176235
// x | 0 going into a bitwise op => skip the | 0
177236
else if (isBitwise(node)) {
178-
while (isOrZero(node[2])) {
179-
node[2] = node[2][2];
180-
}
181-
while (isOrZero(node[3])) {
182-
node[3] = node[3][2];
183-
}
237+
node[2] = removeOrZero(node[2]);
238+
node[3] = removeOrZero(node[3]);
184239
}
185240
// +(+x) => +x
186241
else if (isPlus(node)) {
187-
while (isPlus(node[2])) {
188-
node[2] = node[2][2];
242+
node[2] = removePlus(node[2]);
243+
}
244+
// +(+x) => +x
245+
else if (isFround(node)) {
246+
node[2] = removePlusAndFround(node[2]);
247+
}
248+
// Assignment into a heap coerces.
249+
else if (node->isAssign()) {
250+
auto assign = node->asAssign();
251+
auto target = assign->target();
252+
if (isHeapAccess(target)) {
253+
auto heap = getHeapFromAccess(target);
254+
if (isIntegerHeap(heap)) {
255+
if (heap == HEAP8 || heap == HEAPU8) {
256+
while (isOrZero(assign->value()) ||
257+
isConstantAnd(assign->value(), 255)) {
258+
assign->value() = assign->value()[2];
259+
}
260+
} else if (heap == HEAP16 || heap == HEAPU16) {
261+
while (isOrZero(assign->value()) ||
262+
isConstantAnd(assign->value(), 65535)) {
263+
assign->value() = assign->value()[2];
264+
}
265+
} else {
266+
assert(heap == HEAP32 || heap == HEAPU32);
267+
assign->value() = removeOrZero(assign->value());
268+
}
269+
} else {
270+
assert(isFloatHeap(heap));
271+
if (heap == HEAPF32) {
272+
assign->value() = removePlusAndFround(assign->value());
273+
} else {
274+
assign->value() = removePlus(assign->value());
275+
}
276+
}
189277
}
190278
}
191279
});

test/wasm2js/emscripten.2asm.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ function asmFunc(global, env, buffer) {
4848
HEAP8[128 | 0];
4949
HEAPU16[128 >> 1];
5050
HEAP16[128 >> 1];
51+
HEAP32[16 >> 2] = 1 + 2;
52+
HEAPF32[16 >> 2] = Math_fround(3.0) + Math_fround(4.0);
53+
HEAPF64[16 >> 3] = 5.0 + 6.0;
54+
HEAP8[16 | 0] = 7 + 8;
55+
HEAP16[16 >> 1] = 9 + 10;
5156
}
5257

5358
function __growWasmMemory($0) {

test/wasm2js/emscripten.wast

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@
5252
(i32.const 128)
5353
)
5454
)
55+
(i32.store
56+
(i32.const 16)
57+
(i32.add (i32.const 1) (i32.const 2))
58+
)
59+
(f32.store
60+
(i32.const 16)
61+
(f32.add (f32.const 3) (f32.const 4))
62+
)
63+
(f64.store
64+
(i32.const 16)
65+
(f64.add (f64.const 5) (f64.const 6))
66+
)
67+
(i32.store8
68+
(i32.const 16)
69+
(i32.add (i32.const 7) (i32.const 8))
70+
)
71+
(i32.store16
72+
(i32.const 16)
73+
(i32.add (i32.const 9) (i32.const 10))
74+
)
5575
)
5676
(func $__growWasmMemory (param $0 i32) (result i32)
5777
(grow_memory

test/wasm2js/unaligned.2asm.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,28 +84,28 @@ function asmFunc(global, env, buffer) {
8484

8585
function $4() {
8686
var wasm2js_i32$0 = 0, wasm2js_i32$1 = 0;
87-
(wasm2js_i32$0 = 0, wasm2js_i32$1 = 0), ((HEAP8[wasm2js_i32$0 | 0] = wasm2js_i32$1 & 255, HEAP8[wasm2js_i32$0 + 1 | 0] = wasm2js_i32$1 >>> 8 & 255), HEAP8[wasm2js_i32$0 + 2 | 0] = wasm2js_i32$1 >>> 16 & 255), HEAP8[wasm2js_i32$0 + 3 | 0] = wasm2js_i32$1 >>> 24 & 255;
87+
(wasm2js_i32$0 = 0, wasm2js_i32$1 = 0), ((HEAP8[wasm2js_i32$0 | 0] = wasm2js_i32$1, HEAP8[wasm2js_i32$0 + 1 | 0] = wasm2js_i32$1 >>> 8), HEAP8[wasm2js_i32$0 + 2 | 0] = wasm2js_i32$1 >>> 16), HEAP8[wasm2js_i32$0 + 3 | 0] = wasm2js_i32$1 >>> 24;
8888
}
8989

9090
function $5() {
9191
var i64toi32_i32$1 = 0, wasm2js_i32$0 = 0, wasm2js_i32$1 = 0;
9292
i64toi32_i32$1 = 0;
93-
(wasm2js_i32$0 = i64toi32_i32$1, wasm2js_i32$1 = 0), ((HEAP8[wasm2js_i32$0 | 0] = wasm2js_i32$1 & 255, HEAP8[wasm2js_i32$0 + 1 | 0] = wasm2js_i32$1 >>> 8 & 255), HEAP8[wasm2js_i32$0 + 2 | 0] = wasm2js_i32$1 >>> 16 & 255), HEAP8[wasm2js_i32$0 + 3 | 0] = wasm2js_i32$1 >>> 24 & 255;
94-
(wasm2js_i32$0 = i64toi32_i32$1, wasm2js_i32$1 = 0), ((HEAP8[wasm2js_i32$0 + 4 | 0] = wasm2js_i32$1 & 255, HEAP8[wasm2js_i32$0 + 5 | 0] = wasm2js_i32$1 >>> 8 & 255), HEAP8[wasm2js_i32$0 + 6 | 0] = wasm2js_i32$1 >>> 16 & 255), HEAP8[wasm2js_i32$0 + 7 | 0] = wasm2js_i32$1 >>> 24 & 255;
93+
(wasm2js_i32$0 = i64toi32_i32$1, wasm2js_i32$1 = 0), ((HEAP8[wasm2js_i32$0 | 0] = wasm2js_i32$1, HEAP8[wasm2js_i32$0 + 1 | 0] = wasm2js_i32$1 >>> 8), HEAP8[wasm2js_i32$0 + 2 | 0] = wasm2js_i32$1 >>> 16), HEAP8[wasm2js_i32$0 + 3 | 0] = wasm2js_i32$1 >>> 24;
94+
(wasm2js_i32$0 = i64toi32_i32$1, wasm2js_i32$1 = 0), ((HEAP8[wasm2js_i32$0 + 4 | 0] = wasm2js_i32$1, HEAP8[wasm2js_i32$0 + 5 | 0] = wasm2js_i32$1 >>> 8), HEAP8[wasm2js_i32$0 + 6 | 0] = wasm2js_i32$1 >>> 16), HEAP8[wasm2js_i32$0 + 7 | 0] = wasm2js_i32$1 >>> 24;
9595
}
9696

9797
function $6() {
9898
var wasm2js_i32$0 = 0, wasm2js_i32$1 = 0;
99-
(wasm2js_i32$0 = 0, wasm2js_i32$1 = (wasm2js_scratch_store_f32(Math_fround(0.0)), wasm2js_scratch_load_i32(0))), ((HEAP8[wasm2js_i32$0 | 0] = wasm2js_i32$1 & 255, HEAP8[wasm2js_i32$0 + 1 | 0] = wasm2js_i32$1 >>> 8 & 255), HEAP8[wasm2js_i32$0 + 2 | 0] = wasm2js_i32$1 >>> 16 & 255), HEAP8[wasm2js_i32$0 + 3 | 0] = wasm2js_i32$1 >>> 24 & 255;
99+
(wasm2js_i32$0 = 0, wasm2js_i32$1 = (wasm2js_scratch_store_f32(Math_fround(0.0)), wasm2js_scratch_load_i32(0))), ((HEAP8[wasm2js_i32$0 | 0] = wasm2js_i32$1, HEAP8[wasm2js_i32$0 + 1 | 0] = wasm2js_i32$1 >>> 8), HEAP8[wasm2js_i32$0 + 2 | 0] = wasm2js_i32$1 >>> 16), HEAP8[wasm2js_i32$0 + 3 | 0] = wasm2js_i32$1 >>> 24;
100100
}
101101

102102
function $7() {
103103
var i64toi32_i32$1 = 0, i64toi32_i32$0 = 0, wasm2js_i32$0 = 0, wasm2js_i32$1 = 0;
104104
wasm2js_scratch_store_f64(0.0);
105105
i64toi32_i32$0 = wasm2js_scratch_load_i32(1 | 0) | 0;
106106
i64toi32_i32$1 = 0;
107-
(wasm2js_i32$0 = i64toi32_i32$1, wasm2js_i32$1 = wasm2js_scratch_load_i32(0 | 0) | 0), ((HEAP8[wasm2js_i32$0 | 0] = wasm2js_i32$1 & 255, HEAP8[wasm2js_i32$0 + 1 | 0] = wasm2js_i32$1 >>> 8 & 255), HEAP8[wasm2js_i32$0 + 2 | 0] = wasm2js_i32$1 >>> 16 & 255), HEAP8[wasm2js_i32$0 + 3 | 0] = wasm2js_i32$1 >>> 24 & 255;
108-
(wasm2js_i32$0 = i64toi32_i32$1, wasm2js_i32$1 = i64toi32_i32$0), ((HEAP8[wasm2js_i32$0 + 4 | 0] = wasm2js_i32$1 & 255, HEAP8[wasm2js_i32$0 + 5 | 0] = wasm2js_i32$1 >>> 8 & 255), HEAP8[wasm2js_i32$0 + 6 | 0] = wasm2js_i32$1 >>> 16 & 255), HEAP8[wasm2js_i32$0 + 7 | 0] = wasm2js_i32$1 >>> 24 & 255;
107+
(wasm2js_i32$0 = i64toi32_i32$1, wasm2js_i32$1 = wasm2js_scratch_load_i32(0 | 0) | 0), ((HEAP8[wasm2js_i32$0 | 0] = wasm2js_i32$1, HEAP8[wasm2js_i32$0 + 1 | 0] = wasm2js_i32$1 >>> 8), HEAP8[wasm2js_i32$0 + 2 | 0] = wasm2js_i32$1 >>> 16), HEAP8[wasm2js_i32$0 + 3 | 0] = wasm2js_i32$1 >>> 24;
108+
(wasm2js_i32$0 = i64toi32_i32$1, wasm2js_i32$1 = i64toi32_i32$0), ((HEAP8[wasm2js_i32$0 + 4 | 0] = wasm2js_i32$1, HEAP8[wasm2js_i32$0 + 5 | 0] = wasm2js_i32$1 >>> 8), HEAP8[wasm2js_i32$0 + 6 | 0] = wasm2js_i32$1 >>> 16), HEAP8[wasm2js_i32$0 + 7 | 0] = wasm2js_i32$1 >>> 24;
109109
}
110110

111111
function legalstub$1() {

0 commit comments

Comments
 (0)