From 4c6978e43c5346f07e5cf9457ddab73c9f962240 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Sep 2023 16:03:36 -0700 Subject: [PATCH 1/3] work --- src/passes/OptimizeInstructions.cpp | 18 +++ .../optimize-instructions-multivalue.wast | 103 +++++++++++++++--- 2 files changed, 104 insertions(+), 17 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 0b787105e07..713c25bc681 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2266,6 +2266,24 @@ struct OptimizeInstructions } } + void visitTupleExtract(TupleExtract* curr) { + if (curr->type == Type::unreachable) { + return; + } + + if (auto* make = curr->tuple->dynCast()) { + Builder builder(*getModule()); + + // Store the value of the lane we want in a tee, and return that after a + // drop of the tuple (which might have side effects). + auto valueType = make->type[curr->index]; + Index tempLocal = builder.addVar(getFunction(), valueType); + make->operands[curr->index] = builder.makeLocalTee(tempLocal, make->operands[curr->index], valueType); + auto* get = builder.makeLocalGet(tempLocal, valueType); + replaceCurrent(getDroppedChildrenAndAppend(make, get)); + } + } + Index getMaxBitsForLocal(LocalGet* get) { // check what we know about the local return localInfo[get->index].maxBits; diff --git a/test/lit/passes/optimize-instructions-multivalue.wast b/test/lit/passes/optimize-instructions-multivalue.wast index 310505360bc..d73076a9825 100644 --- a/test/lit/passes/optimize-instructions-multivalue.wast +++ b/test/lit/passes/optimize-instructions-multivalue.wast @@ -3,17 +3,25 @@ (module ;; CHECK: (func $if-identical-arms-tuple (param $x i32) (result i32) - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (if (result i32 i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.tee $1 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.tee $2 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -36,18 +44,24 @@ ) ) ;; CHECK: (func $select-identical-arms-tuple (param $x i32) (result i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (local $2 i32) ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.tee $1 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.tee $2 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) @@ -71,4 +85,59 @@ (local.get $x) ) ) + + ;; CHECK: (func $extract-make (param $x i32) (param $y i32) (result i32) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.tee $2 + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + (func $extract-make (param $x i32) (param $y i32) (result i32) + ;; An extraction from a make can be simplified to just get the right lane. + (tuple.extract 0 + (tuple.make + (local.get $x) + (local.get $y) + ) + ) + ) + + ;; CHECK: (func $extract-make-2 (param $x i32) (param $y i32) (result i32) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.tee $2 + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + (func $extract-make-2 (param $x i32) (param $y i32) (result i32) + ;; As above, but the second lane. + (tuple.extract 1 + (tuple.make + (local.get $x) + (local.get $y) + ) + ) + ) + + ;; CHECK: (func $extract-make-unreachable (param $x i32) (param $y i32) (result i32) + ;; CHECK-NEXT: (tuple.extract 0 + ;; CHECK-NEXT: (tuple.make + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $extract-make-unreachable (param $x i32) (param $y i32) (result i32) + (tuple.extract 0 + (tuple.make + (unreachable) ;; because of this we should do nothing + (local.get $y) + ) + ) + ) ) From 9dced0098cc023ef2c9d905a6ef6720163024a64 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Sep 2023 16:14:12 -0700 Subject: [PATCH 2/3] work --- .../optimize-instructions-multivalue.wast | 72 ++++++------------- 1 file changed, 21 insertions(+), 51 deletions(-) diff --git a/test/lit/passes/optimize-instructions-multivalue.wast b/test/lit/passes/optimize-instructions-multivalue.wast index d73076a9825..0e79384175c 100644 --- a/test/lit/passes/optimize-instructions-multivalue.wast +++ b/test/lit/passes/optimize-instructions-multivalue.wast @@ -3,84 +3,54 @@ (module ;; CHECK: (func $if-identical-arms-tuple (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: (local $tuple (i32 i32)) + ;; CHECK-NEXT: (local $tuple2 (i32 i32)) + ;; CHECK-NEXT: (tuple.extract 0 + ;; CHECK-NEXT: (if (result i32 i32) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.get $tuple) + ;; CHECK-NEXT: (local.get $tuple2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $if-identical-arms-tuple (param $x i32) (result i32) + (local $tuple (i32 i32)) + (local $tuple2 (i32 i32)) (if (result i32) (local.get $x) ;; The tuple.extract can be hoisted out. (tuple.extract 0 - (tuple.make - (i32.const 0) - (i32.const 1) - ) + (local.get $tuple) ) (tuple.extract 0 - (tuple.make - (i32.const 2) - (i32.const 3) - ) + (local.get $tuple2) ) ) ) ;; CHECK: (func $select-identical-arms-tuple (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (local $tuple (i32 i32)) + ;; CHECK-NEXT: (local $tuple2 (i32 i32)) ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: (tuple.extract 0 + ;; CHECK-NEXT: (local.get $tuple) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: (tuple.extract 0 + ;; CHECK-NEXT: (local.get $tuple2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $select-identical-arms-tuple (param $x i32) (result i32) + (local $tuple (i32 i32)) + (local $tuple2 (i32 i32)) (select ;; The tuple.extract cannot be hoisted out, as the spec disallows a ;; select with multiple values in its arms. (tuple.extract 0 - (tuple.make - (i32.const 0) - (i32.const 1) - ) + (local.get $tuple) ) (tuple.extract 0 - (tuple.make - (i32.const 2) - (i32.const 3) - ) + (local.get $tuple2) ) (local.get $x) ) From 598aaa9a4f782a6707c1ed9c8272415d7df31cf1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Sep 2023 16:15:12 -0700 Subject: [PATCH 3/3] done --- 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 713c25bc681..feaee4d44ee 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2278,7 +2278,8 @@ struct OptimizeInstructions // drop of the tuple (which might have side effects). auto valueType = make->type[curr->index]; Index tempLocal = builder.addVar(getFunction(), valueType); - make->operands[curr->index] = builder.makeLocalTee(tempLocal, make->operands[curr->index], valueType); + make->operands[curr->index] = + builder.makeLocalTee(tempLocal, make->operands[curr->index], valueType); auto* get = builder.makeLocalGet(tempLocal, valueType); replaceCurrent(getDroppedChildrenAndAppend(make, get)); }