;; 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 -all --simplify-globals -S -o - | filecheck %s ;; $single-use has a single use, and we can fold a copy of that code into its ;; use. That global then becomes unused. (module ;; CHECK: (type $A (struct (field anyref))) (type $A (struct (field anyref))) ;; CHECK: (type $1 (func)) ;; CHECK: (global $single-use anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $single-use anyref (struct.new $A (i31.new (i32.const 42) ) )) ;; CHECK: (global $other (mut anyref) (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $other (mut anyref) (global.get $single-use)) ;; CHECK: (func $user (type $1) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (global.get $other) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.set $other ;; CHECK-NEXT: (ref.null none) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $user ;; Uses of $other do not affect optimization (drop (global.get $other) ) (global.set $other (ref.null any) ) ) ) ;; As above, but now there is a second use, so we do nothing. (module ;; CHECK: (type $A (struct (field anyref))) (type $A (struct (field anyref))) ;; CHECK: (global $single-use anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $single-use anyref (struct.new $A (i31.new (i32.const 42) ) )) ;; CHECK: (global $other anyref (global.get $single-use)) (global $other anyref (global.get $single-use)) ;; CHECK: (global $other2 anyref (global.get $single-use)) (global $other2 anyref (global.get $single-use)) ) ;; As the first testcase, but now there is a second use in function code, so ;; again we do nothing. (module ;; CHECK: (type $A (struct (field anyref))) (type $A (struct (field anyref))) ;; CHECK: (type $1 (func)) ;; CHECK: (global $single-use anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $single-use anyref (struct.new $A (i31.new (i32.const 42) ) )) ;; CHECK: (global $other anyref (global.get $single-use)) (global $other anyref (global.get $single-use)) ;; CHECK: (func $user (type $1) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (global.get $single-use) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $user (drop (global.get $single-use) ) ) ) ;; As the first testcase, but now $single-use is imported, so there is no code ;; to fold. (module (type $A (struct (field anyref))) ;; CHECK: (import "a" "b" (global $single-use anyref)) (import "a" "b" (global $single-use anyref)) ;; CHECK: (global $other anyref (global.get $single-use)) (global $other anyref (global.get $single-use)) ) ;; As the first testcase, but here the single use is in function code, so ;; we do nothing (as it could be executed more than once). (module ;; CHECK: (type $A (struct (field anyref))) (type $A (struct (field anyref))) ;; CHECK: (type $1 (func)) ;; CHECK: (global $single-use anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $single-use anyref (struct.new $A (i31.new (i32.const 42) ) )) ;; CHECK: (func $user (type $1) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (global.get $single-use) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $user (drop (global.get $single-use) ) ) ) ;; As the first testcase, but now the single use is nested in other code. We ;; can still optimize. (module ;; CHECK: (type $A (struct (field anyref))) (type $A (struct (field anyref))) ;; CHECK: (global $single-use anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $single-use anyref (struct.new $A (i31.new (i32.const 42) ) )) ;; CHECK: (global $other anyref (struct.new $A ;; CHECK-NEXT: (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $other anyref (struct.new $A (global.get $single-use) )) ) ;; Test multiple separate optimizations in one module. (module ;; CHECK: (type $A (struct (field anyref))) (type $A (struct (field anyref))) ;; CHECK: (global $single-use1 anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $single-use1 anyref (struct.new $A (i31.new (i32.const 42) ) )) ;; CHECK: (global $single-use2 anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 1337) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $single-use2 anyref (struct.new $A (i31.new (i32.const 1337) ) )) ;; CHECK: (global $other1 anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $other1 anyref (global.get $single-use1)) ;; CHECK: (global $single-use3 anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 99999) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $single-use3 anyref (struct.new $A (i31.new (i32.const 99999) ) )) ;; CHECK: (global $other2 anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 1337) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $other2 anyref (global.get $single-use2)) ;; CHECK: (global $other3 anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 99999) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $other3 anyref (global.get $single-use3)) ) ;; Test multiple related optimizations in one module: more than one nesting into ;; one global (module ;; CHECK: (type $A (struct (field anyref) (field anyref))) (type $A (struct (field anyref) (field anyref))) ;; CHECK: (global $single-use1 anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null none) ;; CHECK-NEXT: )) (global $single-use1 anyref (struct.new $A (i31.new (i32.const 42) ) (ref.null any) )) ;; CHECK: (global $single-use2 anyref (struct.new $A ;; CHECK-NEXT: (ref.null none) ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 1337) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $single-use2 anyref (struct.new $A (ref.null any) (i31.new (i32.const 1337) ) )) ;; CHECK: (global $other anyref (struct.new $A ;; CHECK-NEXT: (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null none) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.new $A ;; CHECK-NEXT: (ref.null none) ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 1337) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $other anyref (struct.new $A (global.get $single-use1) (global.get $single-use2) )) ) ;; Test multiple related optimizations in one module: a chain. (module ;; CHECK: (type $A (struct (field anyref))) (type $A (struct (field anyref))) ;; CHECK: (global $single-use1 anyref (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: )) (global $single-use1 anyref (i31.new (i32.const 42) )) ;; CHECK: (global $other1 anyref (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $other1 anyref (struct.new $A (global.get $single-use1) )) ;; CHECK: (global $other2 anyref (struct.new $A ;; CHECK-NEXT: (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $other2 anyref (struct.new $A (global.get $other1) )) ;; CHECK: (global $other3 anyref (struct.new $A ;; CHECK-NEXT: (struct.new $A ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )) (global $other3 anyref (global.get $other2)) )