Skip to content

Commit

Permalink
OptimizeInstructions: Simplify tuple.extract of tuple.make (#5938)
Browse files Browse the repository at this point in the history
E.g.

(tuple.extract 1
  (tuple.make (A) (B) (C))

=>

(B)

Modify some existing tests to not be in this trivial form, so that they do not
stop testing what they should.
  • Loading branch information
kripken authored Sep 14, 2023
1 parent 2cbe448 commit 183d4b0
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 32 deletions.
19 changes: 19 additions & 0 deletions src/passes/OptimizeInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2266,6 +2266,25 @@ struct OptimizeInstructions
}
}

void visitTupleExtract(TupleExtract* curr) {
if (curr->type == Type::unreachable) {
return;
}

if (auto* make = curr->tuple->dynCast<TupleMake>()) {
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;
Expand Down
103 changes: 71 additions & 32 deletions test/lit/passes/optimize-instructions-multivalue.wast
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,111 @@

(module
;; CHECK: (func $if-identical-arms-tuple (param $x i32) (result i32)
;; 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: (tuple.make
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: (i32.const 3)
;; CHECK-NEXT: )
;; 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 $tuple (i32 i32))
;; CHECK-NEXT: (local $tuple2 (i32 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: )
;; CHECK-NEXT: (local.get $tuple)
;; CHECK-NEXT: )
;; CHECK-NEXT: (tuple.extract 0
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: (i32.const 3)
;; CHECK-NEXT: )
;; 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)
)
)

;; 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)
)
)
)
)

0 comments on commit 183d4b0

Please sign in to comment.