summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeInstructions.cpp42
-rw-r--r--test/lit/passes/optimize-instructions.wast31
2 files changed, 65 insertions, 8 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 7c450ac06..c0ba2dc02 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -772,16 +772,21 @@ struct OptimizeInstructions
return replaceCurrent(ret);
}
}
- // bitwise operations
- // for and and or, we can potentially conditionalize
if (curr->op == AndInt32 || curr->op == OrInt32) {
- if (auto* ret = conditionalizeExpensiveOnBitwise(curr)) {
- return replaceCurrent(ret);
+ if (curr->op == AndInt32) {
+ if (auto* ret = combineAnd(curr)) {
+ return replaceCurrent(ret);
+ }
}
- }
- // for or, we can potentially combine
- if (curr->op == OrInt32) {
- if (auto* ret = combineOr(curr)) {
+ // for or, we can potentially combine
+ if (curr->op == OrInt32) {
+ if (auto* ret = combineOr(curr)) {
+ return replaceCurrent(ret);
+ }
+ }
+ // bitwise operations
+ // for and and or, we can potentially conditionalize
+ if (auto* ret = conditionalizeExpensiveOnBitwise(curr)) {
return replaceCurrent(ret);
}
}
@@ -2486,6 +2491,27 @@ private:
}
}
+ // We can combine `and` operations, e.g.
+ // (x == 0) & (y == 0) ==> (x | y) == 0
+ Expression* combineAnd(Binary* curr) {
+ using namespace Abstract;
+ using namespace Match;
+ {
+ // (i32(x) == 0) & (i32(y) == 0) ==> i32(x | y) == 0
+ // (i64(x) == 0) & (i64(y) == 0) ==> i64(x | y) == 0
+ Expression *x, *y;
+ if (matches(curr,
+ binary(AndInt32, unary(EqZ, any(&x)), unary(EqZ, any(&y)))) &&
+ x->type == y->type) {
+ auto* inner = curr->left->cast<Unary>();
+ inner->value = Builder(*getModule())
+ .makeBinary(Abstract::getBinary(x->type, Or), x, y);
+ return inner;
+ }
+ }
+ return nullptr;
+ }
+
// We can combine `or` operations, e.g.
// (x > y) | (x == y) ==> x >= y
Expression* combineOr(Binary* binary) {
diff --git a/test/lit/passes/optimize-instructions.wast b/test/lit/passes/optimize-instructions.wast
index 26ef699d1..3504ef857 100644
--- a/test/lit/passes/optimize-instructions.wast
+++ b/test/lit/passes/optimize-instructions.wast
@@ -10971,6 +10971,37 @@
)
))
)
+
+ ;; CHECK: (func $optimize-combined-by-and-equals-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.eqz
+ ;; CHECK-NEXT: (i32.or
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i64.eqz
+ ;; CHECK-NEXT: (i64.or
+ ;; CHECK-NEXT: (local.get $a)
+ ;; CHECK-NEXT: (local.get $b)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $optimize-combined-by-and-equals-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
+ ;; (i32(x) == 0) & (i32(y) == 0) ==> i32(x | y) == 0
+ (drop (i32.and
+ (i32.eq (local.get $x) (i32.const 0))
+ (i32.eq (local.get $y) (i32.const 0))
+ ))
+ ;; (i64(x) == 0) & (i64(y) == 0) ==> i64(x | y) == 0
+ (drop (i32.and
+ (i64.eq (local.get $a) (i64.const 0))
+ (i64.eq (local.get $b) (i64.const 0))
+ ))
+ )
;; CHECK: (func $optimize-relationals (param $x i32) (param $y i32) (param $X i64) (param $Y i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.eq