diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/passes/dae-gc.wast | 250 |
1 files changed, 249 insertions, 1 deletions
diff --git a/test/lit/passes/dae-gc.wast b/test/lit/passes/dae-gc.wast index b3f8eddd2..f80673cf2 100644 --- a/test/lit/passes/dae-gc.wast +++ b/test/lit/passes/dae-gc.wast @@ -9,10 +9,11 @@ (type ${i32} (struct (field i32))) ;; CHECK: (type ${i32_i64} (struct (field i32) (field i64))) + ;; CHECK: (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))) - ;; CHECK: (type ${i32_f32} (struct (field i32) (field f32))) (type ${i32_f32} (struct (field i32) (field f32))) ;; CHECK: (func $foo @@ -293,4 +294,251 @@ ;; "Use" the local to avoid other optimizations kicking in. (drop (local.get $x)) ) + + ;; We cannot refine the return type if nothing is actually returned. + ;; CHECK: (func $refine-return-no-return (result anyref) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $refine-return-no-return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $refine-return-no-return (result anyref) + ;; Call this function, so that we attempt to optimize it. Note that we do not + ;; just drop the result, as that would cause the drop optimizations to kick + ;; in. + (local $temp anyref) + (local.set $temp (call $refine-return-no-return)) + + (unreachable) + ) + + ;; We cannot refine the return type if it is already the best it can be. + ;; CHECK: (func $refine-return-no-refining (result anyref) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $refine-return-no-refining) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + (func $refine-return-no-refining (result anyref) + (local $temp anyref) + (local.set $temp (call $refine-return-no-refining)) + + (ref.null any) + ) + + ;; Refine the return type based on the value flowing out. + ;; CHECK: (func $refine-return-flow (result funcref) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $refine-return-flow) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + (func $refine-return-flow (result anyref) + (local $temp anyref) + (local.set $temp (call $refine-return-flow)) + + (ref.null func) + ) + ;; CHECK: (func $call-refine-return-flow (result funcref) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $call-refine-return-flow) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if (result funcref) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (call $refine-return-flow) + ;; CHECK-NEXT: (call $refine-return-flow) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-refine-return-flow (result anyref) + (local $temp anyref) + (local.set $temp (call $call-refine-return-flow)) + + ;; After refining the return value of the above function, refinalize will + ;; update types here, which will lead to updating the if, and then the entire + ;; function's return value. + (if (result anyref) + (i32.const 1) + (call $refine-return-flow) + (call $refine-return-flow) + ) + ) + + ;; Refine the return type based on a return. + ;; CHECK: (func $refine-return-return (result funcref) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $refine-return-return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $refine-return-return (result anyref) + (local $temp anyref) + (local.set $temp (call $refine-return-return)) + + (return (ref.null func)) + ) + + ;; Refine the return type based on multiple values. + ;; CHECK: (func $refine-return-many (result funcref) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $refine-return-many) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + (func $refine-return-many (result anyref) + (local $temp anyref) + (local.set $temp (call $refine-return-many)) + + (if + (i32.const 1) + (return (ref.null func)) + ) + (if + (i32.const 2) + (return (ref.null func)) + ) + (ref.null func) + ) + + ;; CHECK: (func $refine-return-many-blocked (result anyref) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $refine-return-many-blocked) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null data) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + (func $refine-return-many-blocked (result anyref) + (local $temp anyref) + (local.set $temp (call $refine-return-many-blocked)) + + (if + (i32.const 1) + (return (ref.null func)) + ) + (if + (i32.const 2) + ;; The refined return value is blocked by this return. + (return (ref.null data)) + ) + (ref.null func) + ) + + ;; CHECK: (func $refine-return-many-blocked-2 (result anyref) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $refine-return-many-blocked-2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null data) + ;; CHECK-NEXT: ) + (func $refine-return-many-blocked-2 (result anyref) + (local $temp anyref) + (local.set $temp (call $refine-return-many-blocked-2)) + + (if + (i32.const 1) + (return (ref.null func)) + ) + (if + (i32.const 2) + (return (ref.null func)) + ) + ;; The refined return value is blocked by this value. + (ref.null data) + ) + + ;; CHECK: (func $refine-return-many-middle (result (ref null ${i32})) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $refine-return-many-middle) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null ${i32_i64}) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null ${i32_f32}) + ;; CHECK-NEXT: ) + (func $refine-return-many-middle (result anyref) + (local $temp anyref) + (local.set $temp (call $refine-return-many-middle)) + + ;; Return two different struct types, with an LUB that is not equal to either + ;; of them. + (if + (i32.const 1) + (return (ref.null ${i32_i64})) + ) + (ref.null ${i32_f32}) + ) + + ;; We can refine the return types of tuples. + ;; CHECK: (func $refine-return-tuple (result funcref i32) + ;; CHECK-NEXT: (local $temp anyref) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (tuple.extract 0 + ;; CHECK-NEXT: (call $refine-return-tuple) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (tuple.make + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $refine-return-tuple (result anyref i32) + (local $temp anyref) + (local.set $temp + (tuple.extract 0 + (call $refine-return-tuple) + ) + ) + + (tuple.make + (ref.null func) + (i32.const 1) + ) + ) ) |