diff options
Diffstat (limited to 'src/passes')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 60 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.wast | 132 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.wast.processed | 132 | ||||
-rw-r--r-- | src/passes/Print.cpp | 3 | ||||
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 2 |
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(); |