diff options
3 files changed, 143 insertions, 6 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 263d4a96d..424cbcc67 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -874,14 +874,17 @@ private: auto* left = binary->left; auto* right = binary->right; if (!Properties::emitsBoolean(left) || !Properties::emitsBoolean(right)) return nullptr; - auto leftEffects = EffectAnalyzer(getPassOptions(), left).hasSideEffects(); - auto rightEffects = EffectAnalyzer(getPassOptions(), right).hasSideEffects(); - if (leftEffects && rightEffects) return nullptr; // both must execute - // canonicalize with side effects, if any, happening on the left - if (rightEffects) { + auto leftEffects = EffectAnalyzer(getPassOptions(), left); + auto rightEffects = EffectAnalyzer(getPassOptions(), right); + auto leftSideEffects = leftEffects.hasSideEffects(); + auto rightSideEffects = rightEffects.hasSideEffects(); + if (leftSideEffects && rightSideEffects) return nullptr; // both must execute + // canonicalize with side effects, if any, happening on the left + if (rightSideEffects) { if (CostAnalyzer(left).cost < MIN_COST) return nullptr; // avoidable code is too cheap + if (leftEffects.invalidates(rightEffects)) return nullptr; // cannot reorder std::swap(left, right); - } else if (leftEffects) { + } else if (leftSideEffects) { if (CostAnalyzer(right).cost < MIN_COST) return nullptr; // avoidable code is too cheap } else { // no side effects, reorder based on cost estimation diff --git a/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.txt b/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.txt index e2c4bb786..922f64008 100644 --- a/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.txt +++ b/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.txt @@ -251,4 +251,74 @@ (get_local $5) ) ) + (func $invalidate-conditionalizeExpensiveOnBitwise (type $0) (param $0 i32) (param $1 i32) (result i32) + (if + (i32.eqz + (i32.and + (i32.lt_s + (i32.and + (i32.shr_s + (i32.shl + (i32.add + (get_local $1) + (i32.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 255) + ) + (i32.const 3) + ) + (i32.ne + (tee_local $1 + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + (return + (get_local $0) + ) + ) + (return + (get_local $1) + ) + ) + (func $invalidate-conditionalizeExpensiveOnBitwise-ok (type $0) (param $0 i32) (param $1 i32) (result i32) + (if + (i32.eqz + (if (result i32) + (tee_local $1 + (i32.const 0) + ) + (i32.lt_s + (i32.and + (i32.shr_s + (i32.shl + (i32.add + (get_local $0) + (i32.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 255) + ) + (i32.const 3) + ) + (i32.const 0) + ) + ) + (return + (get_local $0) + ) + ) + (return + (get_local $1) + ) + ) ) diff --git a/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.wast b/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.wast index e1215fa3f..7e8365812 100644 --- a/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.wast +++ b/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.wast @@ -259,5 +259,69 @@ (get_local $5) ) ) + (func $invalidate-conditionalizeExpensiveOnBitwise (param $0 i32) (param $1 i32) (result i32) + (if + (i32.eqz + (i32.and + (i32.lt_s + (i32.and + (i32.shr_s + (i32.shl + (i32.add + (get_local $1) ;; conflict with tee + (i32.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 255) + ) + (i32.const 3) + ) + (i32.ne + (tee_local $1 + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + (return (get_local $0)) + ) + (return (get_local $1)) + ) + (func $invalidate-conditionalizeExpensiveOnBitwise-ok (param $0 i32) (param $1 i32) (result i32) + (if + (i32.eqz + (i32.and + (i32.lt_s + (i32.and + (i32.shr_s + (i32.shl + (i32.add + (get_local $0) ;; no conflict + (i32.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 255) + ) + (i32.const 3) + ) + (i32.ne + (tee_local $1 + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + (return (get_local $0)) + ) + (return (get_local $1)) + ) ) |