diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 26 | ||||
-rw-r--r-- | test/emcc_O2_hello_world.fromasm | 6 | ||||
-rw-r--r-- | test/emcc_O2_hello_world.fromasm.clamp | 6 | ||||
-rw-r--r-- | test/emcc_O2_hello_world.fromasm.imprecise | 6 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm | 130 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm.clamp | 130 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm.imprecise | 130 | ||||
-rw-r--r-- | test/memorygrowth.fromasm | 12 | ||||
-rw-r--r-- | test/memorygrowth.fromasm.clamp | 12 | ||||
-rw-r--r-- | test/memorygrowth.fromasm.imprecise | 12 | ||||
-rw-r--r-- | test/passes/optimize-instructions.txt | 66 | ||||
-rw-r--r-- | test/passes/optimize-instructions.wast | 23 |
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))) |