summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Inlining.cpp9
-rw-r--r--test/lit/passes/inlining-gc.wast45
2 files changed, 53 insertions, 1 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index 78f9966e7..8601b3409 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -292,9 +292,16 @@ doInlining(Module* module, Function* into, const InliningAction& action) {
// Zero out the vars (as we may be in a loop, and may depend on their
// zero-init value
for (Index i = 0; i < from->vars.size(); i++) {
+ auto type = from->vars[i];
+ if (type.isRef() && !type.isNullable()) {
+ // Non-nullable locals do not need to be zeroed out. They have no zero
+ // value, and by definition should not be used before being written to, so
+ // any value we set here would not be observed anyhow.
+ continue;
+ }
block->list.push_back(
builder.makeLocalSet(updater.localMapping[from->getVarIndexBase() + i],
- LiteralUtils::makeZero(from->vars[i], *module)));
+ LiteralUtils::makeZero(type, *module)));
}
// Generate and update the inlined contents
auto* contents = ExpressionManipulator::copy(from->body, *module);
diff --git a/test/lit/passes/inlining-gc.wast b/test/lit/passes/inlining-gc.wast
new file mode 100644
index 000000000..11ac125b2
--- /dev/null
+++ b/test/lit/passes/inlining-gc.wast
@@ -0,0 +1,45 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --inlining --enable-gc-nn-locals -all -S -o - | filecheck %s
+
+(module
+ ;; CHECK: (func $caller-nullable
+ ;; CHECK-NEXT: (local $0 funcref)
+ ;; CHECK-NEXT: (block $__inlined_func$target-nullable
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (ref.null func)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller-nullable
+ ;; Call a function with a nullable local. After the inlining there will
+ ;; be a new local in this function for the use of the inlined code, and also
+ ;; we assign the null value to that local in the inlined block (which does
+ ;; not matter much here, but in general if we had a loop that the inlined
+ ;; block was inside of, that would be important to get the right behavior).
+ (call $target-nullable)
+ )
+
+ (func $target-nullable
+ (local $1 (ref null func))
+ )
+
+ ;; CHECK: (func $caller-non-nullable
+ ;; CHECK-NEXT: (local $0 (ref func))
+ ;; CHECK-NEXT: (block $__inlined_func$target-non-nullable
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller-non-nullable
+ ;; Call a function with a non-nullable local. After the inlining there will
+ ;; be a new local in this function for the use of the inlined code. We do not
+ ;; need to zero it out (such locals cannot be used before being set anyhow, so
+ ;; no zero is needed; and we cannot set a zero anyhow as none exists for the
+ ;; type).
+ (call $target-non-nullable)
+ )
+
+ (func $target-non-nullable
+ (local $1 (ref func))
+ )
+)