diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/passes/heap2local.wast | 228 |
1 files changed, 221 insertions, 7 deletions
diff --git a/test/lit/passes/heap2local.wast b/test/lit/passes/heap2local.wast index 29c25a8df..3736e4990 100644 --- a/test/lit/passes/heap2local.wast +++ b/test/lit/passes/heap2local.wast @@ -239,11 +239,13 @@ ;; CHECK: (func $ignore-unreachable ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (struct.new_with_rtt $struct.A - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (rtt.canon $struct.A) + ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (struct.new_with_rtt $struct.A + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (rtt.canon $struct.A) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -729,7 +731,7 @@ ) ) - ;; CHECK: (func $branch-value (result f64) + ;; CHECK: (func $block-value (result f64) ;; CHECK-NEXT: (local $ref (ref null $struct.A)) ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (local $2 f64) @@ -758,7 +760,7 @@ ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $branch-value (result f64) + (func $block-value (result f64) (local $ref (ref null $struct.A)) (local.set $ref (struct.new_default_with_rtt $struct.A @@ -1530,6 +1532,218 @@ ) ) + ;; CHECK: (func $branch-to-block-no-fallthrough (result f64) + ;; CHECK-NEXT: (local $0 (ref null $struct.A)) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (local $2 f64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result (ref $struct.A)) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (f64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A + ;; CHECK-NEXT: (rtt.canon $struct.A) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result f64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (br_if $block + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (f64.const 2.1828) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $branch-to-block-no-fallthrough (result f64) + (local $0 (ref null $struct.A)) + (local.set $0 + (struct.new_default_with_rtt $struct.A + (rtt.canon $struct.A) + ) + ) + (struct.get $struct.A 1 + (block $block (result (ref null $struct.A)) + (drop + ;; A branch to the block of our allocation. In this case there is no + ;; other value reaching the block, and so our branch is the sole value + ;; which means there is no mixing, and we can optimize this. + (br_if $block + (local.get $0) + (i32.const 0) + ) + ) + (return (f64.const 2.1828)) + ) + ) + ) + + ;; CHECK: (func $two-branches (result f64) + ;; CHECK-NEXT: (local $0 (ref null $struct.A)) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A + ;; CHECK-NEXT: (rtt.canon $struct.A) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.get $struct.A 1 + ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (br_if $block + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (br_if $block + ;; CHECK-NEXT: (ref.null $struct.A) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (f64.const 2.1828) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $two-branches (result f64) + (local $0 (ref null $struct.A)) + (local.set $0 + (struct.new_default_with_rtt $struct.A + (rtt.canon $struct.A) + ) + ) + (struct.get $struct.A 1 + (block $block (result (ref null $struct.A)) + (drop + ;; A branch to the block of our allocation. + (br_if $block + (local.get $0) + (i32.const 0) + ) + ) + (drop + ;; Another branch, causing mixing that prevents optimizations. + (br_if $block + (ref.null $struct.A) + (i32.const 0) + ) + ) + (return (f64.const 2.1828)) + ) + ) + ) + + ;; CHECK: (func $two-branches-b (result f64) + ;; CHECK-NEXT: (local $0 (ref null $struct.A)) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A + ;; CHECK-NEXT: (rtt.canon $struct.A) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.get $struct.A 1 + ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (br_if $block + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (br_if $block + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (f64.const 2.1828) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $two-branches-b (result f64) + (local $0 (ref null $struct.A)) + (local.set $0 + (struct.new_default_with_rtt $struct.A + (rtt.canon $struct.A) + ) + ) + (struct.get $struct.A 1 + (block $block (result (ref null $struct.A)) + (drop + (br_if $block + (local.get $0) + (i32.const 0) + ) + ) + (drop + ;; As in $two-branches, but the value here is our allocation, the same + ;; as in the first branch above us. We do not yet optimize such merges + ;; of our allocation, but we could in the future. + (br_if $block + (local.get $0) + (i32.const 0) + ) + ) + (return (f64.const 2.1828)) + ) + ) + ) + + ;; CHECK: (func $br_if_flow (result f64) + ;; CHECK-NEXT: (local $0 (ref null $struct.A)) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A + ;; CHECK-NEXT: (rtt.canon $struct.A) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.get $struct.A 1 + ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) + ;; CHECK-NEXT: (call $send-ref + ;; CHECK-NEXT: (br_if $block + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (f64.const 2.1828) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $br_if_flow (result f64) + (local $0 (ref null $struct.A)) + (local.set $0 + (struct.new_default_with_rtt $struct.A + (rtt.canon $struct.A) + ) + ) + (struct.get $struct.A 1 + (block $block (result (ref null $struct.A)) + ;; If it were not for the call here then we would be able to optimize + ;; the allocation in this function. (The branch with the allocation is + ;; ok, but the br_if also flows the value into a call, that escapes it.) + (call $send-ref + (br_if $block + (local.get $0) + (i32.const 0) + ) + ) + (return (f64.const 2.1828)) + ) + ) + ) + ;; CHECK: (func $ref-as-non-null ;; CHECK-NEXT: (local $ref (ref null $struct.A)) ;; CHECK-NEXT: (local $1 i32) |