diff options
-rw-r--r-- | src/passes/StackIR.cpp | 10 | ||||
-rw-r--r-- | test/lit/passes/stack-ir-non-nullable.wast | 139 |
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 |