summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/TupleOptimization.cpp9
-rw-r--r--test/lit/passes/tuple-optimization.wast42
2 files changed, 47 insertions, 4 deletions
diff --git a/src/passes/TupleOptimization.cpp b/src/passes/TupleOptimization.cpp
index 25da1c5ec..ca704f1a3 100644
--- a/src/passes/TupleOptimization.cpp
+++ b/src/passes/TupleOptimization.cpp
@@ -25,7 +25,7 @@
// (tuple.extract 3 0
// (local.get $tuple)))
//
-// If there are no other uses, then we just need one of the three lanes. By
+// If there are no other uses, then we just need one of the three elements. By
// lowing them to three separate locals, other passes can remove the other two.
//
// Specifically, this pass seeks out tuple locals that have these properties:
@@ -320,8 +320,13 @@ struct TupleOptimization : public WalkerPass<PostWalker<TupleOptimization>> {
// we were confused earlier and the target should not be.
assert(sourceBase);
+ // The source and target may have different element types due to
+ // subtyping (but their sizes must be equal).
+ auto sourceType = value->type;
+ assert(sourceType.size() == type.size());
+
for (Index i = 0; i < type.size(); i++) {
- auto* get = builder.makeLocalGet(sourceBase + i, type[i]);
+ auto* get = builder.makeLocalGet(sourceBase + i, sourceType[i]);
contents.push_back(builder.makeLocalSet(targetBase + i, get));
}
replace(builder.makeBlock(contents));
diff --git a/test/lit/passes/tuple-optimization.wast b/test/lit/passes/tuple-optimization.wast
index d092d479f..e0d68848e 100644
--- a/test/lit/passes/tuple-optimization.wast
+++ b/test/lit/passes/tuple-optimization.wast
@@ -15,7 +15,7 @@
;; CHECK-NEXT: )
(func $just-set
(local $tuple (tuple i32 i32))
- ;; This tuple local can be optimized into separate locals per lane. The
+ ;; This tuple local can be optimized into separate locals per element. The
;; tuple local itself then has no uses and other passes will remove it.
(local.set $tuple
(tuple.make 2
@@ -38,7 +38,7 @@
;; CHECK-NEXT: )
(func $just-get
(local $tuple (tuple i32 i32))
- ;; The default value of the tuple lanes is used here in the new locals we
+ ;; The default value of the tuple elements is used here in the new locals we
;; add.
(drop
(tuple.extract 2 0
@@ -1026,4 +1026,42 @@
)
)
)
+
+ ;; CHECK: (func $tuple.element.subtyping (type $0)
+ ;; CHECK-NEXT: (local $tuple_null (tuple i32 nullref))
+ ;; CHECK-NEXT: (local $tuple_eq (tuple i32 eqref))
+ ;; CHECK-NEXT: (local $2 i32)
+ ;; CHECK-NEXT: (local $3 nullref)
+ ;; CHECK-NEXT: (local $4 i32)
+ ;; CHECK-NEXT: (local $5 eqref)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (ref.null none)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $5
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $tuple.element.subtyping
+ (local $tuple_null (tuple i32 nullref))
+ (local $tuple_eq (tuple i32 eqref))
+ ;; The tee emits a nullref in the second element, which is written to an
+ ;; element of eqref. That is, the source and the target do not have
+ ;; identical type, which we need to properly handle and not error.
+ (local.set $tuple_eq
+ (local.tee $tuple_null
+ (tuple.make 2
+ (i32.const 0)
+ (ref.null none)
+ )
+ )
+ )
+ )
)