diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 26 | ||||
-rw-r--r-- | test/passes/optimize-instructions.txt | 67 | ||||
-rw-r--r-- | test/passes/optimize-instructions.wast | 75 | ||||
-rw-r--r-- | test/unit.fromasm | 11 | ||||
-rw-r--r-- | test/unit.fromasm.clamp | 11 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise | 11 |
6 files changed, 178 insertions, 23 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 02475e4dc..ad828dafc 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -404,13 +404,15 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, if (auto* ext = Properties::getAlmostSignExt(binary)) { Index extraShifts; auto bits = Properties::getAlmostSignExtBits(binary, extraShifts); - if (auto* load = getFallthrough(ext)->dynCast<Load>()) { - // pattern match a load of 8 bits and a sign extend using a shl of 24 then shr_s of 24 as well, etc. - if ((load->bytes == 1 && bits == 8) || (load->bytes == 2 && bits == 16)) { - // if the value falls through, we can't alter the load, as it might be captured in a tee - if (load->signed_ == true || load == ext) { - load->signed_ = true; - return removeAlmostSignExt(binary); + if (extraShifts == 0) { + if (auto* load = getFallthrough(ext)->dynCast<Load>()) { + // pattern match a load of 8 bits and a sign extend using a shl of 24 then shr_s of 24 as well, etc. + if ((load->bytes == 1 && bits == 8) || (load->bytes == 2 && bits == 16)) { + // if the value falls through, we can't alter the load, as it might be captured in a tee + if (load->signed_ == true || load == ext) { + load->signed_ = true; + return ext; + } } } } @@ -435,11 +437,13 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, } } else if (auto* left = Properties::getSignExtValue(binary->left)) { if (auto* right = Properties::getSignExtValue(binary->right)) { - // we are comparing two sign-exts, so we may as well replace both with cheaper zexts auto bits = Properties::getSignExtBits(binary->left); - binary->left = makeZeroExt(left, bits); - binary->right = makeZeroExt(right, bits); - return binary; + if (Properties::getSignExtBits(binary->right) == bits) { + // we are comparing two sign-exts with the same bits, so we may as well replace both with cheaper zexts + binary->left = makeZeroExt(left, bits); + binary->right = makeZeroExt(right, bits); + return binary; + } } else if (auto* load = binary->right->dynCast<Load>()) { // we are comparing a load to a sign-ext, we may be able to switch to zext auto leftBits = Properties::getSignExtBits(binary->left); diff --git a/test/passes/optimize-instructions.txt b/test/passes/optimize-instructions.txt index f40006f09..41d45d57f 100644 --- a/test/passes/optimize-instructions.txt +++ b/test/passes/optimize-instructions.txt @@ -5,6 +5,7 @@ (type $3 (func (param i32) (result i32))) (type $4 (func (param i32 i32))) (type $5 (func (param i32))) + (type $6 (func (param i32 i32) (result i32))) (memory $0 0) (export "load-off-2" (func $load-off-2)) (func $f (type $0) (param $i1 i32) (param $i2 i64) @@ -1723,4 +1724,70 @@ ) ) ) + (func $unsign-diff-sizes (type $6) (param $x i32) (param $y i32) (result i32) + (i32.ne + (i32.shr_s + (i32.shl + (call $unsign-diff-sizes + (i32.const -1) + (i32.const 5) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.shr_s + (i32.shl + (call $unsign-diff-sizes + (i32.const 1) + (i32.const 2006) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (func $unsign-same-sizes (type $6) (param $x i32) (param $y i32) (result i32) + (i32.ne + (i32.and + (call $unsign-same-sizes + (i32.const -1) + (i32.const 5) + ) + (i32.const 255) + ) + (i32.and + (call $unsign-same-sizes + (i32.const 1) + (i32.const 2006) + ) + (i32.const 255) + ) + ) + ) + (func $fuzz-almost-sign-ext (type $1) + (drop + (i32.shr_s + (i32.shl + (i32.load16_u + (i32.const 2278) + ) + (i32.const 17) + ) + (i32.const 16) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.load16_u + (i32.const 2278) + ) + (i32.const 17) + ) + (i32.const 16) + ) + ) + ) ) diff --git a/test/passes/optimize-instructions.wast b/test/passes/optimize-instructions.wast index 51bd076d1..8ef6f67a5 100644 --- a/test/passes/optimize-instructions.wast +++ b/test/passes/optimize-instructions.wast @@ -2106,4 +2106,79 @@ ) ) ) + (func $unsign-diff-sizes (param $x i32) (param $y i32) (result i32) + (i32.ne + (i32.shr_s + (i32.shl + (call $unsign-diff-sizes + (i32.const -1) + (i32.const 5) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.shr_s + (i32.shl + (call $unsign-diff-sizes + (i32.const 1) + (i32.const 2006) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (func $unsign-same-sizes (param $x i32) (param $y i32) (result i32) + (i32.ne + (i32.shr_s + (i32.shl + (call $unsign-same-sizes + (i32.const -1) + (i32.const 5) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.shr_s + (i32.shl + (call $unsign-same-sizes + (i32.const 1) + (i32.const 2006) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (func $fuzz-almost-sign-ext + (drop + (i32.shr_s + (i32.shl + (i32.load16_u + (i32.const 2278) + ) + (i32.const 17) + ) + (i32.const 16) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shl + (i32.load16_u + (i32.const 2278) + ) + (i32.const 1) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) ) diff --git a/test/unit.fromasm b/test/unit.fromasm index 58272fae8..fd0fb27a0 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -696,11 +696,14 @@ ) ) (call $loadSigned - (i32.shl - (i32.load16_s - (get_local $0) + (i32.shr_s + (i32.shl + (i32.load16_u + (get_local $0) + ) + (i32.const 24) ) - (i32.const 8) + (i32.const 16) ) ) ) diff --git a/test/unit.fromasm.clamp b/test/unit.fromasm.clamp index 645f65e3e..ffe26a3a2 100644 --- a/test/unit.fromasm.clamp +++ b/test/unit.fromasm.clamp @@ -720,11 +720,14 @@ ) ) (call $loadSigned - (i32.shl - (i32.load16_s - (get_local $0) + (i32.shr_s + (i32.shl + (i32.load16_u + (get_local $0) + ) + (i32.const 24) ) - (i32.const 8) + (i32.const 16) ) ) ) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index 0b03e0016..e94c07f7f 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -664,11 +664,14 @@ ) ) (call $loadSigned - (i32.shl - (i32.load16_s - (get_local $0) + (i32.shr_s + (i32.shl + (i32.load16_u + (get_local $0) + ) + (i32.const 24) ) - (i32.const 8) + (i32.const 16) ) ) ) |