@@ -155,9 +155,26 @@ static void optimizeJS(Ref ast) {
155155 return false ;
156156 };
157157
158- auto isConstantAnd = [](Ref node, int num) {
158+ auto isUnary = [](Ref node, IString op) {
159+ return node->isArray () && !node->empty () && node[0 ] == UNARY_PREFIX &&
160+ node[1 ] == op;
161+ };
162+
163+ auto isConstantBitwise = [](Ref node, IString op, int num) {
159164 return node->isArray () && !node->empty () && node[0 ] == BINARY &&
160- node[1 ] == AND && node[3 ]->isNumber () && node[3 ]->getNumber () == num;
165+ node[1 ] == op && node[3 ]->isNumber () && node[3 ]->getNumber () == num;
166+ };
167+
168+ auto isWhile = [](Ref node) {
169+ return node->isArray () && !node->empty () && node[0 ] == WHILE;
170+ };
171+
172+ auto isDo = [](Ref node) {
173+ return node->isArray () && !node->empty () && node[0 ] == DO;
174+ };
175+
176+ auto isIf = [](Ref node) {
177+ return node->isArray () && !node->empty () && node[0 ] == IF;
161178 };
162179
163180 auto removeOrZero = [&](Ref node) {
@@ -211,43 +228,48 @@ static void optimizeJS(Ref ast) {
211228 return false ;
212229 };
213230
231+ auto optimizeBoolean = [&](Ref node) {
232+ // x ^ 1 => !x
233+ if (isConstantBitwise (node, XOR, 1 )) {
234+ node[0 ]->setString (UNARY_PREFIX);
235+ node[1 ]->setString (L_NOT);
236+ node[3 ]->setNull ();
237+ }
238+ return node;
239+ };
240+
214241 // Optimizations
215242
216- // x >> 0 => x | 0
217- traversePost (ast, [](Ref node) {
218- if (node->isArray () && !node->empty () && node[0 ] == BINARY &&
219- node[1 ] == RSHIFT && node[3 ]->isNumber ()) {
220- if (node[3 ]->getNumber () == 0 ) {
221- node[1 ]->setString (OR);
222- }
243+ // Pre-simplification
244+ traversePost (ast, [&](Ref node) {
245+ // x >> 0 => x | 0
246+ if (isConstantBitwise (node, RSHIFT, 0 )) {
247+ node[1 ]->setString (OR);
223248 }
224249 });
225250
226251 traversePost (ast, [&](Ref node) {
227- // x | 0 | 0 => x | 0
228- if (isOrZero (node)) {
229- while (isOrZero (node[2 ])) {
230- node[2 ] = node[2 ][2 ];
231- }
232- if (isBitwise (node[2 ])) {
233- auto child = node[2 ];
234- node[1 ] = child[1 ];
235- node[2 ] = child[2 ];
236- node[3 ] = child[3 ];
237- }
238- }
239- // x | 0 going into a bitwise op => skip the | 0
240- else if (isBitwise (node)) {
252+ if (isBitwise (node)) {
253+ // x | 0 going into a bitwise op => skip the | 0
241254 node[2 ] = removeOrZero (node[2 ]);
242255 node[3 ] = removeOrZero (node[3 ]);
256+ // x | 0 | 0 => x | 0
257+ if (isOrZero (node)) {
258+ if (isBitwise (node[2 ])) {
259+ auto child = node[2 ];
260+ node[1 ] = child[1 ];
261+ node[2 ] = child[2 ];
262+ node[3 ] = child[3 ];
263+ }
264+ }
243265 // A load into an & may allow using a simpler heap, e.g. HEAPU8[..] & 1
244266 // (a load of a boolean) may be HEAP8[..] & 1. The signed heaps are more
245267 // commonly used, so it compresses better, and also they seem to have
246268 // better performance (perhaps since HEAPU32 is at risk of not being a
247269 // smallint).
248270 if (node[1 ] == AND && isHeapAccess (node[2 ])) {
249271 auto heap = getHeapFromAccess (node[2 ]);
250- if (isConstantAnd (node, 1 )) {
272+ if (isConstantBitwise (node, AND , 1 )) {
251273 if (heap == HEAPU8) {
252274 setHeapOnAccess (node[2 ], HEAP8);
253275 } else if (heap == HEAPU16) {
@@ -263,6 +285,8 @@ static void optimizeJS(Ref ast) {
263285 // +(+x) => +x
264286 else if (isFround (node)) {
265287 node[2 ] = removePlusAndFround (node[2 ]);
288+ } else if (isUnary (node, L_NOT)) {
289+ node[2 ] = optimizeBoolean (node[2 ]);
266290 }
267291 // Assignment into a heap coerces.
268292 else if (node->isAssign ()) {
@@ -273,12 +297,12 @@ static void optimizeJS(Ref ast) {
273297 if (isIntegerHeap (heap)) {
274298 if (heap == HEAP8 || heap == HEAPU8) {
275299 while (isOrZero (assign->value ()) ||
276- isConstantAnd (assign->value (), 255 )) {
300+ isConstantBitwise (assign->value (), AND , 255 )) {
277301 assign->value () = assign->value ()[2 ];
278302 }
279303 } else if (heap == HEAP16 || heap == HEAPU16) {
280304 while (isOrZero (assign->value ()) ||
281- isConstantAnd (assign->value (), 65535 )) {
305+ isConstantBitwise (assign->value (), AND , 65535 )) {
282306 assign->value () = assign->value ()[2 ];
283307 }
284308 } else {
@@ -294,6 +318,8 @@ static void optimizeJS(Ref ast) {
294318 }
295319 }
296320 }
321+ } else if (isWhile (node) || isDo (node) || isIf (node)) {
322+ node[1 ] = optimizeBoolean (node[1 ]);
297323 }
298324 });
299325
0 commit comments