Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/ast/bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ struct Bits {
WASM_UNREACHABLE();
}

static Index getEffectiveShifts(Const* amount) {
static Index getEffectiveShifts(Expression* expr) {
auto* amount = expr->cast<Const>();
if (amount->type == i32) {
return getEffectiveShifts(amount->value.geti32(), i32);
} else if (amount->type == i64) {
Expand Down
8 changes: 4 additions & 4 deletions src/ast/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ struct Properties {

// gets the size of the sign-extended value
static Index getSignExtBits(Expression* curr) {
return 32 - curr->cast<Binary>()->right->cast<Const>()->value.geti32();
return 32 - Bits::getEffectiveShifts(curr->cast<Binary>()->right);
}

// Check if an expression is almost a sign-extend: perhaps the inner shift
Expand All @@ -93,7 +93,7 @@ struct Properties {
if (auto* inner = outer->left->dynCast<Binary>()) {
if (inner->op == ShlInt32) {
if (auto* innerConst = inner->right->dynCast<Const>()) {
if (outerConst->value.leU(innerConst->value).geti32()) {
if (Bits::getEffectiveShifts(outerConst) <= Bits::getEffectiveShifts(innerConst)) {
return inner->left;
}
}
Expand All @@ -109,8 +109,8 @@ struct Properties {
// gets the size of the almost sign-extended value, as well as the
// extra shifts, if any
static Index getAlmostSignExtBits(Expression* curr, Index& extraShifts) {
extraShifts = curr->cast<Binary>()->left->cast<Binary>()->right->cast<Const>()->value.geti32() -
curr->cast<Binary>()->right->cast<Const>()->value.geti32();
extraShifts = Bits::getEffectiveShifts(curr->cast<Binary>()->left->cast<Binary>()->right) -
Bits::getEffectiveShifts(curr->cast<Binary>()->right);
return getSignExtBits(curr);
}

Expand Down
8 changes: 4 additions & 4 deletions src/passes/OptimizeInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) {
}
} else if (auto* unary = curr->dynCast<Unary>()) {
switch (unary->op) {
case ClzInt32: case CtzInt32: case PopcntInt32: return 5;
case ClzInt64: case CtzInt64: case PopcntInt64: return 6;
case ClzInt32: case CtzInt32: case PopcntInt32: return 6;
case ClzInt64: case CtzInt64: case PopcntInt64: return 7;
case EqZInt32: case EqZInt64: return 1;
case WrapInt64: return std::min(Index(32), getMaxBits(unary->value, localInfoProvider));
default: {}
Expand Down Expand Up @@ -779,7 +779,7 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
return;
} else if (binary->op == ShlInt32) {
if (auto* c = binary->right->dynCast<Const>()) {
seek(binary->left, mul * Pow2(c->value.geti32()));
seek(binary->left, mul * Pow2(Bits::getEffectiveShifts(c)));
return;
}
} else if (binary->op == MulInt32) {
Expand Down Expand Up @@ -836,7 +836,7 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
}
} else if (curr->op == ShlInt32) {
// shifting a 0 is a 0, unless the shift has side effects
if (left && left->value.geti32() == 0 && !EffectAnalyzer(passOptions, curr->right).hasSideEffects()) {
if (left && Bits::getEffectiveShifts(left) == 0 && !EffectAnalyzer(passOptions, curr->right).hasSideEffects()) {
replaceCurrent(left);
return;
}
Expand Down
10 changes: 9 additions & 1 deletion src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,14 @@ void WasmBinaryWriter::visitSwitch(Switch *curr) {
recurse(curr->value);
}
recurse(curr->condition);
if (!BranchUtils::isBranchTaken(curr)) {
// if the branch is not taken, then it's dangerous to emit it, as
// wasm type checking rules are stricter than ours - we tolerate
// an untaken branch to a target with a different value, but not
// wasm. so just don't emit it
o << int8_t(BinaryConsts::Unreachable);
return;
}
o << int8_t(BinaryConsts::TableSwitch) << U32LEB(curr->targets.size());
for (auto target : curr->targets) {
o << U32LEB(getBreakIndex(target));
Expand Down Expand Up @@ -1796,7 +1804,7 @@ void WasmBinaryBuilder::processExpressions() { // until an end or else marker, o

Expression* WasmBinaryBuilder::popExpression() {
if (expressionStack.empty()) {
throw ParseException("attempted pop from empty stack");
throw ParseException("attempted pop from empty stack at " + std::to_string(pos));
}
auto ret = expressionStack.back();
// to simulate the wasm polymorphic stack mode, leave a final
Expand Down
77 changes: 68 additions & 9 deletions test/passes/optimize-instructions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
(type $5 (func (param i32)))
(type $6 (func (param i32 i32) (result i32)))
(type $7 (func (param i64) (result i64)))
(type $8 (func (result i64)))
(memory $0 0)
(export "load-off-2" (func $load-off-2))
(func $f (type $0) (param $i1 i32) (param $i2 i64)
Expand Down Expand Up @@ -827,11 +828,14 @@
)
)
(drop
(i32.shl
(i32.clz
(i32.const 0)
(i32.shr_s
(i32.shl
(i32.clz
(i32.const 0)
)
(i32.const 26)
)
(i32.const 2)
(i32.const 24)
)
)
(drop
Expand All @@ -853,13 +857,16 @@
)
)
(drop
(i32.shl
(i32.wrap/i64
(i64.clz
(i64.const 0)
(i32.shr_s
(i32.shl
(i32.wrap/i64
(i64.clz
(i64.const 0)
)
)
(i32.const 25)
)
(i32.const 1)
(i32.const 24)
)
)
(drop
Expand Down Expand Up @@ -2061,4 +2068,56 @@
(i32.const 9)
)
)
(func $mix-shifts (type $2) (result i32)
(i32.shr_s
(i32.shl
(i32.const 23)
(i32.const -61)
)
(i32.const 168)
)
)
(func $actually-no-shifts (type $2) (result i32)
(i32.const 33)
)
(func $less-shifts-than-it-seems (type $3) (param $x i32) (result i32)
(i32.const 4800)
)
(func $and-popcount32 (type $2) (result i32)
(i32.and
(i32.popcnt
(i32.const -1)
)
(i32.const 31)
)
)
(func $and-popcount32-big (type $2) (result i32)
(i32.popcnt
(i32.const -1)
)
)
(func $and-popcount64 (type $8) (result i64)
(i64.and
(i64.popcnt
(i64.const -1)
)
(i64.const 63)
)
)
(func $and-popcount64-big (type $8) (result i64)
(i64.and
(i64.popcnt
(i64.const -1)
)
(i64.const 127)
)
)
(func $and-popcount64-bigger (type $8) (result i64)
(i64.and
(i64.popcnt
(i64.const -1)
)
(i64.const 255)
)
)
)
70 changes: 70 additions & 0 deletions test/passes/optimize-instructions.wast
Original file line number Diff line number Diff line change
Expand Up @@ -2496,4 +2496,74 @@
(i32.const 4098) ;; 2 bits effectively
)
)
(func $mix-shifts (result i32)
(i32.shr_s
(i32.shl
(i32.const 23)
(i32.const -61)
)
(i32.const 168)
)
)
(func $actually-no-shifts (result i32)
(i32.add
(i32.shl
(i32.const 23)
(i32.const 32) ;; really 0
)
(i32.const 10)
)
)
(func $less-shifts-than-it-seems (param $x i32) (result i32)
(i32.add
(i32.shl
(i32.const 200)
(i32.const 36) ;; really 4
)
(i32.shl
(i32.const 100)
(i32.const 4)
)
)
)
(func $and-popcount32 (result i32)
(i32.and
(i32.popcnt
(i32.const -1)
)
(i32.const 31)
)
)
(func $and-popcount32-big (result i32)
(i32.and
(i32.popcnt
(i32.const -1)
)
(i32.const 63)
)
)
(func $and-popcount64 (result i64) ;; these are TODOs
(i64.and
(i64.popcnt
(i64.const -1)
)
(i64.const 63)
)
)
(func $and-popcount64-big (result i64)
(i64.and
(i64.popcnt
(i64.const -1)
)
(i64.const 127)
)
)
(func $and-popcount64-bigger (result i64)
(i64.and
(i64.popcnt
(i64.const -1)
)
(i64.const 255)
)
)
)
10 changes: 10 additions & 0 deletions test/polymorphic_stack.wast
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,15 @@
)
)
)
(func $br_table_unreachable_to_also_unreachable (result i32)
(block $a (result i32)
(block $b
(br_table $a $b ;; seems to send a value, but is not taken
(unreachable)
(unreachable)
)
)
)
)
)

10 changes: 10 additions & 0 deletions test/polymorphic_stack.wast.from-wast
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,14 @@
)
)
)
(func $br_table_unreachable_to_also_unreachable (type $1) (result i32)
(block $a (result i32)
(block $b
(br_table $a $b
(unreachable)
(unreachable)
)
)
)
)
)
11 changes: 11 additions & 0 deletions test/polymorphic_stack.wast.fromBinary
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,16 @@
(unreachable)
)
)
(func $br_table_unreachable_to_also_unreachable (type $1) (result i32)
(block $label$0 (result i32)
(block $label$1
(unreachable)
(unreachable)
(unreachable)
(unreachable)
)
(unreachable)
)
)
)

11 changes: 11 additions & 0 deletions test/polymorphic_stack.wast.fromBinary.noDebugInfo
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,16 @@
(unreachable)
)
)
(func $6 (type $1) (result i32)
(block $label$0 (result i32)
(block $label$1
(unreachable)
(unreachable)
(unreachable)
(unreachable)
)
(unreachable)
)
)
)