;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. ;; RUN: wasm-opt %s --simplify-locals -all -S -o - \ ;; RUN: | filecheck %s (module (memory 10 10) ;; CHECK: (type $array (sub (array (mut i8)))) (type $array (sub (array (mut i8)))) ;; CHECK: (type $array16 (sub (array (mut i16)))) (type $array16 (sub (array (mut i16)))) ;; CHECK: (func $no-new-past-store (type $1) ;; CHECK-NEXT: (local $temp stringref) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (string.new_utf8 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (string.new_wtf8 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (string.new_lossy_utf8 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (string.new_wtf16 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $no-new-past-store (local $temp stringref) ;; A string.new cannot be moved past a memory store. (local.set $temp (string.new_utf8 (i32.const 1) (i32.const 2) ) ) (i32.store (i32.const 3) (i32.const 4) ) (drop (local.get $temp) ) (local.set $temp (string.new_wtf8 (i32.const 1) (i32.const 2) ) ) (i32.store (i32.const 3) (i32.const 4) ) (drop (local.get $temp) ) (local.set $temp (string.new_lossy_utf8 (i32.const 1) (i32.const 2) ) ) (i32.store (i32.const 3) (i32.const 4) ) (drop (local.get $temp) ) (local.set $temp (string.new_wtf16 (i32.const 1) (i32.const 2) ) ) (i32.store (i32.const 3) (i32.const 4) ) (drop (local.get $temp) ) ) ;; CHECK: (func $yes-new-past-store (type $1) ;; CHECK-NEXT: (local $temp stringref) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.new_utf8 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $yes-new-past-store (local $temp stringref) ;; A string.new can be moved past a memory load. (local.set $temp (string.new_utf8 (i32.const 1) (i32.const 2) ) ) (drop (i32.load (i32.const 3) ) ) (drop (local.get $temp) ) ) ;; CHECK: (func $no-new-past-store-gc (type $3) (param $array (ref $array)) (param $array16 (ref $array16)) ;; CHECK-NEXT: (local $temp stringref) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (string.new_utf8_array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (array.set $array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (string.new_wtf8_array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (array.set $array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (string.new_lossy_utf8_array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (array.set $array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (string.new_wtf16_array ;; CHECK-NEXT: (local.get $array16) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (array.set $array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $no-new-past-store-gc (param $array (ref $array)) (param $array16 (ref $array16)) (local $temp stringref) ;; A string.new_***_array cannot be moved past a GC store. (local.set $temp (string.new_utf8_array (local.get $array) (i32.const 1) (i32.const 2) ) ) (array.set $array (local.get $array) (i32.const 3) (i32.const 4) ) (drop (local.get $temp) ) (local.set $temp (string.new_wtf8_array (local.get $array) (i32.const 1) (i32.const 2) ) ) (array.set $array (local.get $array) (i32.const 3) (i32.const 4) ) (drop (local.get $temp) ) (local.set $temp (string.new_lossy_utf8_array (local.get $array) (i32.const 1) (i32.const 2) ) ) (array.set $array (local.get $array) (i32.const 3) (i32.const 4) ) (drop (local.get $temp) ) (local.set $temp (string.new_wtf16_array (local.get $array16) (i32.const 1) (i32.const 2) ) ) (array.set $array (local.get $array) (i32.const 3) (i32.const 4) ) (drop (local.get $temp) ) ) ;; CHECK: (func $no-load-past-encode (type $4) (param $ref stringref) ;; CHECK-NEXT: (local $temp i32) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.encode_wtf8 ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.encode_utf8 ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.encode_lossy_utf8 ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 30) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.encode_wtf16 ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 40) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $no-load-past-encode (param $ref stringref) (local $temp i32) ;; string.encode writes to memory, so a load can't be moved past it. (local.set $temp (i32.load (i32.const 1) ) ) (drop (string.encode_wtf8 (local.get $ref) (i32.const 10) ) ) (drop (local.get $temp) ) (local.set $temp (i32.load (i32.const 1) ) ) (drop (string.encode_utf8 (local.get $ref) (i32.const 20) ) ) (drop (local.get $temp) ) (local.set $temp (i32.load (i32.const 1) ) ) (drop (string.encode_lossy_utf8 (local.get $ref) (i32.const 30) ) ) (drop (local.get $temp) ) (local.set $temp (i32.load (i32.const 1) ) ) (drop (string.encode_wtf16 (local.get $ref) (i32.const 40) ) ) (drop (local.get $temp) ) ) ;; CHECK: (func $no-load-past-encode-gc (type $5) (param $ref stringref) (param $array (ref $array)) (param $array16 (ref $array16)) ;; CHECK-NEXT: (local $temp i32) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (array.get_u $array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.encode_wtf8_array ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (array.get_u $array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.encode_utf8_array ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (array.get_u $array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.encode_lossy_utf8_array ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 30) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $temp ;; CHECK-NEXT: (array.get_u $array ;; CHECK-NEXT: (local.get $array) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.encode_wtf16_array ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (local.get $array16) ;; CHECK-NEXT: (i32.const 40) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $no-load-past-encode-gc (param $ref stringref) (param $array (ref $array)) (param $array16 (ref $array16)) (local $temp i32) ;; string.encode_*_array writes to an array, so an array get can't be moved ;; past it. (local.set $temp (array.get $array (local.get $array) (i32.const 0) ) ) (drop (string.encode_wtf8_array (local.get $ref) (local.get $array) (i32.const 10) ) ) (drop (local.get $temp) ) (local.set $temp (array.get $array (local.get $array) (i32.const 0) ) ) (drop (string.encode_utf8_array (local.get $ref) (local.get $array) (i32.const 20) ) ) (drop (local.get $temp) ) (local.set $temp (array.get $array (local.get $array) (i32.const 0) ) ) (drop (string.encode_lossy_utf8_array (local.get $ref) (local.get $array) (i32.const 30) ) ) (drop (local.get $temp) ) (local.set $temp (array.get $array (local.get $array) (i32.const 0) ) ) (drop (string.encode_wtf16_array (local.get $ref) (local.get $array16) (i32.const 40) ) ) (drop (local.get $temp) ) ) ;; CHECK: (func $no-iteration-past-each-other (type $6) (param $iter stringview_iter) ;; CHECK-NEXT: (local $i32 i32) ;; CHECK-NEXT: (local.set $i32 ;; CHECK-NEXT: (stringview_iter.next ;; CHECK-NEXT: (local.get $iter) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (stringview_iter.advance ;; CHECK-NEXT: (local.get $iter) ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $i32) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $i32 ;; CHECK-NEXT: (stringview_iter.next ;; CHECK-NEXT: (local.get $iter) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (stringview_iter.rewind ;; CHECK-NEXT: (local.get $iter) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $i32) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $no-iteration-past-each-other (param $iter stringview_iter) (local $i32 i32) ;; Iteration operations interact with each other, and can't be moved past ;; each other. (local.set $i32 (stringview_iter.next (local.get $iter) ) ) (drop (stringview_iter.advance (local.get $iter) (i32.const 3) ) ) (drop (local.get $i32) ) (local.set $i32 (stringview_iter.next (local.get $iter) ) ) (drop (stringview_iter.rewind (local.get $iter) (i32.const 4) ) ) (drop (local.get $i32) ) ) )