summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeInstructions.cpp19
-rw-r--r--test/emcc_hello_world.fromasm20
-rw-r--r--test/emcc_hello_world.fromasm.imprecise20
-rw-r--r--test/passes/optimize-instructions.txt54
-rw-r--r--test/passes/optimize-instructions.wast66
5 files changed, 150 insertions, 29 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 49100a9f4..844ed06ac 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -305,6 +305,17 @@ static int32_t lowBitMask(int32_t bits) {
return ret >> (32 - bits);
}
+// checks if the input is a mask of lower bits, i.e., all 1s up to some high bit, and all zeros
+// from there. returns the number of masked bits, or 0 if this is not such a mask
+static uint32_t getMaskedBits(int32_t mask) {
+ if (mask == -1) return 32; // all the bits
+ if (mask == 0) return 0; // trivially not a mask
+ // otherwise, see if adding one turns this into a 1-bit thing, 00011111 + 1 => 00100000
+ if (PopCount(mask + 1) != 1) return 0;
+ // this is indeed a mask
+ return 32 - CountLeadingZeroes(mask);
+}
+
// performs a dynCast on the fallthrough value, i.e., looks through
// too and block fallthroughs, etc.
template<typename T>
@@ -436,9 +447,11 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
return binary->left;
}
}
- } else if (mask == 1 && Properties::emitsBoolean(binary->left)) {
- // (bool) & 1 does not need the outer mask
- return binary->left;
+ } else if (auto maskedBits = getMaskedBits(mask)) {
+ if (getMaxBits(binary->left) <= maskedBits) {
+ // a mask of lower bits is not needed if we are already smaller
+ return binary->left;
+ }
}
}
// the square of some operations can be merged
diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm
index 78f0460fa..88db1c1ce 100644
--- a/test/emcc_hello_world.fromasm
+++ b/test/emcc_hello_world.fromasm
@@ -1941,14 +1941,11 @@
(i32.load8_u
(get_local $2)
)
- (i32.and
- (tee_local $1
- (i32.and
- (get_local $1)
- (i32.const 255)
- )
+ (tee_local $1
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
)
- (i32.const 255)
)
)
(block
@@ -9393,13 +9390,10 @@
(i32.shl
(get_local $8)
(i32.xor
- (i32.and
- (tee_local $6
- (i32.eqz
- (get_local $9)
- )
+ (tee_local $6
+ (i32.eqz
+ (get_local $9)
)
- (i32.const 1)
)
(i32.const 1)
)
diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise
index ba1a50ca7..5ed229e6f 100644
--- a/test/emcc_hello_world.fromasm.imprecise
+++ b/test/emcc_hello_world.fromasm.imprecise
@@ -1938,14 +1938,11 @@
(i32.load8_u
(get_local $2)
)
- (i32.and
- (tee_local $1
- (i32.and
- (get_local $1)
- (i32.const 255)
- )
+ (tee_local $1
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
)
- (i32.const 255)
)
)
(block
@@ -9330,13 +9327,10 @@
(i32.shl
(get_local $8)
(i32.xor
- (i32.and
- (tee_local $6
- (i32.eqz
- (get_local $9)
- )
+ (tee_local $6
+ (i32.eqz
+ (get_local $9)
)
- (i32.const 1)
)
(i32.const 1)
)
diff --git a/test/passes/optimize-instructions.txt b/test/passes/optimize-instructions.txt
index 3b4718f6a..31dceaf60 100644
--- a/test/passes/optimize-instructions.txt
+++ b/test/passes/optimize-instructions.txt
@@ -1290,4 +1290,58 @@
)
)
)
+ (func $mask-bits (type $4) (param $0 i32) (param $1 i32)
+ (drop
+ (tee_local $0
+ (i32.const 127)
+ )
+ )
+ (drop
+ (tee_local $0
+ (i32.const 128)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 254)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 1279)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 1290)
+ )
+ )
+ (drop
+ (tee_local $0
+ (i32.const 128)
+ )
+ )
+ (drop
+ (tee_local $0
+ (i32.const 128)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 127)
+ )
+ )
+ )
)
diff --git a/test/passes/optimize-instructions.wast b/test/passes/optimize-instructions.wast
index f8c93d03c..c305ccbbb 100644
--- a/test/passes/optimize-instructions.wast
+++ b/test/passes/optimize-instructions.wast
@@ -1625,4 +1625,70 @@
)
)
)
+ (func $mask-bits (param $0 i32) (param $1 i32)
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 127) ;; 7 bits
+ )
+ (i32.const 255) ;; mask 8, so we don't need this
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128) ;; 8 bits
+ )
+ (i32.const 255) ;; mask 8, so we don't need this
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 254) ;; improper mask, small
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 1279) ;; improper mask, large
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 1290) ;; improper mask, large
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 4095) ;; proper mask, huge
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 511) ;; proper mask, large
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 127) ;; proper mask, just too small
+ )
+ )
+ )
)