summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/lit/passes/directize_all-features.wast600
1 files changed, 596 insertions, 4 deletions
diff --git a/test/lit/passes/directize_all-features.wast b/test/lit/passes/directize_all-features.wast
index 696b43ebf..10bcfc60f 100644
--- a/test/lit/passes/directize_all-features.wast
+++ b/test/lit/passes/directize_all-features.wast
@@ -1,13 +1,16 @@
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; NOTE: This test was ported using port_passes_tests_to_lit.py and could be cleaned up.
-;; RUN: foreach %s %t wasm-opt --directize --all-features -S -o - | filecheck %s
+;; RUN: foreach %s %t wasm-opt --directize --all-features -S -o - | filecheck %s --check-prefix=CHECK
+;; RUN: foreach %s %t wasm-opt --directize --pass-arg=directize-initial-contents-immutable --all-features -S -o - | filecheck %s --check-prefix=IMMUT
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
(elem (i32.const 1) $foo)
@@ -16,6 +19,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 1) $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
;; helper function
(unreachable)
@@ -27,6 +35,12 @@
;; CHECK-NEXT: (local.get $y)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call $foo
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect (type $ii)
(local.get $x)
@@ -38,12 +52,17 @@
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (type $i32_=>_i32 (func (param i32) (result i32)))
+
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
;; CHECK: (table $1 5 5 funcref)
+ ;; IMMUT: (table $1 5 5 funcref)
(table $1 5 5 funcref)
(elem (table $0) (i32.const 1) func $dummy)
(elem (table $1) (i32.const 1) func $f)
@@ -54,12 +73,22 @@
;; CHECK: (func $dummy (param $0 i32) (result i32)
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem $0 (table $0) (i32.const 1) func $dummy)
+
+ ;; IMMUT: (elem $1 (table $1) (i32.const 1) func $f)
+
+ ;; IMMUT: (func $dummy (param $0 i32) (result i32)
+ ;; IMMUT-NEXT: (local.get $0)
+ ;; IMMUT-NEXT: )
(func $dummy (param i32) (result i32)
(local.get 0)
)
;; CHECK: (func $f (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (func $f (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $f (param i32) (param i32)
(unreachable)
)
@@ -69,6 +98,12 @@
;; CHECK-NEXT: (local.get $y)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $g (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call $f
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $g (param $x i32) (param $y i32)
(call_indirect $1 (type $ii)
(local.get $x)
@@ -81,10 +116,13 @@
;; at table edges
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
;; CHECK: (table $1 5 5 funcref)
+ ;; IMMUT: (table $1 5 5 funcref)
(table $1 5 5 funcref)
(elem (table $1) (i32.const 4) func $foo)
;; CHECK: (elem (table $1) (i32.const 4) func $foo)
@@ -92,6 +130,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (table $1) (i32.const 4) func $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -101,6 +144,12 @@
;; CHECK-NEXT: (local.get $y)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call $foo
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect $1 (type $ii)
(local.get $x)
@@ -112,8 +161,10 @@
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
(elem (i32.const 0) $foo)
;; CHECK: (elem (i32.const 0) $foo)
@@ -121,6 +172,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 0) $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -130,6 +186,12 @@
;; CHECK-NEXT: (local.get $y)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call $foo
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect (type $ii)
(local.get $x)
@@ -141,10 +203,13 @@
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
;; CHECK: (table $1 5 5 funcref)
+ ;; IMMUT: (table $1 5 5 funcref)
(table $1 5 5 funcref)
(elem (i32.const 0) $foo $foo $foo $foo $foo)
(elem (table $1) (i32.const 0) func $foo $foo $foo $foo $foo)
@@ -155,6 +220,13 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem $0 (table $0) (i32.const 0) func $foo $foo $foo $foo $foo)
+
+ ;; IMMUT: (elem $1 (table $1) (i32.const 0) func $foo $foo $foo $foo $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -164,6 +236,12 @@
;; CHECK-NEXT: (local.get $y)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call $foo
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect $1 (type $ii)
(local.get $x)
@@ -173,11 +251,13 @@
)
)
-;; imported table
+;; imported table. only optimizable in the immutable case.
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (import "env" "table" (table $table 5 5 funcref))
+ ;; IMMUT: (import "env" "table" (table $table 5 5 funcref))
(import "env" "table" (table $table 5 5 funcref))
(elem (i32.const 1) $foo)
;; CHECK: (elem (i32.const 1) $foo)
@@ -185,6 +265,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 1) $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -195,6 +280,12 @@
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call $foo
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect (type $ii)
(local.get $x)
@@ -202,22 +293,55 @@
(i32.const 1)
)
)
+
+ ;; CHECK: (func $out-of-bounds (param $x i32) (param $y i32)
+ ;; CHECK-NEXT: (call_indirect $table (type $ii)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: (i32.const 999)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (func $out-of-bounds (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call_indirect $table (type $ii)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: (i32.const 999)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ (func $out-of-bounds (param $x i32) (param $y i32)
+ ;; The index here, 999, is out of bounds. We can't optimize that even in the
+ ;; immutable case, since we only assume the initial contents in the table are
+ ;; immutable, and so something might be written to offset 999 later.
+ (call_indirect (type $ii)
+ (local.get $x)
+ (local.get $y)
+ (i32.const 999)
+ )
+ )
)
-;; exported table
+;; exported table. only optimizable in the immutable case.
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
;; CHECK: (elem (i32.const 1) $foo)
;; CHECK: (export "tab" (table $0))
+ ;; IMMUT: (elem (i32.const 1) $foo)
+
+ ;; IMMUT: (export "tab" (table $0))
(export "tab" (table $0))
(elem (i32.const 1) $foo)
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -228,6 +352,12 @@
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call $foo
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect (type $ii)
(local.get $x)
@@ -240,10 +370,14 @@
;; non-constant table offset
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (global $g (mut i32) (i32.const 1))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (global $g (mut i32) (i32.const 1))
+
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
(global $g (mut i32) (i32.const 1))
(elem (global.get $g) $foo)
@@ -252,6 +386,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (global.get $g) $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -262,6 +401,13 @@
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $ii)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: (i32.const 1)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect (type $ii)
(local.get $x)
@@ -273,12 +419,17 @@
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (global $g (mut i32) (i32.const 1))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (global $g (mut i32) (i32.const 1))
+
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
;; CHECK: (table $1 5 5 funcref)
+ ;; IMMUT: (table $1 5 5 funcref)
(table $1 5 5 funcref)
(global $g (mut i32) (i32.const 1))
(elem (table $1) (global.get $g) func $foo)
@@ -287,6 +438,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (table $1) (global.get $g) func $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -297,6 +453,13 @@
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (call_indirect $1 (type $ii)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: (i32.const 1)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect $1 (type $ii)
(local.get $x)
@@ -309,10 +472,14 @@
;; non-constant call index
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (type $i32_i32_i32_=>_none (func (param i32 i32 i32)))
+
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
(elem (i32.const 1) $foo)
;; CHECK: (elem (i32.const 1) $foo)
@@ -320,6 +487,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 1) $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -330,6 +502,13 @@
;; CHECK-NEXT: (local.get $z)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32) (param $z i32)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $ii)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32) (param $z i32)
(call_indirect (type $ii)
(local.get $x)
@@ -342,8 +521,10 @@
;; bad index
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
(elem (i32.const 1) $foo)
;; CHECK: (elem (i32.const 1) $foo)
@@ -351,6 +532,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 1) $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -365,6 +551,17 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (block
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect (type $ii)
(local.get $x)
@@ -377,8 +574,10 @@
;; missing index
(module
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
(elem (i32.const 1) $foo)
;; CHECK: (elem (i32.const 1) $foo)
@@ -386,6 +585,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 1) $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -400,6 +604,17 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (block
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect (type $ii)
(local.get $x)
@@ -414,8 +629,12 @@
;; CHECK: (type $i32_=>_none (func (param i32)))
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $i32_=>_none (func (param i32)))
+
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
(elem (i32.const 1) $foo)
;; CHECK: (elem (i32.const 1) $foo)
@@ -423,6 +642,11 @@
;; CHECK: (func $foo (param $0 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 1) $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32)
(unreachable)
)
@@ -437,6 +661,17 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (block
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(call_indirect (type $ii)
(local.get $x)
@@ -453,6 +688,11 @@
;; CHECK: (func $foo (param $0 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (type $i32_=>_none (func (param i32)))
+
+ ;; IMMUT: (func $foo (param $0 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32)
(unreachable)
)
@@ -464,6 +704,9 @@
;; CHECK: (type $none_=>_none (func))
;; CHECK: (table $0 8 8 funcref)
+ ;; IMMUT: (type $none_=>_none (func))
+
+ ;; IMMUT: (table $0 8 8 funcref)
(table $0 8 8 funcref)
;; CHECK: (func $0
;; CHECK-NEXT: (block $block
@@ -475,6 +718,16 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $0
+ ;; IMMUT-NEXT: (block $block
+ ;; IMMUT-NEXT: (nop)
+ ;; IMMUT-NEXT: (block
+ ;; IMMUT-NEXT: (block
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $0
(block ;; the type of this block will change
(nop)
@@ -487,8 +740,10 @@
(module ;; indirect tail call
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
(elem (i32.const 1) $foo)
;; CHECK: (elem (i32.const 1) $foo)
@@ -496,6 +751,11 @@
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 1) $foo)
+
+ ;; IMMUT: (func $foo (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo (param i32) (param i32)
(unreachable)
)
@@ -505,6 +765,12 @@
;; CHECK-NEXT: (local.get $y)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (return_call $foo
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $bar (param $x i32) (param $y i32)
(return_call_indirect (type $ii)
(local.get $x)
@@ -518,6 +784,9 @@
;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32)))
;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $i32_i32_i32_=>_none (func (param i32 i32 i32)))
+
+ ;; IMMUT: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
(type $none (func))
@@ -525,6 +794,9 @@
;; CHECK: (type $i32_=>_none (func (param i32)))
;; CHECK: (table $0 5 5 funcref)
+ ;; IMMUT: (type $i32_=>_none (func (param i32)))
+
+ ;; IMMUT: (table $0 5 5 funcref)
(table $0 5 5 funcref)
(elem (i32.const 1) $foo1 $foo2)
;; CHECK: (elem (i32.const 1) $foo1 $foo2)
@@ -532,12 +804,20 @@
;; CHECK: (func $foo1 (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 1) $foo1 $foo2)
+
+ ;; IMMUT: (func $foo1 (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo1 (param i32) (param i32)
(unreachable)
)
;; CHECK: (func $foo2 (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (func $foo2 (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo2 (param i32) (param i32)
(unreachable)
)
@@ -562,6 +842,27 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select (param $x i32) (param $y i32) (param $z i32)
+ ;; IMMUT-NEXT: (local $3 i32)
+ ;; IMMUT-NEXT: (local $4 i32)
+ ;; IMMUT-NEXT: (local.set $3
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (local.set $4
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (if
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: (call $foo1
+ ;; IMMUT-NEXT: (local.get $3)
+ ;; IMMUT-NEXT: (local.get $4)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (call $foo2
+ ;; IMMUT-NEXT: (local.get $3)
+ ;; IMMUT-NEXT: (local.get $4)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select (param $x i32) (param $y i32) (param $z i32)
;; Test we can optimize a call_indirect whose index is a select between two
;; constants. We can emit an if and two direct calls for that.
@@ -586,6 +887,17 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-bad-1 (param $x i32) (param $y i32) (param $z i32)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $ii)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: (select
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: (i32.const 2)
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-bad-1 (param $x i32) (param $y i32) (param $z i32)
;; As above but one select arm is not constant.
(call_indirect (type $ii)
@@ -609,6 +921,17 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-bad-2 (param $x i32) (param $y i32) (param $z i32)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $ii)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: (select
+ ;; IMMUT-NEXT: (i32.const 2)
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-bad-2 (param $x i32) (param $y i32) (param $z i32)
;; As above but the other select arm is not constant.
(call_indirect (type $ii)
@@ -639,6 +962,24 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-out-of-range (param $x i32) (param $y i32) (param $z i32)
+ ;; IMMUT-NEXT: (local $3 i32)
+ ;; IMMUT-NEXT: (local $4 i32)
+ ;; IMMUT-NEXT: (local.set $3
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (local.set $4
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (if
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: (call $foo2
+ ;; IMMUT-NEXT: (local.get $3)
+ ;; IMMUT-NEXT: (local.get $4)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-out-of-range (param $x i32) (param $y i32) (param $z i32)
;; Both are constants, but one is out of range for the table, and there is no
;; valid function to call there; emit an unreachable.
@@ -667,6 +1008,21 @@
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-both-out-of-range (param $x i32) (param $y i32) (param $z i32)
+ ;; IMMUT-NEXT: (local $3 i32)
+ ;; IMMUT-NEXT: (local $4 i32)
+ ;; IMMUT-NEXT: (local.set $3
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (local.set $4
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (if
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-both-out-of-range (param $x i32) (param $y i32) (param $z i32)
;; Both are constants, and both are out of range for the table.
(call_indirect (type $ii)
@@ -690,6 +1046,17 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-unreachable-operand (param $x i32) (param $y i32) (param $z i32)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $ii)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: (select
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: (i32.const 2)
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-unreachable-operand (param $x i32) (param $y i32) (param $z i32)
;; One operand is unreachable.
(call_indirect (type $ii)
@@ -713,6 +1080,17 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-unreachable-condition (param $x i32) (param $y i32) (param $z i32)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $ii)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: (select
+ ;; IMMUT-NEXT: (i32.const 1)
+ ;; IMMUT-NEXT: (i32.const 2)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-unreachable-condition (param $x i32) (param $y i32) (param $z i32)
;; The condition is unreachable. We should not even create any vars here, and
;; just not do anything.
@@ -733,6 +1111,13 @@
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-bad-type (param $z i32)
+ ;; IMMUT-NEXT: (if
+ ;; IMMUT-NEXT: (local.get $z)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-bad-type (param $z i32)
;; The type here is $none, which does not match the functions at indexes 1 and
;; 2, so we know they will trap and can emit unreachables.
@@ -754,6 +1139,13 @@
;; CHECK: (type $none_=>_none (func))
;; CHECK: (table $0 15 15 funcref)
+ ;; IMMUT: (type $F (func (param (ref func))))
+
+ ;; IMMUT: (type $i32_=>_none (func (param i32)))
+
+ ;; IMMUT: (type $none_=>_none (func))
+
+ ;; IMMUT: (table $0 15 15 funcref)
(table $0 15 15 funcref)
(type $F (func (param (ref func))))
(elem (i32.const 10) $foo-ref $foo-ref)
@@ -765,6 +1157,13 @@
;; CHECK: (func $foo-ref (param $0 (ref func))
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
+ ;; IMMUT: (elem (i32.const 10) $foo-ref $foo-ref)
+
+ ;; IMMUT: (elem declare func $select-non-nullable)
+
+ ;; IMMUT: (func $foo-ref (param $0 (ref func))
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
(func $foo-ref (param (ref func))
;; helper function
(unreachable)
@@ -789,6 +1188,25 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-non-nullable (param $x i32)
+ ;; IMMUT-NEXT: (local $1 (ref null $i32_=>_none))
+ ;; IMMUT-NEXT: (local.set $1
+ ;; IMMUT-NEXT: (ref.func $select-non-nullable)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (if
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (call $foo-ref
+ ;; IMMUT-NEXT: (ref.as_non_null
+ ;; IMMUT-NEXT: (local.get $1)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (call $foo-ref
+ ;; IMMUT-NEXT: (ref.as_non_null
+ ;; IMMUT-NEXT: (local.get $1)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-non-nullable (param $x i32)
;; Test we can handle a non-nullable value when optimizing a select, during
;; which we place values in locals.
@@ -812,6 +1230,16 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-non-nullable-unreachable-condition
+ ;; IMMUT-NEXT: (call_indirect $0 (type $F)
+ ;; IMMUT-NEXT: (ref.func $select-non-nullable)
+ ;; IMMUT-NEXT: (select
+ ;; IMMUT-NEXT: (i32.const 10)
+ ;; IMMUT-NEXT: (i32.const 11)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-non-nullable-unreachable-condition
;; Test we ignore an unreachable condition and don't make any changes at all
;; to the code (in particular, we shouldn't add any vars).
@@ -835,6 +1263,16 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $select-non-nullable-unreachable-arg (param $x i32)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $F)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: (select
+ ;; IMMUT-NEXT: (i32.const 10)
+ ;; IMMUT-NEXT: (i32.const 11)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $select-non-nullable-unreachable-arg (param $x i32)
;; Test we ignore an unreachable argument and don't make any changes at all
;; to the code (in particular, we shouldn't add any vars).
@@ -852,18 +1290,23 @@
;; A table.set prevents optimization.
(module
;; CHECK: (type $v (func))
+ ;; IMMUT: (type $v (func))
(type $v (func))
;; CHECK: (table $has-set 5 5 funcref)
+ ;; IMMUT: (table $has-set 5 5 funcref)
(table $has-set 5 5 funcref)
;; CHECK: (table $no-set 5 5 funcref)
+ ;; IMMUT: (table $no-set 5 5 funcref)
(table $no-set 5 5 funcref)
;; CHECK: (elem $0 (table $has-set) (i32.const 1) func $foo)
+ ;; IMMUT: (elem $0 (table $has-set) (i32.const 1) func $foo)
(elem $0 (table $has-set) (i32.const 1) $foo)
;; CHECK: (elem $1 (table $no-set) (i32.const 1) func $foo)
+ ;; IMMUT: (elem $1 (table $no-set) (i32.const 1) func $foo)
(elem $1 (table $no-set) (i32.const 1) $foo)
;; CHECK: (func $foo
@@ -872,6 +1315,12 @@
;; CHECK-NEXT: (ref.func $foo)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
+ ;; IMMUT: (func $foo
+ ;; IMMUT-NEXT: (table.set $has-set
+ ;; IMMUT-NEXT: (i32.const 1)
+ ;; IMMUT-NEXT: (ref.func $foo)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
(func $foo
;; Technically this set writes the same value as is already there, but the
;; analysis will give up on optimizing when it sees any set to a table.
@@ -887,8 +1336,13 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $foo)
;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar
+ ;; IMMUT-NEXT: (call $foo)
+ ;; IMMUT-NEXT: (call $foo)
+ ;; IMMUT-NEXT: )
(func $bar
- ;; We can't optimize this one, but we can the one after it.
+ ;; We can't optimize this one, but we can the one after it. (But we can
+ ;; optimize both in the immutable case.)
(call_indirect $has-set (type $v)
(i32.const 1)
)
@@ -897,3 +1351,141 @@
)
)
)
+
+;; An imported table with a non-contiguous range in the initial contents.
+(module
+ ;; CHECK: (type $ii (func (param i32 i32)))
+ ;; IMMUT: (type $ii (func (param i32 i32)))
+ (type $ii (func (param i32 i32)))
+
+ ;; CHECK: (import "env" "table" (table $table 5 5 funcref))
+ ;; IMMUT: (import "env" "table" (table $table 5 5 funcref))
+ (import "env" "table" (table $table 5 5 funcref))
+ (elem (i32.const 1) $foo1)
+ (elem (i32.const 3) $foo2)
+
+ ;; CHECK: (elem $0 (i32.const 1) $foo1)
+
+ ;; CHECK: (elem $1 (i32.const 3) $foo2)
+
+ ;; CHECK: (func $foo1 (param $0 i32) (param $1 i32)
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (elem $0 (i32.const 1) $foo1)
+
+ ;; IMMUT: (elem $1 (i32.const 3) $foo2)
+
+ ;; IMMUT: (func $foo1 (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ (func $foo1 (param i32) (param i32)
+ (unreachable)
+ )
+ ;; CHECK: (func $foo2 (param $0 i32) (param $1 i32)
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (func $foo2 (param $0 i32) (param $1 i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ (func $foo2 (param i32) (param i32)
+ (unreachable)
+ )
+
+ ;; CHECK: (func $bar (param $x i32) (param $y i32)
+ ;; CHECK-NEXT: (call_indirect $table (type $ii)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call_indirect $table (type $ii)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call_indirect $table (type $ii)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call_indirect $table (type $ii)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call_indirect $table (type $ii)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: (i32.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (func $bar (param $x i32) (param $y i32)
+ ;; IMMUT-NEXT: (block
+ ;; IMMUT-NEXT: (block
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (call $foo1
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (block
+ ;; IMMUT-NEXT: (block
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (call $foo2
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: (call_indirect $table (type $ii)
+ ;; IMMUT-NEXT: (local.get $x)
+ ;; IMMUT-NEXT: (local.get $y)
+ ;; IMMUT-NEXT: (i32.const 4)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ (func $bar (param $x i32) (param $y i32)
+ ;; When assuming the initial contents are immutable, we can optimize some
+ ;; of these cases. 0 and 2 are offsets that are known to contain a null, so
+ ;; they will trap, and 1 and 3 contain known contents we can do a direct call
+ ;; to. 4 is out of bounds so we cannot optimize there. (And in all of these,
+ ;; we cannot optimize anything in the non-immutable case, since the table is
+ ;; imported.)
+ (call_indirect (type $ii)
+ (local.get $x)
+ (local.get $y)
+ (i32.const 0)
+ )
+ (call_indirect (type $ii)
+ (local.get $x)
+ (local.get $y)
+ (i32.const 1)
+ )
+ (call_indirect (type $ii)
+ (local.get $x)
+ (local.get $y)
+ (i32.const 2)
+ )
+ (call_indirect (type $ii)
+ (local.get $x)
+ (local.get $y)
+ (i32.const 3)
+ )
+ (call_indirect (type $ii)
+ (local.get $x)
+ (local.get $y)
+ (i32.const 4)
+ )
+ )
+)