summaryrefslogtreecommitdiff
path: root/src/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes')
-rw-r--r--src/passes/OptimizeInstructions.cpp60
-rw-r--r--src/passes/OptimizeInstructions.wast132
-rw-r--r--src/passes/OptimizeInstructions.wast.processed132
-rw-r--r--src/passes/Print.cpp3
-rw-r--r--src/passes/RemoveUnusedBrs.cpp2
5 files changed, 68 insertions, 261 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 48639a341..f467b395e 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -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;
@@ -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
@@ -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>();
diff --git a/src/passes/OptimizeInstructions.wast b/src/passes/OptimizeInstructions.wast
index 48a4e2c9d..5142dc2c6 100644
--- a/src/passes/OptimizeInstructions.wast
+++ b/src/passes/OptimizeInstructions.wast
@@ -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)))
)
)
)
diff --git a/src/passes/OptimizeInstructions.wast.processed b/src/passes/OptimizeInstructions.wast.processed
index 13ccc8241..b69ecdf04 100644
--- a/src/passes/OptimizeInstructions.wast.processed
+++ b/src/passes/OptimizeInstructions.wast.processed
@@ -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"
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 69dc447a8..c3ca4021e 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -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
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 15482de25..d1de0086a 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -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();