diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 14 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.txt | 44 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.wast | 48 |
3 files changed, 103 insertions, 3 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 869512774..79315ac6d 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1591,14 +1591,22 @@ private: return inner; } } - if (ExpressionAnalyzer::equal(inner->right, outer->left)) { + if (ExpressionAnalyzer::equal(inner->right, outer->left) && + canReorder(outer->left, inner->left)) { // x ^ (y ^ x) ==> y + // (note that we need the check for reordering here because if + // e.g. y writes to a local that x reads, the second appearance + // of x would be different from the first) if (outer->op == Abstract::getBinary(type, Abstract::Xor)) { return inner->left; } // x & (y & x) ==> y & x // x | (y | x) ==> y | x + // (here we need the check for reordering for the more obvious + // reason that previously x appeared before y, and now y appears + // first; or, if we tried to emit x [&|] y here, reversing the + // order, we'd be in the same situation as the previous comment) if (outer->op == Abstract::getBinary(type, Abstract::And) || outer->op == Abstract::getBinary(type, Abstract::Or)) { return inner; @@ -1627,7 +1635,9 @@ private: return inner; } } - if (ExpressionAnalyzer::equal(inner->left, outer->right)) { + // See comments in the parallel code earlier about ordering here. + if (ExpressionAnalyzer::equal(inner->left, outer->right) && + canReorder(inner->left, inner->right)) { // (x ^ y) ^ x ==> y if (outer->op == Abstract::getBinary(type, Abstract::Xor)) { return inner->right; diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 5bbaccfea..ee6b1162a 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -4319,6 +4319,50 @@ ) ) ) + (drop + (i32.or + (local.get $x) + (i32.or + (local.tee $x + (i32.const 1) + ) + (local.get $x) + ) + ) + ) + (drop + (i32.or + (i32.or + (local.get $x) + (local.tee $x + (i32.const 1) + ) + ) + (local.get $x) + ) + ) + (drop + (i32.xor + (local.get $x) + (i32.xor + (local.tee $x + (i32.const 1) + ) + (local.get $x) + ) + ) + ) + (drop + (i32.xor + (i32.xor + (local.get $x) + (local.tee $x + (i32.const 1) + ) + ) + (local.get $x) + ) + ) ) (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) (memory.copy diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index c8a48391c..71646de93 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -4805,7 +4805,53 @@ (local.get $x) (local.get $y) ) - )) + )) + ;; x | (y | x) where x and y cannot be reordered - skip + (drop + (i32.or + (local.get $x) + (i32.or + (local.tee $x + (i32.const 1) + ) + (local.get $x) + ) + ) + ) + (drop + (i32.or + (i32.or + (local.get $x) + (local.tee $x + (i32.const 1) + ) + ) + (local.get $x) + ) + ) + ;; x ^ (y ^ x) where x and y cannot be reordered - skip + (drop + (i32.xor + (local.get $x) + (i32.xor + (local.tee $x + (i32.const 1) + ) + (local.get $x) + ) + ) + ) + (drop + (i32.xor + (i32.xor + (local.get $x) + (local.tee $x + (i32.const 1) + ) + ) + (local.get $x) + ) + ) ) (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) (memory.copy ;; skip |