From 31a527677434175db94d369fd09e0518a6f750de Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 21 Sep 2020 12:42:12 +0300 Subject: [PATCH 01/22] Simplify signed reminders which compared with zero --- src/passes/OptimizeInstructions.cpp | 22 ++++++++- .../optimize-instructions_all-features.txt | 10 ++++ .../optimize-instructions_all-features.wast | 47 +++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 1c2445d5d73..19b1acbfe46 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1243,6 +1243,8 @@ struct OptimizeInstructions Expression* optimizeWithConstantOnRight(Binary* curr) { using namespace Match; Builder builder(*getModule()); + Const* c; + Binary* inner; Expression* left; auto* right = curr->right->cast(); auto type = curr->right->type; @@ -1259,8 +1261,26 @@ struct OptimizeInstructions matches(curr, binary(Abstract::And, pure(&left), ival(0)))) { return right; } + // (signed)x % C_pot == 0 ==> x & (C_pot - 1) == 0 + // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 + if (matches(curr, + binary(Abstract::Eq, + binary(&inner, Abstract::RemS, any(&left), constant(&c)), + ival(0))) || + matches(curr, + binary(Abstract::Ne, + binary(&inner, Abstract::RemS, any(&left), constant(&c)), + ival(0)))) { + curr->dump(); + abort(); + if (IsPowerOf2((uint64_t)c->value.getInteger())) { + inner->op = Abstract::getBinary(left->type, Abstract::And); + c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); + } + } + // x == 0 ==> eqz x - if ((matches(curr, binary(Abstract::Eq, any(&left), ival(0))))) { + if (matches(curr, binary(Abstract::Eq, any(&left), ival(0)))) { return builder.makeUnary(EqZInt64, left); } diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 8c21b8494d6..a47817e7469 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -2744,6 +2744,16 @@ (i64.const 0) ) ) + (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) + (drop + (i32.eqz + (i32.rem_s + (local.get $x) + (i32.const 2) + ) + ) + ) + ) (func $orZero (param $0 i32) (result i32) (local.get $0) ) diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index 1b03782e9b5..6c9adf83f37 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -3104,6 +3104,53 @@ (i64.const 1) )) ) + (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) + ;; (signed)x % 2 == 0 + (drop (i32.eq + (i32.rem_s + (local.get $x) + (i32.const 2) + ) + (i32.const 0) + )) + ;; (drop (i64.eq + ;; (i64.rem_s + ;; (local.get $y) + ;; (i64.const 2) + ;; ) + ;; (i64.const 0) + ;; )) + ;; ;; (signed)x % 2 != 0 + ;; (drop (i32.ne + ;; (i32.rem_s + ;; (local.get $x) + ;; (i32.const 2) + ;; ) + ;; (i32.const 0) + ;; )) + ;; (drop (i64.ne + ;; (i64.rem_s + ;; (local.get $y) + ;; (i64.const 2) + ;; ) + ;; (i64.const 0) + ;; )) + ;; ;; + ;; (drop (i32.eq + ;; (i32.rem_s + ;; (local.get $x) + ;; (i32.const 3) ;; skip + ;; ) + ;; (i32.const 0) + ;; )) + ;; (drop (i64.eq + ;; (i64.rem_s + ;; (local.get $y) + ;; (i64.const 3) ;; skip + ;; ) + ;; (i64.const 0) + ;; )) + ) (func $orZero (param $0 i32) (result i32) (i32.or (local.get $0) From 25aca3359ee4078e799b7364d990cc2f6e64c047 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 21 Sep 2020 15:27:24 +0300 Subject: [PATCH 02/22] add match for unary. More tests --- src/passes/OptimizeInstructions.cpp | 18 +++- .../optimize-instructions_all-features.txt | 60 ++++++++++++- .../optimize-instructions_all-features.wast | 87 +++++++++++-------- 3 files changed, 125 insertions(+), 40 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 19b1acbfe46..2f301a5c387 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -570,6 +570,22 @@ struct OptimizeInstructions return ret; } } else if (auto* unary = curr->dynCast()) { + if (unary->op == EqZInt32 || unary->op == EqZInt64) { + using namespace Match; + Const* c; + Binary* inner; + Expression* left; + // eqz((signed)x % C_pot) ==> eqz(x & (C_pot - 1)) + if (matches(unary->value, + Match::binary( + &inner, Abstract::RemS, any(&left), constant(&c)))) { + if (IsPowerOf2((uint64_t)c->value.getInteger())) { + inner->op = Abstract::getBinary(left->type, Abstract::And); + c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); + return unary; + } + } + } if (unary->op == EqZInt32) { if (auto* inner = unary->value->dynCast()) { // Try to invert a relational operation using De Morgan's law @@ -1271,8 +1287,6 @@ struct OptimizeInstructions binary(Abstract::Ne, binary(&inner, Abstract::RemS, any(&left), constant(&c)), ival(0)))) { - curr->dump(); - abort(); if (IsPowerOf2((uint64_t)c->value.getInteger())) { inner->op = Abstract::getBinary(left->type, Abstract::And); c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index a47817e7469..0b2c20388bb 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -2745,11 +2745,69 @@ ) ) (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) + (drop + (i32.eqz + (i32.and + (local.get $x) + (i32.const 3) + ) + ) + ) + (drop + (i64.eqz + (i64.and + (local.get $y) + (i64.const 3) + ) + ) + ) + (drop + (i32.eqz + (i32.and + (local.get $x) + (i32.const 3) + ) + ) + ) + (drop + (i64.eqz + (i64.and + (local.get $y) + (i64.const 1) + ) + ) + ) + (drop + (i32.ne + (i32.and + (local.get $x) + (i32.const 1) + ) + (i32.const 0) + ) + ) + (drop + (i64.ne + (i64.and + (local.get $y) + (i64.const 1) + ) + (i64.const 0) + ) + ) (drop (i32.eqz (i32.rem_s (local.get $x) - (i32.const 2) + (i32.const 3) + ) + ) + ) + (drop + (i64.eqz + (i64.rem_s + (local.get $y) + (i64.const 3) ) ) ) diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index 6c9adf83f37..0cd75f7374d 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -3105,51 +3105,64 @@ )) ) (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) - ;; (signed)x % 2 == 0 + ;; eqz((signed)x % 4) + (drop (i32.eqz + (i32.rem_s + (local.get $x) + (i32.const 4) + ) + )) + (drop (i64.eqz + (i64.rem_s + (local.get $y) + (i64.const 4) + ) + )) + ;; (signed)x % 4 == 0 (drop (i32.eq (i32.rem_s (local.get $x) - (i32.const 2) + (i32.const 4) ) (i32.const 0) )) - ;; (drop (i64.eq - ;; (i64.rem_s - ;; (local.get $y) - ;; (i64.const 2) - ;; ) - ;; (i64.const 0) - ;; )) + (drop (i64.eq + (i64.rem_s + (local.get $y) + (i64.const 2) + ) + (i64.const 0) + )) ;; ;; (signed)x % 2 != 0 - ;; (drop (i32.ne - ;; (i32.rem_s - ;; (local.get $x) - ;; (i32.const 2) - ;; ) - ;; (i32.const 0) - ;; )) - ;; (drop (i64.ne - ;; (i64.rem_s - ;; (local.get $y) - ;; (i64.const 2) - ;; ) - ;; (i64.const 0) - ;; )) + (drop (i32.ne + (i32.rem_s + (local.get $x) + (i32.const 2) + ) + (i32.const 0) + )) + (drop (i64.ne + (i64.rem_s + (local.get $y) + (i64.const 2) + ) + (i64.const 0) + )) ;; ;; - ;; (drop (i32.eq - ;; (i32.rem_s - ;; (local.get $x) - ;; (i32.const 3) ;; skip - ;; ) - ;; (i32.const 0) - ;; )) - ;; (drop (i64.eq - ;; (i64.rem_s - ;; (local.get $y) - ;; (i64.const 3) ;; skip - ;; ) - ;; (i64.const 0) - ;; )) + (drop (i32.eq + (i32.rem_s + (local.get $x) + (i32.const 3) ;; skip + ) + (i32.const 0) + )) + (drop (i64.eq + (i64.rem_s + (local.get $y) + (i64.const 3) ;; skip + ) + (i64.const 0) + )) ) (func $orZero (param $0 i32) (result i32) (i32.or From 8654640599b4eae92798883b138d8eceb9e9c0c0 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 21 Sep 2020 16:42:08 +0300 Subject: [PATCH 03/22] more test --- test/passes/optimize-instructions_all-features.txt | 8 ++++++++ test/passes/optimize-instructions_all-features.wast | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 0b2c20388bb..f2010bfcafd 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -2803,6 +2803,14 @@ ) ) ) + (drop + (i32.eqz + (i32.rem_s + (local.get $x) + (i32.const -4) + ) + ) + ) (drop (i64.eqz (i64.rem_s diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index 0cd75f7374d..99379403f99 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -3156,6 +3156,13 @@ ) (i32.const 0) )) + (drop (i32.eq + (i32.rem_s + (local.get $x) + (i32.const -4) ;; skip + ) + (i32.const 0) + )) (drop (i64.eq (i64.rem_s (local.get $y) From 25c5658c22f6f1b21684cf996dfbd3625ab4647f Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 12:16:37 +0300 Subject: [PATCH 04/22] remove expr == 0 matching --- src/passes/OptimizeInstructions.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 2f301a5c387..0423e493578 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1277,13 +1277,8 @@ struct OptimizeInstructions matches(curr, binary(Abstract::And, pure(&left), ival(0)))) { return right; } - // (signed)x % C_pot == 0 ==> x & (C_pot - 1) == 0 // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 if (matches(curr, - binary(Abstract::Eq, - binary(&inner, Abstract::RemS, any(&left), constant(&c)), - ival(0))) || - matches(curr, binary(Abstract::Ne, binary(&inner, Abstract::RemS, any(&left), constant(&c)), ival(0)))) { From 5601d17055ca88f2138aba3d4de26a7a7ebfce75 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 12:25:52 +0300 Subject: [PATCH 05/22] refactor --- src/passes/OptimizeInstructions.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 0423e493578..fbdc06174da 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -574,14 +574,13 @@ struct OptimizeInstructions using namespace Match; Const* c; Binary* inner; - Expression* left; // eqz((signed)x % C_pot) ==> eqz(x & (C_pot - 1)) if (matches(unary->value, Match::binary( - &inner, Abstract::RemS, any(&left), constant(&c)))) { + &inner, Abstract::RemS, any(), constant(&c)))) { if (IsPowerOf2((uint64_t)c->value.getInteger())) { - inner->op = Abstract::getBinary(left->type, Abstract::And); - c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); + inner->op = Abstract::getBinary(c->type, Abstract::And); + c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); return unary; } } From 0adb236ba15774c3731e5119835bf789ee310c4e Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 12:38:15 +0300 Subject: [PATCH 06/22] remove redundancy and refactoring --- src/passes/OptimizeInstructions.cpp | 36 +++++++++++------------------ 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index fbdc06174da..4d039223168 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -242,13 +242,6 @@ struct OptimizeInstructions // block scope can be removed. using namespace Match; Builder builder(*getModule()); - { - // X == 0 => eqz X - Expression* x; - if (matches(curr, binary(EqInt32, any(&x), i32(0)))) { - return Builder(*getModule()).makeUnary(EqZInt32, x); - } - } { // try to get rid of (0 - ..), that is, a zero only used to negate an // int. an add of a subtract can be flipped in order to remove it: @@ -575,9 +568,9 @@ struct OptimizeInstructions Const* c; Binary* inner; // eqz((signed)x % C_pot) ==> eqz(x & (C_pot - 1)) - if (matches(unary->value, - Match::binary( - &inner, Abstract::RemS, any(), constant(&c)))) { + if (matches( + unary->value, + Match::binary(&inner, Abstract::RemS, any(), constant(&c)))) { if (IsPowerOf2((uint64_t)c->value.getInteger())) { inner->op = Abstract::getBinary(c->type, Abstract::And); c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); @@ -1276,6 +1269,17 @@ struct OptimizeInstructions matches(curr, binary(Abstract::And, pure(&left), ival(0)))) { return right; } + // x == 0 ==> eqz x + if (matches(curr, binary(Abstract::Eq, any(&left), ival(0)))) { + return builder.makeUnary(Abstract::getUnary(left->type, Abstract::EqZ), + left); + } + // Operations on one + // (signed)x % 1 ==> 0 + if (matches(curr, binary(Abstract::RemS, pure(&left), ival(1)))) { + right->value = Literal::makeSingleZero(type); + return right; + } // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 if (matches(curr, binary(Abstract::Ne, @@ -1286,18 +1290,6 @@ struct OptimizeInstructions c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); } } - - // x == 0 ==> eqz x - if (matches(curr, binary(Abstract::Eq, any(&left), ival(0)))) { - return builder.makeUnary(EqZInt64, left); - } - - // Operations on one - // (signed)x % 1 ==> 0 - if (matches(curr, binary(Abstract::RemS, pure(&left), ival(1)))) { - right->value = Literal::makeSingleZero(type); - return right; - } // bool(x) | 1 ==> 1 if (matches(curr, binary(Abstract::Or, pure(&left), ival(1))) && Bits::getMaxBits(left, this) == 1) { From dd6099acd3d0b69c47f5de82ae66b54dd1b3705f Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 29 Sep 2020 17:21:05 +0300 Subject: [PATCH 07/22] update fixtures --- test/passes/optimize-instructions_all-features.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 7ded902eb02..de11f457816 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -2,8 +2,8 @@ (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) - (type $none_=>_none (func)) (type $i32_i64_=>_none (func (param i32 i64))) + (type $none_=>_none (func)) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_=>_none (func (param i32))) (type $none_=>_i64 (func (result i64))) From d2cee70a1ae1986461ea1ed32f41511fcc2d84b4 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 00:56:58 +0300 Subject: [PATCH 08/22] move eqz rule on top --- src/passes/OptimizeInstructions.cpp | 32 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 5b03bd4e69a..0e2b4741a5a 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -294,6 +294,23 @@ struct OptimizeInstructions return sub; } } + { + // eqz((signed)x % C_pot) => eqz(x & (C_pot - 1)) + Const* c; + Unary* eqz; + Binary* inner; + if (matches( + curr, + unary(&eqz, + Abstract::EqZ, + binary(&inner, Abstract::RemS, any(), constant(&c))))) { + if (IsPowerOf2((uint64_t)c->value.getInteger())) { + inner->op = Abstract::getBinary(c->type, Abstract::And); + c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); + return eqz; + } + } + } { // try de-morgan's AND law, // (eqz X) and (eqz Y) === eqz (X or Y) @@ -575,21 +592,6 @@ struct OptimizeInstructions return ret; } } else if (auto* unary = curr->dynCast()) { - if (unary->op == EqZInt32 || unary->op == EqZInt64) { - using namespace Match; - Const* c; - Binary* inner; - // eqz((signed)x % C_pot) ==> eqz(x & (C_pot - 1)) - if (matches( - unary->value, - Match::binary(&inner, Abstract::RemS, any(), constant(&c)))) { - if (IsPowerOf2((uint64_t)c->value.getInteger())) { - inner->op = Abstract::getBinary(c->type, Abstract::And); - c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); - return unary; - } - } - } if (unary->op == EqZInt32) { if (auto* inner = unary->value->dynCast()) { // Try to invert a relational operation using De Morgan's law From 99fe2a67053af950dc8e57a7423c931108023dd2 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 01:17:49 +0300 Subject: [PATCH 09/22] trigger ci --- src/passes/OptimizeInstructions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 0e2b4741a5a..385cbfd894f 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -295,7 +295,7 @@ struct OptimizeInstructions } } { - // eqz((signed)x % C_pot) => eqz(x & (C_pot - 1)) + // eqz((signed)x % C_pot) => eqz(x & (C_pot - 1)) Const* c; Unary* eqz; Binary* inner; From 99df9be9de150380b4e4ad75f59f39efd0e87f95 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 01:21:52 +0300 Subject: [PATCH 10/22] update fixtures after sync with master --- test/passes/optimize-instructions_all-features.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 268b5f6faba..860783f36eb 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -2787,12 +2787,11 @@ ) ) (drop - (i64.ne + (i32.wrap_i64 (i64.and (local.get $y) (i64.const 1) ) - (i64.const 0) ) ) (drop From a881c38c152baaa4e884b187367ba6da4fd44172 Mon Sep 17 00:00:00 2001 From: Max Graey Date: Wed, 30 Sep 2020 01:37:11 +0300 Subject: [PATCH 11/22] Update src/passes/OptimizeInstructions.cpp Co-authored-by: Thomas Lively <7121787+tlively@users.noreply.github.com> --- src/passes/OptimizeInstructions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 8442aab1690..66e584c3270 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1285,7 +1285,7 @@ struct OptimizeInstructions } // x == 0 ==> eqz x if (matches(curr, binary(Abstract::Eq, any(&left), ival(0)))) { - return builder.makeUnary(Abstract::getUnary(left->type, Abstract::EqZ), + return builder.makeUnary(Abstract::getUnary(type, Abstract::EqZ), left); } // Operations on one From 2e41728ae40bbf7ee1b14722d0f622139aea7766 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 01:39:53 +0300 Subject: [PATCH 12/22] refactor --- src/passes/OptimizeInstructions.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 66e584c3270..df5f2412448 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -303,12 +303,11 @@ struct OptimizeInstructions curr, unary(&eqz, Abstract::EqZ, - binary(&inner, Abstract::RemS, any(), constant(&c))))) { - if (IsPowerOf2((uint64_t)c->value.getInteger())) { - inner->op = Abstract::getBinary(c->type, Abstract::And); - c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); - return eqz; - } + binary(&inner, Abstract::RemS, any(), constant(&c)))) && + IsPowerOf2((uint64_t)c->value.getInteger())) { + inner->op = Abstract::getBinary(c->type, Abstract::And); + c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); + return eqz; } } { @@ -1285,8 +1284,7 @@ struct OptimizeInstructions } // x == 0 ==> eqz x if (matches(curr, binary(Abstract::Eq, any(&left), ival(0)))) { - return builder.makeUnary(Abstract::getUnary(type, Abstract::EqZ), - left); + return builder.makeUnary(Abstract::getUnary(type, Abstract::EqZ), left); } // Operations on one // (signed)x % 1 ==> 0 From 998ee263de7f0f67ad67787fa0657ea46f27671c Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 01:42:08 +0300 Subject: [PATCH 13/22] more --- src/passes/OptimizeInstructions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index df5f2412448..30633ff54f8 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1264,8 +1264,6 @@ struct OptimizeInstructions Expression* optimizeWithConstantOnRight(Binary* curr) { using namespace Match; Builder builder(*getModule()); - Const* c; - Binary* inner; Expression* left; auto* right = curr->right->cast(); auto type = curr->right->type; @@ -1292,6 +1290,8 @@ struct OptimizeInstructions right->value = Literal::makeSingleZero(type); return right; } + Const* c; + Binary* inner; // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 if (matches(curr, binary(Abstract::Ne, From cc4bc4e741740965de779ebbf15ef98538485343 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 01:43:54 +0300 Subject: [PATCH 14/22] more (scope) --- src/passes/OptimizeInstructions.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 30633ff54f8..931c793b446 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1290,16 +1290,19 @@ struct OptimizeInstructions right->value = Literal::makeSingleZero(type); return right; } - Const* c; - Binary* inner; - // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 - if (matches(curr, - binary(Abstract::Ne, - binary(&inner, Abstract::RemS, any(&left), constant(&c)), - ival(0)))) { - if (IsPowerOf2((uint64_t)c->value.getInteger())) { - inner->op = Abstract::getBinary(left->type, Abstract::And); - c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); + { + Const* c; + Binary* inner; + // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 + if (matches( + curr, + binary(Abstract::Ne, + binary(&inner, Abstract::RemS, any(&left), constant(&c)), + ival(0)))) { + if (IsPowerOf2((uint64_t)c->value.getInteger())) { + inner->op = Abstract::getBinary(left->type, Abstract::And); + c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); + } } } // bool(x) | 1 ==> 1 From f583965bb57a26fad173126338c358bd321f1668 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 02:00:09 +0300 Subject: [PATCH 15/22] refactor according review --- src/passes/OptimizeInstructions.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 931c793b446..9512c94bf83 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1290,18 +1290,18 @@ struct OptimizeInstructions right->value = Literal::makeSingleZero(type); return right; } + // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 { - Const* c; Binary* inner; - // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 - if (matches( - curr, - binary(Abstract::Ne, - binary(&inner, Abstract::RemS, any(&left), constant(&c)), - ival(0)))) { - if (IsPowerOf2((uint64_t)c->value.getInteger())) { + if (matches(curr, + binary(Abstract::Ne, + binary(&inner, Abstract::RemS, any(&left), ival()), + ival(0)))) { + if (IsPowerOf2((uint64_t)right->value.getInteger())) { inner->op = Abstract::getBinary(left->type, Abstract::And); - c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); + right->value = + right->value.sub(Literal::makeFromInt32(1, left->type)); + return curr; } } } From 4a011713b08ebf03883ab0135efaf59531bb1e14 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 02:01:08 +0300 Subject: [PATCH 16/22] space --- src/passes/OptimizeInstructions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 9512c94bf83..d564dc53d3b 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1290,7 +1290,7 @@ struct OptimizeInstructions right->value = Literal::makeSingleZero(type); return right; } - // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 + // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 { Binary* inner; if (matches(curr, From 6bb1aa59ef1c989e4a05b45fb1f4d1b56c920309 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 02:11:46 +0300 Subject: [PATCH 17/22] revert changes --- src/passes/OptimizeInstructions.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index d564dc53d3b..d035df11f15 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1290,17 +1290,18 @@ struct OptimizeInstructions right->value = Literal::makeSingleZero(type); return right; } - // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 + // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0 { + Const* c; Binary* inner; - if (matches(curr, - binary(Abstract::Ne, - binary(&inner, Abstract::RemS, any(&left), ival()), - ival(0)))) { - if (IsPowerOf2((uint64_t)right->value.getInteger())) { + if (matches( + curr, + binary(Abstract::Ne, + binary(&inner, Abstract::RemS, any(&left), constant(&c)), + ival(0)))) { + if (IsPowerOf2((uint64_t)c->value.getInteger())) { inner->op = Abstract::getBinary(left->type, Abstract::And); - right->value = - right->value.sub(Literal::makeFromInt32(1, left->type)); + c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); return curr; } } From 1ca1bc636678c851c4a6571245a8e9fb2057bab7 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 02:57:12 +0300 Subject: [PATCH 18/22] refactor --- src/passes/OptimizeInstructions.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index d035df11f15..b216f59eb97 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1294,11 +1294,10 @@ struct OptimizeInstructions { Const* c; Binary* inner; - if (matches( - curr, - binary(Abstract::Ne, - binary(&inner, Abstract::RemS, any(&left), constant(&c)), - ival(0)))) { + if (matches(curr, + binary(Abstract::Ne, + binary(&inner, Abstract::RemS, any(&left), ival(&c)), + ival(0)))) { if (IsPowerOf2((uint64_t)c->value.getInteger())) { inner->op = Abstract::getBinary(left->type, Abstract::And); c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); From e8cc01b7ef44f8d286737d681dbc81dc5431a5fb Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 03:01:21 +0300 Subject: [PATCH 19/22] same for eqz rule --- src/passes/OptimizeInstructions.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index b216f59eb97..387e569e088 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -299,11 +299,10 @@ struct OptimizeInstructions Const* c; Unary* eqz; Binary* inner; - if (matches( - curr, - unary(&eqz, - Abstract::EqZ, - binary(&inner, Abstract::RemS, any(), constant(&c)))) && + if (matches(curr, + unary(&eqz, + Abstract::EqZ, + binary(&inner, Abstract::RemS, any(), ival(&c)))) && IsPowerOf2((uint64_t)c->value.getInteger())) { inner->op = Abstract::getBinary(c->type, Abstract::And); c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); From c9fc299581564c344d211d6bbcd70501a524c430 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 03:21:56 +0300 Subject: [PATCH 20/22] more --- src/passes/OptimizeInstructions.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 387e569e088..c59232f23df 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1296,12 +1296,11 @@ struct OptimizeInstructions if (matches(curr, binary(Abstract::Ne, binary(&inner, Abstract::RemS, any(&left), ival(&c)), - ival(0)))) { - if (IsPowerOf2((uint64_t)c->value.getInteger())) { - inner->op = Abstract::getBinary(left->type, Abstract::And); - c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); - return curr; - } + ival(0))) && + IsPowerOf2((uint64_t)c->value.getInteger())) { + inner->op = Abstract::getBinary(left->type, Abstract::And); + c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); + return curr; } } // bool(x) | 1 ==> 1 From 002906a7f391b2eddb584dfde0b910c993475ecc Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 04:05:48 +0300 Subject: [PATCH 21/22] use c->type instead left->type which simplify expr != 0 rule --- src/passes/OptimizeInstructions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index c59232f23df..98f984b2712 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1295,11 +1295,11 @@ struct OptimizeInstructions Binary* inner; if (matches(curr, binary(Abstract::Ne, - binary(&inner, Abstract::RemS, any(&left), ival(&c)), + binary(&inner, Abstract::RemS, any(), ival(&c)), ival(0))) && IsPowerOf2((uint64_t)c->value.getInteger())) { - inner->op = Abstract::getBinary(left->type, Abstract::And); - c->value = c->value.sub(Literal::makeFromInt32(1, left->type)); + inner->op = Abstract::getBinary(c->type, Abstract::And); + c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); return curr; } } From 4bd7810dfd53edddaf7ee3dfb053a1ceec632975 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 30 Sep 2020 04:09:35 +0300 Subject: [PATCH 22/22] simplify eqz rule as well --- src/passes/OptimizeInstructions.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 98f984b2712..1f65ae60928 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -297,16 +297,14 @@ struct OptimizeInstructions { // eqz((signed)x % C_pot) => eqz(x & (C_pot - 1)) Const* c; - Unary* eqz; Binary* inner; if (matches(curr, - unary(&eqz, - Abstract::EqZ, + unary(Abstract::EqZ, binary(&inner, Abstract::RemS, any(), ival(&c)))) && IsPowerOf2((uint64_t)c->value.getInteger())) { inner->op = Abstract::getBinary(c->type, Abstract::And); c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); - return eqz; + return curr; } } {