@@ -128,15 +128,13 @@ static void traversePost(Ref node, std::function<void(Ref)> visit) {
128128 traversePrePost (node, [](Ref node) {}, visit);
129129}
130130
131- #if 0
132131static void replaceInPlace (Ref target, Ref value) {
133132 assert (target->isArray () && value->isArray ());
134- target->resize (value->size());
133+ target->setSize (value->size ());
135134 for (size_t i = 0 ; i < value->size (); i++) {
136135 target[i] = value[i];
137136 }
138137}
139- #endif
140138
141139static void optimizeJS (Ref ast) {
142140 // Helpers
@@ -272,18 +270,44 @@ static void optimizeJS(Ref ast) {
272270 node[3 ] = child[3 ];
273271 }
274272 }
275- // A load into an & may allow using a simpler heap, e.g. HEAPU8[..] & 1
276- // (a load of a boolean) may be HEAP8[..] & 1. The signed heaps are more
277- // commonly used, so it compresses better, and also they seem to have
278- // better performance (perhaps since HEAPU32 is at risk of not being a
279- // smallint).
280- if (node[1 ] == AND && isHeapAccess (node[2 ])) {
273+ if (isHeapAccess (node[2 ])) {
281274 auto heap = getHeapFromAccess (node[2 ]);
282- if (isConstantBitwise (node, AND, 1 )) {
283- if (heap == HEAPU8) {
284- setHeapOnAccess (node[2 ], HEAP8);
275+ IString replacementHeap;
276+ // We can avoid a cast of a load by using the load to do it instead.
277+ if (isOrZero (node)) {
278+ if (isIntegerHeap (heap)) {
279+ replacementHeap = heap;
280+ }
281+ } else if (isConstantBitwise (node, TRSHIFT, 0 )) {
282+ // For signed or unsigned loads smaller than 32 bits, doing an | 0
283+ // was safe either way - they aren't in the range an | 0 can affect.
284+ // For >>> 0 however, a negative value would change, so we still
285+ // need the cast.
286+ if (heap == HEAP32 || heap == HEAPU32) {
287+ replacementHeap = HEAPU32;
285288 } else if (heap == HEAPU16) {
286- setHeapOnAccess (node[2 ], HEAP16);
289+ replacementHeap = HEAPU16;
290+ } else if (heap == HEAPU8) {
291+ replacementHeap = HEAPU8;
292+ }
293+ }
294+ if (!replacementHeap.isNull ()) {
295+ setHeapOnAccess (node[2 ], replacementHeap);
296+ replaceInPlace (node, node[2 ]);
297+ return ;
298+ }
299+ // A load into an & may allow using a simpler heap, e.g. HEAPU8[..] & 1
300+ // (a load of a boolean) may be HEAP8[..] & 1. The signed heaps are more
301+ // commonly used, so it compresses better, and also they seem to have
302+ // better performance (perhaps since HEAPU32 is at risk of not being a
303+ // smallint).
304+ if (node[1 ] == AND) {
305+ if (isConstantBitwise (node, AND, 1 )) {
306+ if (heap == HEAPU8) {
307+ setHeapOnAccess (node[2 ], HEAP8);
308+ } else if (heap == HEAPU16) {
309+ setHeapOnAccess (node[2 ], HEAP16);
310+ }
287311 }
288312 }
289313 }
0 commit comments