diff options
-rw-r--r-- | src/ir/bits.h | 11 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 90 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions.wast | 496 | ||||
-rw-r--r-- | test/passes/optimize-instructions_fuzz-exec.txt | 5 |
4 files changed, 539 insertions, 63 deletions
diff --git a/src/ir/bits.h b/src/ir/bits.h index 96b36a846..25d80fba7 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -437,6 +437,17 @@ Index getMaxBits(Expression* curr, } } +// As getMaxBits, but returns the minimum amount of bits. +inline Index getMinBits(Expression* curr) { + if (auto* c = curr->dynCast<Const>()) { + // Constants are simple: the min and max are identical. + return getMaxBits(c); + } + + // TODO: everything else + return 0; +} + } // namespace wasm::Bits #endif // wasm_ir_bits_h diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 9024d0cb6..9b207d6e7 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1476,6 +1476,11 @@ struct OptimizeInstructions curr, *getModule(), getPassOptions(), result); } + Expression* getDroppedChildrenAndAppend(Expression* curr, Literal value) { + auto* result = Builder(*getModule()).makeConst(value); + return getDroppedChildrenAndAppend(curr, result); + } + void visitRefEq(RefEq* curr) { // The types may prove that the same reference cannot appear on both sides. auto leftType = curr->left->type; @@ -1494,9 +1499,8 @@ struct OptimizeInstructions // possibly appear on both sides is null, but one of the two is non- // nullable, which rules that out. So there is no way that the same // reference can appear on both sides. - auto* result = - Builder(*getModule()).makeConst(Literal::makeZero(Type::i32)); - replaceCurrent(getDroppedChildrenAndAppend(curr, result)); + replaceCurrent( + getDroppedChildrenAndAppend(curr, Literal::makeZero(Type::i32))); return; } @@ -1515,9 +1519,8 @@ struct OptimizeInstructions // cases yet; the foldable case we do handle is the common one of the first // child being a tee and the second a get of that tee. TODO) if (areConsecutiveInputsEqualAndFoldable(curr->left, curr->right)) { - auto* result = - Builder(*getModule()).makeConst(Literal::makeOne(Type::i32)); - replaceCurrent(getDroppedChildrenAndAppend(curr, result)); + replaceCurrent( + getDroppedChildrenAndAppend(curr, Literal::makeOne(Type::i32))); return; } @@ -3965,6 +3968,81 @@ private: return curr; } } + + // Comparisons can sometimes be simplified depending on the number of + // bits, e.g. (unsigned)x > y must be true if x has strictly more bits. + // A common case is a constant on the right, e.g. (x & 255) < 256 must be + // true. + // TODO: use getMinBits in more places, see ideas in + // https://github.com/WebAssembly/binaryen/issues/2898 + { + // Check if there is a nontrivial amount of bits on the left, which may + // provide enough to optimize. + auto leftMaxBits = Bits::getMaxBits(curr->left, this); + auto type = curr->left->type; + if (leftMaxBits < getBitsForType(type)) { + using namespace Abstract; + auto rightMinBits = Bits::getMinBits(curr->right); + auto rightIsNegative = rightMinBits == getBitsForType(type); + if (leftMaxBits < rightMinBits) { + // There are not enough bits on the left for it to be equal to the + // right, making various comparisons obviously false: + // x == y + // (unsigned)x > y + // (unsigned)x >= y + // and the same for signed, if y does not have the sign bit set + // (in that case, the comparison is effectively unsigned). + // + // TODO: In addition to leftMaxBits < rightMinBits, we could + // handle the reverse, and also special cases like all bits + // being 1 on the right, things like (x & 255) <= 255 -> 1 + if (curr->op == Abstract::getBinary(type, Eq) || + curr->op == Abstract::getBinary(type, GtU) || + curr->op == Abstract::getBinary(type, GeU) || + (!rightIsNegative && + (curr->op == Abstract::getBinary(type, GtS) || + curr->op == Abstract::getBinary(type, GeS)))) { + return getDroppedChildrenAndAppend(curr, + Literal::makeZero(Type::i32)); + } + + // And some are obviously true: + // x != y + // (unsigned)x < y + // (unsigned)x <= y + // and likewise for signed, as above. + if (curr->op == Abstract::getBinary(type, Ne) || + curr->op == Abstract::getBinary(type, LtU) || + curr->op == Abstract::getBinary(type, LeU) || + (!rightIsNegative && + (curr->op == Abstract::getBinary(type, LtS) || + curr->op == Abstract::getBinary(type, LeS)))) { + return getDroppedChildrenAndAppend(curr, + Literal::makeOne(Type::i32)); + } + + // For truly signed comparisons, where y's sign bit is set, we can + // also infer some things, since we know y is signed but x is not + // (since x does not have enough bits for the sign bit to be set). + if (rightIsNegative) { + // (signed, non-negative)x > (negative)y => 1 + // (signed, non-negative)x >= (negative)y => 1 + if (curr->op == Abstract::getBinary(type, GtS) || + curr->op == Abstract::getBinary(type, GeS)) { + return getDroppedChildrenAndAppend(curr, + Literal::makeOne(Type::i32)); + } + // (signed, non-negative)x < (negative)y => 0 + // (signed, non-negative)x <= (negative)y => 0 + if (curr->op == Abstract::getBinary(type, LtS) || + curr->op == Abstract::getBinary(type, LeS)) { + return getDroppedChildrenAndAppend( + curr, Literal::makeZero(Type::i32)); + } + } + } + } + } } return nullptr; } diff --git a/test/lit/passes/optimize-instructions.wast b/test/lit/passes/optimize-instructions.wast index c75040a9f..df8037a72 100644 --- a/test/lit/passes/optimize-instructions.wast +++ b/test/lit/passes/optimize-instructions.wast @@ -152,9 +152,8 @@ ) ) ;; CHECK: (func $eqz-gt_s (result i32) - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $eqz-gt_s (result i32) @@ -166,9 +165,8 @@ ) ) ;; CHECK: (func $eqz-ge_s (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $eqz-ge_s (result i32) @@ -180,9 +178,8 @@ ) ) ;; CHECK: (func $eqz-lt_s (result i32) - ;; CHECK-NEXT: (i32.ge_u + ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $eqz-lt_s (result i32) @@ -194,9 +191,8 @@ ) ) ;; CHECK: (func $eqz-le_s (result i32) - ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $eqz-le_s (result i32) @@ -208,9 +204,8 @@ ) ) ;; CHECK: (func $eqz-gt_u (result i32) - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $eqz-gt_u (result i32) @@ -222,9 +217,8 @@ ) ) ;; CHECK: (func $eqz-ge_u (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $eqz-ge_u (result i32) @@ -236,9 +230,8 @@ ) ) ;; CHECK: (func $eqz-lt_u (result i32) - ;; CHECK-NEXT: (i32.ge_u + ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $eqz-lt_u (result i32) @@ -250,9 +243,8 @@ ) ) ;; CHECK: (func $eqz-le_u (result i32) - ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $eqz-le_u (result i32) @@ -463,10 +455,7 @@ ) ) ;; CHECK: (func $eq-zero-lhs (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) (func $eq-zero-lhs (result i32) (i32.eq @@ -497,10 +486,7 @@ ) ) ;; CHECK: (func $eq-zero-lhs-i64 (result i32) - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 100) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) (func $eq-zero-lhs-i64 (result i32) (i64.eq @@ -1385,10 +1371,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 2000) - ;; CHECK-NEXT: (i32.const 3000) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $and-pos1 @@ -12702,13 +12685,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i64.shr_u @@ -12756,13 +12733,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -7) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unsigned-context (param $x i32) (param $y i64) @@ -15314,13 +15285,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $gt_u-added-constant (param $x i32) @@ -15650,4 +15615,429 @@ ) ) ) + + ;; CHECK: (func $too-few-bits (param $x i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $too-few-bits (param $x i32) + ;; Comparison of something with at most 8 bits to something with more than + ;; 8. These must all be false. + (drop + (i32.eq + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + (drop + (i32.gt_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + (drop + (i32.gt_u + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + (drop + (i32.ge_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + (drop + (i32.ge_u + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + ;; These are all true. + (drop + (i32.ne + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + (drop + (i32.lt_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + (drop + (i32.lt_u + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + (drop + (i32.le_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + (drop + (i32.le_u + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 256) + ) + ) + ) + + ;; CHECK: (func $too-few-bits-no (param $x i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.lt_u + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.lt_u + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.le_u + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.le_u + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.ge_u + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.ge_u + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $too-few-bits-no (param $x i32) + ;; Identical to the above, but the constant is changed from 256 to 255. We + ;; cannot optimize here: the number of bits is the same and we can't infer + ;; anything. + (drop + (i32.eq + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + (drop + (i32.ne + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + (drop + (i32.lt_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + (drop + (i32.lt_u + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + (drop + (i32.le_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + (drop + (i32.le_u + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + (drop + (i32.gt_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + (drop + (i32.gt_u + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + (drop + (i32.ge_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + (drop + (i32.ge_u + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 255) + ) + ) + ) + + ;; CHECK: (func $too-few-bits-signed (param $x i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const -2147483648) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $too-few-bits-signed (param $x i32) + ;; As above, but now using only signed operations and the constant on the + ;; right has the sign bit set. The left side is non-negative, which lets us + ;; infer the results here. + ;; These are all false: + (drop + (i32.lt_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 0x80000000) ;; -2147483648 + ) + ) + (drop + (i32.le_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 0x80000000) ;; -2147483648 + ) + ) + ;; These are all true: + (drop + (i32.gt_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 0x80000000) ;; -2147483648 + ) + ) + (drop + (i32.ge_s + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 0x80000000) ;; -2147483648 + ) + ) + ;; This cannot be inferred, as the left has too many possible bits (so it + ;; may have the sign bit set). + (drop + (i32.gt_s + (local.get $x) + (i32.const 0x80000000) ;; -2147483648 + ) + ) + ) + + ;; CHECK: (func $too-few-bits-i64 (param $x i64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i64.eq + ;; CHECK-NEXT: (i64.and + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i64.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i64.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $too-few-bits-i64 (param $x i64) + ;; As above, but with i64 values. We can infer 0 here. + (drop + (i64.eq + (i64.and + (local.get $x) + (i64.const 255) + ) + (i64.const 256) + ) + ) + ;; The constant is now 255 and we cannot optimize here. + (drop + (i64.eq + (i64.and + (local.get $x) + (i64.const 255) + ) + (i64.const 255) + ) + ) + ) ) diff --git a/test/passes/optimize-instructions_fuzz-exec.txt b/test/passes/optimize-instructions_fuzz-exec.txt index 5a8ae7e5f..16b17cf26 100644 --- a/test/passes/optimize-instructions_fuzz-exec.txt +++ b/test/passes/optimize-instructions_fuzz-exec.txt @@ -316,10 +316,7 @@ ) ) (call $log - (i32.eq - (i32.const 8) - (i32.const -2147483648) - ) + (i32.const 0) ) ) (func $shift (param $0 i32) |