summaryrefslogtreecommitdiff
path: root/test/lit
diff options
context:
space:
mode:
Diffstat (limited to 'test/lit')
-rw-r--r--test/lit/passes/optimize-instructions-gc-iit.wast18
-rw-r--r--test/lit/passes/optimize-instructions-gc.wast185
2 files changed, 202 insertions, 1 deletions
diff --git a/test/lit/passes/optimize-instructions-gc-iit.wast b/test/lit/passes/optimize-instructions-gc-iit.wast
index 10bbbfc4a..5409e14c4 100644
--- a/test/lit/passes/optimize-instructions-gc-iit.wast
+++ b/test/lit/passes/optimize-instructions-gc-iit.wast
@@ -136,4 +136,22 @@
)
)
)
+
+ ;; CHECK: (func $ref-eq-ref-cast (param $x eqref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ref-eq-ref-cast (param $x eqref)
+ ;; we can look through a ref.cast if we ignore traps
+ (drop
+ (ref.eq
+ (local.get $x)
+ (ref.cast
+ (local.get $x)
+ (rtt.canon $parent)
+ )
+ )
+ )
+ )
)
diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast
index b00d08193..33f7bef78 100644
--- a/test/lit/passes/optimize-instructions-gc.wast
+++ b/test/lit/passes/optimize-instructions-gc.wast
@@ -1,5 +1,5 @@
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
-;; RUN: wasm-opt %s --optimize-instructions --enable-reference-types --enable-gc -S -o - \
+;; RUN: wasm-opt %s --remove-unused-names --optimize-instructions --enable-reference-types --enable-gc -S -o - \
;; RUN: | filecheck %s
(module
@@ -533,4 +533,187 @@
)
)
)
+
+ ;; CHECK: (func $get-eqref (result eqref)
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ (func $get-eqref (result eqref)
+ (unreachable)
+ )
+
+ ;; CHECK: (func $ref-eq (param $x eqref) (param $y eqref)
+ ;; CHECK-NEXT: (local $lx eqref)
+ ;; CHECK-NEXT: (local $ly eqref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $lx
+ ;; CHECK-NEXT: (call $get-eqref)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ref-eq (param $x eqref) (param $y eqref)
+ (local $lx eqref)
+ (local $ly eqref)
+ ;; identical parameters are equal
+ (drop
+ (ref.eq
+ (local.get $x)
+ (local.get $x)
+ )
+ )
+ ;; different ones might not be
+ (drop
+ (ref.eq
+ (local.get $x)
+ (local.get $y)
+ )
+ )
+ ;; identical locals are
+ (local.set $lx
+ (call $get-eqref)
+ )
+ (drop
+ (ref.eq
+ (local.get $lx)
+ (local.get $lx)
+ )
+ )
+ ;; fallthroughs work ok (but we need --remove-unused-names so that we can
+ ;; trivially tell that there are no breaks)
+ (drop
+ (ref.eq
+ (block (result eqref)
+ (nop)
+ (local.get $x)
+ )
+ (block (result eqref)
+ (nop)
+ (drop
+ (i32.const 10)
+ )
+ (nop)
+ (local.get $x)
+ )
+ )
+ )
+ )
+
+ (func $nothing)
+
+ ;; CHECK: (func $ref-eq-corner-cases (param $x eqref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (block (result eqref)
+ ;; CHECK-NEXT: (call $nothing)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block (result eqref)
+ ;; CHECK-NEXT: (call $nothing)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (struct.new_default_with_rtt $struct
+ ;; CHECK-NEXT: (rtt.canon $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (struct.new_default_with_rtt $struct
+ ;; CHECK-NEXT: (rtt.canon $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ref-eq-corner-cases (param $x eqref)
+ ;; side effects prevent optimization
+ (drop
+ (ref.eq
+ (block (result eqref)
+ (call $nothing)
+ (local.get $x)
+ )
+ (block (result eqref)
+ (call $nothing)
+ (local.get $x)
+ )
+ )
+ )
+ ;; allocation prevents optimization
+ (drop
+ (ref.eq
+ (struct.new_default_with_rtt $struct
+ (rtt.canon $struct)
+ )
+ (struct.new_default_with_rtt $struct
+ (rtt.canon $struct)
+ )
+ )
+ )
+ ;; but irrelevant allocations do not prevent optimization
+ (drop
+ (ref.eq
+ (block (result eqref)
+ ;; an allocation that does not trouble us
+ (drop
+ (struct.new_default_with_rtt $struct
+ (rtt.canon $struct)
+ )
+ )
+ (local.get $x)
+ )
+ (block (result eqref)
+ (drop
+ (struct.new_default_with_rtt $struct
+ (rtt.canon $struct)
+ )
+ )
+ ;; add a nop to make the two inputs to ref.eq not structurally equal,
+ ;; but in a way that does not matter (since only the value falling
+ ;; out does)
+ (nop)
+ (local.get $x)
+ )
+ )
+ )
+ )
+
+ ;; CHECK: (func $ref-eq-ref-cast (param $x eqref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (ref.cast
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (rtt.canon $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ref-eq-ref-cast (param $x eqref)
+ ;; it is almost valid to look through a cast, except that it might trap so
+ ;; there is a side effect
+ (drop
+ (ref.eq
+ (local.get $x)
+ (ref.cast
+ (local.get $x)
+ (rtt.canon $struct)
+ )
+ )
+ )
+ )
)