From 7fb44812fa307a5924e5ada58b4015de6736cce3 Mon Sep 17 00:00:00 2001 From: Max Graey Date: Mon, 29 Aug 2022 18:22:01 +0300 Subject: [OptimizeInstruction] Reorder rules in optimizeSelect (#4984) To unblock some optimizations. For example this: ```wat (select (i32.eqz (local.get $x)) (i32.const 0) (i32.eqz (local.get $y)) ) ``` Was previously optimized as: ```wat (i32.eqz (select (i32.const 1) (local.get $x) (local.get $y) ) ) ``` Because `optimizeSelect` applied `!x ? !y : 0 -> x ? 0 : !y` then `!(x ? 1 : y)`, blocking the next rules which could have folded this to `or` or `and`. After this PR the same example optimizes better: ```wat (i32.eqz (i32.or (local.get $x) (local.get $y) ) ) ``` --- src/passes/OptimizeInstructions.cpp | 64 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index b50f99fbc..9379d8588 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2369,21 +2369,6 @@ private: // Don't bother when `ifFalse` isn't pure - we would need to reverse the // order using a temp local, which would be bad } - { - // Flip select to remove eqz if we can reorder - Select* s; - Expression *ifTrue, *ifFalse, *c; - if (matches( - curr, - select( - &s, any(&ifTrue), any(&ifFalse), unary(EqZInt32, any(&c)))) && - canReorder(ifTrue, ifFalse)) { - s->ifTrue = ifFalse; - s->ifFalse = ifTrue; - s->condition = c; - return s; - } - } { // TODO: Remove this after landing SCCP pass. See: #4161 @@ -2436,6 +2421,25 @@ private: return curr->type == Type::i64 ? builder.makeUnary(ExtendUInt32, c) : c; } } + if (curr->type == Type::i32 && + Bits::getMaxBits(curr->condition, this) <= 1 && + Bits::getMaxBits(curr->ifTrue, this) <= 1 && + Bits::getMaxBits(curr->ifFalse, this) <= 1) { + // The condition and both arms are i32 booleans, which allows us to do + // boolean optimizations. + Expression* x; + Expression* y; + + // x ? y : 0 ==> x & y + if (matches(curr, select(any(&y), ival(0), any(&x)))) { + return builder.makeBinary(AndInt32, y, x); + } + + // x ? 1 : y ==> x | y + if (matches(curr, select(ival(1), any(&y), any(&x)))) { + return builder.makeBinary(OrInt32, y, x); + } + } { // Simplify x < 0 ? -1 : 1 or x >= 0 ? 1 : -1 to // i32(x) >> 31 | 1 @@ -2459,23 +2463,19 @@ private: } } } - if (curr->type == Type::i32 && - Bits::getMaxBits(curr->condition, this) <= 1 && - Bits::getMaxBits(curr->ifTrue, this) <= 1 && - Bits::getMaxBits(curr->ifFalse, this) <= 1) { - // The condition and both arms are i32 booleans, which allows us to do - // boolean optimizations. - Expression* x; - Expression* y; - - // x ? y : 0 ==> x & y - if (matches(curr, select(any(&y), ival(0), any(&x)))) { - return builder.makeBinary(AndInt32, y, x); - } - - // x ? 1 : y ==> x | y - if (matches(curr, select(ival(1), any(&y), any(&x)))) { - return builder.makeBinary(OrInt32, y, x); + { + // Flip select to remove eqz if we can reorder + Select* s; + Expression *ifTrue, *ifFalse, *c; + if (matches( + curr, + select( + &s, any(&ifTrue), any(&ifFalse), unary(EqZInt32, any(&c)))) && + canReorder(ifTrue, ifFalse)) { + s->ifTrue = ifFalse; + s->ifFalse = ifTrue; + s->condition = c; + return s; } } { -- cgit v1.2.3