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
530 changes: 266 additions & 264 deletions bin/binaryen.js

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions bin/wasm.js

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions src/passes/OptimizeInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
if (handOptimized) {
curr = handOptimized;
replaceCurrent(curr);
continue;
}
auto iter = database->patternMap.find(curr->_id);
if (iter == database->patternMap.end()) return;
Expand Down Expand Up @@ -209,6 +210,56 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
}
}
}
} else if (binary->op == EqInt32) {
if (auto* c = binary->right->dynCast<Const>()) {
if (c->value.geti32() == 0) {
// equal 0 => eqz
return Builder(*getModule()).makeUnary(EqZInt32, binary->left);
}
}
if (auto* c = binary->left->dynCast<Const>()) {
if (c->value.geti32() == 0) {
// equal 0 => eqz
return Builder(*getModule()).makeUnary(EqZInt32, binary->right);
}
}
}
} else if (auto* unary = curr->dynCast<Unary>()) {
// de-morgan's laws
if (unary->op == EqZInt32) {
if (auto* inner = unary->value->dynCast<Binary>()) {
switch (inner->op) {
case EqInt32: inner->op = NeInt32; return inner;
case NeInt32: inner->op = EqInt32; return inner;
case LtSInt32: inner->op = GeSInt32; return inner;
case LtUInt32: inner->op = GeUInt32; return inner;
case LeSInt32: inner->op = GtSInt32; return inner;
case LeUInt32: inner->op = GtUInt32; return inner;
case GtSInt32: inner->op = LeSInt32; return inner;
case GtUInt32: inner->op = LeUInt32; return inner;
case GeSInt32: inner->op = LtSInt32; return inner;
case GeUInt32: inner->op = LtUInt32; return inner;

case EqInt64: inner->op = NeInt64; return inner;
case NeInt64: inner->op = EqInt64; return inner;
case LtSInt64: inner->op = GeSInt64; return inner;
case LtUInt64: inner->op = GeUInt64; return inner;
case LeSInt64: inner->op = GtSInt64; return inner;
case LeUInt64: inner->op = GtUInt64; return inner;
case GtSInt64: inner->op = LeSInt64; return inner;
case GtUInt64: inner->op = LeUInt64; return inner;
case GeSInt64: inner->op = LtSInt64; return inner;
case GeUInt64: inner->op = LtUInt64; return inner;

case EqFloat32: inner->op = NeFloat32; return inner;
case NeFloat32: inner->op = EqFloat32; return inner;

case EqFloat64: inner->op = NeFloat64; return inner;
case NeFloat64: inner->op = EqFloat64; return inner;

default: {}
}
}
}
} else if (auto* set = curr->dynCast<SetGlobal>()) {
// optimize out a set of a get
Expand All @@ -218,6 +269,15 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
}
} else if (auto* iff = curr->dynCast<If>()) {
iff->condition = optimizeBoolean(iff->condition);
if (iff->ifFalse) {
if (auto* unary = iff->condition->dynCast<Unary>()) {
if (unary->op == EqZInt32) {
// flip if-else arms to get rid of an eqz
iff->condition = unary->value;
std::swap(iff->ifTrue, iff->ifFalse);
}
}
}
} else if (auto* select = curr->dynCast<Select>()) {
select->condition = optimizeBoolean(select->condition);
auto* condition = select->condition->dynCast<Unary>();
Expand Down
132 changes: 2 additions & 130 deletions src/passes/OptimizeInstructions.wast
Original file line number Diff line number Diff line change
Expand Up @@ -17,138 +17,10 @@
(import $f64.expr "dsl" "f64.expr" (param i32) (result f64))
(import $any.expr "dsl" "any.expr" (param i32) (result i32)) ;; ignorable return type

;; main function. each block here is a pattern pair of input => output
;; TODO for now wasm is not that convenient for a DSL like this. Needs rethinking.

(func $patterns
;; flip if-else arms to get rid of an eqz
(block
(if
(i32.eqz
(call_import $i32.expr (i32.const 0))
)
(call_import $any.expr (i32.const 1))
(call_import $any.expr (i32.const 2))
)
(if
(call_import $i32.expr (i32.const 0))
(call_import $any.expr (i32.const 2))
(call_import $any.expr (i32.const 1))
)
)
;; equal 0 => eqz
(block
(i32.eq
(call_import $any.expr (i32.const 0))
(i32.const 0)
)
(i32.eqz
(call_import $any.expr (i32.const 0))
)
)
(block
(i32.eq
(i32.const 0)
(call_import $any.expr (i32.const 0))
)
(i32.eqz
(call_import $any.expr (i32.const 0))
)
)
;; De Morgans Laws
(block
(i32.eqz (i32.eq (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.ne (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i32.ne (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.eq (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i32.lt_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.ge_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i32.lt_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.ge_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i32.le_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.gt_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i32.le_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.gt_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i32.gt_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.le_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i32.gt_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.le_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i32.ge_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.lt_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i32.ge_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))
(i32.lt_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))
)
(block
(i32.eqz (i64.eq (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.ne (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (i64.ne (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.eq (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (i64.lt_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.ge_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (i64.lt_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.ge_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (i64.le_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.gt_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (i64.le_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.gt_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (i64.gt_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.le_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (i64.gt_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.le_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (i64.ge_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.lt_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (i64.ge_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))
(i64.lt_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))
)
(block
(i32.eqz (f32.eq (call_import $f32.expr (i32.const 0)) (call_import $f32.expr (i32.const 1))))
(f32.ne (call_import $f32.expr (i32.const 0)) (call_import $f32.expr (i32.const 1)))
)
(block
(i32.eqz (f32.ne (call_import $f32.expr (i32.const 0)) (call_import $f32.expr (i32.const 1))))
(f32.eq (call_import $f32.expr (i32.const 0)) (call_import $f32.expr (i32.const 1)))
)
(block
(i32.eqz (f64.eq (call_import $f64.expr (i32.const 0)) (call_import $f64.expr (i32.const 1))))
(f64.ne (call_import $f64.expr (i32.const 0)) (call_import $f64.expr (i32.const 1)))
)
(block
(i32.eqz (f64.ne (call_import $f64.expr (i32.const 0)) (call_import $f64.expr (i32.const 1))))
(f64.eq (call_import $f64.expr (i32.const 0)) (call_import $f64.expr (i32.const 1)))
)
)
)
Expand Down
132 changes: 2 additions & 130 deletions src/passes/OptimizeInstructions.wast.processed
Original file line number Diff line number Diff line change
Expand Up @@ -17,138 +17,10 @@
"(import $f64.expr \"dsl\" \"f64.expr\" (param i32) (result f64))\n"
"(import $any.expr \"dsl\" \"any.expr\" (param i32) (result i32)) ;; ignorable return type\n"
"\n"
";; main function. each block here is a pattern pair of input => output\n"
";; TODO for now wasm is not that convenient for a DSL like this. Needs rethinking.\n"
"\n"
"(func $patterns\n"
";; flip if-else arms to get rid of an eqz\n"
"(block\n"
"(if\n"
"(i32.eqz\n"
"(call_import $i32.expr (i32.const 0))\n"
")\n"
"(call_import $any.expr (i32.const 1))\n"
"(call_import $any.expr (i32.const 2))\n"
")\n"
"(if\n"
"(call_import $i32.expr (i32.const 0))\n"
"(call_import $any.expr (i32.const 2))\n"
"(call_import $any.expr (i32.const 1))\n"
")\n"
")\n"
";; equal 0 => eqz\n"
"(block\n"
"(i32.eq\n"
"(call_import $any.expr (i32.const 0))\n"
"(i32.const 0)\n"
")\n"
"(i32.eqz\n"
"(call_import $any.expr (i32.const 0))\n"
")\n"
")\n"
"(block\n"
"(i32.eq\n"
"(i32.const 0)\n"
"(call_import $any.expr (i32.const 0))\n"
")\n"
"(i32.eqz\n"
"(call_import $any.expr (i32.const 0))\n"
")\n"
")\n"
";; De Morgans Laws\n"
"(block\n"
"(i32.eqz (i32.eq (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.ne (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i32.ne (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.eq (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i32.lt_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.ge_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i32.lt_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.ge_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i32.le_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.gt_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i32.le_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.gt_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i32.gt_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.le_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i32.gt_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.le_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i32.ge_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.lt_s (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i32.ge_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1))))\n"
"(i32.lt_u (call_import $i32.expr (i32.const 0)) (call_import $i32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.eq (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.ne (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.ne (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.eq (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.lt_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.ge_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.lt_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.ge_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.le_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.gt_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.le_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.gt_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.gt_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.le_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.gt_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.le_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.ge_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.lt_s (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (i64.ge_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1))))\n"
"(i64.lt_u (call_import $i64.expr (i32.const 0)) (call_import $i64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (f32.eq (call_import $f32.expr (i32.const 0)) (call_import $f32.expr (i32.const 1))))\n"
"(f32.ne (call_import $f32.expr (i32.const 0)) (call_import $f32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (f32.ne (call_import $f32.expr (i32.const 0)) (call_import $f32.expr (i32.const 1))))\n"
"(f32.eq (call_import $f32.expr (i32.const 0)) (call_import $f32.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (f64.eq (call_import $f64.expr (i32.const 0)) (call_import $f64.expr (i32.const 1))))\n"
"(f64.ne (call_import $f64.expr (i32.const 0)) (call_import $f64.expr (i32.const 1)))\n"
")\n"
"(block\n"
"(i32.eqz (f64.ne (call_import $f64.expr (i32.const 0)) (call_import $f64.expr (i32.const 1))))\n"
"(f64.eq (call_import $f64.expr (i32.const 0)) (call_import $f64.expr (i32.const 1)))\n"
")\n"
")\n"
")\n"
Expand Down
3 changes: 3 additions & 0 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
void visitIf(If *curr) {
printOpening(o, "if");
if (isConcreteWasmType(curr->type)) {
o << ' ' << printWasmType(curr->type);
}
incIndent();
printFullLine(curr->condition);
// ifTrue and False have implict blocks, avoid printing them if possible
Expand Down
2 changes: 1 addition & 1 deletion src/passes/RemoveUnusedBrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
} while (anotherCycle);

if (worked) {
// Our work may alter block and if types, they may now return
// Our work may alter block and if types, they may now return values that we made flow through them
struct TypeUpdater : public WalkerPass<PostWalker<TypeUpdater, Visitor<TypeUpdater>>> {
void visitBlock(Block* curr) {
curr->finalize();
Expand Down
Loading