diff options
author | Alon Zakai (kripken) <alonzakai@gmail.com> | 2017-07-30 11:07:51 -0700 |
---|---|---|
committer | Alon Zakai (kripken) <alonzakai@gmail.com> | 2017-07-30 11:07:51 -0700 |
commit | 6cdffee098cb891c7309eb372aea63c0baa7a2c5 (patch) | |
tree | dbab872c51cfec5bd482030199bccdf1f2c2dde9 /src | |
parent | 56e49752b4258b89660825f2970a7e55067d7122 (diff) | |
download | binaryen-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.h | 15 | ||||
-rw-r--r-- | src/ast/literal-utils.h | 26 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 14 |
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 } } } |