;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.

;; RUN: foreach %s %t wasm-opt -all --deinstrument-branch-hints -S -o - | filecheck %s

(module
  ;; CHECK:      (type $0 (func))

  ;; CHECK:      (type $1 (func (param i32 i32 i32)))

  ;; CHECK:      (import "fuzzing-support" "log-branch" (func $log (type $1) (param i32 i32 i32)))
  (import "fuzzing-support" "log-branch" (func $log (param i32 i32 i32)))

  ;; CHECK:      (func $if (type $0)
  ;; CHECK-NEXT:  (local $temp i32)
  ;; CHECK-NEXT:  (@metadata.code.branch_hint "\00")
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 42)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 1337)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 99)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if
    (local $temp i32)
    ;; The instrumentation should be removed, and the if's condition should
    ;; be 42.
    (@metadata.code.branch_hint "\00")
    (if
      (block (result i32)
        (local.set $temp
          (i32.const 42)
        )
        (call $log
          (i32.const 1)
          (i32.const 0)
          (local.get $temp)
        )
        (local.get $temp)
      )
      (then
        (drop
          (i32.const 1337)
        )
      )
      (else
        (drop
          (i32.const 99)
        )
      )
    )
  )

  ;; CHECK:      (func $br (type $0)
  ;; CHECK-NEXT:  (local $temp i32)
  ;; CHECK-NEXT:  (block $out
  ;; CHECK-NEXT:   (@metadata.code.branch_hint "\01")
  ;; CHECK-NEXT:   (br_if $out
  ;; CHECK-NEXT:    (i32.const 42)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $br
    ;; The same, with a br.
    (local $temp i32)
    (block $out
      (@metadata.code.branch_hint "\01")
      (br_if $out
        (block (result i32)
          (local.set $temp
            (i32.const 42)
          )
          (call $log
            (i32.const 4)
            (i32.const 0)
            (local.get $temp)
          )
          (local.get $temp)
        )
      )
    )
  )

  ;; CHECK:      (func $br-before (type $0)
  ;; CHECK-NEXT:  (local $temp i32)
  ;; CHECK-NEXT:  (block $out
  ;; CHECK-NEXT:   (local.set $temp
  ;; CHECK-NEXT:    (local.get $temp)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (nop)
  ;; CHECK-NEXT:   (@metadata.code.branch_hint "\01")
  ;; CHECK-NEXT:   (br_if $out
  ;; CHECK-NEXT:    (i32.const 42)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $br-before
    ;; As above, but the instrumentation is before us, leaving only a local.get
    ;; in the br's condition. We should still identify the pattern and remove
    ;; the logging (but we leave the local.set for other things to clean up).
    (local $temp i32)
    (block $out
      (local.set $temp
        (i32.const 42)
      )
      (call $log
        (i32.const 4)
        (i32.const 0)
        (local.get $temp)
      )
      (@metadata.code.branch_hint "\01")
      (br_if $out
        (local.get $temp)
      )
    )
  )

  ;; CHECK:      (func $br-before-effects (type $0)
  ;; CHECK-NEXT:  (local $temp i32)
  ;; CHECK-NEXT:  (local $other i32)
  ;; CHECK-NEXT:  (block $out
  ;; CHECK-NEXT:   (local.set $temp
  ;; CHECK-NEXT:    (local.get $temp)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (block
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $other
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (@metadata.code.branch_hint "\01")
  ;; CHECK-NEXT:   (br_if $out
  ;; CHECK-NEXT:    (i32.const 42)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $br-before-effects
    ;; As above, but there are effects in the call's children that we must
    ;; keep.
    (local $temp i32)
    (local $other i32)
    (block $out
      (local.set $temp
        (i32.const 42)
      )
      (call $log
        (i32.const 4)
        (local.tee $other  ;; this tee must be kept around
          (i32.const 0)
        )
        (local.get $temp)
      )
      (@metadata.code.branch_hint "\01")
      (br_if $out
        (local.get $temp)
      )
    )
  )
)
