diff options
author | Alon Zakai <azakai@google.com> | 2021-07-28 13:57:28 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-28 13:57:28 -0700 |
commit | bfe73c86b3dc6918334d678ab564e3dcb739a197 (patch) | |
tree | f1ed567f3ee91f74f8c5a17a0374c917e68c89e7 /test/lit/passes/dae-gc.wast | |
parent | 1ed257a587a30885f42f2c1b6170d662e741ae40 (diff) | |
download | binaryen-bfe73c86b3dc6918334d678ab564e3dcb739a197.tar.gz binaryen-bfe73c86b3dc6918334d678ab564e3dcb739a197.tar.bz2 binaryen-bfe73c86b3dc6918334d678ab564e3dcb739a197.zip |
[Wasm GC] Refine return types of tail calling functions in DeadArgumentElimination (#4036)
To do this we need to look at tail calls and not just returns.
Diffstat (limited to 'test/lit/passes/dae-gc.wast')
-rw-r--r-- | test/lit/passes/dae-gc.wast | 112 |
1 files changed, 109 insertions, 3 deletions
diff --git a/test/lit/passes/dae-gc.wast b/test/lit/passes/dae-gc.wast index 833a56a1f..07bc84f5e 100644 --- a/test/lit/passes/dae-gc.wast +++ b/test/lit/passes/dae-gc.wast @@ -3,18 +3,24 @@ (module ;; CHECK: (type ${i32} (struct (field i32))) + (type ${i32} (struct (field i32))) ;; CHECK: (type ${} (struct )) (type ${} (struct)) - (type ${i32} (struct (field i32))) + ;; CHECK: (type ${i32_i64} (struct (field i32) (field i64))) + (type ${i32_i64} (struct (field i32) (field i64))) + + ;; CHECK: (type $return_{} (func (result (ref ${})))) + (type $return_{} (func (result (ref ${})))) ;; CHECK: (type ${i32_f32} (struct (field i32) (field f32))) + (type ${i32_f32} (struct (field i32) (field f32))) ;; CHECK: (type ${f64} (struct (field f64))) (type ${f64} (struct (field f64))) - (type ${i32_i64} (struct (field i32) (field i64))) - (type ${i32_f32} (struct (field i32) (field f32))) + + (table 1 1 funcref) ;; CHECK: (func $foo ;; CHECK-NEXT: (call $bar) @@ -594,4 +600,104 @@ (func $return-ref-func (result funcref) (ref.func $do-return-call) ) + + ;; Show that we can optimize the return type of a function that does a tail + ;; call. + ;; CHECK: (func $tail-callee (result (ref ${})) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $tail-callee (result (ref ${})) + (unreachable) + ) + ;; CHECK: (func $tail-caller-yes (result (ref ${})) + ;; CHECK-NEXT: (return_call $tail-callee) + ;; CHECK-NEXT: ) + (func $tail-caller-yes (result anyref) + ;; This function's return type can be refined because of this call, whose + ;; target's return type is more specific than anyref. + (return_call $tail-callee) + ) + ;; CHECK: (func $tail-caller-no (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return_call $tail-callee) + ;; CHECK-NEXT: ) + (func $tail-caller-no (result anyref) + ;; This function's return type cannot be refined because of another return + ;; whose type prevents it. + (if (i32.const 1) + (return (ref.null any)) + ) + (return_call $tail-callee) + ) + ;; CHECK: (func $tail-call-caller + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $tail-caller-yes) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $tail-caller-no) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $tail-call-caller + ;; Call the functions to cause optimization to happen. + (drop + (call $tail-caller-yes) + ) + (drop + (call $tail-caller-no) + ) + ) + + ;; As above, but with an indirect tail call. + ;; CHECK: (func $tail-callee-indirect (result (ref ${})) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $tail-callee-indirect (result (ref ${})) + (unreachable) + ) + ;; CHECK: (func $tail-caller-indirect-yes (result (ref ${})) + ;; CHECK-NEXT: (return_call_indirect $0 (type $return_{}) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $tail-caller-indirect-yes (result anyref) + (return_call_indirect (type $return_{}) (i32.const 0)) + ) + ;; CHECK: (func $tail-caller-indirect-no (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return_call_indirect $0 (type $return_{}) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $tail-caller-indirect-no (result anyref) + (if (i32.const 1) + (return (ref.null any)) + ) + (return_call_indirect (type $return_{}) (i32.const 0)) + ) + ;; CHECK: (func $tail-call-caller-indirect + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $tail-caller-indirect-yes) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $tail-caller-indirect-no) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $tail-call-caller-indirect + (drop + (call $tail-caller-indirect-yes) + ) + (drop + (call $tail-caller-indirect-no) + ) + ) ) |