diff options
author | Alon Zakai <azakai@google.com> | 2021-04-22 15:21:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-22 15:21:43 -0700 |
commit | fa28a70db380c893b2c2bd236a422dc9ae1a383c (patch) | |
tree | 77f5779e6343ad41c4be8b33cd7b4066cad5b979 | |
parent | 23a26c75c6d737d6f97ed1048639b41e948fdd58 (diff) | |
download | binaryen-fa28a70db380c893b2c2bd236a422dc9ae1a383c.tar.gz binaryen-fa28a70db380c893b2c2bd236a422dc9ae1a383c.tar.bz2 binaryen-fa28a70db380c893b2c2bd236a422dc9ae1a383c.zip |
OptimizeInstructions: Handle EqZInt64 on an if/select arm, not just 32 (#3837)
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 14 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions.wast | 44 |
2 files changed, 55 insertions, 3 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 23a63646e..c5ffd34b3 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2786,6 +2786,7 @@ private: // Optimize an if-else or a select, something with a condition and two // arms with outputs. template<typename T> void optimizeTernary(T* curr) { + using namespace Abstract; using namespace Match; Builder builder(*getModule()); @@ -2814,27 +2815,34 @@ private: Expression* x; Const* c; auto check = [&](Expression* a, Expression* b) { - if (matches(a, unary(&un, EqZInt32, any(&x))) && matches(b, ival(&c))) { - auto value = c->value.geti32(); + if (matches(a, unary(&un, EqZ, any(&x))) && matches(b, ival(&c))) { + auto value = c->value.getInteger(); return value == 0 || value == 1; } return false; }; if (check(curr->ifTrue, curr->ifFalse) || check(curr->ifFalse, curr->ifTrue)) { + // The new type of curr will be that of the value of the unary, as after + // we move the unary out, its value is curr's direct child. + auto newType = un->value->type; auto updateArm = [&](Expression* arm) -> Expression* { if (arm == un) { // This is the arm that had the eqz, which we need to remove. return un->value; } else { // This is the arm with the constant, which we need to flip. - c->value = Literal(int32_t(1 - c->value.geti32())); + // Note that we also need to set the type to match the other arm. + c->value = + Literal::makeFromInt32(1 - c->value.getInteger(), newType); + c->type = newType; return c; } }; curr->ifTrue = updateArm(curr->ifTrue); curr->ifFalse = updateArm(curr->ifFalse); un->value = curr; + curr->finalize(newType); return replaceCurrent(un); } } diff --git a/test/lit/passes/optimize-instructions.wast b/test/lit/passes/optimize-instructions.wast index fd2637373..058c030dd 100644 --- a/test/lit/passes/optimize-instructions.wast +++ b/test/lit/passes/optimize-instructions.wast @@ -11792,6 +11792,50 @@ ) ) ) + ;; CHECK: (func $ternary-i64-0 (param $x i32) (param $y i64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i64.eqz + ;; CHECK-NEXT: (if (result i64) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i64.const 1) + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ternary-i64-0 (param $x i32) (param $y i64) + (drop + (if (result i32) + (local.get $x) + (i32.const 0) + (i64.eqz + (local.get $y) + ) + ) + ) + ) + ;; CHECK: (func $ternary-i64-1 (param $x i32) (param $y i64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i64.eqz + ;; CHECK-NEXT: (if (result i64) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ternary-i64-1 (param $x i32) (param $y i64) + (drop + (if (result i32) + (local.get $x) + (i64.eqz + (local.get $y) + ) + (i32.const 1) + ) + ) + ) ;; CHECK: (func $ternary-no (param $x i32) (param $y i32) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (select |