From 292d23d51b3f3b6393fc156d187700c8241b2d35 Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Thu, 10 Apr 2025 20:05:16 +0800 Subject: [PATCH 01/11] opt for #7455 --- src/passes/OptimizeInstructions.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 8c13663deba..8407748cece 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2922,6 +2922,19 @@ struct OptimizeInstructions return binary; } } + } else if (binary->op == LtUInt32) { + auto value = Properties::getFallthrough( + binary->right, getPassOptions(), *getModule()); + if (Properties::isConstantExpression(value)) { + if (Properties::getLiteral(value).isZero()) { + // Hoist potential zero to be good for constant propagation + // in case of being blocked by side effect. + // (unsigned)x < 0 ==> i32(0) + Builder builder(*getModule()); + return getDroppedChildrenAndAppend( + binary, LiteralUtils::makeZero(Type::i32, *getModule())); + } + } } if (auto* ext = Properties::getSignExtValue(binary)) { // use a cheaper zero-extent, we just care about the boolean value From 1723a46de0833d1683878d1caaaeb61ca8b178c0 Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Fri, 11 Apr 2025 10:16:51 +0800 Subject: [PATCH 02/11] generalize existing rule --- src/passes/OptimizeInstructions.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 8407748cece..74e660725ce 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2922,18 +2922,17 @@ struct OptimizeInstructions return binary; } } - } else if (binary->op == LtUInt32) { - auto value = Properties::getFallthrough( - binary->right, getPassOptions(), *getModule()); - if (Properties::isConstantExpression(value)) { - if (Properties::getLiteral(value).isZero()) { - // Hoist potential zero to be good for constant propagation - // in case of being blocked by side effect. - // (unsigned)x < 0 ==> i32(0) - Builder builder(*getModule()); - return getDroppedChildrenAndAppend( - binary, LiteralUtils::makeZero(Type::i32, *getModule())); - } + } + if (auto* block = binary->right->dynCast()) { + auto fallthrough = + Properties::getFallthrough(block, getPassOptions(), *getModule()); + if (auto* c = fallthrough->dynCast()) { + Builder builder(*getModule()); + auto ret = getDroppedChildrenAndAppend( + binary, + LiteralUtils::makeFromInt32( + c->value.geti32(), Type::i32, *getModule())); + return ret; } } if (auto* ext = Properties::getSignExtValue(binary)) { From 112e40d7af4537963c2e9b1829a7be794a78a320 Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Fri, 11 Apr 2025 10:35:08 +0800 Subject: [PATCH 03/11] tests --- .../lit/passes/optimize-instructions-mvp.wast | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/test/lit/passes/optimize-instructions-mvp.wast b/test/lit/passes/optimize-instructions-mvp.wast index 9f505a7586f..0ad0f7235bf 100644 --- a/test/lit/passes/optimize-instructions-mvp.wast +++ b/test/lit/passes/optimize-instructions-mvp.wast @@ -175,6 +175,63 @@ ) ) ) + + ;; CHECK: (func $if-lt_u-side-effect (param $i1 i32) (param $i2 i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.load + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (i32.store + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $if-lt_u-side-effect (param $i1 i32) (param $i2 i32) + (if + (i32.lt_u + (i32.load + (i32.const 0) + ) + (block (result i32) + (i32.store + (i32.const 0) + (i32.const 0) + ) + (i32.const 0) + ) + ) + (then + (drop + (i32.const 1) + ) + ) + (else + (drop + (i32.const 0) + ) + ) + ) + ) + ;; CHECK: (func $eqz-gt_s (result i32) ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.const 0) From 8910adb56172f604fb7d7fd1455444666895f942 Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Fri, 11 Apr 2025 14:58:01 +0800 Subject: [PATCH 04/11] NFC --- src/passes/OptimizeInstructions.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 74e660725ce..8bdb78a9819 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2928,11 +2928,10 @@ struct OptimizeInstructions Properties::getFallthrough(block, getPassOptions(), *getModule()); if (auto* c = fallthrough->dynCast()) { Builder builder(*getModule()); - auto ret = getDroppedChildrenAndAppend( + return getDroppedChildrenAndAppend( binary, LiteralUtils::makeFromInt32( c->value.geti32(), Type::i32, *getModule())); - return ret; } } if (auto* ext = Properties::getSignExtValue(binary)) { From 0e195737225047c47fb8fe04bddada13d5cc24bb Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Sat, 12 Apr 2025 20:13:33 +0800 Subject: [PATCH 05/11] Fix: use makeConst instead of makeFromInt32 --- 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 8bdb78a9819..33c787e2d60 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2928,10 +2928,8 @@ struct OptimizeInstructions Properties::getFallthrough(block, getPassOptions(), *getModule()); if (auto* c = fallthrough->dynCast()) { Builder builder(*getModule()); - return getDroppedChildrenAndAppend( - binary, - LiteralUtils::makeFromInt32( - c->value.geti32(), Type::i32, *getModule())); + return getDroppedChildrenAndAppend(binary, + builder.makeConst(c->value)); } } if (auto* ext = Properties::getSignExtValue(binary)) { From 5ba769edf51b4023b087980aa1c852913857afb2 Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Wed, 16 Apr 2025 16:10:05 +0800 Subject: [PATCH 06/11] Fix: apply getFallthrough at lt_u rule --- src/passes/OptimizeInstructions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 33c787e2d60..1e750a8e7c0 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -570,7 +570,8 @@ struct OptimizeInstructions return replaceCurrent(getDroppedChildrenAndAppend(curr, c)); } // unsigned(x) < 0 => i32(0) - if (matches(curr, binary(LtU, any(&x), ival(&c))) && + if (curr->op == Abstract::getBinary(curr->left->type, Abstract::LtU) && + (c = getFallthrough(curr->right)->dynCast()) && c->value.isZero()) { c->value = Literal::makeZero(Type::i32); c->type = Type::i32; From b2d953f79aaf41744a0e112c71f31208cebbce67 Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Wed, 16 Apr 2025 16:11:34 +0800 Subject: [PATCH 07/11] Remove original fix --- src/passes/OptimizeInstructions.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 1e750a8e7c0..92d42b24d22 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2924,15 +2924,6 @@ struct OptimizeInstructions } } } - if (auto* block = binary->right->dynCast()) { - auto fallthrough = - Properties::getFallthrough(block, getPassOptions(), *getModule()); - if (auto* c = fallthrough->dynCast()) { - Builder builder(*getModule()); - return getDroppedChildrenAndAppend(binary, - builder.makeConst(c->value)); - } - } if (auto* ext = Properties::getSignExtValue(binary)) { // use a cheaper zero-extent, we just care about the boolean value // anyhow From ffe6200d778fffe19ba7396a793c8e7b73de314b Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Wed, 16 Apr 2025 16:22:29 +0800 Subject: [PATCH 08/11] Update test --- .../lit/passes/optimize-instructions-mvp.wast | 89 +++++++------------ 1 file changed, 33 insertions(+), 56 deletions(-) diff --git a/test/lit/passes/optimize-instructions-mvp.wast b/test/lit/passes/optimize-instructions-mvp.wast index 0ad0f7235bf..9209c8710b2 100644 --- a/test/lit/passes/optimize-instructions-mvp.wast +++ b/test/lit/passes/optimize-instructions-mvp.wast @@ -176,62 +176,6 @@ ) ) - ;; CHECK: (func $if-lt_u-side-effect (param $i1 i32) (param $i2 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-lt_u-side-effect (param $i1 i32) (param $i2 i32) - (if - (i32.lt_u - (i32.load - (i32.const 0) - ) - (block (result i32) - (i32.store - (i32.const 0) - (i32.const 0) - ) - (i32.const 0) - ) - ) - (then - (drop - (i32.const 1) - ) - ) - (else - (drop - (i32.const 0) - ) - ) - ) - ) - ;; CHECK: (func $eqz-gt_s (result i32) ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.const 0) @@ -11588,6 +11532,25 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.load + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (i32.store + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.ne ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (i32.const 0) @@ -11860,6 +11823,20 @@ ) (i64.const 0) )) + (drop (i32.lt_u + (i32.load + (i32.const 0) + ) + (block (result i32) + (i32.store + (i32.const 0) + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + ;; (unsigned)x > 0 => x != 0 (drop (i32.gt_u From 45e6ef6c84d02afdc44b3382295880f35b699479 Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Wed, 16 Apr 2025 16:26:07 +0800 Subject: [PATCH 09/11] Add test for i64 --- .../lit/passes/optimize-instructions-mvp.wast | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/lit/passes/optimize-instructions-mvp.wast b/test/lit/passes/optimize-instructions-mvp.wast index 9209c8710b2..31cacf51abb 100644 --- a/test/lit/passes/optimize-instructions-mvp.wast +++ b/test/lit/passes/optimize-instructions-mvp.wast @@ -11551,6 +11551,25 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i64.load + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (i64.store + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.ne ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (i32.const 0) @@ -11836,6 +11855,19 @@ ) ) ) + (drop (i64.lt_u + (i64.load + (i32.const 0) + ) + (block (result i64) + (i64.store + (i32.const 0) + (i64.const 0) + ) + (i64.const 0) + ) + ) + ) ;; (unsigned)x > 0 => x != 0 From 9eb6ec58ac1c263a9b1ba0229efae14514d69bfc Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Sat, 19 Apr 2025 14:39:27 +0800 Subject: [PATCH 10/11] fix: reuse const c --- src/passes/OptimizeInstructions.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 92d42b24d22..585072e99c3 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -573,9 +573,10 @@ struct OptimizeInstructions if (curr->op == Abstract::getBinary(curr->left->type, Abstract::LtU) && (c = getFallthrough(curr->right)->dynCast()) && c->value.isZero()) { - c->value = Literal::makeZero(Type::i32); - c->type = Type::i32; - return replaceCurrent(getDroppedChildrenAndAppend(curr, c)); + // We could reuse c here, if we checked it had no more uses + auto zero = + Builder(*getModule()).makeConst(Literal::makeZero(Type::i32)); + return replaceCurrent(getDroppedChildrenAndAppend(curr, zero)); } } } From 1f06dbc0831324e9a74f33f1a74558117f40688e Mon Sep 17 00:00:00 2001 From: Ruiyang Xu Date: Sat, 19 Apr 2025 14:39:40 +0800 Subject: [PATCH 11/11] update test --- test/lit/passes/optimize-instructions-mvp.wast | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/lit/passes/optimize-instructions-mvp.wast b/test/lit/passes/optimize-instructions-mvp.wast index 31cacf51abb..4c184a852c3 100644 --- a/test/lit/passes/optimize-instructions-mvp.wast +++ b/test/lit/passes/optimize-instructions-mvp.wast @@ -11558,12 +11558,12 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (block (result i64) ;; CHECK-NEXT: (i64.store ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i64.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0)