diff options
author | Max Graey <maxgraey@gmail.com> | 2022-08-29 18:22:01 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-29 08:22:01 -0700 |
commit | 7fb44812fa307a5924e5ada58b4015de6736cce3 (patch) | |
tree | fc8838b140979b25321bb62a8334a57e1cb96a99 /src | |
parent | fea999ea89f89947cb72a1846ed1743dbe935d09 (diff) | |
download | binaryen-7fb44812fa307a5924e5ada58b4015de6736cce3.tar.gz binaryen-7fb44812fa307a5924e5ada58b4015de6736cce3.tar.bz2 binaryen-7fb44812fa307a5924e5ada58b4015de6736cce3.zip |
[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)
)
)
```
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 64 |
1 files changed, 32 insertions, 32 deletions
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 @@ -2370,21 +2370,6 @@ private: // 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 // i32(x) ? i32(x) : 0 ==> x @@ -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; } } { |