summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/module-utils.cpp3
-rw-r--r--test/lit/passes/no-inline-monomorphize-inlining.wast125
-rw-r--r--test/lit/passes/no-inline.wast117
3 files changed, 169 insertions, 76 deletions
diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp
index cd865a79c..afe4a4c54 100644
--- a/src/ir/module-utils.cpp
+++ b/src/ir/module-utils.cpp
@@ -36,6 +36,9 @@ Function* copyFunction(Function* func, Module& out, Name newName) {
ret->body = ExpressionManipulator::copy(func->body, out);
ret->module = func->module;
ret->base = func->base;
+ ret->noFullInline = func->noFullInline;
+ ret->noPartialInline = func->noPartialInline;
+
// TODO: copy Stack IR
assert(!func->stackIR);
return out.addFunction(std::move(ret));
diff --git a/test/lit/passes/no-inline-monomorphize-inlining.wast b/test/lit/passes/no-inline-monomorphize-inlining.wast
new file mode 100644
index 000000000..be3b5759d
--- /dev/null
+++ b/test/lit/passes/no-inline-monomorphize-inlining.wast
@@ -0,0 +1,125 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
+
+;; Monomorphization creates a new function, which we can then inline. When we
+;; mark the original as no-inline, we should not inline the copy, as the copy
+;; inherits the metadata.
+
+;; RUN: foreach %s %t wasm-opt --no-inline=*noinline* --monomorphize-always --inlining -all -S -o - | filecheck %s --check-prefix NO_INLINE
+;; RUN: foreach %s %t wasm-opt --monomorphize-always --inlining -all -S -o - | filecheck %s --check-prefix YESINLINE
+
+(module
+ ;; NO_INLINE: (type $A (sub (struct )))
+ ;; YESINLINE: (type $A (sub (struct )))
+ (type $A (sub (struct)))
+
+ ;; NO_INLINE: (type $B (sub $A (struct )))
+ ;; YESINLINE: (type $B (sub $A (struct )))
+ (type $B (sub $A (struct)))
+
+ ;; NO_INLINE: (type $2 (func))
+
+ ;; NO_INLINE: (type $3 (func (param (ref $A))))
+
+ ;; NO_INLINE: (type $4 (func (param (ref $B))))
+
+ ;; NO_INLINE: (func $calls (type $2)
+ ;; NO_INLINE-NEXT: (call $refinable_noinline
+ ;; NO_INLINE-NEXT: (struct.new_default $A)
+ ;; NO_INLINE-NEXT: )
+ ;; NO_INLINE-NEXT: (call $refinable_noinline
+ ;; NO_INLINE-NEXT: (struct.new_default $A)
+ ;; NO_INLINE-NEXT: )
+ ;; NO_INLINE-NEXT: (call $refinable_noinline_2
+ ;; NO_INLINE-NEXT: (struct.new_default $B)
+ ;; NO_INLINE-NEXT: )
+ ;; NO_INLINE-NEXT: (call $refinable_noinline_2
+ ;; NO_INLINE-NEXT: (struct.new_default $B)
+ ;; NO_INLINE-NEXT: )
+ ;; NO_INLINE-NEXT: )
+ ;; YESINLINE: (type $2 (func))
+
+ ;; YESINLINE: (func $calls (type $2)
+ ;; YESINLINE-NEXT: (local $0 (ref $A))
+ ;; YESINLINE-NEXT: (local $1 (ref $A))
+ ;; YESINLINE-NEXT: (local $2 (ref $B))
+ ;; YESINLINE-NEXT: (local $3 (ref $B))
+ ;; YESINLINE-NEXT: (block
+ ;; YESINLINE-NEXT: (block $__inlined_func$refinable_noinline
+ ;; YESINLINE-NEXT: (local.set $0
+ ;; YESINLINE-NEXT: (struct.new_default $A)
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: (drop
+ ;; YESINLINE-NEXT: (local.get $0)
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: (block
+ ;; YESINLINE-NEXT: (block $__inlined_func$refinable_noinline$1
+ ;; YESINLINE-NEXT: (local.set $1
+ ;; YESINLINE-NEXT: (struct.new_default $A)
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: (drop
+ ;; YESINLINE-NEXT: (local.get $1)
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: (block
+ ;; YESINLINE-NEXT: (block $__inlined_func$refinable_noinline_2$2
+ ;; YESINLINE-NEXT: (local.set $2
+ ;; YESINLINE-NEXT: (struct.new_default $B)
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: (drop
+ ;; YESINLINE-NEXT: (local.get $2)
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: (block
+ ;; YESINLINE-NEXT: (block $__inlined_func$refinable_noinline_2$3
+ ;; YESINLINE-NEXT: (local.set $3
+ ;; YESINLINE-NEXT: (struct.new_default $B)
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: (drop
+ ;; YESINLINE-NEXT: (local.get $3)
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: )
+ ;; YESINLINE-NEXT: )
+ (func $calls
+ ;; Two calls with $A, two with $B. The calls to $B will both go to the
+ ;; same new monomorphized function which has a refined parameter of $B.
+ ;;
+ ;; In NO_INLINE we will not inline any of these 4 calls (if we did not
+ ;; propagate the no-inline flag to the copied function, we would incorrectly
+ ;; inline the monomorphized ones). In YESINLINE mode we will inline all 4.
+ ;;
+ (call $refinable_noinline
+ (struct.new $A)
+ )
+ (call $refinable_noinline
+ (struct.new $A)
+ )
+ (call $refinable_noinline
+ (struct.new $B)
+ )
+ (call $refinable_noinline
+ (struct.new $B)
+ )
+ )
+
+ ;; NO_INLINE: (func $refinable_noinline (type $3) (param $ref (ref $A))
+ ;; NO_INLINE-NEXT: (drop
+ ;; NO_INLINE-NEXT: (local.get $ref)
+ ;; NO_INLINE-NEXT: )
+ ;; NO_INLINE-NEXT: )
+ (func $refinable_noinline (param $ref (ref $A))
+ ;; Some content to make it worth inlining.
+ (drop
+ (local.get $ref)
+ )
+ )
+)
+;; NO_INLINE: (func $refinable_noinline_2 (type $4) (param $ref (ref $B))
+;; NO_INLINE-NEXT: (drop
+;; NO_INLINE-NEXT: (local.get $ref)
+;; NO_INLINE-NEXT: )
+;; NO_INLINE-NEXT: )
diff --git a/test/lit/passes/no-inline.wast b/test/lit/passes/no-inline.wast
index 3321dc1ad..5e5c1ea0e 100644
--- a/test/lit/passes/no-inline.wast
+++ b/test/lit/passes/no-inline.wast
@@ -513,6 +513,8 @@
;; NO_PART: (import "out" "func" (func $import))
;; NO_FULL: (type $0 (func))
+ ;; NO_FULL: (type $1 (func (param i32)))
+
;; NO_FULL: (import "out" "func" (func $import))
;; NO_BOTH: (type $0 (func))
@@ -763,10 +765,6 @@
;; NO_FULL-NEXT: (local $1 i32)
;; NO_FULL-NEXT: (local $2 i32)
;; NO_FULL-NEXT: (local $3 i32)
- ;; NO_FULL-NEXT: (local $4 i32)
- ;; NO_FULL-NEXT: (local $5 i32)
- ;; NO_FULL-NEXT: (local $6 i32)
- ;; NO_FULL-NEXT: (local $7 i32)
;; NO_FULL-NEXT: (block
;; NO_FULL-NEXT: (block $__inlined_func$byn-split-inlineable-B$maybe-partial-or-full-1
;; NO_FULL-NEXT: (local.set $0
@@ -774,11 +772,8 @@
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: (if
;; NO_FULL-NEXT: (local.get $0)
- ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-outlined-B$maybe-partial-or-full-1$4
- ;; NO_FULL-NEXT: (local.set $4
- ;; NO_FULL-NEXT: (local.get $0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (call $import)
+ ;; NO_FULL-NEXT: (call $byn-split-outlined-B$maybe-partial-or-full-1
+ ;; NO_FULL-NEXT: (local.get $0)
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: )
@@ -790,11 +785,8 @@
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: (if
;; NO_FULL-NEXT: (local.get $1)
- ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-outlined-B$maybe-partial-or-full-1$5
- ;; NO_FULL-NEXT: (local.set $5
- ;; NO_FULL-NEXT: (local.get $1)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (call $import)
+ ;; NO_FULL-NEXT: (call $byn-split-outlined-B$maybe-partial-or-full-1
+ ;; NO_FULL-NEXT: (local.get $1)
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: )
@@ -808,37 +800,8 @@
;; NO_FULL-NEXT: (i32.eqz
;; NO_FULL-NEXT: (local.get $2)
;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-outlined-A$maybe-partial-or-full-2$6
- ;; NO_FULL-NEXT: (local.set $6
- ;; NO_FULL-NEXT: (local.get $2)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (block
- ;; NO_FULL-NEXT: (nop)
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $byn-split-outlined-A$maybe-partial-or-full-2
+ ;; NO_FULL-NEXT: (local.get $2)
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: )
@@ -852,37 +815,8 @@
;; NO_FULL-NEXT: (i32.eqz
;; NO_FULL-NEXT: (local.get $3)
;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-outlined-A$maybe-partial-or-full-2$7
- ;; NO_FULL-NEXT: (local.set $7
- ;; NO_FULL-NEXT: (local.get $3)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (block
- ;; NO_FULL-NEXT: (nop)
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: (drop
- ;; NO_FULL-NEXT: (i32.const 0)
- ;; NO_FULL-NEXT: )
- ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $byn-split-outlined-A$maybe-partial-or-full-2
+ ;; NO_FULL-NEXT: (local.get $3)
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: )
;; NO_FULL-NEXT: )
@@ -923,3 +857,34 @@
)
)
)
+;; NO_FULL: (func $byn-split-outlined-B$maybe-partial-or-full-1 (param $x i32)
+;; NO_FULL-NEXT: (call $import)
+;; NO_FULL-NEXT: )
+
+;; NO_FULL: (func $byn-split-outlined-A$maybe-partial-or-full-2 (param $x i32)
+;; NO_FULL-NEXT: (nop)
+;; NO_FULL-NEXT: (drop
+;; NO_FULL-NEXT: (i32.const 0)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: (drop
+;; NO_FULL-NEXT: (i32.const 0)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: (drop
+;; NO_FULL-NEXT: (i32.const 0)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: (drop
+;; NO_FULL-NEXT: (i32.const 0)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: (drop
+;; NO_FULL-NEXT: (i32.const 0)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: (drop
+;; NO_FULL-NEXT: (i32.const 0)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: (drop
+;; NO_FULL-NEXT: (i32.const 0)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: (drop
+;; NO_FULL-NEXT: (i32.const 0)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: )