Skip to content

Commit 7fb4481

Browse files
authored
[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) ) ) ```
1 parent fea999e commit 7fb4481

File tree

3 files changed

+63
-42
lines changed

3 files changed

+63
-42
lines changed

src/passes/OptimizeInstructions.cpp

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,21 +2369,6 @@ struct OptimizeInstructions
23692369
// Don't bother when `ifFalse` isn't pure - we would need to reverse the
23702370
// order using a temp local, which would be bad
23712371
}
2372-
{
2373-
// Flip select to remove eqz if we can reorder
2374-
Select* s;
2375-
Expression *ifTrue, *ifFalse, *c;
2376-
if (matches(
2377-
curr,
2378-
select(
2379-
&s, any(&ifTrue), any(&ifFalse), unary(EqZInt32, any(&c)))) &&
2380-
canReorder(ifTrue, ifFalse)) {
2381-
s->ifTrue = ifFalse;
2382-
s->ifFalse = ifTrue;
2383-
s->condition = c;
2384-
return s;
2385-
}
2386-
}
23872372
{
23882373
// TODO: Remove this after landing SCCP pass. See: #4161
23892374

@@ -2436,6 +2421,25 @@ struct OptimizeInstructions
24362421
return curr->type == Type::i64 ? builder.makeUnary(ExtendUInt32, c) : c;
24372422
}
24382423
}
2424+
if (curr->type == Type::i32 &&
2425+
Bits::getMaxBits(curr->condition, this) <= 1 &&
2426+
Bits::getMaxBits(curr->ifTrue, this) <= 1 &&
2427+
Bits::getMaxBits(curr->ifFalse, this) <= 1) {
2428+
// The condition and both arms are i32 booleans, which allows us to do
2429+
// boolean optimizations.
2430+
Expression* x;
2431+
Expression* y;
2432+
2433+
// x ? y : 0 ==> x & y
2434+
if (matches(curr, select(any(&y), ival(0), any(&x)))) {
2435+
return builder.makeBinary(AndInt32, y, x);
2436+
}
2437+
2438+
// x ? 1 : y ==> x | y
2439+
if (matches(curr, select(ival(1), any(&y), any(&x)))) {
2440+
return builder.makeBinary(OrInt32, y, x);
2441+
}
2442+
}
24392443
{
24402444
// Simplify x < 0 ? -1 : 1 or x >= 0 ? 1 : -1 to
24412445
// i32(x) >> 31 | 1
@@ -2459,23 +2463,19 @@ struct OptimizeInstructions
24592463
}
24602464
}
24612465
}
2462-
if (curr->type == Type::i32 &&
2463-
Bits::getMaxBits(curr->condition, this) <= 1 &&
2464-
Bits::getMaxBits(curr->ifTrue, this) <= 1 &&
2465-
Bits::getMaxBits(curr->ifFalse, this) <= 1) {
2466-
// The condition and both arms are i32 booleans, which allows us to do
2467-
// boolean optimizations.
2468-
Expression* x;
2469-
Expression* y;
2470-
2471-
// x ? y : 0 ==> x & y
2472-
if (matches(curr, select(any(&y), ival(0), any(&x)))) {
2473-
return builder.makeBinary(AndInt32, y, x);
2474-
}
2475-
2476-
// x ? 1 : y ==> x | y
2477-
if (matches(curr, select(ival(1), any(&y), any(&x)))) {
2478-
return builder.makeBinary(OrInt32, y, x);
2466+
{
2467+
// Flip select to remove eqz if we can reorder
2468+
Select* s;
2469+
Expression *ifTrue, *ifFalse, *c;
2470+
if (matches(
2471+
curr,
2472+
select(
2473+
&s, any(&ifTrue), any(&ifFalse), unary(EqZInt32, any(&c)))) &&
2474+
canReorder(ifTrue, ifFalse)) {
2475+
s->ifTrue = ifFalse;
2476+
s->ifFalse = ifTrue;
2477+
s->condition = c;
2478+
return s;
24792479
}
24802480
}
24812481
{

test/lit/passes/asyncify_optimize-level=1.wast

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -752,8 +752,14 @@
752752
;; CHECK-NEXT: )
753753
;; CHECK-NEXT: )
754754
;; CHECK-NEXT: (if
755-
;; CHECK-NEXT: (select
756-
;; CHECK-NEXT: (i32.const 0)
755+
;; CHECK-NEXT: (i32.and
756+
;; CHECK-NEXT: (i32.eqz
757+
;; CHECK-NEXT: (select
758+
;; CHECK-NEXT: (local.get $1)
759+
;; CHECK-NEXT: (i32.const 0)
760+
;; CHECK-NEXT: (global.get $__asyncify_state)
761+
;; CHECK-NEXT: )
762+
;; CHECK-NEXT: )
757763
;; CHECK-NEXT: (i32.or
758764
;; CHECK-NEXT: (i32.eqz
759765
;; CHECK-NEXT: (local.get $2)
@@ -763,11 +769,6 @@
763769
;; CHECK-NEXT: (i32.const 2)
764770
;; CHECK-NEXT: )
765771
;; CHECK-NEXT: )
766-
;; CHECK-NEXT: (select
767-
;; CHECK-NEXT: (local.get $1)
768-
;; CHECK-NEXT: (i32.const 0)
769-
;; CHECK-NEXT: (global.get $__asyncify_state)
770-
;; CHECK-NEXT: )
771772
;; CHECK-NEXT: )
772773
;; CHECK-NEXT: (block
773774
;; CHECK-NEXT: (call $import3
@@ -906,8 +907,10 @@
906907
;; CHECK-NEXT: )
907908
;; CHECK-NEXT: )
908909
;; CHECK-NEXT: (if
909-
;; CHECK-NEXT: (select
910-
;; CHECK-NEXT: (i32.const 0)
910+
;; CHECK-NEXT: (i32.and
911+
;; CHECK-NEXT: (i32.eqz
912+
;; CHECK-NEXT: (global.get $__asyncify_state)
913+
;; CHECK-NEXT: )
911914
;; CHECK-NEXT: (i32.or
912915
;; CHECK-NEXT: (i32.eqz
913916
;; CHECK-NEXT: (local.get $1)
@@ -917,7 +920,6 @@
917920
;; CHECK-NEXT: (i32.const 2)
918921
;; CHECK-NEXT: )
919922
;; CHECK-NEXT: )
920-
;; CHECK-NEXT: (global.get $__asyncify_state)
921923
;; CHECK-NEXT: )
922924
;; CHECK-NEXT: (return
923925
;; CHECK-NEXT: (i32.const 2)

test/lit/passes/optimize-instructions.wast

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,25 @@
732732
)
733733
)
734734
)
735+
;; CHECK: (func $select-and-eqz (param $x i32) (param $y i32) (result i32)
736+
;; CHECK-NEXT: (i32.eqz
737+
;; CHECK-NEXT: (i32.or
738+
;; CHECK-NEXT: (local.get $x)
739+
;; CHECK-NEXT: (local.get $y)
740+
;; CHECK-NEXT: )
741+
;; CHECK-NEXT: )
742+
;; CHECK-NEXT: )
743+
(func $select-and-eqz (param $x i32) (param $y i32) (result i32)
744+
(select
745+
(i32.eqz
746+
(local.get $x)
747+
)
748+
(i32.const 0)
749+
(i32.eqz
750+
(local.get $y)
751+
)
752+
)
753+
)
735754
;; CHECK: (func $select-or-side-effects (param $x i32) (param $y i32) (result i32)
736755
;; CHECK-NEXT: (i32.or
737756
;; CHECK-NEXT: (i32.eq

0 commit comments

Comments
 (0)