summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeInstructions.cpp26
-rw-r--r--test/emcc_O2_hello_world.fromasm6
-rw-r--r--test/emcc_O2_hello_world.fromasm.clamp6
-rw-r--r--test/emcc_O2_hello_world.fromasm.imprecise6
-rw-r--r--test/emcc_hello_world.fromasm130
-rw-r--r--test/emcc_hello_world.fromasm.clamp130
-rw-r--r--test/emcc_hello_world.fromasm.imprecise130
-rw-r--r--test/memorygrowth.fromasm12
-rw-r--r--test/memorygrowth.fromasm.clamp12
-rw-r--r--test/memorygrowth.fromasm.imprecise12
-rw-r--r--test/passes/optimize-instructions.txt66
-rw-r--r--test/passes/optimize-instructions.wast23
12 files changed, 292 insertions, 267 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 37fb37ace..06f3d5b02 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -562,6 +562,32 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
}
}
}
+ // bitwise operations
+ if (binary->op == AndInt32) {
+ // try de-morgan's AND law,
+ // (eqz X) and (eqz Y) === eqz (X or Y)
+ // Note that the OR and XOR laws do not work here, as these
+ // are not booleans (we could check if they are, but a boolean
+ // would already optimize with the eqz anyhow, unless propagating).
+ // But for AND, the left is true iff X and Y are each all zero bits,
+ // and the right is true if the union of their bits is zero; same.
+ if (auto* left = binary->left->dynCast<Unary>()) {
+ if (left->op == EqZInt32) {
+ if (auto* right = binary->right->dynCast<Unary>()) {
+ if (right->op == EqZInt32) {
+ // reuse one unary, drop the other
+ auto* leftValue = left->value;
+ left->value = binary;
+ binary->left = leftValue;
+ binary->right = right->value;
+ binary->op = OrInt32;
+ return left;
+ }
+ }
+ }
+ }
+ }
+ // for and and or, we can potentially conditionalize
if (binary->op == AndInt32 || binary->op == OrInt32) {
return conditionalizeExpensiveOnBitwise(binary);
}
diff --git a/test/emcc_O2_hello_world.fromasm b/test/emcc_O2_hello_world.fromasm
index 8d7fbec6f..c9bb769e0 100644
--- a/test/emcc_O2_hello_world.fromasm
+++ b/test/emcc_O2_hello_world.fromasm
@@ -1674,11 +1674,9 @@
)
(block
(if
- (i32.and
- (i32.eqz
+ (i32.eqz
+ (i32.or
(get_local $6)
- )
- (i32.eqz
(get_local $30)
)
)
diff --git a/test/emcc_O2_hello_world.fromasm.clamp b/test/emcc_O2_hello_world.fromasm.clamp
index 8d7fbec6f..c9bb769e0 100644
--- a/test/emcc_O2_hello_world.fromasm.clamp
+++ b/test/emcc_O2_hello_world.fromasm.clamp
@@ -1674,11 +1674,9 @@
)
(block
(if
- (i32.and
- (i32.eqz
+ (i32.eqz
+ (i32.or
(get_local $6)
- )
- (i32.eqz
(get_local $30)
)
)
diff --git a/test/emcc_O2_hello_world.fromasm.imprecise b/test/emcc_O2_hello_world.fromasm.imprecise
index 2a716a896..21e641976 100644
--- a/test/emcc_O2_hello_world.fromasm.imprecise
+++ b/test/emcc_O2_hello_world.fromasm.imprecise
@@ -1673,11 +1673,9 @@
)
(block
(if
- (i32.and
- (i32.eqz
+ (i32.eqz
+ (i32.or
(get_local $6)
- )
- (i32.eqz
(get_local $30)
)
)
diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm
index 2b03ce2a0..3246cd8d1 100644
--- a/test/emcc_hello_world.fromasm
+++ b/test/emcc_hello_world.fromasm
@@ -3659,27 +3659,20 @@
(br $__rjti$3)
)
(if
- (i32.and
- (i32.eqz
- (tee_local $7
- (i32.load
- (tee_local $5
- (get_local $19)
- )
+ (i32.or
+ (tee_local $7
+ (i32.load
+ (tee_local $5
+ (get_local $19)
)
)
)
- (i32.eqz
- (tee_local $8
- (i32.load offset=4
- (get_local $5)
- )
+ (tee_local $8
+ (i32.load offset=4
+ (get_local $5)
)
)
)
- (set_local $8
- (get_local $26)
- )
(block
(set_local $5
(get_local $7)
@@ -3707,27 +3700,24 @@
)
)
(br_if $while-in32
- (i32.eqz
- (i32.and
- (i32.eqz
- (tee_local $5
- (call $_bitshift64Lshr
- (get_local $5)
- (get_local $7)
- (i32.const 3)
- )
- )
- )
- (i32.eqz
- (tee_local $7
- (get_global $tempRet0)
- )
+ (i32.or
+ (tee_local $5
+ (call $_bitshift64Lshr
+ (get_local $5)
+ (get_local $7)
+ (i32.const 3)
)
)
+ (tee_local $7
+ (get_global $tempRet0)
+ )
)
)
)
)
+ (set_local $8
+ (get_local $26)
+ )
)
(set_local $5
(if (result i32)
@@ -6478,38 +6468,22 @@
)
)
(if
- (i32.and
- (i32.eqz
- (tee_local $8
- (i32.load
- (tee_local $5
- (get_local $19)
- )
+ (i32.or
+ (tee_local $8
+ (i32.load
+ (tee_local $5
+ (get_local $19)
)
)
)
- (i32.eqz
- (tee_local $11
- (i32.load offset=4
- (get_local $5)
- )
+ (tee_local $11
+ (i32.load offset=4
+ (get_local $5)
)
)
)
(block
(set_local $5
- (get_local $26)
- )
- (set_local $8
- (i32.const 0)
- )
- (set_local $9
- (i32.const 4091)
- )
- (br $__rjti$8)
- )
- (block
- (set_local $5
(get_local $8)
)
(set_local $8
@@ -6537,23 +6511,17 @@
)
)
(br_if $while-in123
- (i32.eqz
- (i32.and
- (i32.eqz
- (tee_local $5
- (call $_bitshift64Lshr
- (get_local $5)
- (get_local $11)
- (i32.const 4)
- )
- )
- )
- (i32.eqz
- (tee_local $11
- (get_global $tempRet0)
- )
+ (i32.or
+ (tee_local $5
+ (call $_bitshift64Lshr
+ (get_local $5)
+ (get_local $11)
+ (i32.const 4)
)
)
+ (tee_local $11
+ (get_global $tempRet0)
+ )
)
)
(set_local $5
@@ -6569,15 +6537,13 @@
(i32.const 8)
)
)
- (i32.and
- (i32.eqz
+ (i32.eqz
+ (i32.or
(i32.load
(tee_local $11
(get_local $19)
)
)
- )
- (i32.eqz
(i32.load offset=4
(get_local $11)
)
@@ -6606,6 +6572,18 @@
)
(br $__rjti$8)
)
+ (block
+ (set_local $5
+ (get_local $26)
+ )
+ (set_local $8
+ (i32.const 0)
+ )
+ (set_local $9
+ (i32.const 4091)
+ )
+ (br $__rjti$8)
+ )
)
)
(set_local $5
@@ -9378,11 +9356,9 @@
)
)
(if
- (i32.and
- (i32.eqz
+ (i32.eqz
+ (i32.or
(get_local $4)
- )
- (i32.eqz
(get_local $0)
)
)
diff --git a/test/emcc_hello_world.fromasm.clamp b/test/emcc_hello_world.fromasm.clamp
index 84c48ed9d..2f52a5eac 100644
--- a/test/emcc_hello_world.fromasm.clamp
+++ b/test/emcc_hello_world.fromasm.clamp
@@ -3709,27 +3709,20 @@
(br $__rjti$3)
)
(if
- (i32.and
- (i32.eqz
- (tee_local $7
- (i32.load
- (tee_local $5
- (get_local $19)
- )
+ (i32.or
+ (tee_local $7
+ (i32.load
+ (tee_local $5
+ (get_local $19)
)
)
)
- (i32.eqz
- (tee_local $8
- (i32.load offset=4
- (get_local $5)
- )
+ (tee_local $8
+ (i32.load offset=4
+ (get_local $5)
)
)
)
- (set_local $8
- (get_local $26)
- )
(block
(set_local $5
(get_local $7)
@@ -3757,27 +3750,24 @@
)
)
(br_if $while-in32
- (i32.eqz
- (i32.and
- (i32.eqz
- (tee_local $5
- (call $_bitshift64Lshr
- (get_local $5)
- (get_local $7)
- (i32.const 3)
- )
- )
- )
- (i32.eqz
- (tee_local $7
- (get_global $tempRet0)
- )
+ (i32.or
+ (tee_local $5
+ (call $_bitshift64Lshr
+ (get_local $5)
+ (get_local $7)
+ (i32.const 3)
)
)
+ (tee_local $7
+ (get_global $tempRet0)
+ )
)
)
)
)
+ (set_local $8
+ (get_local $26)
+ )
)
(set_local $5
(if (result i32)
@@ -6528,38 +6518,22 @@
)
)
(if
- (i32.and
- (i32.eqz
- (tee_local $8
- (i32.load
- (tee_local $5
- (get_local $19)
- )
+ (i32.or
+ (tee_local $8
+ (i32.load
+ (tee_local $5
+ (get_local $19)
)
)
)
- (i32.eqz
- (tee_local $11
- (i32.load offset=4
- (get_local $5)
- )
+ (tee_local $11
+ (i32.load offset=4
+ (get_local $5)
)
)
)
(block
(set_local $5
- (get_local $26)
- )
- (set_local $8
- (i32.const 0)
- )
- (set_local $9
- (i32.const 4091)
- )
- (br $__rjti$8)
- )
- (block
- (set_local $5
(get_local $8)
)
(set_local $8
@@ -6587,23 +6561,17 @@
)
)
(br_if $while-in123
- (i32.eqz
- (i32.and
- (i32.eqz
- (tee_local $5
- (call $_bitshift64Lshr
- (get_local $5)
- (get_local $11)
- (i32.const 4)
- )
- )
- )
- (i32.eqz
- (tee_local $11
- (get_global $tempRet0)
- )
+ (i32.or
+ (tee_local $5
+ (call $_bitshift64Lshr
+ (get_local $5)
+ (get_local $11)
+ (i32.const 4)
)
)
+ (tee_local $11
+ (get_global $tempRet0)
+ )
)
)
(set_local $5
@@ -6619,15 +6587,13 @@
(i32.const 8)
)
)
- (i32.and
- (i32.eqz
+ (i32.eqz
+ (i32.or
(i32.load
(tee_local $11
(get_local $19)
)
)
- )
- (i32.eqz
(i32.load offset=4
(get_local $11)
)
@@ -6656,6 +6622,18 @@
)
(br $__rjti$8)
)
+ (block
+ (set_local $5
+ (get_local $26)
+ )
+ (set_local $8
+ (i32.const 0)
+ )
+ (set_local $9
+ (i32.const 4091)
+ )
+ (br $__rjti$8)
+ )
)
)
(set_local $5
@@ -9428,11 +9406,9 @@
)
)
(if
- (i32.and
- (i32.eqz
+ (i32.eqz
+ (i32.or
(get_local $4)
- )
- (i32.eqz
(get_local $0)
)
)
diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise
index bcc64a662..b387f8cac 100644
--- a/test/emcc_hello_world.fromasm.imprecise
+++ b/test/emcc_hello_world.fromasm.imprecise
@@ -3614,27 +3614,20 @@
(br $__rjti$3)
)
(if
- (i32.and
- (i32.eqz
- (tee_local $7
- (i32.load
- (tee_local $5
- (get_local $19)
- )
+ (i32.or
+ (tee_local $7
+ (i32.load
+ (tee_local $5
+ (get_local $19)
)
)
)
- (i32.eqz
- (tee_local $8
- (i32.load offset=4
- (get_local $5)
- )
+ (tee_local $8
+ (i32.load offset=4
+ (get_local $5)
)
)
)
- (set_local $8
- (get_local $26)
- )
(block
(set_local $5
(get_local $7)
@@ -3662,27 +3655,24 @@
)
)
(br_if $while-in32
- (i32.eqz
- (i32.and
- (i32.eqz
- (tee_local $5
- (call $_bitshift64Lshr
- (get_local $5)
- (get_local $7)
- (i32.const 3)
- )
- )
- )
- (i32.eqz
- (tee_local $7
- (get_global $tempRet0)
- )
+ (i32.or
+ (tee_local $5
+ (call $_bitshift64Lshr
+ (get_local $5)
+ (get_local $7)
+ (i32.const 3)
)
)
+ (tee_local $7
+ (get_global $tempRet0)
+ )
)
)
)
)
+ (set_local $8
+ (get_local $26)
+ )
)
(set_local $5
(if (result i32)
@@ -6417,38 +6407,22 @@
)
)
(if
- (i32.and
- (i32.eqz
- (tee_local $8
- (i32.load
- (tee_local $5
- (get_local $19)
- )
+ (i32.or
+ (tee_local $8
+ (i32.load
+ (tee_local $5
+ (get_local $19)
)
)
)
- (i32.eqz
- (tee_local $11
- (i32.load offset=4
- (get_local $5)
- )
+ (tee_local $11
+ (i32.load offset=4
+ (get_local $5)
)
)
)
(block
(set_local $5
- (get_local $26)
- )
- (set_local $8
- (i32.const 0)
- )
- (set_local $9
- (i32.const 4091)
- )
- (br $__rjti$8)
- )
- (block
- (set_local $5
(get_local $8)
)
(set_local $8
@@ -6476,23 +6450,17 @@
)
)
(br_if $while-in123
- (i32.eqz
- (i32.and
- (i32.eqz
- (tee_local $5
- (call $_bitshift64Lshr
- (get_local $5)
- (get_local $11)
- (i32.const 4)
- )
- )
- )
- (i32.eqz
- (tee_local $11
- (get_global $tempRet0)
- )
+ (i32.or
+ (tee_local $5
+ (call $_bitshift64Lshr
+ (get_local $5)
+ (get_local $11)
+ (i32.const 4)
)
)
+ (tee_local $11
+ (get_global $tempRet0)
+ )
)
)
(set_local $5
@@ -6508,15 +6476,13 @@
(i32.const 8)
)
)
- (i32.and
- (i32.eqz
+ (i32.eqz
+ (i32.or
(i32.load
(tee_local $11
(get_local $19)
)
)
- )
- (i32.eqz
(i32.load offset=4
(get_local $11)
)
@@ -6545,6 +6511,18 @@
)
(br $__rjti$8)
)
+ (block
+ (set_local $5
+ (get_local $26)
+ )
+ (set_local $8
+ (i32.const 0)
+ )
+ (set_local $9
+ (i32.const 4091)
+ )
+ (br $__rjti$8)
+ )
)
)
(set_local $5
@@ -9317,11 +9295,9 @@
)
)
(if
- (i32.and
- (i32.eqz
+ (i32.eqz
+ (i32.or
(get_local $4)
- )
- (i32.eqz
(get_local $0)
)
)
diff --git a/test/memorygrowth.fromasm b/test/memorygrowth.fromasm
index 7345d440e..560b34249 100644
--- a/test/memorygrowth.fromasm
+++ b/test/memorygrowth.fromasm
@@ -1711,14 +1711,11 @@
(if
(tee_local $3
(if (result i32)
- (i32.and
- (i32.eqz
- (get_local $5)
- )
- (i32.eqz
- (get_local $33)
- )
+ (i32.or
+ (get_local $5)
+ (get_local $33)
)
+ (get_local $5)
(block (result i32)
(if
(i32.eqz
@@ -1847,7 +1844,6 @@
)
)
)
- (get_local $5)
)
)
(block
diff --git a/test/memorygrowth.fromasm.clamp b/test/memorygrowth.fromasm.clamp
index 7345d440e..560b34249 100644
--- a/test/memorygrowth.fromasm.clamp
+++ b/test/memorygrowth.fromasm.clamp
@@ -1711,14 +1711,11 @@
(if
(tee_local $3
(if (result i32)
- (i32.and
- (i32.eqz
- (get_local $5)
- )
- (i32.eqz
- (get_local $33)
- )
+ (i32.or
+ (get_local $5)
+ (get_local $33)
)
+ (get_local $5)
(block (result i32)
(if
(i32.eqz
@@ -1847,7 +1844,6 @@
)
)
)
- (get_local $5)
)
)
(block
diff --git a/test/memorygrowth.fromasm.imprecise b/test/memorygrowth.fromasm.imprecise
index acf1fdd59..6e5e9e996 100644
--- a/test/memorygrowth.fromasm.imprecise
+++ b/test/memorygrowth.fromasm.imprecise
@@ -1710,14 +1710,11 @@
(if
(tee_local $3
(if (result i32)
- (i32.and
- (i32.eqz
- (get_local $5)
- )
- (i32.eqz
- (get_local $33)
- )
+ (i32.or
+ (get_local $5)
+ (get_local $33)
)
+ (get_local $5)
(block (result i32)
(if
(i32.eqz
@@ -1846,7 +1843,6 @@
)
)
)
- (get_local $5)
)
)
(block
diff --git a/test/passes/optimize-instructions.txt b/test/passes/optimize-instructions.txt
index d30e8f22e..50858c81d 100644
--- a/test/passes/optimize-instructions.txt
+++ b/test/passes/optimize-instructions.txt
@@ -2198,6 +2198,72 @@
(i32.const 0)
)
)
+ (func $de-morgan-2 (; 55 ;) (type $4) (param $x i32) (param $y i32)
+ (drop
+ (i32.eqz
+ (i32.or
+ (get_local $x)
+ (get_local $y)
+ )
+ )
+ )
+ (drop
+ (i32.or
+ (i32.eqz
+ (get_local $x)
+ )
+ (i32.eqz
+ (get_local $y)
+ )
+ )
+ )
+ (drop
+ (i32.xor
+ (i32.eqz
+ (get_local $x)
+ )
+ (i32.eqz
+ (get_local $y)
+ )
+ )
+ )
+ (drop
+ (i32.and
+ (i32.eqz
+ (get_local $x)
+ )
+ (get_local $y)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $x)
+ (i32.eqz
+ (get_local $y)
+ )
+ )
+ )
+ (drop
+ (i32.and
+ (i32.eqz
+ (get_local $x)
+ )
+ (i32.wrap/i64
+ (i64.const 2)
+ )
+ )
+ )
+ (drop
+ (i32.and
+ (i32.wrap/i64
+ (i64.const 1)
+ )
+ (i32.eqz
+ (get_local $y)
+ )
+ )
+ )
+ )
)
(module
(type $0 (func))
diff --git a/test/passes/optimize-instructions.wast b/test/passes/optimize-instructions.wast
index 4ee2b0c86..34b805f3d 100644
--- a/test/passes/optimize-instructions.wast
+++ b/test/passes/optimize-instructions.wast
@@ -2640,6 +2640,29 @@
(i32.const 0)
)
)
+ (func $de-morgan-2 (param $x i32) (param $y i32)
+ (drop
+ (i32.and (i32.eqz (get_local $x)) (i32.eqz (get_local $y)))
+ )
+ (drop
+ (i32.or (i32.eqz (get_local $x)) (i32.eqz (get_local $y)))
+ )
+ (drop
+ (i32.xor (i32.eqz (get_local $x)) (i32.eqz (get_local $y)))
+ )
+ (drop
+ (i32.and (i32.eqz (get_local $x)) (get_local $y))
+ )
+ (drop
+ (i32.and (get_local $x) (i32.eqz (get_local $y)))
+ )
+ (drop
+ (i32.and (i32.eqz (get_local $x)) (i32.wrap/i64 (i64.const 2)))
+ )
+ (drop
+ (i32.and (i32.wrap/i64 (i64.const 1)) (i32.eqz (get_local $y)))
+ )
+ )
)
(module
(import "env" "memory" (memory $0 (shared 256 256)))