diff options
author | Alon Zakai <azakai@google.com> | 2023-02-15 13:05:25 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-15 13:05:25 -0800 |
commit | c4d15efc62fb6e6b55dd128e62896c93ca52c98a (patch) | |
tree | 9d24b32068ece1bc76d55067f4464b0df4e308b8 /test | |
parent | 8f98375c051f2b8e1be87e7eb97e88d73cfb2c26 (diff) | |
download | binaryen-c4d15efc62fb6e6b55dd128e62896c93ca52c98a.tar.gz binaryen-c4d15efc62fb6e6b55dd128e62896c93ca52c98a.tar.bz2 binaryen-c4d15efc62fb6e6b55dd128e62896c93ca52c98a.zip |
Unreachability fixes for inlining (#5492)
We must refinalize as inlining unreachable code can lead to
more things becoming unreachable.
We also must uniquify label names before refinalizing, as the
IR must be valid at that time, so that code is moved.
This causes some minor changes to existing test code (some
label changes, and refinalization makes more things
unreachable), but only the two new tests show actual problems
that needed to be fixed.
Diffstat (limited to 'test')
-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 |
4 files changed, 96 insertions, 31 deletions
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 |