summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2022-08-29 18:22:01 +0300
committerGitHub <noreply@github.com>2022-08-29 08:22:01 -0700
commit7fb44812fa307a5924e5ada58b4015de6736cce3 (patch)
treefc8838b140979b25321bb62a8334a57e1cb96a99 /src
parentfea999ea89f89947cb72a1846ed1743dbe935d09 (diff)
downloadbinaryen-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.cpp64
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;
}
}
{