summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai (kripken) <alonzakai@gmail.com>2017-07-30 11:07:51 -0700
committerAlon Zakai (kripken) <alonzakai@gmail.com>2017-07-30 11:07:51 -0700
commit6cdffee098cb891c7309eb372aea63c0baa7a2c5 (patch)
treedbab872c51cfec5bd482030199bccdf1f2c2dde9 /src
parent56e49752b4258b89660825f2970a7e55067d7122 (diff)
downloadbinaryen-6cdffee098cb891c7309eb372aea63c0baa7a2c5.tar.gz
binaryen-6cdffee098cb891c7309eb372aea63c0baa7a2c5.tar.bz2
binaryen-6cdffee098cb891c7309eb372aea63c0baa7a2c5.zip
fix optimizing two shifts into one; if the number of effective shifts overflows, it is not vali to just add them
Diffstat (limited to 'src')
-rw-r--r--src/ast/bits.h15
-rw-r--r--src/ast/literal-utils.h26
-rw-r--r--src/passes/OptimizeInstructions.cpp14
3 files changed, 41 insertions, 14 deletions
diff --git a/src/ast/bits.h b/src/ast/bits.h
index c7d2ea4f0..11cf7b06d 100644
--- a/src/ast/bits.h
+++ b/src/ast/bits.h
@@ -42,11 +42,20 @@ struct Bits {
// gets the number of effective shifts a shift operation does. In
// wasm, only 5 bits matter for 32-bit shifts, and 6 for 64.
- static uint32_t getEffectiveShifts(Const* amount) {
+ static Index getEffectiveShifts(Index amount, WasmType type) {
+ if (type == i32) {
+ return amount & 31;
+ } else if (type == i64) {
+ return amount & 63;
+ }
+ WASM_UNREACHABLE();
+ }
+
+ static Index getEffectiveShifts(Const* amount) {
if (amount->type == i32) {
- return amount->value.geti32() & 31;
+ return getEffectiveShifts(amount->value.geti32(), i32);
} else if (amount->type == i64) {
- return amount->value.geti64() & 63;
+ return getEffectiveShifts(amount->value.geti64(), i64);
}
WASM_UNREACHABLE();
}
diff --git a/src/ast/literal-utils.h b/src/ast/literal-utils.h
index 7e75e8bc8..afa8146b9 100644
--- a/src/ast/literal-utils.h
+++ b/src/ast/literal-utils.h
@@ -23,21 +23,31 @@ namespace wasm {
namespace LiteralUtils {
-inline Expression* makeZero(WasmType type, Module& wasm) {
- Literal value;
+inline Literal makeLiteralFromInt32(int32_t x, WasmType type) {
switch (type) {
- case i32: value = Literal(int32_t(0)); break;
- case i64: value = Literal(int64_t(0)); break;
- case f32: value = Literal(float(0)); break;
- case f64: value = Literal(double(0)); break;
+ case i32: return Literal(int32_t(x)); break;
+ case i64: return Literal(int64_t(x)); break;
+ case f32: return Literal(float(x)); break;
+ case f64: return Literal(double(x)); break;
default: WASM_UNREACHABLE();
}
+}
+
+inline Literal makeLiteralZero(WasmType type) {
+ return makeLiteralFromInt32(0, type);
+}
+
+inline Expression* makeFromInt32(int32_t x, WasmType type, Module& wasm) {
auto* ret = wasm.allocator.alloc<Const>();
- ret->value = value;
- ret->type = value.type;
+ ret->value = makeLiteralFromInt32(x, type);
+ ret->type = type;
return ret;
}
+inline Expression* makeZero(WasmType type, Module& wasm) {
+ return makeFromInt32(0, type, wasm);
+}
+
} // namespace LiteralUtils
} // namespace wasm
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 424cbcc67..60222c3cd 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -29,6 +29,7 @@
#include <ast/effects.h>
#include <ast/manipulation.h>
#include <ast/properties.h>
+#include <ast/literal-utils.h>
namespace wasm {
@@ -533,9 +534,16 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
} else if (left->op == OrInt32) {
leftRight->value = leftRight->value.or_(right->value);
return left;
- } else if (left->op == ShlInt32 || left->op == ShrUInt32 || left->op == ShrSInt32) {
- leftRight->value = leftRight->value.add(right->value);
- return left;
+ } else if (left->op == ShlInt32 || left->op == ShrUInt32 || left->op == ShrSInt32 ||
+ left->op == ShlInt64 || left->op == ShrUInt64 || left->op == ShrSInt64) {
+ // shifts only use an effective amount from the constant, so adding must
+ // be done carefully
+ auto total = Bits::getEffectiveShifts(leftRight) + Bits::getEffectiveShifts(right);
+ if (total == Bits::getEffectiveShifts(total, left->type)) {
+ // no overflow, we can do this
+ leftRight->value = LiteralUtils::makeLiteralFromInt32(total, left->type);
+ return left;
+ } // TODO: handle overflows
}
}
}