diff options
-rw-r--r-- | src/ir/effects.h | 8 | ||||
-rw-r--r-- | src/passes/MinifyImportsAndExports.cpp | 1 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 21 | ||||
-rw-r--r-- | test/passes/optimize-instructions.txt | 25 | ||||
-rw-r--r-- | test/passes/optimize-instructions.wast | 28 |
5 files changed, 80 insertions, 3 deletions
diff --git a/src/ir/effects.h b/src/ir/effects.h index 8919c6da4..8c95f463d 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -283,6 +283,14 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { isAtomic = true; } void visitUnreachable(Unreachable *curr) { branches = true; } + + // Helpers + + static bool canReorder(PassOptions& passOptions, Expression* a, Expression* b) { + EffectAnalyzer aEffects(passOptions, a); + EffectAnalyzer bEffects(passOptions, b); + return !aEffects.invalidates(bEffects); + } }; } // namespace wasm diff --git a/src/passes/MinifyImportsAndExports.cpp b/src/passes/MinifyImportsAndExports.cpp index 9cbc3b19a..f32859384 100644 --- a/src/passes/MinifyImportsAndExports.cpp +++ b/src/passes/MinifyImportsAndExports.cpp @@ -64,7 +64,6 @@ struct MinifyImportsAndExports : public Pass { reserved.insert("enum"); reserved.insert("void"); reserved.insert("this"); - reserved.insert("void"); reserved.insert("with"); validInitialChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$"; diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 255ff4cbd..7cdc048f7 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -380,16 +380,32 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, // Y // X // ) + // Note that this reorders X and Y, so we need to be careful about that. if (auto* sub = binary->left->dynCast<Binary>()) { if (sub->op == SubInt32) { if (auto* subZero = sub->left->dynCast<Const>()) { if (subZero->value.geti32() == 0) { - sub->left = binary->right; - return sub; + if (EffectAnalyzer::canReorder(getPassOptions(), sub->right, binary->right)) { + sub->left = binary->right; + return sub; + } } } } } + // The flip case is even easier, as no reordering occurs: + // (i32.add + // Y + // (i32.sub + // (i32.const 0) + // X + // ) + // ) + // => + // (i32.sub + // Y + // X + // ) if (auto* sub = binary->right->dynCast<Binary>()) { if (sub->op == SubInt32) { if (auto* subZero = sub->left->dynCast<Const>()) { @@ -761,6 +777,7 @@ private: constant += value * mul; constants.push_back(c); } + return; } else if (auto* binary = curr->dynCast<Binary>()) { if (binary->op == AddInt32) { seek(binary->left, mul); diff --git a/test/passes/optimize-instructions.txt b/test/passes/optimize-instructions.txt index 5a0a45e3d..51a5113b1 100644 --- a/test/passes/optimize-instructions.txt +++ b/test/passes/optimize-instructions.txt @@ -2997,6 +2997,31 @@ ) ) ) + (func $add-sub-zero-reorder-1 (; 73 ;) (type $3) (param $temp i32) (result i32) + (i32.add + (i32.add + (i32.sub + (i32.const 0) + (get_local $temp) + ) + (tee_local $temp + (i32.const 1) + ) + ) + (i32.const 2) + ) + ) + (func $add-sub-zero-reorder-2 (; 74 ;) (type $3) (param $temp i32) (result i32) + (i32.add + (i32.sub + (tee_local $temp + (i32.const 1) + ) + (get_local $temp) + ) + (i32.const 2) + ) + ) ) (module (type $0 (func)) diff --git a/test/passes/optimize-instructions.wast b/test/passes/optimize-instructions.wast index aa979c62a..53ed761d8 100644 --- a/test/passes/optimize-instructions.wast +++ b/test/passes/optimize-instructions.wast @@ -3526,6 +3526,34 @@ ) ) ) + (func $add-sub-zero-reorder-1 (param $temp i32) (result i32) + (i32.add + (i32.add + (i32.sub + (i32.const 0) ;; this zero looks like we could remove it by subtracting the get of $temp from the parent, but that would reorder it *after* the tee :( + (get_local $temp) + ) + (tee_local $temp ;; cannot move this tee before the get + (i32.const 1) + ) + ) + (i32.const 2) + ) + ) + (func $add-sub-zero-reorder-2 (param $temp i32) (result i32) + (i32.add + (i32.add + (tee_local $temp ;; in this order, the tee already comes first, so all is good for the optimization + (i32.const 1) + ) + (i32.sub + (i32.const 0) + (get_local $temp) + ) + ) + (i32.const 2) + ) + ) ) (module (import "env" "memory" (memory $0 (shared 256 256))) |