summaryrefslogtreecommitdiff
path: root/test/lit/passes
diff options
context:
space:
mode:
Diffstat (limited to 'test/lit/passes')
-rw-r--r--test/lit/passes/precompute-gc.wast359
1 files changed, 358 insertions, 1 deletions
diff --git a/test/lit/passes/precompute-gc.wast b/test/lit/passes/precompute-gc.wast
index 9402aa068..0cd6d2c2c 100644
--- a/test/lit/passes/precompute-gc.wast
+++ b/test/lit/passes/precompute-gc.wast
@@ -1,8 +1,13 @@
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
-;; RUN: wasm-opt %s --remove-unused-names --precompute-propagate -all -S -o - \
+;; RUN: wasm-opt %s --remove-unused-names --precompute-propagate --fuzz-exec -all -S -o - \
;; RUN: | filecheck %s
(module
+ (type $struct (struct (mut i32)))
+ (type $empty (struct))
+
+ (import "fuzzing-support" "log-i32" (func $log (param i32)))
+
;; CHECK: (func $test-fallthrough (result i32)
;; CHECK-NEXT: (local $x funcref)
;; CHECK-NEXT: (local.set $x
@@ -34,4 +39,356 @@
(local.get $x)
)
)
+
+ ;; CHECK: (func $load-from-struct
+ ;; CHECK-NEXT: (local $x (ref null $struct))
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (struct.new_with_rtt $struct
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (rtt.canon $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (struct.get $struct 0
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (struct.new_with_rtt $struct
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: (rtt.canon $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (struct.get $struct 0
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (struct.set $struct 0
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (struct.get $struct 0
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $load-from-struct
+ (local $x (ref null $struct))
+ (local.set $x
+ (struct.new_with_rtt $struct
+ (i32.const 1)
+ (rtt.canon $struct)
+ )
+ )
+ ;; we don't precompute these, as we don't know if the GC data was modified
+ ;; elsewhere (we'd need immutability or escape analysis)
+ (call $log
+ (struct.get $struct 0 (local.get $x))
+ )
+ ;; Assign a new struct
+ (local.set $x
+ (struct.new_with_rtt $struct
+ (i32.const 2)
+ (rtt.canon $struct)
+ )
+ )
+ (call $log
+ (struct.get $struct 0 (local.get $x))
+ )
+ ;; Assign a new value
+ (struct.set $struct 0
+ (local.get $x)
+ (i32.const 3)
+ )
+ (call $log
+ (struct.get $struct 0 (local.get $x))
+ )
+ )
+ ;; CHECK: (func $load-from-struct-bad-merge (param $i i32)
+ ;; CHECK-NEXT: (local $x (ref null $struct))
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (local.get $i)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (struct.new_with_rtt $struct
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (rtt.canon $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (struct.new_with_rtt $struct
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: (rtt.canon $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (struct.get $struct 0
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $load-from-struct-bad-merge (param $i i32)
+ (local $x (ref null $struct))
+ ;; a merge of two different $x values cannot be precomputed
+ (if
+ (local.get $i)
+ (local.set $x
+ (struct.new_with_rtt $struct
+ (i32.const 1)
+ (rtt.canon $struct)
+ )
+ )
+ (local.set $x
+ (struct.new_with_rtt $struct
+ (i32.const 2)
+ (rtt.canon $struct)
+ )
+ )
+ )
+ (call $log
+ (struct.get $struct 0 (local.get $x))
+ )
+ )
+ ;; CHECK: (func $modify-gc-heap (param $x (ref null $struct))
+ ;; CHECK-NEXT: (struct.set $struct 0
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (i32.add
+ ;; CHECK-NEXT: (struct.get $struct 0
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $modify-gc-heap (param $x (ref null $struct))
+ (struct.set $struct 0
+ (local.get $x)
+ (i32.add
+ (struct.get $struct 0
+ (local.get $x)
+ )
+ (i32.const 1)
+ )
+ )
+ )
+ ;; --fuzz-exec verifies the output of this function, checking that the change
+ ;; makde in modify-gc-heap is not ignored
+ ;; CHECK: (func $load-from-struct-bad-escape
+ ;; CHECK-NEXT: (local $x (ref null $struct))
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (struct.new_with_rtt $struct
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (rtt.canon $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $modify-gc-heap
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (struct.get $struct 0
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $load-from-struct-bad-escape (export "test")
+ (local $x (ref null $struct))
+ (local.set $x
+ (struct.new_with_rtt $struct
+ (i32.const 1)
+ (rtt.canon $struct)
+ )
+ )
+ (call $modify-gc-heap
+ (local.get $x)
+ )
+ (call $log
+ (struct.get $struct 0 (local.get $x))
+ )
+ )
+ ;; CHECK: (func $load-from-struct-bad-arrive (param $x (ref null $struct))
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (struct.get $struct 0
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $load-from-struct-bad-arrive (param $x (ref null $struct))
+ ;; a parameter cannot be precomputed
+ (call $log
+ (struct.get $struct 0 (local.get $x))
+ )
+ )
+ ;; CHECK: (func $ref-comparisons (param $x (ref null $struct)) (param $y (ref null $struct))
+ ;; CHECK-NEXT: (local $z (ref null $struct))
+ ;; CHECK-NEXT: (local $w (ref null $struct))
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (ref.null $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (ref.null $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $log
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ref-comparisons
+ (param $x (ref null $struct))
+ (param $y (ref null $struct))
+ (local $z (ref null $struct))
+ (local $w (ref null $struct))
+ ;; incoming parameters are unknown
+ (call $log
+ (ref.eq
+ (local.get $x)
+ (local.get $y)
+ )
+ )
+ (call $log
+ (ref.eq
+ (local.get $x)
+ ;; locals are ref.null which are known, and will be propagated
+ (local.get $z)
+ )
+ )
+ (call $log
+ (ref.eq
+ (local.get $x)
+ (local.get $w)
+ )
+ )
+ ;; null-initialized locals are known and can be compared
+ (call $log
+ (ref.eq
+ (local.get $z)
+ (local.get $w)
+ )
+ )
+ )
+ ;; CHECK: (func $new-ref-comparisons (result i32)
+ ;; CHECK-NEXT: (local $x (ref null $struct))
+ ;; CHECK-NEXT: (local $y (ref null $struct))
+ ;; CHECK-NEXT: (local $tempresult i32)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (struct.new_with_rtt $struct
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (rtt.canon $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $y
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $tempresult
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $tempresult)
+ ;; CHECK-NEXT: )
+ (func $new-ref-comparisons (result i32)
+ (local $x (ref null $struct))
+ (local $y (ref null $struct))
+ (local $tempresult i32)
+ (local.set $x
+ (struct.new_with_rtt $struct
+ (i32.const 1)
+ (rtt.canon $struct)
+ )
+ )
+ (local.set $y
+ (local.get $x)
+ )
+ ;; assign the result, so that propagate calculates the ref.eq
+ (local.set $tempresult
+ (ref.eq
+ (local.get $x)
+ (local.get $y)
+ )
+ )
+ ;; this value could be precomputed in principle, however, we currently do not
+ ;; precompute GC references, and so nothing will be done.
+ (local.get $tempresult)
+ )
+ ;; CHECK: (func $propagate-equal (result i32)
+ ;; CHECK-NEXT: (local $tempresult i32)
+ ;; CHECK-NEXT: (local $tempref (ref null $empty))
+ ;; CHECK-NEXT: (local.set $tempresult
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (local.tee $tempref
+ ;; CHECK-NEXT: (struct.new_default_with_rtt $empty
+ ;; CHECK-NEXT: (rtt.canon $empty)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $tempref)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $tempresult)
+ ;; CHECK-NEXT: )
+ (func $propagate-equal (result i32)
+ (local $tempresult i32)
+ (local $tempref (ref null $empty))
+ ;; assign the result, so that propagate calculates the ref.eq
+ (local.set $tempresult
+ (ref.eq
+ ;; allocate one struct
+ (local.tee $tempref
+ (struct.new_with_rtt $empty
+ (rtt.canon $empty)
+ )
+ )
+ (local.get $tempref)
+ )
+ )
+ ;; this value could be precomputed in principle, however, we currently do not
+ ;; precompute GC references, and so nothing will be done.
+ (local.get $tempresult)
+ )
+ ;; CHECK: (func $propagate-unequal (result i32)
+ ;; CHECK-NEXT: (local $tempresult i32)
+ ;; CHECK-NEXT: (local $tempref (ref null $empty))
+ ;; CHECK-NEXT: (local.set $tempresult
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (struct.new_default_with_rtt $empty
+ ;; CHECK-NEXT: (rtt.canon $empty)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (struct.new_default_with_rtt $empty
+ ;; CHECK-NEXT: (rtt.canon $empty)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $tempresult)
+ ;; CHECK-NEXT: )
+ (func $propagate-unequal (result i32)
+ (local $tempresult i32)
+ (local $tempref (ref null $empty))
+ ;; assign the result, so that propagate calculates the ref.eq
+ (local.set $tempresult
+ ;; allocate two different structs
+ (ref.eq
+ (struct.new_with_rtt $empty
+ (rtt.canon $empty)
+ )
+ (struct.new_with_rtt $empty
+ (rtt.canon $empty)
+ )
+ )
+ )
+ ;; this value could be precomputed in principle, however, we currently do not
+ ;; precompute GC references, and so nothing will be done.
+ (local.get $tempresult)
+ )
)