summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/StackIR.cpp10
-rw-r--r--test/lit/passes/stack-ir-non-nullable.wast139
2 files changed, 145 insertions, 4 deletions
diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp
index 4d5b867bd..c57bea83f 100644
--- a/src/passes/StackIR.cpp
+++ b/src/passes/StackIR.cpp
@@ -389,10 +389,14 @@ private:
assert(setIndex < getIndex);
auto* set = insts[setIndex]->origin->cast<LocalSet>();
- if (func->isParam(set->index) ||
- !func->getLocalType(set->index).isNonNullable()) {
+ auto localType = func->getLocalType(set->index);
+ // Note we do not need to handle tuples here, as the parent ignores them
+ // anyhow (hence we can check non-nullability instead of non-
+ // defaultability).
+ assert(localType.isSingle());
+ if (func->isParam(set->index) || !localType.isNonNullable()) {
// This local cannot pose a problem for validation (params are always
- // initialized, and nullable locals may be uninitialized).
+ // initialized, and it is ok if nullable locals are uninitialized).
return true;
}
diff --git a/test/lit/passes/stack-ir-non-nullable.wast b/test/lit/passes/stack-ir-non-nullable.wast
index ac34b5107..0dfc4d370 100644
--- a/test/lit/passes/stack-ir-non-nullable.wast
+++ b/test/lit/passes/stack-ir-non-nullable.wast
@@ -339,7 +339,144 @@
(local.get $temp)
)
- ;; CHECK: (func $if-non-ref (type $4) (param $param i32) (result i32)
+ ;; CHECK: (func $if-nondefaultable (type $1) (param $param (ref eq)) (result (ref eq))
+ ;; CHECK-NEXT: (local $temp (i32 (ref eq)))
+ ;; CHECK-NEXT: i32.const 0
+ ;; CHECK-NEXT: local.get $param
+ ;; CHECK-NEXT: tuple.make
+ ;; CHECK-NEXT: local.set $temp
+ ;; CHECK-NEXT: local.get $temp
+ ;; CHECK-NEXT: tuple.extract 1
+ ;; CHECK-NEXT: i32.const 1
+ ;; CHECK-NEXT: ref.i31
+ ;; CHECK-NEXT: ref.eq
+ ;; CHECK-NEXT: if
+ ;; CHECK-NEXT: i32.const 2
+ ;; CHECK-NEXT: i32.const 3
+ ;; CHECK-NEXT: ref.i31
+ ;; CHECK-NEXT: tuple.make
+ ;; CHECK-NEXT: local.set $temp
+ ;; CHECK-NEXT: else
+ ;; CHECK-NEXT: i32.const 4
+ ;; CHECK-NEXT: i32.const 5
+ ;; CHECK-NEXT: ref.i31
+ ;; CHECK-NEXT: tuple.make
+ ;; CHECK-NEXT: local.set $temp
+ ;; CHECK-NEXT: end
+ ;; CHECK-NEXT: local.get $temp
+ ;; CHECK-NEXT: tuple.extract 1
+ ;; CHECK-NEXT: )
+ (func $if-nondefaultable (param $param (ref eq)) (result (ref eq))
+ (local $temp (i32 (ref eq)))
+ ;; As the original testcase, but now $temp is a nondefaultable tuple rather
+ ;; than a non-nullable reference by itself. We cannot remove the first set
+ ;; here.
+ (local.set $temp
+ (tuple.make
+ (i32.const 0)
+ (local.get $param)
+ )
+ )
+ (if
+ (ref.eq
+ (tuple.extract 1
+ (local.get $temp)
+ )
+ (i31.new
+ (i32.const 1)
+ )
+ )
+ (local.set $temp
+ (tuple.make
+ (i32.const 2)
+ (i31.new
+ (i32.const 3)
+ )
+ )
+ )
+ (local.set $temp
+ (tuple.make
+ (i32.const 4)
+ (i31.new
+ (i32.const 5)
+ )
+ )
+ )
+ )
+ (tuple.extract 1
+ (local.get $temp)
+ )
+ )
+
+ ;; CHECK: (func $if-defaultable (type $4) (param $param eqref) (result eqref)
+ ;; CHECK-NEXT: (local $temp (i32 eqref))
+ ;; CHECK-NEXT: i32.const 0
+ ;; CHECK-NEXT: local.get $param
+ ;; CHECK-NEXT: tuple.make
+ ;; CHECK-NEXT: local.set $temp
+ ;; CHECK-NEXT: local.get $temp
+ ;; CHECK-NEXT: tuple.extract 1
+ ;; CHECK-NEXT: i32.const 1
+ ;; CHECK-NEXT: ref.i31
+ ;; CHECK-NEXT: ref.eq
+ ;; CHECK-NEXT: if
+ ;; CHECK-NEXT: i32.const 2
+ ;; CHECK-NEXT: i32.const 3
+ ;; CHECK-NEXT: ref.i31
+ ;; CHECK-NEXT: tuple.make
+ ;; CHECK-NEXT: local.set $temp
+ ;; CHECK-NEXT: else
+ ;; CHECK-NEXT: i32.const 4
+ ;; CHECK-NEXT: i32.const 5
+ ;; CHECK-NEXT: ref.i31
+ ;; CHECK-NEXT: tuple.make
+ ;; CHECK-NEXT: local.set $temp
+ ;; CHECK-NEXT: end
+ ;; CHECK-NEXT: local.get $temp
+ ;; CHECK-NEXT: tuple.extract 1
+ ;; CHECK-NEXT: )
+ (func $if-defaultable (param $param (ref null eq)) (result (ref null eq))
+ (local $temp (i32 (ref null eq)))
+ ;; As the last testcase, but now $temp is a defaultable tuple. We still do not
+ ;; optimize away the set here, as we ignore tuples in local2stack.
+ (local.set $temp
+ (tuple.make
+ (i32.const 0)
+ (local.get $param)
+ )
+ )
+ (if
+ (ref.eq
+ (tuple.extract 1
+ (local.get $temp)
+ )
+ (i31.new
+ (i32.const 1)
+ )
+ )
+ (local.set $temp
+ (tuple.make
+ (i32.const 2)
+ (i31.new
+ (i32.const 3)
+ )
+ )
+ )
+ (local.set $temp
+ (tuple.make
+ (i32.const 4)
+ (i31.new
+ (i32.const 5)
+ )
+ )
+ )
+ )
+ (tuple.extract 1
+ (local.get $temp)
+ )
+ )
+
+ ;; CHECK: (func $if-non-ref (type $5) (param $param i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: local.get $param
;; CHECK-NEXT: i32.eqz