| ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. |
| |
| ;; RUN: foreach %s %t wasm-opt --optimize-j2cl -all -S -o - | filecheck %s |
| |
| ;; Simple primitives are hoisted. |
| (module |
| ;; CHECK: (type $0 (func)) |
| |
| ;; CHECK: (global $field-i32@Foo i32 (i32.const 1)) |
| (global $field-i32@Foo (mut i32) (i32.const 0)) |
| ;; CHECK: (global $field-f64@Foo f64 (f64.const 1)) |
| (global $field-f64@Foo (mut f64) (f64.const 0)) |
| |
| ;; CHECK: (func $clinit_<once>_@Foo (type $0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $clinit_<once>_@Foo |
| (global.set $field-i32@Foo (i32.const 1)) |
| (global.set $field-f64@Foo (f64.const 1)) |
| ) |
| ) |
| |
| ;; Fields with more complex constant initialization are hoisted. |
| (module |
| |
| ;; CHECK: (type $A (struct (field i32))) |
| (type $A (struct (field i32))) |
| |
| ;; CHECK: (type $1 (func)) |
| |
| ;; CHECK: (global $referredField@Foo i32 (i32.const 42)) |
| (global $referredField@Foo i32 (i32.const 42)) |
| |
| ;; CHECK: (global $referredFieldMut@Foo (mut i32) (i32.const 42)) |
| (global $referredFieldMut@Foo (mut i32) (i32.const 42)) |
| |
| ;; CHECK: (global $field1@Foo anyref (struct.new $A |
| ;; CHECK-NEXT: (global.get $referredField@Foo) |
| ;; CHECK-NEXT: )) |
| (global $field1@Foo (mut anyref) (ref.null none)) |
| |
| ;; CHECK: (global $field2@Foo (mut anyref) (ref.null none)) |
| (global $field2@Foo (mut anyref) (ref.null none)) |
| |
| ;; CHECK: (global $field3@Foo anyref (global.get $field1@Foo)) |
| (global $field3@Foo (mut anyref) (ref.null none)) |
| |
| ;; CHECK: (func $clinit_<once>_@Foo (type $1) |
| ;; CHECK-NEXT: (global.set $field2@Foo |
| ;; CHECK-NEXT: (struct.new $A |
| ;; CHECK-NEXT: (global.get $referredFieldMut@Foo) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $clinit_<once>_@Foo |
| ;; Referred field is immutable, should hoist |
| (global.set $field1@Foo (struct.new $A ( |
| global.get $referredField@Foo) |
| )) |
| |
| ;; Referred field is mutable, should not hoist |
| (global.set $field2@Foo (struct.new $A |
| (global.get $referredFieldMut@Foo) |
| )) |
| |
| ;; Referred field is mutable but hoistable hence also this one. |
| ;; (Note that requires multiple iterations in a single run) |
| (global.set $field3@Foo (global.get $field1@Foo)) |
| ) |
| ) |
| |
| ;; Fields initialized to a non-default value shouldn't be hoisted. |
| (module |
| ;; CHECK: (type $A (struct)) |
| (type $A (struct)) |
| ;; CHECK: (type $1 (func)) |
| |
| ;; CHECK: (global $field-i32@Foo (mut i32) (i32.const 2)) |
| (global $field-i32@Foo (mut i32) (i32.const 2)) |
| |
| ;; CHECK: (global $field-any@Foo (mut anyref) (struct.new_default $A)) |
| (global $field-any@Foo (mut anyref) (struct.new $A)) |
| |
| ;; CHECK: (func $clinit_<once>_@Foo (type $1) |
| ;; CHECK-NEXT: (global.set $field-i32@Foo |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (global.set $field-any@Foo |
| ;; CHECK-NEXT: (struct.new_default $A) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $clinit_<once>_@Foo |
| (global.set $field-i32@Foo (i32.const 1)) |
| (global.set $field-any@Foo (struct.new $A)) |
| ) |
| ) |
| |
| ;; Non-block body is optimized |
| (module |
| |
| ;; CHECK: (type $0 (func)) |
| |
| ;; CHECK: (global $field@Foo i32 (i32.const 1)) |
| (global $field@Foo (mut i32) (i32.const 0)) |
| |
| ;; CHECK: (func $clinit_<once>_@Foo (type $0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $clinit_<once>_@Foo |
| (global.set $field@Foo (i32.const 1)) |
| ) |
| ) |
| |
| ;; $$class-initialized are not hoisted |
| (module |
| |
| ;; CHECK: (type $0 (func)) |
| |
| ;; CHECK: (global $$class-initialized@Foo (mut i32) (i32.const 0)) |
| (global $$class-initialized@Foo (mut i32) (i32.const 0)) |
| |
| ;; CHECK: (func $clinit_<once>_@Foo (type $0) |
| ;; CHECK-NEXT: (global.set $$class-initialized@Foo |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $clinit_<once>_@Foo |
| (global.set $$class-initialized@Foo (i32.const 1)) |
| ) |
| ) |
| |
| ;; Fields from different classes are not hoisted. |
| (module |
| |
| ;; CHECK: (type $0 (func)) |
| |
| ;; CHECK: (global $field@Foo (mut i32) (i32.const 0)) |
| (global $field@Foo (mut i32) (i32.const 0)) |
| |
| ;; CHECK: (func $clinit_<once>_@Bar (type $0) |
| ;; CHECK-NEXT: (global.set $field@Foo |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $clinit_<once>_@Bar |
| ;; Note that $clinit is @Bar and field is @Foo. |
| (global.set $field@Foo (i32.const 1)) |
| ) |
| ) |
| |
| ;; Getters are transitively inlined and their constants hoisted. |
| (module |
| ;; CHECK: (type $0 (func (result i32))) |
| |
| ;; CHECK: (global $$var1@Zoo i32 (i32.const 2)) |
| (global $$var1@Zoo (mut i32) (i32.const 0)) |
| ;; CHECK: (global $$var2@Zoo i32 (i32.const 2)) |
| (global $$var2@Zoo (mut i32) (i32.const 0)) |
| ;; CHECK: (global $$var3@Zoo i32 (i32.const 2)) |
| (global $$var3@Zoo (mut i32) (i32.const 0)) |
| |
| ;; CHECK: (func $getVar1_<once>_@Zoo (type $0) (result i32) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| (func $getVar1_<once>_@Zoo (result i32) |
| (if (global.get $$var1@Zoo) |
| (then |
| (return (global.get $$var1@Zoo)) |
| ) |
| ) |
| (global.set $$var1@Zoo (i32.const 2)) |
| (return (global.get $$var1@Zoo)) |
| ) |
| |
| ;; CHECK: (func $getVar2_<once>_@Zoo (type $0) (result i32) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| (func $getVar2_<once>_@Zoo (result i32) |
| (if (global.get $$var2@Zoo) |
| (then |
| (return (global.get $$var2@Zoo)) |
| ) |
| ) |
| (global.set $$var2@Zoo (call $getVar1_<once>_@Zoo)) |
| (return (global.get $$var2@Zoo)) |
| ) |
| |
| ;; CHECK: (func $getVar3_<once>_@Zoo (type $0) (result i32) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| (func $getVar3_<once>_@Zoo (result i32) |
| (if (global.get $$var3@Zoo) |
| (then |
| (return (global.get $$var3@Zoo)) |
| ) |
| ) |
| (global.set $$var3@Zoo (call $getVar2_<once>_@Zoo)) |
| (return (global.get $$var3@Zoo)) |
| ) |
| ) |
| |
| ;; Simple once functions are inlined |
| (module |
| ;; CHECK: (type $0 (func)) |
| |
| ;; CHECK: (type $1 (func (result i32))) |
| |
| ;; CHECK: (global $$var1@Zoo (mut i32) (i32.const 2)) |
| (global $$var1@Zoo (mut i32) (i32.const 2)) |
| ;; CHECK: (global $$var2@Zoo (mut i32) (i32.const 3)) |
| (global $$var2@Zoo (mut i32) (i32.const 3)) |
| |
| |
| ;; CHECK: (func $notOnceFunction@Zoo (type $0) |
| ;; CHECK-NEXT: ) |
| (func $notOnceFunction@Zoo |
| ) |
| |
| ;; CHECK: (func $nop_<once>_@Zoo (type $0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $nop_<once>_@Zoo |
| (nop) |
| ) |
| |
| ;; CHECK: (func $empty_<once>_@Zoo (type $0) |
| ;; CHECK-NEXT: ) |
| (func $empty_<once>_@Zoo |
| ) |
| |
| ;; CHECK: (func $simpleCall_<once>_@Zoo (type $0) |
| ;; CHECK-NEXT: (call $notOnceFunction@Zoo) |
| ;; CHECK-NEXT: ) |
| (func $simpleCall_<once>_@Zoo |
| (call $notOnceFunction@Zoo) |
| ) |
| |
| ;; CHECK: (func $globalGet_<once>_@Zoo (type $1) (result i32) |
| ;; CHECK-NEXT: (global.get $$var1@Zoo) |
| ;; CHECK-NEXT: ) |
| (func $globalGet_<once>_@Zoo (result i32) |
| (global.get $$var1@Zoo) |
| ) |
| |
| ;; CHECK: (func $globalSet_<once>_@Zoo (type $0) |
| ;; CHECK-NEXT: (global.set $$var2@Zoo |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $globalSet_<once>_@Zoo |
| (global.set $$var2@Zoo (i32.const 3)) |
| ) |
| |
| ;; CHECK: (func $caller_@Zoo (type $1) (result i32) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: (block |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call $notOnceFunction@Zoo) |
| ;; CHECK-NEXT: (global.set $$var2@Zoo |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (global.get $$var1@Zoo) |
| ;; CHECK-NEXT: ) |
| (func $caller_@Zoo (result i32) |
| (call $nop_<once>_@Zoo) |
| (call $empty_<once>_@Zoo) |
| (call $simpleCall_<once>_@Zoo) |
| (call $globalSet_<once>_@Zoo) |
| (call $globalGet_<once>_@Zoo) |
| ) |
| ) |
| |
| ;; Simple once functions that would be inlined if cleaned up. |
| (module |
| ;; CHECK: (type $0 (func (result i32))) |
| |
| ;; CHECK: (type $1 (func)) |
| |
| ;; CHECK: (global $$var1@Zoo (mut i32) (i32.const 2)) |
| (global $$var1@Zoo (mut i32) (i32.const 2)) |
| |
| |
| ;; CHECK: (func $justReturn_<once>_@Zoo (type $1) |
| ;; CHECK-NEXT: (return) |
| ;; CHECK-NEXT: ) |
| (func $justReturn_<once>_@Zoo |
| (return) |
| ) |
| |
| ;; CHECK: (func $returnGlobalGet_<once>_@Zoo (type $0) (result i32) |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (global.get $$var1@Zoo) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $returnGlobalGet_<once>_@Zoo (result i32) |
| (return (global.get $$var1@Zoo)) |
| ) |
| |
| ;; CHECK: (func $caller_@Zoo (type $0) (result i32) |
| ;; CHECK-NEXT: (call $justReturn_<once>_@Zoo) |
| ;; CHECK-NEXT: (call $returnGlobalGet_<once>_@Zoo) |
| ;; CHECK-NEXT: ) |
| (func $caller_@Zoo (result i32) |
| (call $justReturn_<once>_@Zoo) |
| (call $returnGlobalGet_<once>_@Zoo) |
| ) |
| ) |
| |
| ;; Hoist constants for getters that have transitive dependencies. |
| (module |
| ;; CHECK: (type $A (struct (field i32))) |
| (type $A (struct (field i32))) |
| |
| ;; CHECK: (type $1 (func (result (ref null $A)))) |
| |
| ;; CHECK: (global $$class@X (ref null $A) (struct.new $A |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: )) |
| (global $$class@X (mut (ref null $A)) (ref.null $A)) |
| ;; CHECK: (global $$class@Y (ref null $A) (global.get $$class@X)) |
| (global $$class@Y (mut (ref null $A)) (ref.null $A)) |
| |
| ;; CHECK: (func $f_<once>_@X (type $1) (result (ref null $A)) |
| ;; CHECK-NEXT: (global.get $$class@X) |
| ;; CHECK-NEXT: ) |
| (func $f_<once>_@X (result (ref null $A)) |
| (block (result (ref null $A)) |
| (if (i32.eqz (ref.is_null (global.get $$class@X))) |
| (then |
| (return (global.get $$class@X)) |
| ) |
| ) |
| (global.set $$class@X (struct.new $A (i32.const 2))) |
| (global.get $$class@X) |
| ) |
| ) |
| |
| ;; CHECK: (func $f_<once>_@Y (type $1) (result (ref null $A)) |
| ;; CHECK-NEXT: (global.get $$class@Y) |
| ;; CHECK-NEXT: ) |
| (func $f_<once>_@Y (result (ref null $A)) |
| (block (result (ref null $A)) |
| (if |
| (i32.eqz (ref.is_null (global.get $$class@Y))) |
| (then |
| (return (global.get $$class@Y)) |
| ) |
| ) |
| (global.set $$class@Y (call $f_<once>_@X)) |
| (global.get $$class@Y) |
| ) |
| ) |
| ) |