summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Inlining.cpp15
-rw-r--r--test/lit/passes/inlining-optimizing_optimize-level=3.wast28
-rw-r--r--test/lit/passes/inlining-unreachable.wast79
-rw-r--r--test/lit/passes/inlining_enable-tail-call.wast2
-rw-r--r--test/lit/passes/inlining_optimize-level=3.wast18
5 files changed, 106 insertions, 36 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index 4475db7b0..7df5c8f29 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -413,6 +413,16 @@ static Expression* doInlining(Module* module,
// Make the block reachable by adding a break to it
block->list.push_back(builder.makeBreak(block->name));
}
+ // Anything we inlined into may now have non-unique label names, fix it up.
+ // Note that we must do this before refinalization, as otherwise duplicate
+ // block labels can lead to errors (the IR must be valid before we
+ // refinalize).
+ wasm::UniqueNameMapper::uniquify(into->body);
+ // Inlining unreachable contents can make things in the function we inlined
+ // into unreachable.
+ ReFinalize().walkFunctionInModule(into, module);
+ // New locals we added may require fixups for nondefaultability.
+ // FIXME Is this not done automatically?
TypeUpdating::handleNonDefaultableLocals(into, *module);
return block;
}
@@ -1039,11 +1049,6 @@ struct Inlining : public Pass {
assert(inlinedUses[inlinedName] <= infos[inlinedName].refs);
}
}
- for (auto func : inlinedInto) {
- // Anything we inlined into may now have non-unique label names, fix it
- // up.
- wasm::UniqueNameMapper::uniquify(func->body);
- }
if (optimize && inlinedInto.size() > 0) {
OptUtils::optimizeAfterInlining(inlinedInto, module, getPassRunner());
}
diff --git a/test/lit/passes/inlining-optimizing_optimize-level=3.wast b/test/lit/passes/inlining-optimizing_optimize-level=3.wast
index feaa3171a..d51b48e9c 100644
--- a/test/lit/passes/inlining-optimizing_optimize-level=3.wast
+++ b/test/lit/passes/inlining-optimizing_optimize-level=3.wast
@@ -8418,7 +8418,7 @@
;; CHECK-NEXT: (br $__rjti$8)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $label$break$L8
- ;; CHECK-NEXT: (block $__rjti$28
+ ;; CHECK-NEXT: (block $__rjti$20
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.and
;; CHECK-NEXT: (local.tee $9
@@ -8441,15 +8441,15 @@
;; CHECK-NEXT: (local.set $8
;; CHECK-NEXT: (local.get $5)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (loop $while-in9
- ;; CHECK-NEXT: (br_if $__rjti$28
+ ;; CHECK-NEXT: (loop $while-in5
+ ;; CHECK-NEXT: (br_if $__rjti$20
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (i32.load8_u
;; CHECK-NEXT: (local.get $8)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br_if $while-in9
+ ;; CHECK-NEXT: (br_if $while-in5
;; CHECK-NEXT: (i32.and
;; CHECK-NEXT: (local.tee $9
;; CHECK-NEXT: (i32.ne
@@ -8482,7 +8482,7 @@
;; CHECK-NEXT: (local.get $5)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br_if $__rjti$28
+ ;; CHECK-NEXT: (br_if $__rjti$20
;; CHECK-NEXT: (local.get $9)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $9
@@ -8498,15 +8498,15 @@
;; CHECK-NEXT: (local.get $8)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block $__rjto$010
- ;; CHECK-NEXT: (block $__rjti$011
- ;; CHECK-NEXT: (br_if $__rjti$011
+ ;; CHECK-NEXT: (block $__rjto$06
+ ;; CHECK-NEXT: (block $__rjti$07
+ ;; CHECK-NEXT: (br_if $__rjti$07
;; CHECK-NEXT: (i32.le_u
;; CHECK-NEXT: (local.get $9)
;; CHECK-NEXT: (i32.const 3)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (loop $while-in312
+ ;; CHECK-NEXT: (loop $while-in38
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (i32.and
@@ -8534,7 +8534,7 @@
;; CHECK-NEXT: (i32.const 4)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br_if $while-in312
+ ;; CHECK-NEXT: (br_if $while-in38
;; CHECK-NEXT: (i32.gt_u
;; CHECK-NEXT: (local.tee $9
;; CHECK-NEXT: (i32.sub
@@ -8545,11 +8545,11 @@
;; CHECK-NEXT: (i32.const 3)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__rjti$011)
+ ;; CHECK-NEXT: (br $__rjti$07)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__rjto$010)
+ ;; CHECK-NEXT: (br $__rjto$06)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
@@ -8564,7 +8564,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $9
- ;; CHECK-NEXT: (loop $while-in5 (result i32)
+ ;; CHECK-NEXT: (loop $while-in59 (result i32)
;; CHECK-NEXT: (br_if $label$break$L8
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (i32.load8_u
@@ -8578,7 +8578,7 @@
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br_if $while-in5
+ ;; CHECK-NEXT: (br_if $while-in59
;; CHECK-NEXT: (local.tee $9
;; CHECK-NEXT: (i32.sub
;; CHECK-NEXT: (local.get $9)
diff --git a/test/lit/passes/inlining-unreachable.wast b/test/lit/passes/inlining-unreachable.wast
index 054d73545..e8797d5b9 100644
--- a/test/lit/passes/inlining-unreachable.wast
+++ b/test/lit/passes/inlining-unreachable.wast
@@ -32,7 +32,7 @@
)
;; CHECK: (func $call-trap-result (type $none_=>_i32) (result i32)
- ;; CHECK-NEXT: (block $__inlined_func$trap-result (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$trap-result
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -77,12 +77,10 @@
;; CHECK: (func $caller (type $none_=>_none)
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block (result i32)
- ;; CHECK-NEXT: (block $__inlined_func$callee (result i32)
- ;; CHECK-NEXT: (br $__inlined_func$callee
- ;; CHECK-NEXT: (call $imported
- ;; CHECK-NEXT: (unreachable)
- ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$callee
+ ;; CHECK-NEXT: (call $imported
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -102,3 +100,70 @@
)
)
)
+
+(module
+ ;; CHECK: (type $A (func))
+ (type $A (func))
+
+ (func $0
+ (nop)
+ (call_ref $A
+ (ref.null nofunc) ;; In Binaryen IR this makes the call_ref unreachable.
+ )
+ )
+
+ ;; CHECK: (func $1 (type $A)
+ ;; CHECK-NEXT: (block $__inlined_func$0
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $1 (type $A)
+ ;; After inlining, this function body will become unreachable.
+ (call $0)
+ )
+)
+
+(module
+ ;; CHECK: (type $none_=>_f64 (func (result f64)))
+
+ ;; CHECK: (func $0 (type $none_=>_f64) (result f64)
+ ;; CHECK-NEXT: (block $block
+ ;; CHECK-NEXT: (br_if $block
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$1
+ ;; CHECK-NEXT: (block $block0
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $0 (result f64)
+ (block $block
+ (br_if $block
+ (i32.const 0)
+ )
+ )
+ (return
+ ;; The inlined function has the same label, $block. We should not be
+ ;; confused by that when we inline the unreachable code (an error can
+ ;; occur if we mix up the two blocks or think they are identical; to avoid
+ ;; that we should fix up the duplicate labels before doing anything that
+ ;; depends on valid label names, like refinalization).
+ (call $1)
+ )
+ )
+
+ (func $1 (result f64)
+ (block $block
+ (unreachable)
+ )
+ )
+)
diff --git a/test/lit/passes/inlining_enable-tail-call.wast b/test/lit/passes/inlining_enable-tail-call.wast
index 3b80f84ea..ed642594c 100644
--- a/test/lit/passes/inlining_enable-tail-call.wast
+++ b/test/lit/passes/inlining_enable-tail-call.wast
@@ -394,7 +394,7 @@
;; CHECK: (func $0
;; CHECK-NEXT: (block $__inlined_func$1
;; CHECK-NEXT: (call_indirect (type $T)
- ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: (unreachable)
diff --git a/test/lit/passes/inlining_optimize-level=3.wast b/test/lit/passes/inlining_optimize-level=3.wast
index cba2f46fc..e5a0bc7e1 100644
--- a/test/lit/passes/inlining_optimize-level=3.wast
+++ b/test/lit/passes/inlining_optimize-level=3.wast
@@ -149,9 +149,9 @@
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block (result i32)
- ;; CHECK-NEXT: (block $__inlined_func$no-calls1 (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$no-calls0 (result i32)
;; CHECK-NEXT: (block (result i32)
- ;; CHECK-NEXT: (block $__inlined_func$yes2 (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$yes1 (result i32)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -164,7 +164,7 @@
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__inlined_func$yes-calls-but-one-use (result i32)
;; CHECK-NEXT: (block (result i32)
- ;; CHECK-NEXT: (block $__inlined_func$yes3 (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$yes2 (result i32)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -193,7 +193,7 @@
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__inlined_func$yes-loops-but-one-use (result i32)
- ;; CHECK-NEXT: (loop $loop-in2 (result i32)
+ ;; CHECK-NEXT: (loop $loop-in0 (result i32)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -202,7 +202,7 @@
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__inlined_func$no-loops-but-one-use-but-exported (result i32)
- ;; CHECK-NEXT: (loop $loop-in3 (result i32)
+ ;; CHECK-NEXT: (loop $loop-in2 (result i32)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -211,7 +211,7 @@
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__inlined_func$no-loops-but-one-use-but-tabled (result i32)
- ;; CHECK-NEXT: (loop $loop-in4 (result i32)
+ ;; CHECK-NEXT: (loop $loop-in3 (result i32)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -441,7 +441,7 @@
;; CHECK: (func $foo
;; CHECK-NEXT: (block $__inlined_func$bar_0
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block $__inlined_func$bar (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$bar
;; CHECK-NEXT: (br $__inlined_func$bar_0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -461,8 +461,8 @@
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (block $__inlined_func$0_0
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block (result i32)
- ;; CHECK-NEXT: (block $__inlined_func$0_0_0 (result i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$0_0_0
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (br_if $__inlined_func$0_0