;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; RUN: foreach %s %t wasm-opt --gto --closed-world -all -S -o - | filecheck %s

;; RMW ops are combined reads and writes, so they keep fields alive and mutable.
(module
  ;; CHECK:      (type $A (shared (struct (field (mut i32)))))
  (type $A (shared (struct (mut i32))))

  ;; CHECK:      (type $1 (func (param (ref $A)) (result i32)))

  ;; CHECK:      (func $rmw (type $1) (param $0 (ref $A)) (result i32)
  ;; CHECK-NEXT:  (struct.atomic.rmw.add $A 0
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rmw (param (ref $A)) (result i32)
    (struct.atomic.rmw.add $A 0
      (local.get 0)
      (i32.const 0)
    )
  )
)

;; Even when it is a copy from a field to itself, xchg keeps the field alive.
;; Optimizing this is left to ConstantFieldPropagation.
(module
  ;; CHECK:      (type $A (shared (struct (field (mut i32)))))
  (type $A (shared (struct (mut i32))))

  ;; CHECK:      (type $1 (func (param (ref $A) (ref $A)) (result i32)))

  ;; CHECK:      (func $xchg (type $1) (param $0 (ref $A)) (param $1 (ref $A)) (result i32)
  ;; CHECK-NEXT:  (struct.atomic.rmw.xchg $A 0
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (struct.atomic.get $A 0
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $xchg (param (ref $A) (ref $A)) (result i32)
    (struct.atomic.rmw.xchg $A 0
      (local.get 0)
      (struct.atomic.get $A 0
        (local.get 1)
      )
    )
  )
)

;; Same with cmpxchg.
(module
  ;; CHECK:      (type $A (shared (struct (field (mut i32)))))
  (type $A (shared (struct (mut i32))))

  ;; CHECK:      (type $1 (func (param (ref $A) i32 (ref $A)) (result i32)))

  ;; CHECK:      (func $cmpxchg (type $1) (param $0 (ref $A)) (param $1 i32) (param $2 (ref $A)) (result i32)
  ;; CHECK-NEXT:  (struct.atomic.rmw.cmpxchg $A 0
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:   (struct.atomic.get $A 0
  ;; CHECK-NEXT:    (local.get $2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $cmpxchg (param (ref $A) i32 (ref $A)) (result i32)
    (struct.atomic.rmw.cmpxchg $A 0
      (local.get 0)
      (local.get 1)
      (struct.atomic.get $A 0
        (local.get 2)
      )
    )
  )
)
