diff options
-rw-r--r-- | src/passes/Inlining.cpp | 15 | ||||
-rw-r--r-- | test/lit/passes/inlining-optimizing_optimize-level=3.wast | 28 | ||||
-rw-r--r-- | test/lit/passes/inlining-unreachable.wast | 79 | ||||
-rw-r--r-- | test/lit/passes/inlining_enable-tail-call.wast | 2 | ||||
-rw-r--r-- | test/lit/passes/inlining_optimize-level=3.wast | 18 |
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 |