;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: wasm-opt %s --optimize-instructions --mvp-features -S -o - | filecheck %s

(module
  ;; CHECK:      (type $0 (func (param i32 i64)))
  (type $0 (func (param i32 i64)))

  ;; CHECK:      (import "a" "b" (func $get-f64 (result f64)))
  (import "a" "b" (func $get-f64 (result f64)))

  ;; CHECK:      (import "a" "c" (func $set-i32 (param i32)))
  (import "a" "c" (func $set-i32 (param i32)))

  (memory 0)

  ;; CHECK:      (func $and-and (param $i1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (local.get $i1)
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $and-and (param $i1 i32) (result i32)
    (i32.and
      (i32.and
        (local.get $i1)
        (i32.const 5)
      )
      (i32.const 3)
    )
  )
  ;; CHECK:      (func $or-or (param $i1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.or
  ;; CHECK-NEXT:   (local.get $i1)
  ;; CHECK-NEXT:   (i32.const 3)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $or-or (param $i1 i32) (result i32)
    (i32.or
      (i32.or
        (local.get $i1)
        (i32.const 1)
      )
      (i32.const 2)
    )
  )
  ;; CHECK:      (func $xor-xor (param $i1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.xor
  ;; CHECK-NEXT:   (local.get $i1)
  ;; CHECK-NEXT:   (i32.const 5)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $xor-xor (param $i1 i32) (result i32)
    (i32.xor
      (i32.xor
        (local.get $i1)
        (i32.const -2)
      )
      (i32.const -5)
    )
  )
  ;; CHECK:      (func $mul-mul (param $i1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (local.get $i1)
  ;; CHECK-NEXT:   (i32.const -10)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $mul-mul (param $i1 i32) (result i32)
    (i32.mul
      (i32.mul
        (local.get $i1)
        (i32.const -2)
      )
      (i32.const 5)
    )
  )
  ;; overflow also valid
  ;; CHECK:      (func $mul-mul-overflow (param $i1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (local.get $i1)
  ;; CHECK-NEXT:   (i32.const -133169153)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $mul-mul-overflow (param $i1 i32) (result i32)
    (i32.mul
      (i32.mul
        (local.get $i1)
        (i32.const 0xfffff)
      )
      (i32.const 0x8000001)
    )
  )
  ;; CHECK:      (func $if-eqz-one-arm (param $i1 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (local.get $i1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-one-arm (param $i1 i32)
    (if
      (i32.eqz
        (local.get $i1)
      )
      (then
        (drop
          (i32.const 10)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-one-arm-effect-condition-1 (param $i1 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $i1
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-one-arm-effect-condition-1 (param $i1 i32)
    (if
      (i32.eqz
        (local.tee $i1
          (i32.const 0)
        )
      )
      (then
        (drop
          (i32.const 10)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-one-arm-effect-condition-2 (param $i1 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $i1
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-one-arm-effect-condition-2 (param $i1 i32)
    (if
      (i32.eqz
        (local.tee $i1
          (i32.const 1)
        )
      )
      (then
        (drop
          (i32.const 10)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-one-arm-effect-condition-3 (param $i1 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $i1
  ;; CHECK-NEXT:      (i32.const 100)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-one-arm-effect-condition-3 (param $i1 i32)
    (if
      (i32.eqz
        (local.tee $i1
          (i32.const 100)
        )
      )
      (then
        (drop
          (i32.const 10)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-two-arms (param $i1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (local.get $i1)
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 12)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-two-arms (param $i1 i32)
    (if
      (i32.eqz
        (local.get $i1)
      )
      (then
        (drop
          (i32.const 11)
        )
      )
      (else
        (drop
          (i32.const 12)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-two-arms-effect-condition-1 (param $i1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.tee $i1
  ;; CHECK-NEXT:       (i32.const 0)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 12)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-two-arms-effect-condition-1 (param $i1 i32)
    (if
      (i32.eqz
        (local.tee $i1
          (i32.const 0)
        )
      )
      (then
        (drop
          (i32.const 11)
        )
      )
      (else
        (drop
          (i32.const 12)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-two-arms-effect-condition-2 (param $i1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.tee $i1
  ;; CHECK-NEXT:       (i32.const 1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 12)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-two-arms-effect-condition-2 (param $i1 i32)
    (if
      (i32.eqz
        (local.tee $i1
          (i32.const 1)
        )
      )
      (then
        (drop
          (i32.const 11)
        )
      )
      (else
        (drop
          (i32.const 12)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-two-arms-effect-condition-3 (param $i1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.tee $i1
  ;; CHECK-NEXT:       (i32.const 100)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 12)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-two-arms-effect-condition-3 (param $i1 i32)
    (if
      (i32.eqz
        (local.tee $i1
          (i32.const 100)
        )
      )
      (then
        (drop
          (i32.const 11)
        )
      )
      (else
        (drop
          (i32.const 12)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-two-arms-i64 (param $i2 i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (i64.eqz
  ;; CHECK-NEXT:     (local.get $i2)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 12)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-two-arms-i64 (param $i2 i64)
    (if
      (i64.eqz
        (local.get $i2)
      )
      (then
        (drop
          (i32.const 11)
        )
      )
      (else
        (drop
          (i32.const 12)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-two-arms-i64-effect-condition-1 (param $i2 i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.tee $i2
  ;; CHECK-NEXT:       (i64.const 0)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 12)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-two-arms-i64-effect-condition-1 (param $i2 i64)
    (if
      (i64.eqz
        (local.tee $i2
          (i64.const 0)
        )
      )
      (then
        (drop
          (i32.const 11)
        )
      )
      (else
        (drop
          (i32.const 12)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-two-arms-i64-effect-condition-2 (param $i2 i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.tee $i2
  ;; CHECK-NEXT:       (i64.const 1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 12)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-two-arms-i64-effect-condition-2 (param $i2 i64)
    (if
      (i64.eqz
        (local.tee $i2
          (i64.const 1)
        )
      )
      (then
        (drop
          (i32.const 11)
        )
      )
      (else
        (drop
          (i32.const 12)
        )
      )
    )
  )
  ;; CHECK:      (func $if-eqz-two-arms-i64-effect-condition-3 (param $i2 i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.tee $i2
  ;; CHECK-NEXT:       (i64.const 100)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 12)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-two-arms-i64-effect-condition-3 (param $i2 i64)
    (if
      (i64.eqz
        (local.tee $i2
          (i64.const 100)
        )
      )
      (then
        (drop
          (i32.const 11)
        )
      )
      (else
        (drop
          (i32.const 12)
        )
      )
    )
  )

  ;; CHECK:      (func $eqz-gt_s (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-gt_s (result i32)
    (i32.eqz
      (i32.gt_s
        (i32.const 1)
        (i32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-ge_s (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-ge_s (result i32)
    (i32.eqz
      (i32.ge_s
        (i32.const 1)
        (i32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-lt_s (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-lt_s (result i32)
    (i32.eqz
      (i32.lt_s
        (i32.const 1)
        (i32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-le_s (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-le_s (result i32)
    (i32.eqz
      (i32.le_s
        (i32.const 1)
        (i32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-gt_u (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-gt_u (result i32)
    (i32.eqz
      (i32.gt_u
        (i32.const 1)
        (i32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-ge_u (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-ge_u (result i32)
    (i32.eqz
      (i32.ge_u
        (i32.const 1)
        (i32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-lt_u (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-lt_u (result i32)
    (i32.eqz
      (i32.lt_u
        (i32.const 1)
        (i32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-le_u (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-le_u (result i32)
    (i32.eqz
      (i32.le_u
        (i32.const 1)
        (i32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-gt (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (f32.gt
  ;; CHECK-NEXT:    (f32.const 1)
  ;; CHECK-NEXT:    (f32.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-gt (result i32)
    (i32.eqz
      (f32.gt
        (f32.const 1)
        (f32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-ge (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (f32.ge
  ;; CHECK-NEXT:    (f32.const 1)
  ;; CHECK-NEXT:    (f32.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-ge (result i32)
    (i32.eqz
      (f32.ge
        (f32.const 1)
        (f32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-lt (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (f32.lt
  ;; CHECK-NEXT:    (f32.const 1)
  ;; CHECK-NEXT:    (f32.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-lt (result i32)
    (i32.eqz
      (f32.lt
        (f32.const 1)
        (f32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-le (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (f32.le
  ;; CHECK-NEXT:    (f32.const 1)
  ;; CHECK-NEXT:    (f32.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-le (result i32)
    (i32.eqz
      (f32.le
        (f32.const 1)
        (f32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-gt-f64 (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (f64.gt
  ;; CHECK-NEXT:    (f64.const 1)
  ;; CHECK-NEXT:    (f64.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-gt-f64 (result i32)
    (i32.eqz
      (f64.gt
        (f64.const 1)
        (f64.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-ge-f64 (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (f64.ge
  ;; CHECK-NEXT:    (f64.const 1)
  ;; CHECK-NEXT:    (f64.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-ge-f64 (result i32)
    (i32.eqz
      (f64.ge
        (f64.const 1)
        (f64.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-lt-f64 (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (f64.lt
  ;; CHECK-NEXT:    (f64.const 1)
  ;; CHECK-NEXT:    (f64.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-lt-f64 (result i32)
    (i32.eqz
      (f64.lt
        (f64.const 1)
        (f64.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-le-f64 (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (f64.le
  ;; CHECK-NEXT:    (f64.const 1)
  ;; CHECK-NEXT:    (f64.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-le-f64 (result i32)
    (i32.eqz
      (f64.le
        (f64.const 1)
        (f64.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-eq (result i32)
  ;; CHECK-NEXT:  (f32.ne
  ;; CHECK-NEXT:   (f32.const 1)
  ;; CHECK-NEXT:   (f32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-eq (result i32)
    (i32.eqz
      (f32.eq
        (f32.const 1)
        (f32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-ne (result i32)
  ;; CHECK-NEXT:  (f32.eq
  ;; CHECK-NEXT:   (f32.const 1)
  ;; CHECK-NEXT:   (f32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-ne (result i32)
    (i32.eqz
      (f32.ne
        (f32.const 1)
        (f32.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-eq-f64 (result i32)
  ;; CHECK-NEXT:  (f64.ne
  ;; CHECK-NEXT:   (f64.const 1)
  ;; CHECK-NEXT:   (f64.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-eq-f64 (result i32)
    (i32.eqz
      (f64.eq
        (f64.const 1)
        (f64.const 2)
      )
    )
  )
  ;; CHECK:      (func $eqz-ne-f64 (result i32)
  ;; CHECK-NEXT:  (f64.eq
  ;; CHECK-NEXT:   (f64.const 1)
  ;; CHECK-NEXT:   (f64.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eqz-ne-f64 (result i32)
    (i32.eqz
      (f64.ne
        (f64.const 1)
        (f64.const 2)
      )
    )
  )

  ;; we handle only 0 in the right position, as we assume a const is there, and
  ;; don't care about whether both are consts here (precompute does that, so no
  ;; need)
  ;; CHECK:      (func $eq-zero-rhs (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-zero-rhs (result i32)
    (i32.eq
      (i32.const 100)
      (i32.const 0)
    )
  )
  ;; CHECK:      (func $eq-zero-lhs (result i32)
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $eq-zero-lhs (result i32)
    (i32.eq
      (i32.const 0)
      (i32.const 100)
    )
  )
  ;; CHECK:      (func $eq-zero-zero (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-zero-zero (result i32)
    (i32.eq
      (i32.const 0)
      (i32.const 0)
    )
  )
  ;; CHECK:      (func $eq-zero-rhs-i64 (result i32)
  ;; CHECK-NEXT:  (i64.eqz
  ;; CHECK-NEXT:   (i64.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-zero-rhs-i64 (result i32)
    (i64.eq
      (i64.const 100)
      (i64.const 0)
    )
  )
  ;; CHECK:      (func $eq-zero-lhs-i64 (result i32)
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $eq-zero-lhs-i64 (result i32)
    (i64.eq
      (i64.const 0)
      (i64.const 100)
    )
  )
  ;; CHECK:      (func $eq-zero-zero-i64 (result i32)
  ;; CHECK-NEXT:  (i64.eqz
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-zero-zero-i64 (result i32)
    (i64.eq
      (i64.const 0)
      (i64.const 0)
    )
  )
  ;; CHECK:      (func $if-eqz-eqz
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 123)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-eqz-eqz
    (if
      (i32.eqz
        (i32.eqz
          (i32.const 123)
        )
      )
      (then
        (nop)
      )
    )
  )
  ;; CHECK:      (func $select-eqz (param $i1 i32) (result i32)
  ;; CHECK-NEXT:  (select
  ;; CHECK-NEXT:   (i32.const 102)
  ;; CHECK-NEXT:   (i32.const 101)
  ;; CHECK-NEXT:   (local.get $i1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-eqz (param $i1 i32) (result i32)
    (select
      (i32.const 101)
      (i32.const 102)
      (i32.eqz
        (local.get $i1)
      )
    )
  )
  ;; CHECK:      (func $select-eqz-noreorder (param $i1 i32) (result i32)
  ;; CHECK-NEXT:  (select
  ;; CHECK-NEXT:   (local.tee $i1
  ;; CHECK-NEXT:    (i32.const 103)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (local.tee $i1
  ;; CHECK-NEXT:    (i32.const 104)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (local.get $i1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-eqz-noreorder (param $i1 i32) (result i32)
    (select
      (local.tee $i1
        (i32.const 103)
      ) ;; these conflict
      (local.tee $i1
        (i32.const 104)
      )
      (i32.eqz
        (local.get $i1)
      )
    )
  )
  ;; CHECK:      (func $select-eqz-eqz (result i32)
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $select-eqz-eqz (result i32)
    (select
      (i32.const 0)
      (i32.const 1)
      (i32.eqz
        (i32.eqz
          (i32.const 2)
        )
      )
    )
  )
  ;; CHECK:      (func $select-sign-32-lt (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.or
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 31)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-sign-32-lt (param $x i32) (result i32)
    (select
      (i32.const -1)
      (i32.const 1)
      (i32.lt_s
        (local.get $x)
        (i32.const 0)
      )
    )
  )
  ;; CHECK:      (func $select-sign-32-ge (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.or
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 31)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-sign-32-ge (param $x i32) (result i32)
    (select
      (i32.const 1)
      (i32.const -1)
      (i32.ge_s
        (local.get $x)
        (i32.const 0)
      )
    )
  )
  ;; CHECK:      (func $select-sign-64-lt (param $x i64) (result i64)
  ;; CHECK-NEXT:  (i64.or
  ;; CHECK-NEXT:   (i64.shr_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i64.const 63)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i64.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-sign-64-lt (param $x i64) (result i64)
    (select
      (i64.const -1)
      (i64.const 1)
      (i64.lt_s
        (local.get $x)
        (i64.const 0)
      )
    )
  )
  ;; CHECK:      (func $select-sign-64-ge (param $x i64) (result i64)
  ;; CHECK-NEXT:  (i64.or
  ;; CHECK-NEXT:   (i64.shr_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i64.const 63)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i64.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-sign-64-ge (param $x i64) (result i64)
    (select
      (i64.const 1)
      (i64.const -1)
      (i64.ge_s
        (local.get $x)
        (i64.const 0)
      )
    )
  )
  ;; CHECK:      (func $select-sign-lt-skip-1 (param $x i32) (result i64)
  ;; CHECK-NEXT:  (select
  ;; CHECK-NEXT:   (i64.const -1)
  ;; CHECK-NEXT:   (i64.const 1)
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-sign-lt-skip-1 (param $x i32) (result i64)
    (select
      (i64.const -1)
      (i64.const 1)
      (i32.lt_s
        (local.get $x)
        (i32.const 0)
      )
    )
  )
  ;; CHECK:      (func $select-sign-lt-skip-2 (param $x i64) (result i32)
  ;; CHECK-NEXT:  (select
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:   (i64.lt_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-sign-lt-skip-2 (param $x i64) (result i32)
    (select
      (i32.const -1)
      (i32.const 1)
      (i64.lt_s
        (local.get $x)
        (i64.const 0)
      )
    )
  )
  ;; CHECK:      (func $select-or (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (i32.or
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.const 1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-or (param $x i32) (param $y i32) (result i32)
    (select
      (i32.const 1)
      (i32.eq
        (local.get $y)
        (i32.const 1337)
      )
      (i32.and
        (local.get $x)
        (i32.const 1)
      )
    )
  )
  ;; CHECK:      (func $select-and-eqz (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-and-eqz (param $x i32) (param $y i32) (result i32)
    (select
      (i32.eqz
        (local.get $x)
      )
      (i32.const 0)
      (i32.eqz
        (local.get $y)
      )
    )
  )
  ;; CHECK:      (func $select-or-side-effects (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (i32.or
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (call $select-or-side-effects
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (call $select-or-side-effects
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-or-side-effects (param $x i32) (param $y i32) (result i32)
    ;; When there are side effects, the order of the operations must remain
    ;; correct.
    (select
      (i32.const 1)
      (i32.eq
        (call $select-or-side-effects
          (local.get $x)
          (local.get $y)
        )
        (i32.const 1337)
      )
      (i32.and
        (call $select-or-side-effects
          (local.get $y)
          (local.get $x)
        )
        (i32.const 1)
      )
    )
  )
  ;; CHECK:      (func $select-or-no-bits (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const 2)
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i32.const 1337)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 42)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 42)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i32.const 1337)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-or-no-bits (param $x i32) (param $y i32)
    ;; The following cannot be optimized into an "or" operation due to maxBits
    ;; not being known to be 1.
    (drop
      (select
        ;; Too many bits in ifTrue
        (i32.const 2)
        (i32.eq
          (local.get $y)
          (i32.const 1337)
        )
        (i32.eq
          (local.get $x)
          (i32.const 42)
        )
      )
    )
    (drop
      (select
        (i32.const 1)
        ;; Too many bits in ifFalse
        (local.get $y)
        (i32.eq
          (local.get $x)
          (i32.const 42)
        )
      )
    )
    (drop
      (select
        (i32.const 1)
        (i32.eq
          (local.get $y)
          (i32.const 1337)
        )
        ;; Too many bits in condition
        (local.get $x)
      )
    )
  )
  ;; CHECK:      (func $select-or-no-type (param $x i32) (param $y i64) (result i64)
  ;; CHECK-NEXT:  (select
  ;; CHECK-NEXT:   (i64.const 1)
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-or-no-type (param $x i32) (param $y i64) (result i64)
    ;; An i64 result cannot be optimized into an "or" of the ifTrue and the
    ;; condition due to their types being different.
    (select
      (i64.const 1)
      (i64.and
        (local.get $y)
        (i64.const 1)
      )
      (i32.and
        (local.get $x)
        (i32.const 1)
      )
    )
  )
  ;; CHECK:      (func $select-or-negation (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.const 1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 20)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-or-negation (param $x i32) (param $y i32) (result i32)
    (select
      ;; We can turn this select into an and by negating the condition.
      (i32.const 0)
      (i32.eq
        (local.get $y)
        (i32.const 1337)
      )
      (i32.lt_u
        (local.get $x)
        (i32.const 20)
      )
    )
  )
  ;; CHECK:      (func $select-or-no-const (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (select
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.const 1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-or-no-const (param $x i32) (param $y i32) (result i32)
    (select
      ;; The wrong const (should be 0 or 1).
      (i32.const 2)
      (i32.eq
        (local.get $y)
        (i32.const 1337)
      )
      (i32.and
        (local.get $x)
        (i32.const 1)
      )
    )
  )
  ;; CHECK:      (func $select-and (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.const 1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 42)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-and (param $x i32) (param $y i32) (result i32)
    (select
      (i32.eq
        (local.get $y)
        (i32.const 1337)
      )
      (i32.const 0)
      (i32.eq
        (local.get $x)
        (i32.const 42)
      )
    )
  )
  ;; CHECK:      (func $select-and-negation (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (i32.or
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.const 1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 42)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-and-negation (param $x i32) (param $y i32) (result i32)
    (select
      (i32.eq
        (local.get $y)
        (i32.const 1337)
      )
      ;; With a 1 here, we negate the condition.
      (i32.const 1)
      (i32.eq
        (local.get $x)
        (i32.const 42)
      )
    )
  )
  ;; CHECK:      (func $select-and-negation-impossible (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (select
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.const 1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 31)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-and-negation-impossible (param $x i32) (param $y i32) (result i32)
    (select
      (i32.eq
        (local.get $y)
        (i32.const 1337)
      )
      ;; With a 1 here, we must negate the condition, but the condition here
      ;; cannot be negated in a simple way, so skip.
      (i32.const 1)
      (i32.shr_u
        (local.get $x)
        (i32.const 31)
      )
    )
  )
  ;; CHECK:      (func $select-and-negation-impossible-float (param $x f64) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (select
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.const 1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:   (f64.le
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const 3.14159)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-and-negation-impossible-float (param $x f64) (param $y i32) (result i32)
    (select
      (i32.eq
        (local.get $y)
        (i32.const 1337)
      )
      ;; With a 1 here, we must negate the condition, but the condition here
      ;; cannot be negated due to it operating on floats (where NaNs cause
      ;; difficulties), so we skip.
      (i32.const 1)
      (f64.le
        (local.get $x)
        (f64.const 3.14159)
      )
    )
  )
  ;; CHECK:      (func $select-and-no-const (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (select
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.const 1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 42)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-and-no-const (param $x i32) (param $y i32) (result i32)
    (select
      (i32.eq
        (local.get $y)
        (i32.const 1337)
      )
      ;; The wrong constant (should be 0 or 1).
      (i32.const 2)
      (i32.eq
        (local.get $x)
        (i32.const 42)
      )
    )
  )
  ;; CHECK:      (func $load8_s-and-255 (result i32)
  ;; CHECK-NEXT:  (i32.load8_u
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $load8_s-and-255 (result i32)
    (i32.and (i32.load8_s (i32.const 0)) (i32.const 255))
  )
  ;; CHECK:      (func $load8_u-and-255 (result i32)
  ;; CHECK-NEXT:  (i32.load8_u
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $load8_u-and-255 (result i32)
    (i32.and (i32.load8_u (i32.const 1)) (i32.const 255))
  )
  ;; CHECK:      (func $load8_s-and-254 (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (i32.load8_s
  ;; CHECK-NEXT:    (i32.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 254)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $load8_s-and-254 (result i32)
    (i32.and (i32.load8_s (i32.const 2)) (i32.const 254))
  )
  ;; CHECK:      (func $load8_u-and-1 (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (i32.load8_u
  ;; CHECK-NEXT:    (i32.const 3)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $load8_u-and-1 (result i32)
    (i32.and (i32.load8_u (i32.const 3)) (i32.const 1))
  )
  ;; CHECK:      (func $load16_s-and-65535 (result i32)
  ;; CHECK-NEXT:  (i32.load16_u
  ;; CHECK-NEXT:   (i32.const 4)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $load16_s-and-65535 (result i32)
    (i32.and (i32.load16_s (i32.const 4)) (i32.const 65535))
  )
  ;; CHECK:      (func $load16_u-and-65535 (result i32)
  ;; CHECK-NEXT:  (i32.load16_u
  ;; CHECK-NEXT:   (i32.const 5)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $load16_u-and-65535 (result i32)
    (i32.and (i32.load16_u (i32.const 5)) (i32.const 65535))
  )
  ;; CHECK:      (func $load16_s-and-65534 (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (i32.load16_s
  ;; CHECK-NEXT:    (i32.const 6)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 65534)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $load16_s-and-65534 (result i32)
    (i32.and (i32.load16_s (i32.const 6)) (i32.const 65534))
  )
  ;; CHECK:      (func $load16_u-and-1 (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (i32.load16_u
  ;; CHECK-NEXT:    (i32.const 7)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $load16_u-and-1 (result i32)
    (i32.and (i32.load16_u (i32.const 7)) (i32.const 1))
  )
  ;; CHECK:      (func $store8-and-255
  ;; CHECK-NEXT:  (i32.store8
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store8-and-255
    (i32.store8 (i32.const 8) (i32.and (i32.const -1) (i32.const 255)))
  )
  ;; CHECK:      (func $store8-and-254
  ;; CHECK-NEXT:  (i32.store8
  ;; CHECK-NEXT:   (i32.const 9)
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const -2)
  ;; CHECK-NEXT:    (i32.const 254)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store8-and-254
    (i32.store8 (i32.const 9) (i32.and (i32.const -2) (i32.const 254)))
  )
  ;; CHECK:      (func $store16-and-65535
  ;; CHECK-NEXT:  (i32.store16
  ;; CHECK-NEXT:   (i32.const 10)
  ;; CHECK-NEXT:   (i32.const -3)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store16-and-65535
    (i32.store16 (i32.const 10) (i32.and (i32.const -3) (i32.const 65535)))
  )
  ;; CHECK:      (func $store16-and-65534
  ;; CHECK-NEXT:  (i32.store16
  ;; CHECK-NEXT:   (i32.const 11)
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const -4)
  ;; CHECK-NEXT:    (i32.const 65534)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store16-and-65534
    (i32.store16 (i32.const 11) (i32.and (i32.const -4) (i32.const 65534)))
  )
  ;; CHECK:      (func $store8-wrap (param $x i64)
  ;; CHECK-NEXT:  (i64.store8
  ;; CHECK-NEXT:   (i32.const 11)
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store8-wrap (param $x i64)
    (i32.store8 (i32.const 11) (i32.wrap_i64 (local.get $x)))
  )
  ;; CHECK:      (func $store16-wrap (param $x i64)
  ;; CHECK-NEXT:  (i64.store16
  ;; CHECK-NEXT:   (i32.const 11)
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store16-wrap (param $x i64)
    (i32.store16 (i32.const 11) (i32.wrap_i64 (local.get $x)))
  )
  ;; CHECK:      (func $store-wrap (param $x i64)
  ;; CHECK-NEXT:  (i64.store32
  ;; CHECK-NEXT:   (i32.const 11)
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store-wrap (param $x i64)
    (i32.store (i32.const 11) (i32.wrap_i64 (local.get $x)))
  )
  ;; CHECK:      (func $store8-neg1
  ;; CHECK-NEXT:  (i32.store8
  ;; CHECK-NEXT:   (i32.const 7)
  ;; CHECK-NEXT:   (i32.const 255)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store8-neg1
    (i32.store8 (i32.const 7) (i32.const -1))           ;; 255
  )
  ;; CHECK:      (func $store8-255
  ;; CHECK-NEXT:  (i32.store8
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (i32.const 255)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store8-255
    (i32.store8 (i32.const 8) (i32.const 255))
  )
  ;; CHECK:      (func $store8-256
  ;; CHECK-NEXT:  (i32.store8
  ;; CHECK-NEXT:   (i32.const 9)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store8-256
    (i32.store8 (i32.const 9) (i32.const 256))          ;; 0
  )
  ;; CHECK:      (func $store16-neg1
  ;; CHECK-NEXT:  (i32.store16
  ;; CHECK-NEXT:   (i32.const 13)
  ;; CHECK-NEXT:   (i32.const 65535)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store16-neg1
    (i32.store16 (i32.const 13) (i32.const -1))         ;; 65535
  )
  ;; CHECK:      (func $store16-65535
  ;; CHECK-NEXT:  (i32.store16
  ;; CHECK-NEXT:   (i32.const 10)
  ;; CHECK-NEXT:   (i32.const 65535)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store16-65535
    (i32.store16 (i32.const 10) (i32.const 65535))
  )
  ;; CHECK:      (func $store16-65536
  ;; CHECK-NEXT:  (i32.store16
  ;; CHECK-NEXT:   (i32.const 11)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store16-65536
    (i32.store16 (i32.const 11) (i32.const 65536))      ;; 0
  )
  ;; CHECK:      (func $store-65536
  ;; CHECK-NEXT:  (i32.store
  ;; CHECK-NEXT:   (i32.const 14)
  ;; CHECK-NEXT:   (i32.const 65536)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store-65536
    (i32.store (i32.const 14) (i32.const 65536))
  )
  ;; CHECK:      (func $store8-255-i64
  ;; CHECK-NEXT:  (i64.store8
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (i64.const 255)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store8-255-i64
    (i64.store8 (i32.const 8) (i64.const 255))
  )
  ;; CHECK:      (func $store8-256-i64
  ;; CHECK-NEXT:  (i64.store8
  ;; CHECK-NEXT:   (i32.const 9)
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store8-256-i64
    (i64.store8 (i32.const 9) (i64.const 256))          ;; 0
  )
  ;; CHECK:      (func $store16-65535-i64
  ;; CHECK-NEXT:  (i64.store16
  ;; CHECK-NEXT:   (i32.const 10)
  ;; CHECK-NEXT:   (i64.const 65535)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store16-65535-i64
    (i64.store16 (i32.const 10) (i64.const 65535))
  )
  ;; CHECK:      (func $store16-65536-i64
  ;; CHECK-NEXT:  (i64.store16
  ;; CHECK-NEXT:   (i32.const 11)
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store16-65536-i64
    (i64.store16 (i32.const 11) (i64.const 65536))      ;; 0
  )
  ;; CHECK:      (func $store32-4294967295
  ;; CHECK-NEXT:  (i64.store32
  ;; CHECK-NEXT:   (i32.const 12)
  ;; CHECK-NEXT:   (i64.const 4294967295)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store32-4294967295
    (i64.store32 (i32.const 12) (i64.const 4294967295))
  )
  ;; CHECK:      (func $store32-4294967296
  ;; CHECK-NEXT:  (i64.store32
  ;; CHECK-NEXT:   (i32.const 13)
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store32-4294967296
    (i64.store32 (i32.const 13) (i64.const 4294967296)) ;; 0
  )
  ;; CHECK:      (func $store-4294967296
  ;; CHECK-NEXT:  (i64.store
  ;; CHECK-NEXT:   (i32.const 14)
  ;; CHECK-NEXT:   (i64.const 4294967296)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store-4294967296
    (i64.store (i32.const 14) (i64.const 4294967296))
  )
  ;; CHECK:      (func $and-neg1
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const 100)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $and-neg1
    (drop (i32.and (i32.const 100) (i32.const -1)))
    (drop (i32.and (i32.const 100) (i32.const  1)))
  )
  ;; CHECK:      (func $and-pos1
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.const 1000)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.const 1000)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const 100)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $and-pos1
    (drop (i32.and (i32.eqz (i32.const 1000)) (i32.const 1)))
    (drop (i32.and (i32.const 1) (i32.eqz (i32.const 1000))))
    (drop (i32.and (i32.const 100) (i32.const 1)))
    (drop (i32.and (i32.lt_s (i32.const 2000) (i32.const 3000)) (i32.const 1)))
  )
  ;; CHECK:      (func $canonicalize-unreachable
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.div_s
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.div_s
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-unreachable
    (drop (i32.and (unreachable) (i32.const 1))) ;; ok to reorder
    (drop (i32.and (i32.const 1) (unreachable)))
    (drop (i32.div_s (unreachable) (i32.const 1))) ;; not ok
    (drop (i32.div_s (i32.const 1) (unreachable)))
  )
  ;; CHECK:      (func $canonicalize-consts-vars (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const 2)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 3)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 4)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.tee $x
  ;; CHECK-NEXT:     (i32.const -4)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-consts-vars (param $x i32) (param $y i32)
    (drop (i32.and (i32.const 1) (i32.const 2)))
    (drop (i32.and (i32.const 2) (i32.const 1)))
    (drop (i32.and (local.get $x) (i32.const 3)))
    (drop (i32.and (i32.const 4) (local.get $x)))
    (drop (i32.and (local.get $x) (local.get $y)))
    (drop (i32.and (local.get $y) (local.get $x)))
    (drop (i32.and (local.get $y) (local.tee $x (i32.const -4))))
  )
  ;; CHECK:      (func $canonicalize-block-var (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (i32.const -5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (i32.const -6)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-block-var (param $x i32)
    (drop (i32.and
      (block (result i32)
        (i32.const -5)
      )
      (local.get $x)
    ))
    (drop (i32.and
      (local.get $x)
      (block (result i32)
        (i32.const -6)
      )
    ))
  )
  ;; CHECK:      (func $canonicalize-block-loop
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (loop (result i32)
  ;; CHECK-NEXT:     (i32.const 6)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (i32.const 8)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (loop (result i32)
  ;; CHECK-NEXT:     (i32.const 7)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (loop (result i32)
  ;; CHECK-NEXT:     (call $and-pos1)
  ;; CHECK-NEXT:     (i32.const 9)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (call $and-pos1)
  ;; CHECK-NEXT:     (i32.const 12)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (loop (result i32)
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (loop (result i32)
  ;; CHECK-NEXT:     (call $and-pos1)
  ;; CHECK-NEXT:     (i32.const 13)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (call $and-pos1)
  ;; CHECK-NEXT:     (i32.const 14)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (call $and-pos1)
  ;; CHECK-NEXT:     (i32.const 14)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (loop (result i32)
  ;; CHECK-NEXT:     (call $and-pos1)
  ;; CHECK-NEXT:     (i32.const 13)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-block-loop
    (drop (i32.and
      (block (result i32)
        (i32.const 5)
      )
      (loop (result i32)
        (i32.const 6)
      )
    ))
    (drop (i32.and
      (loop (result i32)
        (i32.const 7)
      )
      (block (result i32)
        (i32.const 8)
      )
    ))
    (drop (i32.and
      (loop (result i32)
        (call $and-pos1)
        (i32.const 9)
      )
      (block (result i32)
        (i32.const 10)
      )
    ))
    (drop (i32.and
      (loop (result i32)
        (i32.const 11)
      )
      (block (result i32)
        (call $and-pos1)
        (i32.const 12)
      )
    ))
    (drop (i32.and
      (loop (result i32)
        (call $and-pos1)
        (i32.const 13)
      )
      (block (result i32)
        (call $and-pos1)
        (i32.const 14)
      )
    ))
    (drop (i32.and
      (block (result i32)
        (call $and-pos1)
        (i32.const 14)
      )
      (loop (result i32)
        (call $and-pos1)
        (i32.const 13)
      )
    ))
  )
  ;; CHECK:      (func $canonicalize-gt_s-gt-u
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.gt_u
  ;; CHECK-NEXT:     (i32.const 16)
  ;; CHECK-NEXT:     (i32.const 17)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.gt_u
  ;; CHECK-NEXT:     (i32.const 18)
  ;; CHECK-NEXT:     (i32.const 19)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.gt_u
  ;; CHECK-NEXT:     (i32.const 20)
  ;; CHECK-NEXT:     (i32.const 21)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.gt_u
  ;; CHECK-NEXT:     (i32.const 22)
  ;; CHECK-NEXT:     (i32.const 23)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-gt_s-gt-u
    (drop (i32.and
      (i32.gt_s
        (i32.const 16)
        (i32.const 17)
      )
      (i32.gt_u
        (i32.const 18)
        (i32.const 19)
      )
    ))
    (drop (i32.and
      (i32.gt_u
        (i32.const 20)
        (i32.const 21)
      )
      (i32.gt_s
        (i32.const 22)
        (i32.const 23)
      )
    ))
  )
  ;; CHECK:      (func $canonicalize-cmp-near-zero (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.le_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-cmp-near-zero (param $x i32)
    ;; i32(x) > -1  ==>  x >= 0
    (drop (i32.gt_s
      (local.get $x)
      (i32.const -1)
    ))
    ;; i32(x) <= -1  ==>  x < 0
    (drop (i32.le_s
      (local.get $x)
      (i32.const -1)
    ))
    ;; -1 < i32(x)  ==>  x >= 0
    (drop (i32.lt_s
      (i32.const -1)
      (local.get $x)
    ))
    ;; -1 >= i32(x)  ==>  x < 0
    (drop (i32.ge_s
      (i32.const -1)
      (local.get $x)
    ))
    ;; i32(x) < 1   ==>   x <= 0
    (drop (i32.lt_s
      (local.get $x)
      (i32.const 1)
    ))
    ;; (signed)x >= 1   ==>   x > 0
    (drop (i32.ge_s
      (local.get $x)
      (i32.const 1)
    ))
    ;; u32(x) < 1   ==>   x == 0
    (drop (i32.lt_u
      (local.get $x)
      (i32.const 1)
    ))
    ;; u32(x) >= 1   ==>   x != 0
    (drop (i32.ge_u
      (local.get $x)
      (i32.const 1)
    ))
  )
  ;; CHECK:      (func $canonicalize-cmp-near-min-max (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -9223372036854775808)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -9223372036854775808)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 9223372036854775807)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 9223372036854775807)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-cmp-near-min-max (param $x i32) (param $y i64)
    ;; (signed)x < s_min + 1   ==>   x == s_min
    (drop (i32.lt_s
      (local.get $x)
      (i32.const -2147483647)
    ))
    (drop (i64.lt_s
      (local.get $y)
      (i64.const -9223372036854775807)
    ))
    ;; (signed)x >= s_min + 1   ==>   x != s_min
    (drop (i32.ge_s
      (local.get $x)
      (i32.const -2147483647)
    ))
    (drop (i64.ge_s
      (local.get $y)
      (i64.const -9223372036854775807)
    ))
    ;; (signed)x > s_max - 1   ==>   x == s_max
    (drop (i32.gt_s
      (local.get $x)
      (i32.const 2147483646)
    ))
    (drop (i64.gt_s
      (local.get $y)
      (i64.const 9223372036854775806)
    ))
    ;; (signed)x <= s_max - 1   ==>   x != s_max
    (drop (i32.le_s
      (local.get $x)
      (i32.const 2147483646)
    ))
    (drop (i64.le_s
      (local.get $y)
      (i64.const 9223372036854775806)
    ))
    ;; (unsigned)x <= u_max - 1   ==>   x != u_max
    (drop (i32.le_u
      (local.get $x)
      (i32.const -2)
    ))
    (drop (i64.le_u
      (local.get $y)
      (i64.const -2)
    ))
    ;; (unsigned)x > u_max - 1   ==>   x == u_max
    (drop (i32.gt_u
      (local.get $x)
      (i32.const -2)
    ))
    (drop (i64.gt_u
      (local.get $y)
      (i64.const -2)
    ))
  )
  ;; CHECK:      (func $canonicalize-cmp-const (param $x i32) (param $fx f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.le_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.ne
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:    (f64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.gt
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:    (f64.const -2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.le
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:    (f64.const inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.ge
  ;; CHECK-NEXT:    (f64.const 1)
  ;; CHECK-NEXT:    (f64.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-cmp-const (param $x i32) (param $fx f64)
    (drop (i32.gt_s
      (i32.const 1)
      (local.get $x)
    ))
    (drop (i32.gt_u
      (i32.const 0)
      (local.get $x)
    ))
    (drop (i32.ne
      (i32.const -1)
      (local.get $x)
    ))
    (drop (f64.ne
      (f64.const -1)
      (local.get $fx)
    ))
    (drop (f64.lt
      (f64.const -2)
      (local.get $fx)
    ))
    (drop (f64.ge
      (f64.const inf)
      (local.get $fx)
    ))
    (drop (f64.le
      (f64.const nan)
      (local.get $fx)
    ))
    ;; skip
    (drop (f64.ge
      (f64.const 1)
      (f64.const 2)
    ))
  )
  ;; CHECK:      (func $canonicalize-nested-vars (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.ctz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.ctz
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.ctz
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.ctz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-nested-vars (param $x i32) (param $y i32)
    (drop (i32.add (i32.ctz (local.get $x)) (i32.ctz (local.get $y))))
    (drop (i32.add (i32.ctz (local.get $y)) (i32.ctz (local.get $x))))
  )
  ;; CHECK:      (func $canonicalize-ctz-eqz (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.ctz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.ctz
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-ctz-eqz (param $x i32) (param $y i32)
    (drop (i32.add (i32.ctz (local.get $x)) (i32.eqz (local.get $y))))
    (drop (i32.add (i32.eqz (local.get $x)) (i32.ctz (local.get $y))))
  )
  ;; CHECK:      (func $canonicalize-consts-floats (param $x f32) (param $y f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.add
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (f64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 3.4000000953674316)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (f64.const 3.4)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.min
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 3.4000000953674316)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.min
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (f64.const 3.4)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.max
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 3.4000000953674316)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.max
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (f64.const 3.4)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.copysign
  ;; CHECK-NEXT:    (f32.const 1)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.copysign
  ;; CHECK-NEXT:    (f64.const 1)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $canonicalize-consts-floats (param $x f32) (param $y f64)
    (drop (f32.sub (local.get $x) (f32.const 1.0)))
    (drop (f64.sub (local.get $y) (f64.const 1.0)))

    (drop (f32.mul (f32.const 3.4) (local.get $x)))
    (drop (f64.mul (f64.const 3.4) (local.get $y)))

    (drop (f32.min (f32.const 3.4) (local.get $x)))
    (drop (f64.min (f64.const 3.4) (local.get $y)))

    (drop (f32.max (f32.const 3.4) (local.get $x)))
    (drop (f64.max (f64.const 3.4) (local.get $y)))

    (drop (f32.min (f32.const nan) (local.get $x)))
    (drop (f64.min (f64.const nan) (local.get $y)))

    (drop (f32.max (f32.const nan) (local.get $x)))
    (drop (f64.max (f64.const nan) (local.get $y)))

    ;; skips
    (drop (f32.copysign (f32.const 1.0) (local.get $x)))
    (drop (f64.copysign (f64.const 1.0) (local.get $y)))
  )
  ;; CHECK:      (func $ne0 (result i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (call $ne0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (call $ne0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.ne
  ;; CHECK-NEXT:     (call $ne0)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.ne
  ;; CHECK-NEXT:     (call $ne0)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 1)
  ;; CHECK-NEXT: )
  (func $ne0 (result i32)
    (if (i32.ne (call $ne0) (i32.const 0))
      (then
        (nop)
      )
    )
    (if (i32.ne (i32.const 0) (call $ne0))
      (then
        (nop)
      )
    )
    ;; through an or
    (if
      (i32.or
        (i32.ne (i32.const 0) (call $ne0))
        (i32.ne (i32.const 0) (call $ne0))
      )
      (then
        (nop)
      )
    )
    ;; but not an and
    (if
      (i32.and
        (i32.ne (i32.const 0) (call $ne0))
        (i32.ne (i32.const 0) (call $ne0))
      )
      (then
        (nop)
      )
    )
    (i32.const 1)
  )
  ;; CHECK:      (func $recurse-bool
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (call $ne0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (call $ne1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $recurse-bool
    (if
      (if (result i32)
        (i32.const 1)
        (then
          (i32.ne (call $ne0) (i32.const 0))
        )
        (else
          (i32.ne (call $ne1) (i32.const 0))
        )
      )
      (then
        (nop)
      )
    )
    (if
      (block (result i32)
        (nop)
        (i32.ne (call $ne0) (i32.const 0))
      )
      (then
        (nop)
      )
    )
  )
  ;; CHECK:      (func $ne1 (result i32)
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $ne1 (result i32)
    (unreachable)
  )
  ;; CHECK:      (func $store-off-2-add-consts (param $0 i32)
  ;; CHECK-NEXT:  (i32.store
  ;; CHECK-NEXT:   (i32.const 6)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store
  ;; CHECK-NEXT:   (i32.const 6)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store-off-2-add-consts (param $0 i32)
    (i32.store offset=2
      (i32.add
        (i32.const 1)
        (i32.const 3)
      )
      (local.get $0)
    )
    (i32.store offset=2
      (i32.add
        (i32.const 3)
        (i32.const 1)
      )
      (local.get $0)
    )
  )
  ;; CHECK:      (func $store-off-2-add-var-const (param $0 i32)
  ;; CHECK-NEXT:  (i32.store offset=2
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 5)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store offset=2
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 7)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store-off-2-add-var-const (param $0 i32)
    (i32.store offset=2
      (i32.add
        (local.get $0)
        (i32.const 5)
      )
      (local.get $0)
    )
    (i32.store offset=2
      (i32.add
        (i32.const 7)
        (local.get $0)
      )
      (local.get $0)
    )
  )
  ;; CHECK:      (func $store-off-2-add-var-negative-const (param $0 i32)
  ;; CHECK-NEXT:  (i32.store offset=2
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 11)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store offset=2
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 13)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store-off-2-add-var-negative-const (param $0 i32)
    (i32.store offset=2
      (i32.add
        (i32.const -11) ;; do not fold this!
        (local.get $0)
      )
      (local.get $0)
    )
    (i32.store offset=2
      (i32.add
        (local.get $0)
        (i32.const -13) ;; do not fold this!
      )
      (local.get $0)
    )
  )
  ;; CHECK:      (func $store-off-2-negative-const (param $0 i32)
  ;; CHECK-NEXT:  (i32.store
  ;; CHECK-NEXT:   (i32.const 4)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store offset=2
  ;; CHECK-NEXT:   (i32.const -2)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store-off-2-negative-const (param $0 i32)
    (i32.store offset=2
      (i32.add
        (i32.const -15)
        (i32.const 17)
      )
      (local.get $0)
    )
    (i32.store offset=2
      (i32.add
        (i32.const -21)
        (i32.const 19)
      )
      (local.get $0)
    )
  )
  ;; CHECK:      (func $store-off-2-const (param $0 i32)
  ;; CHECK-NEXT:  (i32.store
  ;; CHECK-NEXT:   (i32.const 25)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store offset=2
  ;; CHECK-NEXT:   (i32.const -25)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store-off-2-const (param $0 i32)
    (i32.store offset=2
      (i32.const 23)
      (local.get $0)
    )
    (i32.store offset=2
      (i32.const -25)
      (local.get $0)
    )
  )
  ;; CHECK:      (func $load-off-2 (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.load
  ;; CHECK-NEXT:    (i32.const 8)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.load
  ;; CHECK-NEXT:    (i32.const 8)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.load offset=2
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 6)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.load
  ;; CHECK-NEXT:    (i32.const 10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.load offset=2
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $load-off-2 (param $0 i32) (result i32)
    (drop
      (i32.load offset=2
        (i32.add
          (i32.const 2)
          (i32.const 4)
        )
      )
    )
    (drop
      (i32.load offset=2
        (i32.add
          (i32.const 4)
          (i32.const 2)
        )
      )
    )
    (drop
      (i32.load offset=2
        (i32.add
          (local.get $0)
          (i32.const 6)
        )
      )
    )
    (drop
      (i32.load offset=2
        (i32.const 8)
      )
    )
    (i32.load offset=2
      (i32.add
        (i32.const 10)
        (local.get $0)
      )
    )
  )
  ;; eq of sign-ext to const, can be a zext
  ;; CHECK:      (func $eq-sext-24-zero (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-sext-24-zero (param $0 i32) (result i32)
    (i32.eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 24)
      )
      (i32.const 0)
    )
  )
  ;; CHECK:      (func $eq-sext-16-zero (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 65535)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-sext-16-zero (param $0 i32) (result i32)
    (i32.eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 16)
        )
        (i32.const 16)
      )
      (i32.const 0)
    )
  )
  ;; CHECK:      (func $eq-sext-5-zero (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 134217727)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-sext-5-zero (param $0 i32) (result i32)
    (i32.eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 5) ;; weird size, but still valid
        )
        (i32.const 5)
      )
      (i32.const 0)
    )
  )
  ;; CHECK:      (func $eq-sext-24-const (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.eq
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-sext-24-const (param $0 i32) (result i32)
    (i32.eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 24)
      )
      (i32.const 100) ;; non-zero
    )
  )
  ;; CHECK:      (func $eq-sext-24-big-positive-const (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $eq-sext-24-big-positive-const (param $0 i32) (result i32)
    (i32.eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 24)
      )
      (i32.const 32767) ;; non-zero and bigger than the mask, with sign bit
    )
  )
  ;; CHECK:      (func $eq-sext-24-negative-const (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $eq-sext-24-negative-const (param $0 i32) (result i32)
    (i32.eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 24)
      )
      (i32.const -149) ;; non-zero and bigger than the mask, without sign bit
    )
  )
  ;; eq of two sign-ext, can both be a zext
  ;; CHECK:      (func $eq-sext-sext-24 (param $0 i32) (param $1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.eq
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-sext-sext-24 (param $0 i32) (param $1 i32) (result i32)
    (i32.eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 24)
      )
      (i32.shr_s
        (i32.shl
          (local.get $1)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
  )
  ;; CHECK:      (func $eq-sext-sext-16 (param $0 i32) (param $1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.eq
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 65535)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (i32.const 65535)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-sext-sext-16 (param $0 i32) (param $1 i32) (result i32)
    (i32.eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 16)
        )
        (i32.const 16)
      )
      (i32.shr_s
        (i32.shl
          (local.get $1)
          (i32.const 16)
        )
        (i32.const 16)
      )
    )
  )
  ;; corner cases we should not opt
  ;; CHECK:      (func $eq-sext-smaller-shr (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 23)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-sext-smaller-shr (param $0 i32) (result i32)
    (i32.eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 23) ;; different shift, smaller
      )
      (i32.const 0)
    )
  )
  ;; CHECK:      (func $eq-sext-unsigned-shr (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-sext-unsigned-shr (param $0 i32) (result i32)
    (i32.eq
      (i32.shr_u ;; unsigned
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 24)
      )
      (i32.const 0)
    )
  )
  ;; CHECK:      (func $lt_s-sext-zero (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.lt_s
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $lt_s-sext-zero (param $0 i32) (result i32)
    (i32.lt_s ;; non-eq
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 24)
      )
      (i32.const 0)
    )
  )
  ;; CHECK:      (func $if-sext-unreachable (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (if (result i32)
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (unreachable)
  ;; CHECK-NEXT:     (i32.const 16)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (i32.const 111)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (i32.const 222)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-sext-unreachable (param $0 i32) (result i32)
    (if (result i32)
      (i32.shr_s
        (i32.shl
          (unreachable) ;; ignore an unreachable value
          (i32.const 16)
        )
        (i32.const 16)
      )
      (then
        (i32.const 111)
      )
      (else
        (i32.const 222)
      )
    )
  )
  ;; CHECK:      (func $sext-24-100 (result i32)
  ;; CHECK-NEXT:  (i32.const 100)
  ;; CHECK-NEXT: )
  (func $sext-24-100 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.const 100) ;; small!
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-127 (result i32)
  ;; CHECK-NEXT:  (i32.const 127)
  ;; CHECK-NEXT: )
  (func $sext-24-127 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.const 127) ;; just small enough
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-128 (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.const 128)
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-128 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.const 128) ;; just too big
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-var (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-var (param $0 i32) (result i32)
    (i32.shr_s
      (i32.shl
        (local.get $0) ;; who knows...
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-unreachable (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-unreachable (result i32)
    (i32.shr_s
      (i32.shl
        (unreachable) ;; ignore
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-div (result i32)
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $sext-24-div (result i32)
    (i32.shr_s
      (i32.shl
        (i32.div_s      ;; we don't precompute this, but we do know the limit on
          (i32.const 1) ;; max bits, and the sign bit cannot be 1, so this all
          (i32.const 2) ;; ends up as zero.
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-param (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-param (param $x i32) (result i32)
    (i32.shr_s
      (i32.shl
        (local.get $x) ;; we don't know what this is, and so optimize nothing
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-and-127-unknown (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 127)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-and-127-unknown (param $x i32) (result i32)
    (i32.shr_s
      (i32.shl
        (i32.and ;; takes the min, here it is ok
          (i32.const 127)
          (local.get $x)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-and-128-129 (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (i32.const 128)
  ;; CHECK-NEXT:     (i32.const 129)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-and-128-129 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.and ;; takes the min, here it is not
          (i32.const 128)
          (i32.const 129)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-xor-127-126 (result i32)
  ;; CHECK-NEXT:  (i32.xor
  ;; CHECK-NEXT:   (i32.const 127)
  ;; CHECK-NEXT:   (i32.const 126)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-xor-127-126 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.xor ;; takes the max, here it is ok
          (i32.const 127)
          (i32.const 126)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-xor-127-128 (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.xor
  ;; CHECK-NEXT:     (i32.const 127)
  ;; CHECK-NEXT:     (i32.const 128)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-xor-127-128 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.xor ;; takes the max, here it is not
          (i32.const 127)
          (i32.const 128)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-or-127-126 (result i32)
  ;; CHECK-NEXT:  (i32.or
  ;; CHECK-NEXT:   (i32.const 127)
  ;; CHECK-NEXT:   (i32.const 126)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-or-127-126 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.or ;; takes the max, here it is ok
          (i32.const 127)
          (i32.const 126)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-or-127-128 (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (i32.const 127)
  ;; CHECK-NEXT:     (i32.const 128)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-or-127-128 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.or ;; takes the max, here it is not
          (i32.const 127)
          (i32.const 128)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shl-32-2 (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.const 32)
  ;; CHECK-NEXT:    (i32.const 26)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shl-32-2 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shl ;; adds, here it is too much
          (i32.const 32)
          (i32.const 2)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shl-32-1 (result i32)
  ;; CHECK-NEXT:  (i32.shl
  ;; CHECK-NEXT:   (i32.const 32)
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shl-32-1 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shl ;; adds, here it is ok
          (i32.const 32)
          (i32.const 1)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shl-32-35 (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.const 32)
  ;; CHECK-NEXT:    (i32.const 27)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shl-32-35 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shl ;; adds, here it is too much and "overflows"
          (i32.const 32)
          (i32.const 35)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_u-256-1 (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (i32.const 256)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_u-256-1 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_u ;; subtracts, here it is still too much
          (i32.const 256)
          (i32.const 1)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_u-256-2 (result i32)
  ;; CHECK-NEXT:  (i32.shr_u
  ;; CHECK-NEXT:   (i32.const 256)
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_u-256-2 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_u ;; subtracts, here it is ok
          (i32.const 256)
          (i32.const 2)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_u-128-35 (result i32)
  ;; CHECK-NEXT:  (i32.shr_u
  ;; CHECK-NEXT:   (i32.const 128)
  ;; CHECK-NEXT:   (i32.const 3)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_u-128-35 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_u ;; subtracts, here it "overflows"
          (i32.const 128)
          (i32.const 35)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_s-256-1 (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (i32.const 256)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_s-256-1 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_s ;; subtracts, here it is still too much
          (i32.const 256)
          (i32.const 1)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_s-256-2 (result i32)
  ;; CHECK-NEXT:  (i32.shr_u
  ;; CHECK-NEXT:   (i32.const 256)
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_s-256-2 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_s ;; subtracts, here it is ok
          (i32.const 256)
          (i32.const 2)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_s-128-35 (result i32)
  ;; CHECK-NEXT:  (i32.shr_u
  ;; CHECK-NEXT:   (i32.const 128)
  ;; CHECK-NEXT:   (i32.const 3)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_s-128-35 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_s ;; subtracts, here it "overflows"
          (i32.const 128)
          (i32.const 35)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_s-neg1-32 (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_s-neg1-32 (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_s ;; subtracts, here there is a sign bit, so it stays 32 bits no matter how much we shift
          (i32.const -1)
          (i32.const 32)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_s-and-masked-sign (result i32)
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $sext-24-shr_s-and-masked-sign (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_s ;; subtracts, here we mask out that sign bit
          (i32.and
            (i32.const -1)
            (i32.const 2147483647)
          )
          (i32.const 31) ;; no sign bit, so the shift zeroes us out, and
        )                ;; later shifts cannot add bits, so the result is 0
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-ne (result i32)
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $sext-24-ne (result i32)
    (i32.shr_s
      (i32.shl
        (i32.ne ;; 1 bit
          (i32.const -1)
          (i32.const -1)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-le (result i32)
  ;; CHECK-NEXT:  (f32.le
  ;; CHECK-NEXT:   (f32.const -1)
  ;; CHECK-NEXT:   (f32.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-le (result i32)
    (i32.shr_s
      (i32.shl
        (f32.le
          (f32.const -1)
          (f32.const -1)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-clz (result i32)
  ;; CHECK-NEXT:  (i32.clz
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-clz (result i32)
    (i32.shr_s
      (i32.shl
        (i32.clz ;; assumed 5 bits
          (i32.const 0)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shl-clz (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.clz
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 26)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shl-clz (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shl
          (i32.clz ;; assumed 5 bits
            (i32.const 0)
          )
          (i32.const 2) ;; + 2, so 7
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shl-clz-too-big (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.clz
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 27)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shl-clz-too-big (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shl
          (i32.clz ;; assumed 5 bits
            (i32.const 0)
          )
          (i32.const 3) ;; + 3, so 8, too much
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-wrap-clz (result i32)
  ;; CHECK-NEXT:  (i32.wrap_i64
  ;; CHECK-NEXT:   (i64.clz
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-wrap-clz (result i32)
    (i32.shr_s
      (i32.shl
        (i32.wrap_i64 ;; preserves 6
          (i64.clz ;; assumed 6 bits
            (i64.const 0)
          )
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shl-wrap-clz (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.wrap_i64
  ;; CHECK-NEXT:     (i64.clz
  ;; CHECK-NEXT:      (i64.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 25)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shl-wrap-clz (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shl
          (i32.wrap_i64 ;; preserves 6
            (i64.clz ;; assumed 6 bits
              (i64.const 0)
            )
          )
          (i32.const 1) ;; + 1, so 7
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shl-wrap-clz-too-big (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.wrap_i64
  ;; CHECK-NEXT:     (i64.clz
  ;; CHECK-NEXT:      (i64.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 26)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shl-wrap-clz-too-big (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shl
          (i32.wrap_i64 ;; preserves 6
            (i64.clz ;; assumed 6 bits
              (i64.const 0)
            )
          )
          (i32.const 2) ;; + 2, so 8, too much
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-eqz (result i32)
  ;; CHECK-NEXT:  (i32.eqz
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-eqz (result i32)
    (i32.shr_s
      (i32.shl
        (i32.eqz ;; 1 bit
          (i32.const -1)
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_u-wrap-too-big (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:    (i32.const -16777216)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_u-wrap-too-big (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_u
          (i32.wrap_i64 ;; down to 32
            (i64.const -1) ;; 64
          )
          (i32.const 24) ;; 32 - 24 = 8
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_u-wrap (result i32)
  ;; CHECK-NEXT:  (i32.shr_u
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:   (i32.const 25)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_u-wrap (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_u
          (i32.wrap_i64 ;; down to 32
            (i64.const -1) ;; 64
          )
          (i32.const 25) ;; 32 - 25 = 7, ok
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_u-wrap-extend-too-big (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:    (i32.const -16777216)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_u-wrap-extend-too-big (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_u
          (i32.wrap_i64 ;; stay 32
            (i64.extend_i32_s
              (i32.const -1)
            )
          )
          (i32.const 24) ;; 32 - 24 = 8
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-shr_u-wrap-extend (result i32)
  ;; CHECK-NEXT:  (i32.shr_u
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:   (i32.const 25)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-shr_u-wrap-extend (result i32)
    (i32.shr_s
      (i32.shl
        (i32.shr_u
          (i32.wrap_i64 ;; stay 32
            (i64.extend_i32_s
              (i32.const -1)
            )
          )
          (i32.const 25) ;; 32 - 25 = 7, ok
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $sext-24-xor (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.xor
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.le_u
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:      (i32.const 2)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sext-24-xor (param $0 i32) (result i32) ;; fuzz testcase
    (i32.shr_s
      (i32.shl
        (i32.xor ;; should be 32 bits
          (i32.le_u ;; 1 bit
            (local.get $0)
            (i32.const 2)
          )
          (local.get $0) ;; unknown, so 32 bits
        )
        (i32.const 24)
      )
      (i32.const 24)
    )
  )
  ;; CHECK:      (func $linear-sums (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 4)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (i32.shl
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:      (i32.const 3)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 12)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 4)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 18)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 6)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const -4)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 26)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const -20)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 22)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 14)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 66)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 44)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.mul
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 14)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 34)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $linear-sums (param $0 i32) (param $1 i32)
    (drop
      (i32.add
        (i32.add
          (local.get $1)
          (i32.const 16)
        )
        (i32.shl
          (i32.add
            (local.get $0)
            (i32.const -1) ;; -16, so cancels out!
          )
          (i32.const 4)
        )
      )
    )
    (drop
      (i32.add
        (i32.add
          (local.get $1)
          (i32.const 20)
        )
        (i32.shl
          (i32.add
            (local.get $0)
            (i32.const -1) ;; -8, so sum is +12
          )
          (i32.const 3)
        )
      )
    )
    (drop
      (i32.add ;; simple sum
        (i32.const 1)
        (i32.const 3)
      )
    )
    (drop
      (i32.add ;; nested sum
        (i32.add
          (i32.const 1)
          (i32.const 3)
        )
        (i32.add
          (i32.const 5)
          (i32.const 9)
        )
      )
    )
    (drop
      (i32.add
        (i32.add
          (i32.const 1)
          (i32.const 3)
        )
        (i32.sub ;; internal sub
          (i32.const 5)
          (i32.const 3)
        )
      )
    )
    (drop
      (i32.sub ;; external sub
        (i32.add
          (i32.const 1)
          (i32.const 3)
        )
        (i32.add
          (i32.const 5)
          (i32.const 3)
        )
      )
    )
    (drop
      (i32.sub ;; external sub
        (i32.add
          (i32.const 1)
          (i32.const 3)
        )
        (i32.sub ;; and also internal sub
          (i32.const 5)
          (i32.const 3)
        )
      )
    )
    (drop
      (i32.add
        (i32.add
          (i32.const 1)
          (i32.const 3)
        )
        (i32.sub ;; negating sub
          (i32.const 0)
          (i32.const 3)
        )
      )
    )
    (drop
      (i32.add
        (i32.sub
          (i32.const 0)
          (i32.sub ;; two negating subs
            (i32.const 0)
            (i32.add
              (i32.const 3)
              (i32.const 20)
            )
          )
        )
        (i32.add
          (i32.const 1)
          (i32.const 2)
        )
      )
    )
    (drop
      (i32.add
        (i32.add
          (i32.const 0)
          (i32.sub ;; one negating sub
            (i32.const 0)
            (i32.add
              (i32.const 3)
              (i32.const 20)
            )
          )
        )
        (i32.add
          (i32.const 1)
          (i32.const 2)
        )
      )
    )
    (drop
      (i32.add
        (i32.shl ;; shifted value
          (i32.const 1)
          (i32.const 3)
        )
        (i32.add
          (i32.const 5)
          (i32.const 9)
        )
      )
    )
    (drop
      (i32.add
        (i32.shl ;; shifted value
          (i32.const 1)
          (local.get $0) ;; but not by const
        )
        (i32.add
          (i32.const 5)
          (i32.const 9)
        )
      )
    )
    (drop
      (i32.add
        (i32.shl ;; shifted nested value
          (i32.sub
            (local.get $1)
            (i32.const 10)
          )
          (i32.const 3)
        )
        (i32.add
          (i32.const 5)
          (i32.const 9)
        )
      )
    )
    (drop
      (i32.add
        (i32.mul ;; multiplied
          (i32.const 10)
          (i32.const 3)
        )
        (i32.add
          (i32.const 5)
          (i32.const 9)
        )
      )
    )
    (drop
      (i32.add
        (i32.mul ;; multiplied by nonconstant - can't recurse
          (i32.const 10)
          (local.get $0)
        )
        (i32.add
          (i32.const 5)
          (i32.const 9)
        )
      )
    )
    (drop
      (i32.add
        (i32.mul ;; nested mul
          (i32.add
            (i32.const 10)
            (local.get $0)
          )
          (i32.const 2)
        )
        (i32.add
          (i32.const 5)
          (i32.const 9)
        )
      )
    )
    (drop
      (i32.add
        (i32.add
          (local.get $0)
          (i32.const 10) ;; cancelled out with the below
        )
        (i32.sub
          (i32.const -5)
          (i32.const 5)
        )
      )
    )
  )
  ;; CHECK:      (func $almost-sign-ext (param $0 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (i32.const 100)
  ;; CHECK-NEXT:     (i32.const 25)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.const 50)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $almost-sign-ext (param $0 i32)
    (drop
      (i32.shr_s
        (i32.shl
          (i32.const 100) ;; too big, there is a sign bit, due to the extra shift
          (i32.const 25)
        )
        (i32.const 24) ;; different shift, but larger, so ok to opt if we leave a shift, in theory
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (i32.const 50) ;; small enough, no sign bit
          (i32.const 25)
        )
        (i32.const 24) ;; different shift, but larger, so ok to opt if we leave a shift
      )
    )
  )
  ;; CHECK:      (func $squaring (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 8)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 11)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 8)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 203)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 19)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 19)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 19)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (i32.shr_s
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 11)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 8)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $squaring (param $0 i32) (param $1 i32)
    (drop
      (i32.and
        (i32.and
          (local.get $0)
          (i32.const 11)
        )
        (i32.const 200)
      )
    )
    (drop
      (i32.and
        (i32.and
          (local.get $0)
          (i32.const 11)
        )
        (local.get $0) ;; non-const, cannot optimize this!
      )
    )
    (drop
      (i32.and
        (i32.and
          (i32.const 11) ;; flipped order
          (local.get $0)
        )
        (i32.const 200)
      )
    )
    (drop
      (i32.or
        (i32.or
          (local.get $0)
          (i32.const 11)
        )
        (i32.const 200)
      )
    )
    (drop
      (i32.shl
        (i32.shl
          (local.get $0)
          (i32.const 11)
        )
        (i32.const 200)
      )
    )
    (drop
      (i32.shr_s
        (i32.shr_s
          (local.get $0)
          (i32.const 11)
        )
        (i32.const 200)
      )
    )
    (drop
      (i32.shr_u
        (i32.shr_u
          (local.get $0)
          (i32.const 11)
        )
        (i32.const 200)
      )
    )
    (drop
      (i32.shr_u
        (i32.shr_s ;; but do not optimize a mixture or different shifts!
          (local.get $0)
          (i32.const 11)
        )
        (i32.const 200)
      )
    )
  )
  ;; CHECK:      (func $sign-ext-ne (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 111)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sign-ext-ne (param $0 i32) (param $1 i32)
    ;; ne of sign-ext to const, can be a zext
    (drop
      (i32.ne
        (i32.shr_s
          (i32.shl
            (local.get $0)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const 65000)
      )
    )
    (drop
      (i32.ne
        (i32.shr_s
          (i32.shl
            (local.get $0)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const 64872) ;; no sign bit
      )
    )
    (drop
      (i32.ne
        (i32.shr_s
          (i32.shl
            (local.get $0)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const -149) ;; no sign bit, not all ones
      )
    )
    (drop
      (i32.ne
        (i32.shr_s
          (i32.shl
            (local.get $0)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const 111)
      )
    )
    (drop
      (i32.ne
        (i32.shr_s
          (i32.shl
            (local.get $0)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.shr_s
          (i32.shl
            (local.get $1)
            (i32.const 24)
          )
          (i32.const 24)
        )
      )
    )
  )
  ;; CHECK:      (func $sign-ext-eqz (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sign-ext-eqz (param $0 i32) (param $1 i32)
    (drop
      (i32.eqz
        (i32.shr_s
          (i32.shl
            (local.get $0)
            (i32.const 24)
          )
          (i32.const 24)
        )
      )
    )
  )
  ;; CHECK:      (func $sign-ext-boolean (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 100)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 200)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sign-ext-boolean (param $0 i32) (param $1 i32)
    (drop
      (if (result i32)
        (i32.shr_s
          (i32.shl
            (local.get $0)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (then
          (i32.const 100)
        )
        (else
          (i32.const 200)
        )
      )
    )
  )
  ;; CHECK:      (func $add-sub-zero (param $0 i32) (param $1 i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $add-sub-zero (param $0 i32) (param $1 i64)
    (drop
      (i32.add
        (local.get $0)
        (i32.const 0)
      )
    )
    (drop
      (i32.sub
        (local.get $0)
        (i32.const 0)
      )
    )
    (drop
      (i64.add
        (local.get $1)
        (i64.const 0)
      )
    )
    (drop
      (i64.sub
        (local.get $1)
        (i64.const 0)
      )
    )
  )
  ;; CHECK:      (func $store-signext (param $0 i32)
  ;; CHECK-NEXT:  (i32.store8
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store8
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 25)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 25)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store8
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store16
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store16
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 17)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 17)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store16
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 16)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 8)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 8)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $store-signext (param $0 i32)
    (i32.store8
      (i32.const 8)
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24) ;; exact size we store, sign-ext of 8 bits
        )
        (i32.const 24)
      )
    )
    (i32.store8
      (i32.const 8)
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 25) ;; 7 bits. so the ext can alter a bit we store, do not optimize
        )
        (i32.const 25)
      )
    )
    (i32.store8
      (i32.const 8)
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 23) ;; 9 bits, this is good to optimize
        )
        (i32.const 23)
      )
    )
    (i32.store16
      (i32.const 8)
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 16) ;; exact size we store, sign-ext of 16 bits
        )
        (i32.const 16)
      )
    )
    (i32.store16
      (i32.const 8)
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 17) ;; 15 bits. so the ext can alter a bit we store, do not optimize
        )
        (i32.const 17)
      )
    )
    (i32.store16
      (i32.const 8)
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 14) ;; 17 bits, this is good to optimize
        )
        (i32.const 14)
      )
    )
    (i32.store
      (i32.const 8)
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 16) ;; 4 bytes stored, do nothing
        )
        (i32.const 16)
      )
    )
    (i32.store
      (i32.const 8)
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 8) ;; 4 bytes stored, do nothing
        )
        (i32.const 8)
      )
    )
  )
  ;; CHECK:      (func $sign-ext-tee (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.tee $0
  ;; CHECK-NEXT:      (i32.const 128)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $0
  ;; CHECK-NEXT:    (i32.const 127)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sign-ext-tee (param $0 i32) (param $1 i32)
    (drop
      (i32.shr_s
        (i32.shl
          (local.tee $0
            (i32.const 128) ;; too big
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.tee $0
            (i32.const 127) ;; just right
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
  )
  ;; CHECK:      (func $sign-ext-load (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.load8_s
  ;; CHECK-NEXT:    (i32.const 256)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (i32.shr_u
  ;; CHECK-NEXT:      (i32.load8_s
  ;; CHECK-NEXT:       (i32.const 256)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (i32.load8_u
  ;; CHECK-NEXT:     (i32.const 256)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.load16_s
  ;; CHECK-NEXT:    (i32.const 256)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $1
  ;; CHECK-NEXT:    (i32.load8_s
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.tee $1
  ;; CHECK-NEXT:      (i32.load8_u
  ;; CHECK-NEXT:       (i32.const 1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.tee $1
  ;; CHECK-NEXT:     (i32.load8_s
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $1
  ;; CHECK-NEXT:    (i32.load8_u
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sign-ext-load (param $0 i32) (param $1 i32)
    (drop
      (i32.shr_s
        (i32.shl
          (i32.load8_s ;; one byte, so perfect
            (i32.const 256)
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (i32.shr_u
            (i32.load8_s ;; one byte, but sexted to 32
              (i32.const 256)
            )
            (i32.const 1)
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (i32.shr_u
            (i32.load8_u ;; one byte, but reduced to 7
              (i32.const 256)
            )
            (i32.const 1)
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (i32.load16_s ;; two, so perfect
            (i32.const 256)
          )
          (i32.const 16)
        )
        (i32.const 16)
      )
    )
    ;; through tees, we cannot alter the load sign
    (drop
      (i32.shr_s
        (i32.shl
          (local.tee $1
            (i32.load8_s
              (i32.const 1)
            )
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.tee $1
            (i32.load8_u
              (i32.const 1)
            )
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.and
        (local.tee $1
          (i32.load8_s
            (i32.const 1)
          )
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.and
        (local.tee $1
          (i32.load8_u
            (i32.const 1)
          )
        )
        (i32.const 255)
      )
    )
  )
  ;; CHECK:      (func $mask-bits (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $0
  ;; CHECK-NEXT:    (i32.const 127)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $0
  ;; CHECK-NEXT:    (i32.const 128)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (i32.const 128)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 254)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (i32.const 128)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1279)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (i32.const 128)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1290)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $0
  ;; CHECK-NEXT:    (i32.const 128)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $0
  ;; CHECK-NEXT:    (i32.const 128)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (i32.const 128)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 127)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $mask-bits (param $0 i32) (param $1 i32)
    (drop
      (i32.and
        (local.tee $0
          (i32.const 127) ;; 7 bits
        )
        (i32.const 255) ;; mask 8, so we don't need this
      )
    )
    (drop
      (i32.and
        (local.tee $0
          (i32.const 128) ;; 8 bits
        )
        (i32.const 255) ;; mask 8, so we don't need this
      )
    )
    (drop
      (i32.and
        (local.tee $0
          (i32.const 128)
        )
        (i32.const 254) ;; improper mask, small
      )
    )
    (drop
      (i32.and
        (local.tee $0
          (i32.const 128)
        )
        (i32.const 1279) ;; improper mask, large
      )
    )
    (drop
      (i32.and
        (local.tee $0
          (i32.const 128)
        )
        (i32.const 1290) ;; improper mask, large
      )
    )
    (drop
      (i32.and
        (local.tee $0
          (i32.const 128)
        )
        (i32.const 4095) ;; proper mask, huge
      )
    )
    (drop
      (i32.and
        (local.tee $0
          (i32.const 128)
        )
        (i32.const 511) ;; proper mask, large
      )
    )
    (drop
      (i32.and
        (local.tee $0
          (i32.const 128)
        )
        (i32.const 127) ;; proper mask, just too small
      )
    )
  )
  ;; CHECK:      (func $local-info-zero-ext (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (local $x i32)
  ;; CHECK-NEXT:  (local $y i32)
  ;; CHECK-NEXT:  (local $z i32)
  ;; CHECK-NEXT:  (local $w i32)
  ;; CHECK-NEXT:  (local.set $x
  ;; CHECK-NEXT:   (i32.const 212)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $y
  ;; CHECK-NEXT:   (i32.const 500)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 212)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $z
  ;; CHECK-NEXT:   (i32.const 212)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $z
  ;; CHECK-NEXT:   (i32.const 220)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $w
  ;; CHECK-NEXT:   (i32.const 212)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $w
  ;; CHECK-NEXT:   (i32.const 1000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $local-info-zero-ext (param $0 i32) (param $1 i32)
    (local $x i32)
    (local $y i32)
    (local $z i32)
    (local $w i32)
    (local.set $x
      (i32.const 212) ;; mask is unneeded, we are small
    )
    (drop
      (i32.and
        (local.get $x)
        (i32.const 255)
      )
    )
    (local.set $y
      (i32.const 500) ;; mask is needed, we are too big
    )
    (drop
      (i32.and
        (local.get $y)
        (i32.const 255)
      )
    )
    (local.set $0
      (i32.const 212) ;; mask is unneeded, but we are a param, not a var, so no
    )
    (drop
      (i32.and
        (local.get $0)
        (i32.const 255)
      )
    )
    (local.set $z
      (i32.const 212) ;; mask is unneeded, we are small
    )
    (local.set $z
      (i32.const 220) ;; mask is still unneeded even with 2 uses
    )
    (drop
      (i32.and
        (local.get $z)
        (i32.const 255)
      )
    )
    (local.set $w
      (i32.const 212) ;; mask is unneeded, we are small
    )
    (local.set $w
      (i32.const 1000) ;; mask is needed, one use is too big
    )
    (drop
      (i32.and
        (local.get $w)
        (i32.const 255)
      )
    )
  )
  ;; CHECK:      (func $local-info-sign-ext-bitsize (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (local $x i32)
  ;; CHECK-NEXT:  (local $y i32)
  ;; CHECK-NEXT:  (local $z i32)
  ;; CHECK-NEXT:  (local $w i32)
  ;; CHECK-NEXT:  (local.set $x
  ;; CHECK-NEXT:   (i32.const 127)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $y
  ;; CHECK-NEXT:   (i32.const 128)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 127)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $z
  ;; CHECK-NEXT:   (i32.const 127)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $z
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $w
  ;; CHECK-NEXT:   (i32.const 127)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $w
  ;; CHECK-NEXT:   (i32.const 150)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $w)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $local-info-sign-ext-bitsize (param $0 i32) (param $1 i32)
    (local $x i32)
    (local $y i32)
    (local $z i32)
    (local $w i32)
    (local.set $x
      (i32.const 127) ;; mask is unneeded, we are small
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $x)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $y
      (i32.const 128) ;; mask is needed, we are too big
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $y)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $0
      (i32.const 127) ;; mask is unneeded, but we are a param, not a var, so no
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $z
      (i32.const 127) ;; mask is unneeded, we are small
    )
    (local.set $z
      (i32.const 100) ;; mask is still unneeded even with 2 uses
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $z)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $w
      (i32.const 127) ;; mask is unneeded, we are small
    )
    (local.set $w
      (i32.const 150) ;; mask is needed, one use is too big
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $w)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
  )
  ;; CHECK:      (func $local-info-sign-ext-already-exted (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (local $x i32)
  ;; CHECK-NEXT:  (local $y i32)
  ;; CHECK-NEXT:  (local $z i32)
  ;; CHECK-NEXT:  (local $w i32)
  ;; CHECK-NEXT:  (local.set $x
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $y
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 16)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $z
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $z
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $w
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $w
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 23)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $w)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 23)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $local-info-sign-ext-already-exted (param $0 i32) (param $1 i32)
    (local $x i32)
    (local $y i32)
    (local $z i32)
    (local $w i32)
    (local.set $x
      (i32.shr_s
        (i32.shl
          (local.get $0) ;; already sign-exted here, so no need later
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $x)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $y
      (i32.shr_s
        (i32.shl
          (local.get $0) ;; already sign-exted here, but wrong bit size
          (i32.const 16)
        )
        (i32.const 16)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $y)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $0
      (i32.shr_s
        (i32.shl
          (local.get $0) ;; already sign-exted here, so no need later, but we are a param
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $0)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $z
      (i32.shr_s
        (i32.shl
          (local.get $0) ;; already sign-exted here, so no need later
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $z
      (i32.shr_s
        (i32.shl
          (local.get $1) ;; already sign-exted here, so no need later
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $z)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $w
      (i32.shr_s
        (i32.shl
          (local.get $0) ;; already sign-exted here, so no need later
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $w
      (i32.shr_s
        (i32.shl
          (local.get $0) ;; not quite a sign-ext
          (i32.const 23)
        )
        (i32.const 24)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $w)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (drop ;; odd corner case
      (i32.shr_s
        (i32.shl
          (local.get $0) ;; param, so we should know nothing
          (i32.const 24)
        )
        (i32.const 23) ;; different shift, smaller
      )
    )
  )
  ;; CHECK:      (func $signed-loads-fill-the-bits (param $$e i32) (result i32)
  ;; CHECK-NEXT:  (local $$0 i32)
  ;; CHECK-NEXT:  (local $$conv i32)
  ;; CHECK-NEXT:  (local.set $$0
  ;; CHECK-NEXT:   (i32.load8_s
  ;; CHECK-NEXT:    (i32.const 1024)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $$conv
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $$0)
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (return
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $$e)
  ;; CHECK-NEXT:    (local.get $$conv)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $signed-loads-fill-the-bits (param $$e i32) (result i32)
    (local $$0 i32)
    (local $$conv i32)
    (local.set $$0
      (i32.load8_s ;; one byte, but 32 bits due to sign-extend
        (i32.const 1024)
      )
    )
    (local.set $$conv
      (i32.and
        (local.get $$0)
        (i32.const 255) ;; so we need this zexting!
      )
    )
    (return
      (i32.eq
        (local.get $$conv)
        (local.get $$e)
      )
    )
  )
  ;; CHECK:      (func $local-info-sign-ext-already-exted-by-load (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (local $x i32)
  ;; CHECK-NEXT:  (local $y i32)
  ;; CHECK-NEXT:  (local $z i32)
  ;; CHECK-NEXT:  (local $w i32)
  ;; CHECK-NEXT:  (local.set $x
  ;; CHECK-NEXT:   (i32.load8_s
  ;; CHECK-NEXT:    (i32.const 1024)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $y
  ;; CHECK-NEXT:   (i32.load8_u
  ;; CHECK-NEXT:    (i32.const 1024)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $z
  ;; CHECK-NEXT:   (i32.load16_s
  ;; CHECK-NEXT:    (i32.const 1024)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $local-info-sign-ext-already-exted-by-load (param $0 i32) (param $1 i32)
    (local $x i32)
    (local $y i32)
    (local $z i32)
    (local $w i32)
    (local.set $x
      (i32.load8_s (i32.const 1024)) ;; 8 bits, sign extended, no need to do it again
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $x)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $y
      (i32.load8_u (i32.const 1024)) ;; 8 bits, zext, so bad
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $y)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
    (local.set $z
      (i32.load16_s (i32.const 1024)) ;; 16 bits sign-extended, wrong size
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $z)
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
  )
  ;; CHECK:      (func $compare-load-s-sign-extend (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.load8_u
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.load8_u
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.load8_u
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.shr_s
  ;; CHECK-NEXT:     (i32.shl
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:      (i32.const 24)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.load8_s
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.shr_s
  ;; CHECK-NEXT:     (i32.shl
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:      (i32.const 16)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 16)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.load8_u
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.shr_s
  ;; CHECK-NEXT:     (i32.shl
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:      (i32.const 24)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.load8_s
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.shr_s
  ;; CHECK-NEXT:     (i32.shl
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:      (i32.const 16)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 16)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $compare-load-s-sign-extend (param $0 i32) (param $1 i32)
    (drop
      (i32.eq
        (i32.load8_s
          (local.get $0)
        )
        (i32.shr_s
          (i32.shl
            (local.get $1)
            (i32.const 24)
          )
          (i32.const 24)
        )
      )
    )
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $1)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.load8_s
          (local.get $0) ;; flip order, we should canonicalize
        )
      )
    )
    (drop
      (i32.eq
        (i32.load8_u ;; unsigned, bad
          (local.get $0)
        )
        (i32.shr_s
          (i32.shl
            (local.get $1)
            (i32.const 24)
          )
          (i32.const 24)
        )
      )
    )
    (drop
      (i32.eq
        (i32.load8_s
          (local.get $0)
        )
        (i32.shr_s
          (i32.shl
            (local.get $1)
            (i32.const 16) ;; wrong size
          )
          (i32.const 16)
        )
      )
    )
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $1)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.load8_u ;; unsigned, bad
          (local.get $0)
        )
      )
    )
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $1)
            (i32.const 16) ;; wrong size
          )
          (i32.const 16)
        )
        (i32.load8_s
          (local.get $0)
        )
      )
    )
  )
  ;; CHECK:      (func $unsign-diff-sizes (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (i32.ne
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (call $unsign-diff-sizes
  ;; CHECK-NEXT:      (i32.const -1)
  ;; CHECK-NEXT:      (i32.const 5)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 24)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 24)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (call $unsign-diff-sizes
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:      (i32.const 2006)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 16)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $unsign-diff-sizes (param $x i32) (param $y i32) (result i32)
    (i32.ne
      (i32.shr_s
        (i32.shl
          (call $unsign-diff-sizes
            (i32.const -1)
            (i32.const 5)
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
      (i32.shr_s
        (i32.shl
          (call $unsign-diff-sizes
            (i32.const 1)
            (i32.const 2006)
          )
          (i32.const 16)
        )
        (i32.const 16)
      )
    )
  )
  ;; CHECK:      (func $unsign-same-sizes (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (i32.ne
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (call $unsign-same-sizes
  ;; CHECK-NEXT:     (i32.const -1)
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (call $unsign-same-sizes
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (i32.const 2006)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $unsign-same-sizes (param $x i32) (param $y i32) (result i32)
    (i32.ne
      (i32.shr_s
        (i32.shl
          (call $unsign-same-sizes
            (i32.const -1)
            (i32.const 5)
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
      (i32.shr_s
        (i32.shl
          (call $unsign-same-sizes
            (i32.const 1)
            (i32.const 2006)
          )
          (i32.const 24)
        )
        (i32.const 24)
      )
    )
  )
  ;; CHECK:      (func $fuzz-almost-sign-ext
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (i32.load16_u
  ;; CHECK-NEXT:      (i32.const 2278)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 17)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (i32.load16_u
  ;; CHECK-NEXT:      (i32.const 2278)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 17)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $fuzz-almost-sign-ext
    (drop
      (i32.shr_s
        (i32.shl
          (i32.load16_u
            (i32.const 2278)
          )
          (i32.const 17)
        )
        (i32.const 16)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (i32.shl
            (i32.load16_u
              (i32.const 2278)
            )
            (i32.const 1)
          )
          (i32.const 16)
        )
        (i32.const 16)
      )
    )
  )
  ;; CHECK:      (func $fuzz-comp-impossible (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 127)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 252)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $fuzz-comp-impossible (param $x i32)
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $x)
            (i32.const 16)
          )
          (i32.const 16)
        )
        (i32.const 65535) ;; impossible to be equal, the effective sign bit is set, but not the higher bits, which the sign-ext will set on the non-const value
      )
    )
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $x)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $x)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const 127) ;; safe
      )
    )
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $x)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const 128) ;; unsafe again
      )
    )
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $x)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const 4223) ;; more big bits, so sign bit though
      )
    )
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $x)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const 4224) ;; more big bits
      )
    )
    (drop
      (i32.eq
        (i32.shr_s
          (i32.shl
            (local.get $x)
            (i32.const 24)
          )
          (i32.const 24)
        )
        (i32.const -4) ;; safe even with more big bits, as they are all 1s
      )
    )
  )
  ;; CHECK:      (func $if-parallel (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $0
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $0
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (unreachable)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.add
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:      (unreachable)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.add
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:      (unreachable)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-parallel (param $0 i32) (param $1 i32)
    (drop
      (if (result i32)
        (local.get $0)
        (then
          (i32.add (local.get $1) (i32.const 1))
        )
        (else
          (i32.add (local.get $1) (i32.const 1))
        )
      )
    )
    (drop
      (if (result i32)
        (local.tee $0 (local.get $1)) ;; side effects!
        (then
          (i32.add (local.get $1) (i32.const 1))
        )
        (else
          (i32.add (local.get $1) (i32.const 1))
        )
      )
    )
    (drop
      (if (result i32)
        (local.get $0)
        (then
          (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if
        )
        (else
          (i32.add (local.get $1) (unreachable))
        )
      )
    )
    (drop
      (if (result i32)
        (local.tee $0 (local.get $1)) ;; side effects!
        (then
          (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if
        )
        (else
          (i32.add (local.get $1) (unreachable))
        )
      )
    )
    (drop
      (if (result i32)
        (unreachable) ;; !!!
        (then
          (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if
        )
        (else
          (i32.add (local.get $1) (unreachable))
        )
      )
    )
  )
  ;; CHECK:      (func $select-parallel (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $0
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-parallel (param $0 i32) (param $1 i32)
    (drop
      (select
        (i32.add (local.get $1) (i32.const 1))
        (i32.add (local.get $1) (i32.const 1))
        (local.get $0)
      )
    )
    (drop
      (select
        (local.tee $0 (local.get $1)) ;; side effects!
        (local.tee $0 (local.get $1)) ;; side effects!
        (local.get $0)
      )
    )
    (drop
      (select
        (i32.add (local.get $1) (i32.const 1))
        (i32.add (local.get $1) (i32.const 1))
        (local.tee $0 (local.get $1)) ;; side effects! (but no interference with values)
      )
    )
    (drop
      (select
        (local.tee $0 (local.get $1)) ;; side effects! interference!
        (local.tee $0 (local.get $1)) ;; side effects! interference!
        (local.tee $0 (local.get $1)) ;; side effects! interference!
      )
    )
    (drop
      (select
        (local.tee $0 (local.get $1)) ;; side effects!
        (local.tee $0 (local.get $1)) ;; side effects!
        (unreachable) ;; side effects! (but no interference with values)
      )
    )
  )
  ;; CHECK:      (func $zero-shifts-is-not-sign-ext
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.load16_s align=1
  ;; CHECK-NEXT:     (i32.const 790656516)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const -5431187)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (i32.load16_s align=1
  ;; CHECK-NEXT:      (i32.const 790656516)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const -5431187)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $zero-shifts-is-not-sign-ext
   (drop
    (i32.eq
     (i32.const -5431187)
     (i32.add
      (i32.const 0)
      (i32.shr_s
       (i32.shl
        (i32.load16_s align=1
         (i32.const 790656516)
        )
        (i32.const 0)
       )
       (i32.const 0)
      )
     )
    )
   )
   (drop
    (i32.eq
     (i32.const -5431187)
     (i32.add
      (i32.const 0)
      (i32.shr_s
       (i32.shl
        (i32.load16_s align=1
         (i32.const 790656516)
        )
        (i32.const 1)
       )
       (i32.const 0)
      )
     )
    )
   )
  )
  ;; CHECK:      (func $zero-ops (result i32)
  ;; CHECK-NEXT:  (return
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.load16_s align=1
  ;; CHECK-NEXT:     (i32.const 790656516)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const -1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $zero-ops (result i32)
   (return
    (i32.eq
     (i32.const -1337)
     (i32.shr_u
      (i32.add
       (i32.const 0)
       (i32.shr_s
        (i32.shl
         (i32.load16_s align=1
          (i32.const 790656516)
         )
         (i32.const 0)
        )
        (i32.const 0)
       )
      )
      (i32.const 0)
     )
    )
   )
  )
  ;; CHECK:      (func $zero-ops-64 (result i32)
  ;; CHECK-NEXT:  (return
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (i64.load16_s align=1
  ;; CHECK-NEXT:     (i32.const 790656516)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const -1337)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $zero-ops-64 (result i32)
   (return
    (i64.eq
     (i64.const -1337)
     (i64.shr_u
      (i64.add
       (i64.const 0)
       (i64.shr_s
        (i64.shl
         (i64.load16_s align=1
          (i32.const 790656516)
         )
         (i64.const 0)
        )
        (i64.const 0)
       )
      )
      (i64.const 0)
     )
    )
   )
  )
  ;; CHECK:      (func $zero-ops-64-special (result i32)
  ;; CHECK-NEXT:  (return
  ;; CHECK-NEXT:   (i32.wrap_i64
  ;; CHECK-NEXT:    (i64.popcnt
  ;; CHECK-NEXT:     (i64.const 7377)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $zero-ops-64-special (result i32)
    (return
      (i32.wrap_i64
        (i64.popcnt
          (i64.sub
            (i64.shl
              (i64.const 4294783828)
              (i64.const 17179869183)
            )
            (i64.const -7377)
          )
        )
      )
    )
  )
  ;; CHECK:      (func $sign-ext-1-and-ne (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $sign-ext-1-and-ne)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 1)
  ;; CHECK-NEXT: )
  (func $sign-ext-1-and-ne (result i32)
   (select
    (i32.ne
     (i32.const 1333788672)
     (i32.shr_s
      (i32.shl
       (call $sign-ext-1-and-ne)
       (i32.const 1)
      )
      (i32.const 1)
     )
    )
    (i32.const 2)
    (i32.const 1)
   )
  )
  ;; CHECK:      (func $neg-shifts-and-255 (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (i32.const -99)
  ;; CHECK-NEXT:   (i32.const 255)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $neg-shifts-and-255 (result i32)
    (i32.and
     (i32.shr_u
      (i32.const -99)
      (i32.const -32) ;; this shift does nothing
     )
     (i32.const 255)
    )
  )
  ;; CHECK:      (func $neg-shifts-and-255-b (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (i32.const -2349025)
  ;; CHECK-NEXT:   (i32.const 255)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $neg-shifts-and-255-b (result i32)
   (i32.and
    (i32.shl
     (i32.const -2349025)
     (i32.const -32) ;; this shift does nothing
    )
    (i32.const 255)
   )
  )
  ;; CHECK:      (func $left-shifts-square-overflow (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $left-shifts-square-overflow (param $x i32) (result i32)
   (i32.shl
    (i32.shl
     (local.get $x)
     (i32.const 31)
    )
    (i32.const 1)
   )
  )
  ;; CHECK:      (func $left-shifts-square-overflow-with-side-effect (param $x i32) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $ne0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $left-shifts-square-overflow-with-side-effect (param $x i32) (result i32)
   (i32.shl
    (i32.shl
     (call $ne0) ;; side effect
     (i32.const 31)
    )
    (i32.const 5)
   )
  )
  ;; CHECK:      (func $right-shifts-square-overflow-unsigned (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $right-shifts-square-overflow-unsigned (param $x i32) (result i32)
   (i32.shr_u
    (i32.shr_u
     (local.get $x)
     (i32.const 65535) ;; 31 bits effectively
    )
    (i32.const 32767) ;; also 31 bits, so two shifts that force the value into nothing for sure
   )
  )
  ;; CHECK:      (func $shifts-square-overflow-signed (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.shr_s
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 31)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $shifts-square-overflow-signed (param $x i32) (result i32)
   (i32.shr_s
    (i32.shr_s
     (local.get $x)
     (i32.const 65535) ;; 31 bits effectively
    )
    (i32.const 32767) ;; also 31 bits, so two shifts that force the value into nothing for sure
   )
  )
  ;; CHECK:      (func $shifts-square-no-overflow-small (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.shr_u
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 9)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $shifts-square-no-overflow-small (param $x i32) (result i32)
   (i32.shr_u
    (i32.shr_u
     (local.get $x)
     (i32.const 1031) ;; 7 bits effectively
    )
    (i32.const 4098) ;; 2 bits effectively
   )
  )
  ;; CHECK:      (func $left-shifts-square-overflow-unsigned-64 (param $x i64) (result i64)
  ;; CHECK-NEXT:  (i64.const 0)
  ;; CHECK-NEXT: )
  (func $left-shifts-square-overflow-unsigned-64 (param $x i64) (result i64)
   (i64.shl
    (i64.shl
     (local.get $x)
     (i64.const 2)
    )
    (i64.const 63)
   )
  )
  ;; CHECK:      (func $right-shifts-square-overflow-unsigned-64 (param $x i64) (result i64)
  ;; CHECK-NEXT:  (i64.const 0)
  ;; CHECK-NEXT: )
  (func $right-shifts-square-overflow-unsigned-64 (param $x i64) (result i64)
   (i64.shr_u
    (i64.shr_u
     (local.get $x)
     (i64.const 65535) ;; 63 bits effectively
    )
    (i64.const 64767) ;; also 63 bits, so two shifts that force the value into nothing for sure
   )
  )
  ;; CHECK:      (func $right-shifts-square-overflow-signed-64 (param $x i64) (result i64)
  ;; CHECK-NEXT:  (i64.shr_s
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i64.const 63)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $right-shifts-square-overflow-signed-64 (param $x i64) (result i64)
   (i64.shr_s
    (i64.shr_s
     (local.get $x)
     (i64.const 65535) ;; 63 bits effectively
    )
    (i64.const 64767) ;; also 63 bits, so two shifts that force the value into nothing for sure
   )
  )
  ;; CHECK:      (func $shifts-square-no-overflow-small-64 (param $x i64) (result i64)
  ;; CHECK-NEXT:  (i64.shr_u
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i64.const 9)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $shifts-square-no-overflow-small-64 (param $x i64) (result i64)
   (i64.shr_u
    (i64.shr_u
     (local.get $x)
     (i64.const 1031) ;; 7 bits effectively
    )
    (i64.const 4098) ;; 2 bits effectively
   )
  )
  ;; CHECK:      (func $shifts-square-unreachable (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.shr_u
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:    (i32.const 1031)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 4098)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $shifts-square-unreachable (param $x i32) (result i32)
   (i32.shr_u
    (i32.shr_u
     (unreachable)
     (i32.const 1031) ;; 7 bits effectively
    )
    (i32.const 4098) ;; 2 bits effectively
   )
  )
  ;; CHECK:      (func $mix-shifts (result i32)
  ;; CHECK-NEXT:  (i32.shr_u
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.const 65535)
  ;; CHECK-NEXT:    (i32.const 3)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $mix-shifts (result i32)
    (i32.shr_s
      (i32.shl
        (i32.const 65535)
        (i32.const -61)
      )
      (i32.const 168)
    )
  )
  ;; CHECK:      (func $mix-shifts-with-same-const-signed (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -9223372036854775808)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.shr_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 4)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 5)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shl
  ;; CHECK-NEXT:    (i64.shr_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 63)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $mix-shifts-with-same-const-signed (param $x i32) (param $y i64)
    (drop
      (i32.shl
        (i32.shr_s
          (local.get $x)
          (i32.const 4)
        )
        (i32.const 4)
      )
    )
    (drop
      (i64.shl
        (i64.shr_s
          (local.get $y)
          (i64.const 63)
        )
        (i64.const 127) ;; effective shift is 63
      )
    )

    ;; skips
    (drop
      (i32.shl
        (i32.shr_s
          (local.get $x)
          (i32.const 4)
        )
        (i32.const 5)
      )
    )
    (drop
      (i64.shl
        (i64.shr_s
          (local.get $y)
          (i64.const 63)
        )
        (i64.const 1)
      )
    )
  )
  ;; CHECK:      (func $mix-shifts-with-same-const-unsigned (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -9223372036854775808)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 4)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 5)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shl
  ;; CHECK-NEXT:    (i64.shr_u
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 63)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $mix-shifts-with-same-const-unsigned (param $x i32) (param $y i64)
    (drop
      (i32.shl
        (i32.shr_u
          (local.get $x)
          (i32.const 4)
        )
        (i32.const 4)
      )
    )
    (drop
      (i64.shl
        (i64.shr_u
          (local.get $y)
          (i64.const 63)
        )
        (i64.const 127) ;; effective shift is 63
      )
    )

    ;; skips
    (drop
      (i32.shl
        (i32.shr_u
          (local.get $x)
          (i32.const 4)
        )
        (i32.const 5)
      )
    )
    (drop
      (i64.shl
        (i64.shr_u
          (local.get $y)
          (i64.const 63)
        )
        (i64.const 1)
      )
    )
  )
  ;; CHECK:      (func $reversed-mix-shifts-with-same-const (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 268435455)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 4)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shr_u
  ;; CHECK-NEXT:    (i64.shl
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 4)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 8)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 6)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 6)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $reversed-mix-shifts-with-same-const (param $x i32) (param $y i64)
    (drop
      (i32.shr_u
        (i32.shl
          (local.get $x)
          (i32.const 4)
        )
        (i32.const 4)
      )
    )
    (drop
      (i32.shr_u
        (i32.shl
          (local.get $x)
          (i32.const 31)
        )
        (i32.const 31)
      )
    )
    (drop
      (i64.shr_u
        (i64.shl
          (local.get $y)
          (i64.const 127) ;; effective shift is 63
        )
        (i64.const 63) ;; effective shift is 63
      )
    )

    ;; skips
    (drop
      (i32.shr_u
        (i32.shl
          (local.get $x)
          (i32.const 5)
        )
        (i32.const 4)
      )
    )
    (drop
      (i64.shr_u
        (i64.shl
          (local.get $y)
          (i64.const 4)
        )
        (i64.const 8)
      )
    )
    (drop
      (i32.shr_s
        (i32.shl
          (local.get $x)
          (i32.const 6)
        )
        (i32.const 6)
      )
    )
  )
  ;; CHECK:      (func $actually-no-shifts (result i32)
  ;; CHECK-NEXT:  (i32.const 33)
  ;; CHECK-NEXT: )
  (func $actually-no-shifts (result i32)
    (i32.add
      (i32.shl
        (i32.const 23)
        (i32.const 32) ;; really 0
      )
      (i32.const 10)
    )
  )
  ;; CHECK:      (func $less-shifts-than-it-seems (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.const 4800)
  ;; CHECK-NEXT: )
  (func $less-shifts-than-it-seems (param $x i32) (result i32)
    (i32.add
      (i32.shl
        (i32.const 200)
        (i32.const 36) ;; really 4
      )
      (i32.shl
        (i32.const 100)
        (i32.const 4)
      )
    )
  )
  ;; CHECK:      (func $rotate-left-square-no-overflow-small (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.rotl
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 7)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rotate-left-square-no-overflow-small (param $x i32) (result i32)
    (i32.rotl
      (i32.rotl
        (local.get $x)
        (i32.const 3)
      )
      (i32.const 4)
    )
  )
  ;; CHECK:      (func $rotate-right-square-no-overflow-small (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.rotr
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 7)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rotate-right-square-no-overflow-small (param $x i32) (result i32)
    (i32.rotr
      (i32.rotr
        (local.get $x)
        (i32.const 3)
      )
      (i32.const 4)
    )
  )
  ;; CHECK:      (func $rotate-left-square-no-shifts (param $x i32) (result i32)
  ;; CHECK-NEXT:  (local.get $x)
  ;; CHECK-NEXT: )
  (func $rotate-left-square-no-shifts (param $x i32) (result i32)
    (i32.rotl
      (i32.rotl
        (local.get $x)
        (i32.const 12)
      )
      (i32.const 20)
    )
  )
  ;; CHECK:      (func $rotate-right-square-no-shifts (param $x i32) (result i32)
  ;; CHECK-NEXT:  (local.get $x)
  ;; CHECK-NEXT: )
  (func $rotate-right-square-no-shifts (param $x i32) (result i32)
    (i32.rotr
      (i32.rotr
        (local.get $x)
        (i32.const 30)
      )
      (i32.const 2)
    )
  )
  ;; CHECK:      (func $rotate-right-left-pos (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.rotl
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 23)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rotate-right-left-pos (param $x i32) (result i32)
    (i32.rotr
      (i32.rotl
        (local.get $x)
        (i32.const 27)
      )
      (i32.const 4)
    )
  )
  ;; CHECK:      (func $rotate-left-right-pos (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.rotr
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 7)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rotate-left-right-pos (param $x i32) (result i32)
    (i32.rotl
      (i32.rotr
        (local.get $x)
        (i32.const 12)
      )
      (i32.const 5)
    )
  )
  ;; CHECK:      (func $rotate-right-left-neg (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.rotl
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 27)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rotate-right-left-neg (param $x i32) (result i32)
    (i32.rotr
      (i32.rotl
        (local.get $x)
        (i32.const 5)
      )
      (i32.const 10)
    )
  )
  ;; CHECK:      (func $rotate-left-right-neg (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.rotr
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 27)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rotate-left-right-neg (param $x i32) (result i32)
    (i32.rotl
      (i32.rotr
        (local.get $x)
        (i32.const 5)
      )
      (i32.const 10)
    )
  )
  ;; CHECK:      (func $rotate-right-left-none (param $x i32) (result i32)
  ;; CHECK-NEXT:  (local.get $x)
  ;; CHECK-NEXT: )
  (func $rotate-right-left-none (param $x i32) (result i32)
    (i32.rotr
      (i32.rotl
        (local.get $x)
        (i32.const 16)
      )
      (i32.const 16)
    )
  )
  ;; CHECK:      (func $rotate-left-right-none (param $x i32) (result i32)
  ;; CHECK-NEXT:  (local.get $x)
  ;; CHECK-NEXT: )
  (func $rotate-left-right-none (param $x i32) (result i32)
    (i32.rotl
      (i32.rotr
        (local.get $x)
        (i32.const 16)
      )
      (i32.const 16)
    )
  )
  ;; CHECK:      (func $rotate-right-left-overflow (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.rotl
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 27)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rotate-right-left-overflow (param $x i32) (result i32)
    (i32.rotr
      (i32.rotl
        (local.get $x)
        (i32.const 18)
      )
      (i32.const 23)
    )
  )
  ;; CHECK:      (func $rotate-left-right-overflow (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.rotr
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 27)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rotate-left-right-overflow (param $x i32) (result i32)
    (i32.rotl
      (i32.rotr
        (local.get $x)
        (i32.const 18)
      )
      (i32.const 23)
    )
  )
  ;; CHECK:      (func $and-popcount32 (result i32)
  ;; CHECK-NEXT:  (i32.and
  ;; CHECK-NEXT:   (i32.popcnt
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 31)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $and-popcount32 (result i32)
    (i32.and
      (i32.popcnt
        (i32.const -1)
      )
      (i32.const 31)
    )
  )
  ;; CHECK:      (func $and-popcount32-big (result i32)
  ;; CHECK-NEXT:  (i32.popcnt
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $and-popcount32-big (result i32)
    (i32.and
      (i32.popcnt
        (i32.const -1)
      )
      (i32.const 63)
    )
  )
  ;; CHECK:      (func $and-popcount64 (result i64)
  ;; CHECK-NEXT:  (i64.and
  ;; CHECK-NEXT:   (i64.popcnt
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i64.const 63)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $and-popcount64 (result i64) ;; these are TODOs
    (i64.and
      (i64.popcnt
        (i64.const -1)
      )
      (i64.const 63)
    )
  )
  ;; CHECK:      (func $and-popcount64-big (result i64)
  ;; CHECK-NEXT:  (i64.and
  ;; CHECK-NEXT:   (i64.popcnt
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i64.const 127)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $and-popcount64-big (result i64)
    (i64.and
      (i64.popcnt
        (i64.const -1)
      )
      (i64.const 127)
    )
  )
  ;; CHECK:      (func $and-popcount64-bigger (result i64)
  ;; CHECK-NEXT:  (i64.and
  ;; CHECK-NEXT:   (i64.popcnt
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i64.const 255)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $and-popcount64-bigger (result i64)
    (i64.and
      (i64.popcnt
        (i64.const -1)
      )
      (i64.const 255)
    )
  )
  ;; CHECK:      (func $optimizeAddedConstants-filters-through-nonzero (result i32)
  ;; CHECK-NEXT:  (i32.const -536902656)
  ;; CHECK-NEXT: )
  (func $optimizeAddedConstants-filters-through-nonzero (result i32)
   (i32.sub
    (i32.add
     (i32.shl
      (i32.const -536870912)
      (i32.wrap_i64
       (i64.const 0)
      )
     )
     (i32.const -32768)
    )
    (i32.const -1024)
   )
  )
  ;; CHECK:      (func $optimizeAddedConstants-filters-through-nonzero-b (result i32)
  ;; CHECK-NEXT:  (i32.const -31744)
  ;; CHECK-NEXT: )
  (func $optimizeAddedConstants-filters-through-nonzero-b (result i32)
   (i32.sub
    (i32.add
     (i32.shl
      (i32.const -536870912)
      (i32.wrap_i64
       (i64.const -1)
      )
     )
     (i32.const -32768)
    )
    (i32.const -1024)
   )
  )
  ;; CHECK:      (func $optimizeAddedConstants-mul-lshift-32 (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 12)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimizeAddedConstants-mul-lshift-32 (param $x i32) (result i32)
   (i32.shl
    (i32.mul
     (local.get $x)
     (i32.const 3)
    )
    (i32.const 2)
   )
  )
  ;; CHECK:      (func $optimizeAddedConstants-mul-lshift-64 (param $x i64) (result i64)
  ;; CHECK-NEXT:  (i64.mul
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i64.const 12)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimizeAddedConstants-mul-lshift-64 (param $x i64) (result i64)
   (i64.shl
    (i64.mul
     (local.get $x)
     (i64.const 3)
    )
    (i64.const 2)
   )
  )
  ;; CHECK:      (func $optimizeAddedConstants-lshift-mul-32 (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 12)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimizeAddedConstants-lshift-mul-32 (param $x i32) (result i32)
   (i32.mul
    (i32.shl
     (local.get $x)
     (i32.const 2)
    )
    (i32.const 3)
   )
  )
  ;; CHECK:      (func $optimizeAddedConstants-lshift-mul-64 (param $x i64) (result i64)
  ;; CHECK-NEXT:  (i64.mul
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i64.const 12)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimizeAddedConstants-lshift-mul-64 (param $x i64) (result i64)
   (i64.mul
    (i64.shl
     (local.get $x)
     (i64.const 2)
    )
    (i64.const 3)
   )
  )
  ;; CHECK:      (func $return-proper-value-from-shift-left-by-zero (result i32)
  ;; CHECK-NEXT:  (if (result i32)
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (loop $label$0 (result i32)
  ;; CHECK-NEXT:     (block $label$1
  ;; CHECK-NEXT:      (br_if $label$1
  ;; CHECK-NEXT:       (i32.load
  ;; CHECK-NEXT:        (i32.const 0)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const -62)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 40)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $return-proper-value-from-shift-left-by-zero (result i32)
   (if (result i32)
    (i32.sub
     (i32.add
      (loop $label$0 (result i32)
       (block $label$1
        (br_if $label$1
         (i32.shl
          (i32.load
           (i32.const 0)
          )
          (i32.const -31904) ;; really 0 shifts
         )
        )
       )
       (i32.const -62)
      )
      (i32.const 38)
     )
     (i32.const -2)
    )
    (then
     (i32.const 1)
    )
    (else
     (i32.const 0)
    )
   )
  )
  ;; CHECK:      (func $de-morgan-2 (param $x i32) (param $y i32) (param $z i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.xor
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.wrap_i64
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $de-morgan-2 (param $x i32) (param $y i32) (param $z i64)
    (drop
      (i32.and (i32.eqz (local.get $x)) (i32.eqz (local.get $y)))
    )
    (drop
      (i32.or (i32.eqz (local.get $x)) (i32.eqz (local.get $y)))
    )
    (drop
      (i32.xor (i32.eqz (local.get $x)) (i32.eqz (local.get $y)))
    )
    (drop
      (i32.and (i32.eqz (local.get $x)) (local.get $y))
    )
    (drop
      (i32.and (local.get $x) (i32.eqz (local.get $y)))
    )
    (drop
      (i32.and (i32.eqz (local.get $x)) (i32.wrap_i64 (local.get $z)))
    )
    (drop
      (i32.and (i32.wrap_i64 (i64.const 1)) (i32.eqz (local.get $y)))
    )
  )
  ;; CHECK:      (func $subzero1 (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.sub
  ;; CHECK-NEXT:   (i32.const 32)
  ;; CHECK-NEXT:   (i32.clz
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $subzero1 (param $0 i32) (result i32)
    (i32.add
     (i32.sub
      (i32.const 1)
      (i32.clz
       (local.get $0)
      )
     )
     (i32.const 31)
    )
  )
  ;; CHECK:      (func $subzero2 (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.sub
  ;; CHECK-NEXT:   (i32.const 32)
  ;; CHECK-NEXT:   (i32.clz
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $subzero2 (param $0 i32) (result i32)
    (i32.add
     (i32.const 31)
     (i32.sub
      (i32.const 1)
      (i32.clz
       (local.get $0)
      )
     )
    )
  )
  ;; CHECK:      (func $subzero3 (param $0 i32) (param $1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.sub
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:   (i32.clz
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $subzero3 (param $0 i32) (param $1 i32) (result i32)
    (i32.add
     (i32.sub
      (i32.const 0)
      (i32.clz
       (local.get $0)
      )
     )
     (local.get $1)
    )
  )
  ;; CHECK:      (func $subzero4 (param $0 i32) (param $1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.sub
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (i32.clz
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $subzero4 (param $0 i32) (param $1 i32) (result i32)
    (i32.add
     (local.get $0)
     (i32.sub
      (i32.const 0)
      (i32.clz
       (local.get $1)
      )
     )
    )
  )
  ;; CHECK:      (func $remove-signs-for-mul-i32 (param $0 i32) (param $1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $remove-signs-for-mul-i32 (param $0 i32) (param $1 i32) (result i32)
    (i32.mul
      (i32.sub
        (i32.const 0)
        (local.get $0)
      )
      (i32.sub
        (i32.const 0)
        (local.get $1)
      )
    )
  )
  ;; CHECK:      (func $remove-signs-for-mul-i64 (param $0 i64) (param $1 i64) (result i64)
  ;; CHECK-NEXT:  (i64.mul
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $remove-signs-for-mul-i64 (param $0 i64) (param $1 i64) (result i64)
    (i64.mul
      (i64.sub
        (i64.const 0)
        (local.get $0)
      )
      (i64.sub
        (i64.const 0)
        (local.get $1)
      )
    )
  )
  ;; CHECK:      (func $propagate-sign-for-i32-lhs (param $0 i32) (param $1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.sub
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (i32.mul
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-i32-lhs (param $0 i32) (param $1 i32) (result i32)
    (i32.mul
      (i32.sub
        (i32.const 0)
        (local.get $0)
      )
      (local.get $1)
    )
  )
  ;; CHECK:      (func $propagate-sign-for-i32-rhs (param $0 i32) (param $1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.sub
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (i32.mul
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-i32-rhs (param $0 i32) (param $1 i32) (result i32)
    (i32.mul
      (local.get $0)
      (i32.sub
        (i32.const 0)
        (local.get $1)
      )
    )
  )
  ;; CHECK:      (func $propagate-sign-for-i64-lhs (param $0 i64) (param $1 i64) (result i64)
  ;; CHECK-NEXT:  (i64.sub
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:   (i64.mul
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-i64-lhs (param $0 i64) (param $1 i64) (result i64)
    (i64.mul
      (i64.sub
        (i64.const 0)
        (local.get $0)
      )
      (local.get $1)
    )
  )
  ;; CHECK:      (func $propagate-sign-for-i64-rhs (param $0 i64) (param $1 i64) (result i64)
  ;; CHECK-NEXT:  (i64.sub
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:   (i64.mul
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-i64-rhs (param $0 i64) (param $1 i64) (result i64)
    (i64.mul
      (local.get $0)
      (i64.sub
        (i64.const 0)
        (local.get $1)
      )
    )
  )
  ;; CHECK:      (func $propagate-sign-for-i32-rhs-side (param $0 i32) (param $1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.sub
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (i32.mul
  ;; CHECK-NEXT:    (call $subzero4
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-i32-rhs-side (param $0 i32) (param $1 i32) (result i32)
    (i32.mul
      (call $subzero4
        (local.get $0)
        (local.get $1)
      )
      (i32.sub
        (i32.const 0)
        (local.get $1)
      )
    )
  )
  ;; CHECK:      (func $propagate-sign-for-mul-i32-lhs-const (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (i32.const -3)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-mul-i32-lhs-const (param $0 i32) (result i32)
    (i32.mul
      (i32.const 3)
      (i32.sub
        (i32.const 0)
        (local.get $0)
      )
    )
  )
  ;; CHECK:      (func $propagate-sign-for-mul-i32-lhs-const-pot (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.sub
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (i32.mul
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-mul-i32-lhs-const-pot (param $0 i32) (result i32)
    (i32.mul
      (i32.const 2)
      (i32.sub
        (i32.const 0)
        (local.get $0)
      )
    )
  )
  ;; CHECK:      (func $propagate-sign-for-mul-i32-rhs-const (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (i32.const 5)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-mul-i32-rhs-const (param $0 i32) (result i32)
    (i32.mul
      (i32.sub
        (i32.const 0)
        (local.get $0)
      )
      (i32.const -5)
    )
  )
  ;; CHECK:      (func $propagate-sign-for-i32-both-sign-consts (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:   (i32.const 5)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-i32-both-sign-consts (param $0 i32) (result i32)
    (i32.mul
      (i32.const -5)
      (i32.sub
        (i32.const 0)
        (i32.const 2)
      )
    )
  )
  ;; CHECK:      (func $propagate-sign-for-mul-i32-smin (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.shl
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (i32.const 31)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-mul-i32-smin (param $0 i32) (result i32)
    (i32.mul
      (i32.sub
        (i32.const 0)
        (local.get $0)
      )
      (i32.const 0x80000000)
    )
  )
  ;; CHECK:      (func $propagate-sign-for-mul-i32-skip-2 (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (i32.const 3)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $propagate-sign-for-mul-i32-skip-2 (param $0 i32) (result i32)
    (i32.mul
      (local.get $0)
      (i32.sub
        (i32.const 0)
        (i32.const 3)
      )
    )
  )
  ;; CHECK:      (func $mul-32-power-2 (param $x i32) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $mul-32-power-2
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $mul-32-power-2
  ;; CHECK-NEXT:    (i32.mul
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $mul-32-power-2
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $mul-32-power-2
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $mul-32-power-2
  ;; CHECK-NEXT:    (i32.mul
  ;; CHECK-NEXT:     (call $mul-32-power-2
  ;; CHECK-NEXT:      (i32.const 123)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $mul-32-power-2
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $mul-32-power-2
  ;; CHECK-NEXT:    (i32.shl
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 31)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $mul-32-power-2 (param $x i32) (result i32)
    (drop
      (call $mul-32-power-2
        (i32.mul
          (local.get $x)
          (i32.const 4)
        )
      )
    )
    (drop
      (call $mul-32-power-2
        (i32.mul
          (local.get $x)
          (i32.const 5)
        )
      )
    )
    (drop
      (call $mul-32-power-2
        (i32.mul
          (local.get $x)
          (i32.const 1)
        )
      )
    )
    (drop
      (call $mul-32-power-2
        (i32.mul
          (local.get $x)
          (i32.const 0)
        )
      )
    )
    (drop
      (call $mul-32-power-2
        (i32.mul
          (call $mul-32-power-2 (i32.const 123)) ;; side effects
          (i32.const 0)
        )
      )
    )
    (drop
      (call $mul-32-power-2
        (i32.mul
          (local.get $x)
          (i32.const 0xffffffff)
        )
      )
    )
    (drop
      (call $mul-32-power-2
        (i32.mul
          (local.get $x)
          (i32.const 0x80000000)
        )
      )
    )
    (unreachable)
  )
    ;; CHECK:      (func $mul-64-power-2 (param $x i64) (result i64)
    ;; CHECK-NEXT:  (drop
    ;; CHECK-NEXT:   (call $mul-64-power-2
    ;; CHECK-NEXT:    (i64.shl
    ;; CHECK-NEXT:     (local.get $x)
    ;; CHECK-NEXT:     (i64.const 2)
    ;; CHECK-NEXT:    )
    ;; CHECK-NEXT:   )
    ;; CHECK-NEXT:  )
    ;; CHECK-NEXT:  (drop
    ;; CHECK-NEXT:   (call $mul-64-power-2
    ;; CHECK-NEXT:    (i64.mul
    ;; CHECK-NEXT:     (local.get $x)
    ;; CHECK-NEXT:     (i64.const 5)
    ;; CHECK-NEXT:    )
    ;; CHECK-NEXT:   )
    ;; CHECK-NEXT:  )
    ;; CHECK-NEXT:  (drop
    ;; CHECK-NEXT:   (call $mul-64-power-2
    ;; CHECK-NEXT:    (local.get $x)
    ;; CHECK-NEXT:   )
    ;; CHECK-NEXT:  )
    ;; CHECK-NEXT:  (drop
    ;; CHECK-NEXT:   (call $mul-64-power-2
    ;; CHECK-NEXT:    (i64.const 0)
    ;; CHECK-NEXT:   )
    ;; CHECK-NEXT:  )
    ;; CHECK-NEXT:  (drop
    ;; CHECK-NEXT:   (call $mul-64-power-2
    ;; CHECK-NEXT:    (i64.mul
    ;; CHECK-NEXT:     (call $mul-64-power-2
    ;; CHECK-NEXT:      (i64.const 123)
    ;; CHECK-NEXT:     )
    ;; CHECK-NEXT:     (i64.const 0)
    ;; CHECK-NEXT:    )
    ;; CHECK-NEXT:   )
    ;; CHECK-NEXT:  )
    ;; CHECK-NEXT:  (drop
    ;; CHECK-NEXT:   (call $mul-64-power-2
    ;; CHECK-NEXT:    (i64.sub
    ;; CHECK-NEXT:     (i64.const 0)
    ;; CHECK-NEXT:     (local.get $x)
    ;; CHECK-NEXT:    )
    ;; CHECK-NEXT:   )
    ;; CHECK-NEXT:  )
    ;; CHECK-NEXT:  (drop
    ;; CHECK-NEXT:   (call $mul-64-power-2
    ;; CHECK-NEXT:    (i64.shl
    ;; CHECK-NEXT:     (local.get $x)
    ;; CHECK-NEXT:     (i64.const 63)
    ;; CHECK-NEXT:    )
    ;; CHECK-NEXT:   )
    ;; CHECK-NEXT:  )
    ;; CHECK-NEXT:  (unreachable)
    ;; CHECK-NEXT: )
    (func $mul-64-power-2 (param $x i64) (result i64)
    (drop
      (call $mul-64-power-2
        (i64.mul
          (local.get $x)
          (i64.const 4)
        )
      )
    )
    (drop
      (call $mul-64-power-2
        (i64.mul
          (local.get $x)
          (i64.const 5)
        )
      )
    )
    (drop
      (call $mul-64-power-2
        (i64.mul
          (local.get $x)
          (i64.const 1)
        )
      )
    )
    (drop
      (call $mul-64-power-2
        (i64.mul
          (local.get $x)
          (i64.const 0)
        )
      )
    )
    (drop
      (call $mul-64-power-2
        (i64.mul
          (call $mul-64-power-2 (i64.const 123)) ;; side effects
          (i64.const 0)
        )
      )
    )
    (drop
      (call $mul-64-power-2
        (i64.mul
          (local.get $x)
          (i64.const 0xffffffffffffffff)
        )
      )
    )
    (drop
      (call $mul-64-power-2
        (i64.mul
          (local.get $x)
          (i64.const 0x8000000000000000)
        )
      )
    )
    (unreachable)
  )
  ;; CHECK:      (func $div-32-power-2 (param $x i32) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $div-32-power-2
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $div-32-power-2
  ;; CHECK-NEXT:    (i32.div_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $div-32-power-2
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $div-32-power-2
  ;; CHECK-NEXT:    (i32.div_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $div-32-power-2
  ;; CHECK-NEXT:    (i32.div_u
  ;; CHECK-NEXT:     (call $div-32-power-2
  ;; CHECK-NEXT:      (i32.const 123)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $div-32-power-2
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const -1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $div-32-power-2
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 31)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $div-32-power-2 (param $x i32) (result i32)
    (drop
      (call $div-32-power-2
        (i32.div_u
          (local.get $x)
          (i32.const 4)
        )
      )
    )
    (drop
      (call $div-32-power-2
        (i32.div_u
          (local.get $x)
          (i32.const 5)
        )
      )
    )
    (drop
      (call $div-32-power-2
        (i32.div_u
          (local.get $x)
          (i32.const 1)
        )
      )
    )
    (drop
      (call $div-32-power-2
        (i32.div_u
          (local.get $x)
          (i32.const 0)
        )
      )
    )
    (drop
      (call $div-32-power-2
        (i32.div_u
          (call $div-32-power-2 (i32.const 123)) ;; side effects
          (i32.const 0)
        )
      )
    )
    (drop
      (call $div-32-power-2
        (i32.div_u
          (local.get $x)
          (i32.const 0xffffffff)
        )
      )
    )
    (drop
      (call $div-32-power-2
        (i32.div_u
          (local.get $x)
          (i32.const 0x80000000)
        )
      )
    )
    (unreachable)
  )
  ;; CHECK:      (func $urem-32-power-2 (param $x i32) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $urem-32-power-2
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $urem-32-power-2
  ;; CHECK-NEXT:    (i32.rem_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $urem-32-power-2
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $urem-32-power-2
  ;; CHECK-NEXT:    (i32.rem_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $urem-32-power-2
  ;; CHECK-NEXT:    (i32.rem_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const -1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $urem-32-power-2
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2147483647)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (call $urem-32-power-2
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $urem-32-power-2 (param $x i32) (result i32)
    (drop
      (call $urem-32-power-2
        (i32.rem_u
          (local.get $x)
          (i32.const 4)
        )
      )
    )
    (drop
      (call $urem-32-power-2
        (i32.rem_u
          (local.get $x)
          (i32.const 5)
        )
      )
    )
    (drop
      (call $urem-32-power-2
        (i32.rem_u
          (local.get $x)
          (i32.const 1)
        )
      )
    )
    (drop
      (call $urem-32-power-2
        (i32.rem_u
          (local.get $x)
          (i32.const 0)
        )
      )
    )
    (drop
      (call $urem-32-power-2
        (i32.rem_u
          (local.get $x)
          (i32.const 0xffffffff)
        )
      )
    )
    (drop
      (call $urem-32-power-2
        (i32.rem_u
          (local.get $x)
          (i32.const 0x80000000)
        )
      )
    )
    ;; (unsigned)x % 1
    (drop
      (call $urem-32-power-2
        (i32.rem_u
          (local.get $x)
          (i32.const 1)
        )
      )
    )
    (unreachable)
  )
  ;; CHECK:      (func $fdiv-32-power-2 (param $x f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 0.5)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const -0.5)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 2.3283064365386963e-10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 5.421010862427522e-20)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 8507059173023461586584365e13)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 1.1754943508222875e-38)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const -8507059173023461586584365e13)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const -1.1754943508222875e-38)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 5.877471754111438e-39)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 5.877471754111438e-39)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const -inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $fdiv-32-power-2 (param $x f32)
    (drop (f32.div
      (local.get $x)
      (f32.const 2)
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const -2)
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const 4294967296)
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const 18446744073709551616)
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const 0x1p-126)
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const 0x1p+126)
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const -0x1p-126)
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const -0x1p+126)
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const 0x1p-127) ;; skip
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const 0x1p-127) ;; skip
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const 0) ;; skip
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const nan) ;; skip
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const inf) ;; skip
    ))
    (drop (f32.div
      (local.get $x)
      (f32.const -inf) ;; skip
    ))
  )
  ;; CHECK:      (func $fdiv-64-power-2 (param $x f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const 0.5)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const -0.5)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const 2.3283064365386963e-10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const 5.421010862427522e-20)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const 4494232837155789769323262e283)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const 2.2250738585072014e-308)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const -4494232837155789769323262e283)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const -2.2250738585072014e-308)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const 1.1125369292536007e-308)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const 8988465674311579538646525e283)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f64.const -inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $fdiv-64-power-2 (param $x f64)
    (drop (f64.div
      (local.get $x)
      (f64.const 2)
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const -2)
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const 4294967296)
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const 18446744073709551616)
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const 0x1p-1022)
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const 0x1p+1022)
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const -0x1p-1022)
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const -0x1p+1022)
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const 0x1p-1023) ;; skip
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const 0x1p+1023) ;; skip
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const 0) ;; skip
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const nan) ;; skip
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const inf) ;; skip
    ))
    (drop (f64.div
      (local.get $x)
      (f64.const -inf) ;; skip
    ))
  )
  ;; CHECK:      (func $srem-by-const (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.rem_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.rem_s
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -9223372036854775808)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $srem-by-const (param $x i32) (param $y i64)
    ;; (signed)x % 1
    (drop (i32.rem_s
      (local.get $x)
      (i32.const 1)
    ))
    (drop (i64.rem_s
      (local.get $y)
      (i64.const 1)
    ))
    ;; (signed)x % 0x80000000 -> x & 0x7FFFFFFF
    (drop (i32.rem_s
      (local.get $x)
      (i32.const 0x80000000)
    ))
    ;; (signed)x % 0x8000000000000000 -> x & 0x7FFFFFFFFFFFFFFF
    (drop (i64.rem_s
      (local.get $y)
      (i64.const 0x8000000000000000)
    ))
  )
  ;; CHECK:      (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.wrap_i64
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2147483647)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2147483647)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 9223372036854775807)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 9223372036854775807)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.rem_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.rem_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64)
    ;; eqz((signed)x % 4)
    (drop (i32.eqz
      (i32.rem_s
        (local.get $x)
        (i32.const 4)
      )
    ))
    (drop (i64.eqz
      (i64.rem_s
        (local.get $y)
        (i64.const 4)
      )
    ))
    ;; eqz((signed)x % -4)
    (drop (i32.eqz
      (i32.rem_s
        (local.get $x)
        (i32.const -4)
      )
    ))
    (drop (i64.eqz
      (i64.rem_s
        (local.get $y)
        (i64.const -4)
      )
    ))
    ;; (signed)x % 4 == 0
    (drop (i32.eq
      (i32.rem_s
        (local.get $x)
        (i32.const 4)
      )
      (i32.const 0)
    ))
    (drop (i64.eq
      (i64.rem_s
        (local.get $y)
        (i64.const 2)
      )
      (i64.const 0)
    ))
    ;; (signed)x % -4 == 0
    (drop (i32.eq
      (i32.rem_s
        (local.get $x)
        (i32.const -4)
      )
      (i32.const 0)
    ))
    (drop (i64.eq
      (i64.rem_s
        (local.get $y)
        (i64.const -4)
      )
      (i64.const 0)
    ))
    ;; (signed)x % 2 != 0
    (drop (i32.ne
      (i32.rem_s
        (local.get $x)
        (i32.const 2)
      )
      (i32.const 0)
    ))
    (drop (i64.ne
      (i64.rem_s
        (local.get $y)
        (i64.const 2)
      )
      (i64.const 0)
    ))
    ;; (signed)x % -1 == 0  ->  0 == 0
    (drop (i32.eq
      (i32.rem_s
        (local.get $x)
        (i32.const -1)
      )
      (i32.const 0)
    ))
    ;; (signed)x % 0x80000000 == 0
    (drop (i32.eq
      (i32.rem_s
        (local.get $x)
        (i32.const 0x80000000)
      )
      (i32.const 0)
    ))
    ;; (signed)x % 0x80000000 != 0
    (drop (i32.ne
      (i32.rem_s
        (local.get $x)
        (i32.const 0x80000000)
      )
      (i32.const 0)
    ))
    ;; (signed)x % 0x8000000000000000 == 0
    (drop (i64.eq
      (i64.rem_s
        (local.get $y)
        (i64.const 0x8000000000000000)
      )
      (i64.const 0)
    ))
    ;; (signed)x % 0x8000000000000000 != 0
    (drop (i64.ne
      (i64.rem_s
        (local.get $y)
        (i64.const 0x8000000000000000)
      )
      (i64.const 0)
    ))
    ;;
    (drop (i32.eq
      (i32.rem_s
        (local.get $x)
        (i32.const 3) ;; skip
      )
      (i32.const 0)
    ))
    (drop (i64.eq
      (i64.rem_s
        (local.get $y)
        (i64.const 3) ;; skip
      )
      (i64.const 0)
    ))
  )
  ;; CHECK:      (func $orZero (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (local.get $0)
  ;; CHECK-NEXT: )
  (func $orZero (param $0 i32) (result i32)
    (i32.or
      (local.get $0)
      (i32.const 0)
    )
  )
  ;; CHECK:      (func $andZero (param $0 i32) (param $1 i64) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $0
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i64)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $1
  ;; CHECK-NEXT:      (i64.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $0
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (block (result i32)
  ;; CHECK-NEXT:      (local.set $0
  ;; CHECK-NEXT:       (i32.const 1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i64)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $1
  ;; CHECK-NEXT:      (i64.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (block (result i64)
  ;; CHECK-NEXT:      (local.set $1
  ;; CHECK-NEXT:       (i64.const 1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (i64.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $andZero (param $0 i32) (param $1 i64) (result i32)
    (drop
      (i32.and
        (local.get $0)
        (i32.const 0)
      )
    )
    (drop
      (i64.and
        (local.get $1)
        (i64.const 0)
      )
    )
    ;; side effects. we must keep the tee, but
    ;; can drop it.
    (drop
      (i32.and
        (local.tee $0
          (i32.const 1)
        )
        (i32.const 0)
      )
    )
    (drop
      (i64.and
        (local.tee $1
          (i64.const 1)
        )
        (i64.const 0)
      )
    )
    ;; We can optimize out the |and| even if the 0 is at the end of a block.
    (drop
      (i32.and
        (local.tee $0
          (i32.const 1)
        )
        (block (result i32)
          (local.set $0
            (i32.const 1)
          )
          (i32.const 0)
        )
      )
    )
    (drop
      (i64.and
        (local.tee $1
          (i64.const 1)
        )
        (block (result i64)
          (local.set $1
            (i64.const 1)
          )
          (i64.const 0)
        )
      )
    )
    (unreachable)
  )
  ;; CHECK:      (func $abstract-additions (param $x32 i32) (param $x64 i64) (param $y32 f32) (param $y64 f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x32)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x32)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x32)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x32)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x64)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x64)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x64)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x64)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $y32)
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $y64)
  ;; CHECK-NEXT:    (f64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x32)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x64)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $y32)
  ;; CHECK-NEXT:    (f32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $y64)
  ;; CHECK-NEXT:    (f64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x32)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x32)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x64)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x64)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $y32)
  ;; CHECK-NEXT:    (f32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $y64)
  ;; CHECK-NEXT:    (f64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.div
  ;; CHECK-NEXT:    (local.get $y32)
  ;; CHECK-NEXT:    (f32.const 1.2000000476837158)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (local.get $x32)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:    (local.get $x64)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:    (local.get $y32)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.sub
  ;; CHECK-NEXT:    (f64.const -0)
  ;; CHECK-NEXT:    (local.get $y64)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x32)
  ;; CHECK-NEXT:    (i32.const 10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.le_u
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $x32)
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 20)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x32)
  ;; CHECK-NEXT:    (i32.const 30)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (local.get $x64)
  ;; CHECK-NEXT:    (i64.const 10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x32)
  ;; CHECK-NEXT:    (i32.const 10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $x32)
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x32)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x32)
  ;; CHECK-NEXT:    (i32.const 30)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x32)
  ;; CHECK-NEXT:     (i32.const 30)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x32)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $x32)
  ;; CHECK-NEXT:     (i32.const 30)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x32)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x32)
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x32)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $abstract-additions (param $x32 i32) (param $x64 i64) (param $y32 f32) (param $y64 f64)
    (drop
      (i32.or
        (i32.const 0)
        (local.get $x32)
      )
    )
    (drop
      (i32.shl
        (local.get $x32)
        (i32.const 0)
      )
    )
    (drop
      (i32.shr_u
        (local.get $x32)
        (i32.const 0)
      )
    )
    (drop
      (i32.shr_s
        (local.get $x32)
        (i32.const 0)
      )
    )
    (drop
      (i64.or
        (i64.const 0)
        (local.get $x64)
      )
    )
    (drop
      (i64.shl
        (local.get $x64)
        (i64.const 0)
      )
    )
    (drop
      (i64.shr_u
        (local.get $x64)
        (i64.const 0)
      )
    )
    (drop
      (i64.shr_s
        (local.get $x64)
        (i64.const 0)
      )
    )
    (drop
      (i32.mul
        (local.get $x32)
        (i32.const 0)
      )
    )
    (drop
      (i64.mul
        (local.get $x64)
        (i64.const 0)
      )
    )
    (drop
      (f32.mul
        (local.get $y32)
        (f32.const 0)
      )
    )
    (drop
      (f64.mul
        (local.get $y64)
        (f64.const 0)
      )
    )
    (drop
      (i32.mul
        (local.get $x32)
        (i32.const 1)
      )
    )
    (drop
      (i64.mul
        (local.get $x64)
        (i64.const 1)
      )
    )
    (drop
      (f32.mul
        (local.get $y32)
        (f32.const 1)
      )
    )
    (drop
      (f64.mul
        (local.get $y64)
        (f64.const 1)
      )
    )
    (drop
      (i32.and
        (local.get $x32)
        (i32.const 0)
      )
    )
    (drop
      (i64.and
        (local.get $x64)
        (i64.const 0)
      )
    )
    (drop
      (i32.and
        (unreachable)
        (i32.const 0)
      )
    )
    (drop
      (i64.and
        (unreachable)
        (i64.const 0)
      )
    )
    (drop
      (i32.div_s
        (local.get $x32)
        (i32.const 1)
      )
    )
    (drop
      (i32.div_u
        (local.get $x32)
        (i32.const 1)
      )
    )
    (drop
      (i64.div_s
        (local.get $x64)
        (i64.const 1)
      )
    )
    (drop
      (i64.div_u
        (local.get $x64)
        (i64.const 1)
      )
    )
    (drop
      (f32.div
        (local.get $y32)
        (f32.const 1)
      )
    )
    (drop
      (f64.div
        (local.get $y64)
        (f64.const 1)
      )
    )
    (drop
      (f32.div
        (local.get $y32)
        (f32.const 1.2)
      )
    )
    (drop
      (i32.mul
        (local.get $x32)
        (i32.const -1)
      )
    )
    (drop
      (i64.mul
        (local.get $x64)
        (i64.const -1)
      )
    )
    (drop
      (f32.mul
        (local.get $y32)
        (f32.const -1)
      )
    )
    (drop
      (f64.mul
        (local.get $y64)
        (f64.const -1)
      )
    )
    (drop
      (i32.eq
        (i32.add
          (local.get $x32)
          (i32.const 10)
        )
        (i32.const 20)
      )
    )
    (drop
      (i32.le_u
        (i32.add
          (local.get $x32)
          (i32.const 10)
        )
        (i32.const 20)
      )
    )
    (drop
      (i32.eq
        (i32.sub
          (local.get $x32)
          (i32.const 10)
        )
        (i32.const 20)
      )
    )
    (drop
      (i64.eq
        (i64.add
          (local.get $x64)
          (i64.const 10)
        )
        (i64.const 20)
      )
    )
    (drop
      (i32.eq
        (i32.const 20)
        (i32.add
          (local.get $x32)
          (i32.const 10)
        )
      )
    )
    (drop
      (i32.eq
        (i32.add
          (local.get $x32)
          (i32.const 10)
        )
        (i32.add
          (local.get $x32)
          (i32.const 20)
        )
      )
    )
    (drop
      (i32.eq
        (i32.sub
          (local.get $x32)
          (i32.const 10)
        )
        (i32.const 20)
      )
    )
    (drop
      (i32.eq
        (i32.add
          (local.get $x32)
          (i32.const 10)
        )
        (i32.sub
          (local.get $x32)
          (i32.const 20)
        )
      )
    )
    (drop
      (i32.eq
        (i32.sub
          (local.get $x32)
          (i32.const 10)
        )
        (i32.add
          (local.get $x32)
          (i32.const 20)
        )
      )
    )
    (drop
      (i32.eq
        (i32.sub
          (local.get $x32)
          (i32.const 10)
        )
        (i32.sub
          (local.get $x32)
          (i32.const 20)
        )
      )
    )
    (drop
      (i64.le_s
        (i64.sub
          (local.get $x64)
          (i64.const 288230376151711744)
        )
        (i64.const 9223372036854775807)
      )
    )
  )
  ;; CHECK:      (func $negatives-are-sometimes-better (param $x i32) (param $y i64) (param $z f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -64)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -64)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -8192)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -1048576)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -134217728)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -64)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.add
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -64)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -8192)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -1048576)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -134217728)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -17179869184)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -2199023255552)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -281474976710656)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -36028797018963968)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -4611686018427387904)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (f32.const 64)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $negatives-are-sometimes-better (param $x i32) (param $y i64) (param $z f32)
    (drop (i32.add (local.get $x) (i32.const 0x40)))
    (drop (i32.sub (local.get $x) (i32.const 0x40)))
    (drop (i32.add (local.get $x) (i32.const 0x2000)))
    (drop (i32.add (local.get $x) (i32.const 0x100000)))
    (drop (i32.add (local.get $x) (i32.const 0x8000000)))

    (drop (i64.add (local.get $y) (i64.const 0x40)))
    (drop (i64.sub (local.get $y) (i64.const 0x40)))
    (drop (i64.add (local.get $y) (i64.const 0x2000)))
    (drop (i64.add (local.get $y) (i64.const 0x100000)))
    (drop (i64.add (local.get $y) (i64.const 0x8000000)))

    (drop (i64.add (local.get $y) (i64.const 0x400000000)))
    (drop (i64.add (local.get $y) (i64.const 0x20000000000)))
    (drop (i64.add (local.get $y) (i64.const 0x1000000000000)))
    (drop (i64.add (local.get $y) (i64.const 0x80000000000000)))
    (drop (i64.add (local.get $y) (i64.const 0x4000000000000000)))

    (drop (f32.add (local.get $z) (f32.const 0x40)))
  )
  ;; CHECK:      (func $shift-a-zero (param $x i32) (param $y i64) (param $z f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $shift-a-zero (param $x i32) (param $y i64) (param $z f32)
    (drop
      (i32.shl
        (i32.const 0)
        (local.get $x)
      )
    )
    (drop
      (i32.shr_u
        (i32.const 0)
        (local.get $x)
      )
    )
    (drop
      (i32.shr_s
        (i32.const 0)
        (local.get $x)
      )
    )
    (drop
      (i64.shl
        (i64.const 0)
        (local.get $y)
      )
    )
    (drop
      (i32.shl
        (i32.const 0)
        (unreachable)
      )
    )
  )
  ;; CHECK:      (func $identical-siblings (param $x i32) (param $y i64) (param $z f64) (param $xx i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.sub
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $xx)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $identical-siblings (param $x i32) (param $y i64) (param $z f64) (param $xx i32)
    (drop
      (i32.sub
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i64.sub
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (f64.sub
        (local.get $z)
        (local.get $z)
      )
    )
    (drop
      (i32.sub
        (local.get $x)
        (local.get $xx)
      )
    )
    (drop
      (i32.sub
        (unreachable)
        (unreachable)
      )
    )
    (drop
      (i32.add
        (local.get $x)
        (local.get $x)
      )
    )
    ;; more ops
    (drop
      (i32.xor
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.ne
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.lt_s
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.lt_u
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.gt_s
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.gt_u
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.and
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.or
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.eq
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.le_s
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.le_u
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.ge_s
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i32.ge_u
        (local.get $x)
        (local.get $x)
      )
    )
    (drop
      (i64.xor
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.ne
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.lt_s
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.lt_u
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.gt_s
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.gt_u
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.and
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.or
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.eq
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.le_s
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.le_u
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.ge_s
        (local.get $y)
        (local.get $y)
      )
    )
    (drop
      (i64.ge_u
        (local.get $y)
        (local.get $y)
      )
    )
  )
  ;; CHECK:      (func $all_ones (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $x
  ;; CHECK-NEXT:      (i32.const 1337)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i64)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $y
  ;; CHECK-NEXT:      (i64.const 1337)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $all_ones (param $x i32) (param $y i64)
    (drop
      (i32.and
        (local.get $x)
        (i32.const -1)
      )
    )
    (drop
      (i32.or
        (local.get $x)
        (i32.const -1)
      )
    )
    (drop
      (i32.or
        (local.tee $x
          (i32.const 1337)
        )
        (i32.const -1)
      )
    )
    (drop
      (i64.and
        (local.get $y)
        (i64.const -1)
      )
    )
    (drop
      (i64.or
        (local.get $y)
        (i64.const -1)
      )
    )
    (drop
      (i64.or
        (local.tee $y
          (i64.const 1337)
        )
        (i64.const -1)
      )
    )
  )
  ;; CHECK:      (func $xor (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $xor (param $x i32) (param $y i64)
    (drop
      (i32.xor
        (local.get $x)
        (i32.const 0)
      )
    )
  )
  ;; CHECK:      (func $select-on-const (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 3)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $x
  ;; CHECK-NEXT:    (i32.const 5)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.tee $x
  ;; CHECK-NEXT:      (i32.const 6)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 7)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const 4)
  ;; CHECK-NEXT:    (local.tee $x
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $x
  ;; CHECK-NEXT:    (i32.const 6)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.le_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (i32.eqz
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i64.eqz
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (i64.eqz
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i64.ge_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i64.lt_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i64.lt_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i64.ge_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 2)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-on-const (param $x i32) (param $y i64)
    (drop
      (select
        (i32.const 2)
        (local.get $x)
        (i32.const 0)
      )
    )
    (drop
      (select
        (i32.const 3)
        (local.get $x)
        (i32.const 1)
      )
    )
    (drop
      (select
        (i32.const 4)
        (local.tee $x
          (i32.const 5)
        )
        (i32.const 0)
      )
    )
    (drop
      (select
        (local.tee $x
          (i32.const 6)
        )
        (i32.const 7)
        (i32.const 0)
      )
    )
    (drop
      (select
        (i32.const 4)
        (local.tee $x
          (i32.const 5)
        )
        (i32.const 1)
      )
    )
    (drop
      (select
        (local.tee $x
          (i32.const 6)
        )
        (i32.const 7)
        (i32.const 1)
      )
    )
    (drop
      (select
        (i32.const 1)
        (i32.const 0)
        (local.get $x)
      )
    )
    (drop
      (select
        (i32.const 0)
        (i32.const 1)
        (local.get $x)
      )
    )
    (drop
      (select
        (i32.const 0)
        (i32.const 1)
        (i32.lt_s
          (local.get $x)
          (i32.const 0)
        )
      )
    )
    (drop
      (select
        (i32.const 1)
        (i32.const 0)
        (i32.lt_s
          (local.get $x)
          (i32.const 0)
        )
      )
    )
    (drop
      (select
        (i32.const 0)
        (i32.const 1)
        (i32.ge_s
          (local.get $x)
          (i32.const 0)
        )
      )
    )
    (drop
      (select
        (i32.const 1)
        (i32.const 0)
        (i32.gt_s
          (local.get $x)
          (i32.const 0)
        )
      )
    )
    (drop
      (select
        (i32.const 0)
        (i32.const 1)
        (i32.gt_s
          (local.get $x)
          (i32.const 0)
        )
      )
    )
    (drop
      (select
        (i32.const 1)
        (i32.const 0)
        (i32.ge_s
          (local.get $x)
          (i32.const 0)
        )
      )
    )
    (drop
      (select
        (i64.const 1)
        (i64.const 0)
        (local.get $x)
      )
    )
    (drop
      (select
        (i64.const 0)
        (i64.const 1)
        (local.get $x)
      )
    )
    (drop
      (select
        (i64.const 1)
        (i64.const 0)
        (i64.eqz
          (local.get $y)
        )
      )
    )
    (drop
      (select
        (i64.const 0)
        (i64.const 1)
        (i64.eqz
          (local.get $y)
        )
      )
    )
    (drop
      (select
        (i64.const 0)
        (i64.const 1)
        (i64.lt_s
          (local.get $y)
          (i64.const 0)
        )
      )
    )
    (drop
      (select
        (i64.const 1)
        (i64.const 0)
        (i64.lt_s
          (local.get $y)
          (i64.const 0)
        )
      )
    )
    (drop
      (select
        (i64.const 0)
        (i64.const 1)
        (i64.ge_s
          (local.get $y)
          (i64.const 0)
        )
      )
    )
    (drop
      (select
        (i64.const 1)
        (i64.const 0)
        (i64.ge_s
          (local.get $y)
          (i64.const 0)
        )
      )
    )
    ;; optimize boolean
    (drop
      (select
        (local.get $x)
        (i32.const 0)
        (i32.eqz
          (i32.const 0)
        )
      )
    )
    (drop
      (select
        (local.get $x)
        (i32.const 2)
        (i32.eqz
          (i32.const 2)
        )
      )
    )
    (drop
      (select
        (local.get $x)
        (i32.const 2)
        (i32.eqz
          (i32.eqz
            (local.get $x)
          )
        )
      )
    )
    (drop
      (select
        (local.get $y)
        (i64.const 0)
        (i64.eqz
          (i64.const 0)
        )
      )
    )
    (drop
      (select
        (local.get $y)
        (i64.const 2)
        (i64.eqz
          (i64.const 2)
        )
      )
    )
  )
  ;; CHECK:      (func $optimize-boolean (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (i32.const 2)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i64.eqz
  ;; CHECK-NEXT:     (i64.and
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:      (i64.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.wrap_i64
  ;; CHECK-NEXT:    (i64.shr_u
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 63)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 31)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.shr_u
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 63)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.shr_u
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 63)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.wrap_i64
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.wrap_i64
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2147483647)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-boolean (param $x i32) (param $y i64)
    ;; bool(-x) -> bool(x)
    (drop
      (select
        (i32.const 1)
        (i32.const 2)
        (i32.sub
          (i32.const 0)
          (local.get $x)
        )
      )
    )
    ;; i32(bool(expr)) == 1 -> bool(expr)
    (drop (i32.eq
      (i32.and
        (local.get $x)
        (i32.const 1)
      )
      (i32.const 1)
    ))
    ;; i32(bool(expr)) != 1 -> !bool(expr)
    (drop (i32.ne
      (i32.and
        (local.get $x)
        (i32.const 1)
      )
      (i32.const 1)
    ))
    ;; i32(bool(expr)) ^ 1 -> !bool(expr)
    (drop (i32.xor
      (i32.and
        (local.get $x)
        (i32.const 1)
      )
      (i32.const 1)
    ))
    ;; i64(bool(expr)) ^ 1 -> extend(!bool(expr))
    (drop (i64.xor
      (i64.and
        (local.get $y)
        (i64.const 1)
      )
      (i64.const 1)
    ))
    ;; i64(bool(expr)) != 0 -> i32(bool(expr))
    (drop (i64.ne
      (i64.shr_u
        (local.get $y)
        (i64.const 63)
      )
      (i64.const 0)
    ))
    ;; eqz((i32(bool(expr)) != 0) != 0)
    (drop (i32.eqz
      (i32.ne
        (i32.ne
          (i32.shr_u
            (local.get $x)
            (i32.const 31)
          )
          (i32.const 0)
        )
        (i32.const 0)
      )
    ))
    ;; i32.eqz(wrap(i64(x)))
    (drop (i32.eqz
      (i32.wrap_i64
        (i64.shr_u
          (local.get $y)
          (i64.const 63)
        )
      )
    ))
    ;; eqz((i64(bool(expr)) != 0) != 0)
    (drop (i32.eqz
      (i32.ne
        (i64.ne
          (i64.shr_u
            (local.get $y)
            (i64.const 63)
          )
          (i64.const 0)
        )
        (i32.const 0)
      )
    ))
    ;; eqz((i64(bool(expr)) != 0) != 0)
    (drop (i32.eqz
      (i32.ne
        (i64.ne
          (local.get $y)
          (i64.const 0)
        )
        (i32.const 0)
      )
    ))
    ;; i32.eqz(wrap(i64(x))) -> skip
    (drop (i32.eqz
      (i32.wrap_i64
        (local.get $y)
      )
    ))
    ;; i64(bool(expr)) == 1 -> i32(bool(expr))
    (drop (i64.eq
      (i64.and
        (local.get $y)
        (i64.const 1)
      )
      (i64.const 1)
    ))
    ;; i64(bool(expr)) != 1 -> !i64(bool(expr))
    (drop (i64.ne
      (i64.and
        (local.get $y)
        (i64.const 1)
      )
      (i64.const 1)
    ))
    ;; i32(bool(expr)) & 1 -> bool(expr)
    (drop (i32.and
      (i32.and
        (local.get $x)
        (i32.const 1)
      )
      (i32.const 1)
    ))
    ;; i32(bool(expr)) | 1 -> 1
    (drop (i32.or
      (i32.and
        (local.get $x)
        (i32.const 1)
      )
      (i32.const 1)
    ))
    ;; i64(bool(expr)) & 1 -> i64(bool(expr))
    (drop (i64.and
      (i64.and
        (local.get $y)
        (i64.const 1)
      )
      (i64.const 1)
    ))
    ;; i64(bool(expr)) | 1 -> 1
    (drop (i64.or
      (i64.and
        (local.get $y)
        (i64.const 1)
      )
      (i64.const 1)
    ))
    ;; i32(bool(expr)) != 0 -> i32(bool(expr))
    (drop (i32.ne
      (i32.and
        (local.get $x)
        (i32.const 1)
      )
      (i32.const 0)
    ))
    ;; i32(bool(expr)) != 0 -> i32(bool(expr))
    (drop (i32.ne
      (i64.ne
        (local.get $y)
        (i64.const 0)
      )
      (i32.const 0)
    ))
    ;; (i32(expr) != 0) != 0 -> (expr != 0)
    (drop (i32.ne
      (i32.ne
        (local.get $x)
        (i32.const 0)
      )
      (i32.const 0)
    ))
    ;; (signed)x % 4 ? 1 : 0
    (drop (if (result i32)
      (i32.rem_s
        (local.get $x)
        (i32.const 4)
      )
      (then
            (i32.const 1)
      )
      (else
            (i32.const 0)
      )
    ))
    ;; (signed)x % min_s ? 1 : 0
    (drop (if (result i32)
      (i32.rem_s
        (local.get $x)
        (i32.const 0x80000000)
      )
      (then
            (i32.const 1)
      )
      (else
            (i32.const 0)
      )
    ))
  )
  ;; CHECK:      (func $fold-eqz-eqz (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $fold-eqz-eqz (param $x i32) (param $y i64)
    ;; i32.eqz(i32.eqz(x))  ->  x != 0
    (drop (i32.eqz (i32.eqz (local.get $x))))
    ;; i32.eqz(i64.eqz(y))  ->  y != 0
    (drop (i32.eqz (i64.eqz (local.get $y))))
  )
  ;; CHECK:      (func $optimize-bitwise-oprations (param $x i32) (param $y i32) (param $z i64) (param $w i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.rotl
  ;; CHECK-NEXT:    (i32.const -2)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.rotl
  ;; CHECK-NEXT:    (i64.const -2)
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-bitwise-oprations (param $x i32) (param $y i32) (param $z i64) (param $w i64)
    ;; ~(1 << x)  ->  rotl(-2, x)
    (drop (i32.xor
      (i32.shl
        (i32.const 1)
        (local.get $x)
      )
      (i32.const -1)
    ))
    (drop (i64.xor
      (i64.shl
        (i64.const 1)
        (local.get $z)
      )
      (i64.const -1)
    ))
  )
  ;; CHECK:      (func $getFallthrough
  ;; CHECK-NEXT:  (local $x0 i32)
  ;; CHECK-NEXT:  (local $x1 i32)
  ;; CHECK-NEXT:  (local $x2 i32)
  ;; CHECK-NEXT:  (local $x3 i32)
  ;; CHECK-NEXT:  (local $x4 i32)
  ;; CHECK-NEXT:  (local $x5 i32)
  ;; CHECK-NEXT:  (local $x6 i32)
  ;; CHECK-NEXT:  (local $x7 i32)
  ;; CHECK-NEXT:  (local.set $x0
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $x1
  ;; CHECK-NEXT:   (local.tee $x2
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $x3
  ;; CHECK-NEXT:   (loop (result i32)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x3)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $x4
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 2)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x4)
  ;; CHECK-NEXT:    (i32.const 7)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $x5
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (unreachable)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x5)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $x6
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (unreachable)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x6)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block $out (result i32)
  ;; CHECK-NEXT:    (local.set $x7
  ;; CHECK-NEXT:     (br_if $out
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x7)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $getFallthrough ;; unit tests for Properties::getFallthrough
    (local $x0 i32)
    (local $x1 i32)
    (local $x2 i32)
    (local $x3 i32)
    (local $x4 i32)
    (local $x5 i32)
    (local $x6 i32)
    (local $x7 i32)
    ;; the trivial case
    (local.set $x0 (i32.const 1))
    (drop (i32.and (local.get $x0) (i32.const 7)))
    ;; tees
    (local.set $x1 (local.tee $x2 (i32.const 1)))
    (drop (i32.and (local.get $x1) (i32.const 7)))
    ;; loop
    (local.set $x3 (loop (result i32) (i32.const 1)))
    (drop (i32.and (local.get $x3) (i32.const 7)))
    ;; if - two sides, can't
    (local.set $x4 (if (result i32) (i32.const 1) (then (i32.const 2) )(else (i32.const 3))))
    (drop (i32.and (local.get $x4) (i32.const 7)))
    ;; if - one side, can
    (local.set $x5 (if (result i32) (i32.const 1) (then (unreachable) )(else (i32.const 3))))
    (drop (i32.and (local.get $x5) (i32.const 7)))
    ;; if - one side, can
    (local.set $x6 (if (result i32) (i32.const 1) (then (i32.const 3) )(else (unreachable))))
    (drop (i32.and (local.get $x6) (i32.const 7)))
    ;; br_if with value
    (drop
      (block $out (result i32)
        (local.set $x7 (br_if $out (i32.const 1) (i32.const 1)))
        (drop (i32.and (local.get $x7) (i32.const 7)))
        (unreachable)
      )
    )
  )
  ;; CHECK:      (func $tee-with-unreachable-value (result f64)
  ;; CHECK-NEXT:  (local $var$0 i32)
  ;; CHECK-NEXT:  (block $label$1 (result f64)
  ;; CHECK-NEXT:   (local.tee $var$0
  ;; CHECK-NEXT:    (br_if $label$1
  ;; CHECK-NEXT:     (f64.const 1)
  ;; CHECK-NEXT:     (unreachable)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $tee-with-unreachable-value (result f64)
   (local $var$0 i32)
   (block $label$1 (result f64)
    (local.tee $var$0
     (br_if $label$1 ;; the f64 does not actually flow through this, it's unreachable (and the type is wrong - but unchecked)
      (f64.const 1)
      (unreachable)
     )
    )
   )
  )
  ;; CHECK:      (func $add-sub-zero-reorder-1 (param $temp i32) (result i32)
  ;; CHECK-NEXT:  (i32.add
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:     (local.get $temp)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.tee $temp
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $add-sub-zero-reorder-1 (param $temp i32) (result i32)
   (i32.add
    (i32.add
     (i32.sub
      (i32.const 0) ;; this zero looks like we could remove it by subtracting the get of $temp from the parent, but that would reorder it *after* the tee :(
      (local.get $temp)
     )
     (local.tee $temp ;; cannot move this tee before the get
      (i32.const 1)
     )
    )
    (i32.const 2)
   )
  )
  ;; CHECK:      (func $add-sub-zero-reorder-2 (param $temp i32) (result i32)
  ;; CHECK-NEXT:  (i32.add
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.tee $temp
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $temp)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $add-sub-zero-reorder-2 (param $temp i32) (result i32)
   (i32.add
    (i32.add
     (local.tee $temp ;; in this order, the tee already comes first, so all is good for the optimization
      (i32.const 1)
     )
     (i32.sub
      (i32.const 0)
      (local.get $temp)
     )
    )
    (i32.const 2)
   )
  )
  ;; CHECK:      (func $const-float-zero (param $fx f32) (param $fy f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.add
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:    (f64.const -0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.add
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:    (f64.const -0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.add
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:    (f64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.sub
  ;; CHECK-NEXT:    (f64.const 0)
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.add
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:    (f64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (f32.const -nan:0x34546d)
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $const-float-zero (param $fx f32) (param $fy f64)
    ;; x - 0.0   ==>   x
    (drop (f32.sub
      (local.get $fx)
      (f32.const 0)
    ))
    (drop (f64.sub
      (local.get $fy)
      (f64.const 0)
    ))
    ;; x + (-0.0)   ==>   x
    (drop (f32.add
      (local.get $fx)
      (f32.const -0)
    ))
    (drop (f64.add
      (local.get $fy)
      (f64.const -0)
    ))
    ;; x - (-0.0)   ==>   x + 0.0
    (drop (f32.sub
      (local.get $fx)
      (f32.const -0) ;; skip
    ))
    (drop (f64.sub
      (local.get $fy)
      (f64.const -0) ;; skip
    ))
    ;; 0.0 - x   ==>   0.0 - x
    (drop (f32.sub
      (f32.const 0)
      (local.get $fx) ;; skip
    ))
    (drop (f64.sub
      (f64.const 0)
      (local.get $fy) ;; skip
    ))
    ;; x + 0.0   ==>   x + 0.0
    (drop (f32.add
      (local.get $fx) ;; skip
      (f32.const 0)
    ))
    (drop (f64.add
      (local.get $fy) ;; skip
      (f64.const 0)
    ))
    (drop (f32.sub
      (f32.const -nan:0x34546d) ;; skip
      (f32.const 0)
    ))
  )

  ;; CHECK:      (func $simplify-add-sub-with-neg-float (param $a f32) (param $b f32) (param $x f64) (param $y f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.sub
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.add
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.neg
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.sub
  ;; CHECK-NEXT:    (f64.neg
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (f32.neg
  ;; CHECK-NEXT:     (local.tee $a
  ;; CHECK-NEXT:      (f32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify-add-sub-with-neg-float (param $a f32) (param $b f32) (param $x f64) (param $y f64)
    ;; -x + y     ==>   y - x
    (drop (f32.add (f32.neg (local.get $a)) (local.get $b)))
    (drop (f64.add (f64.neg (local.get $x)) (local.get $y)))

    ;; x + (-y)   ==>   x - y
    (drop (f32.add (local.get $a) (f32.neg (local.get $b))))
    (drop (f64.add (local.get $x) (f64.neg (local.get $y))))

    ;; x - (-y)   ==>   x + y
    (drop (f32.sub (local.get $a) (f32.neg (local.get $b))))
    (drop (f64.sub (local.get $x) (f64.neg (local.get $y))))

    ;; skips
    ;; -x - y  ->  skip
    (drop (f32.sub (f32.neg (local.get $a)) (local.get $b)))
    (drop (f64.sub (f64.neg (local.get $x)) (local.get $y)))
    ;; -x + y  ->  skip,  iff can't reorder
    (drop (f32.add (f32.neg (local.tee $a (f32.const 1.0))) (local.get $a)))
  )
  ;; CHECK:      (func $simplify-add-sub-with-neg-float-zeros (param $a f32) (param $b f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify-add-sub-with-neg-float-zeros (param $a f32) (param $b f32)
    ;; edge cases for -x + y
    (drop (f32.add (f32.neg (f32.const 0)) (local.get $b)))
    (drop (f32.add (f32.neg (local.get $a)) (f32.const 0)))
    (drop (f32.add (f32.neg (f32.const -0)) (local.get $b)))
    (drop (f32.add (f32.neg (local.get $a)) (f32.const -0)))
    ;; edge cases for x + (-y)
    (drop (f32.add (f32.const 0) (f32.neg (local.get $b))))
    (drop (f32.add (local.get $a) (f32.neg (f32.const 0))))
    (drop (f32.add (f32.const -0) (f32.neg (local.get $b))))
    (drop (f32.add (local.get $a) (f32.neg (f32.const -0))))
    ;; edge cases for x - (-y)
    (drop (f32.sub (f32.const 0) (f32.neg (local.get $b))))
    (drop (f32.sub (local.get $a) (f32.neg (f32.const 0))))
    (drop (f32.sub (f32.const -0) (f32.neg (local.get $b))))
    (drop (f32.sub (local.get $a) (f32.neg (f32.const -0))))
  )
  ;; CHECK:      (func $simplify-add-sub-with-neg-float-nans (param $a f32) (param $b f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const nan:0x400000)
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -nan:0x400000)
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const nan:0x400000)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -nan:0x400000)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (f32.const nan:0x400000)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (f32.const -nan:0x400000)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify-add-sub-with-neg-float-nans (param $a f32) (param $b f32)
    ;; edge cases for -x + y
    (drop (f32.add (f32.neg (f32.const nan)) (local.get $b)))
    (drop (f32.add (f32.neg (local.get $a)) (f32.const nan)))
    (drop (f32.add (f32.neg (f32.const -nan)) (local.get $b)))
    (drop (f32.add (f32.neg (local.get $a)) (f32.const -nan)))
    ;; edge cases for x + (-y)
    (drop (f32.add (f32.const nan) (f32.neg (local.get $b))))
    (drop (f32.add (local.get $a) (f32.neg (f32.const nan))))
    (drop (f32.add (f32.const -nan) (f32.neg (local.get $b))))
    (drop (f32.add (local.get $a) (f32.neg (f32.const -nan))))
    ;; edge cases for x - (-y)
    (drop (f32.sub (f32.const nan) (f32.neg (local.get $b))))
    (drop (f32.sub (local.get $a) (f32.neg (f32.const nan))))
    (drop (f32.sub (f32.const -nan) (f32.neg (local.get $b))))
    (drop (f32.sub (local.get $a) (f32.neg (f32.const -nan))))
  )
  ;; CHECK:      (func $simplify-add-sub-with-neg-float-infs (param $a f32) (param $b f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const -inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const inf)
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -inf)
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const inf)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const -inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -inf)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const -inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const -inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify-add-sub-with-neg-float-infs (param $a f32) (param $b f32)
    ;; edge cases for -x + y
    (drop (f32.add (f32.neg (f32.const inf)) (local.get $b)))
    (drop (f32.add (f32.neg (local.get $a)) (f32.const inf)))
    (drop (f32.add (f32.neg (f32.const -inf)) (local.get $b)))
    (drop (f32.add (f32.neg (local.get $a)) (f32.const -inf)))
    ;; edge cases for x + (-y)
    (drop (f32.add (f32.const inf) (f32.neg (local.get $b))))
    (drop (f32.add (local.get $a) (f32.neg (f32.const inf))))
    (drop (f32.add (f32.const -inf) (f32.neg (local.get $b))))
    (drop (f32.add (local.get $a) (f32.neg (f32.const -inf))))
    ;; edge cases for x - (-y)
    (drop (f32.sub (f32.const inf) (f32.neg (local.get $b))))
    (drop (f32.sub (local.get $a) (f32.neg (f32.const inf))))
    (drop (f32.sub (f32.const -inf) (f32.neg (local.get $b))))
    (drop (f32.sub (local.get $a) (f32.neg (f32.const -inf))))
  )
  ;; CHECK:      (func $simplify-add-sub-with-neg-float-mins (param $a f32) (param $b f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const -1.401298464324817e-45)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const 1.401298464324817e-45)
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const 1.401298464324817e-45)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -1.401298464324817e-45)
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const 1.401298464324817e-45)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const -1.401298464324817e-45)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -1.401298464324817e-45)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const 1.401298464324817e-45)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const 1.401298464324817e-45)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const 1.401298464324817e-45)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:    (f32.const -1.401298464324817e-45)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (f32.const -1.401298464324817e-45)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify-add-sub-with-neg-float-mins (param $a f32) (param $b f32)
    ;; edge cases for -x + y
    (drop (f32.add (f32.neg (f32.const 1.401298464324817e-45)) (local.get $b)))  ;; +min value
    (drop (f32.add (f32.neg (local.get $a)) (f32.const 1.401298464324817e-45)))  ;; +min value
    (drop (f32.add (f32.neg (f32.const -1.401298464324817e-45)) (local.get $b))) ;; -min value
    (drop (f32.add (f32.neg (local.get $a)) (f32.const -1.401298464324817e-45))) ;; -min value
    ;; edge cases for x + (-y)
    (drop (f32.add (f32.const 1.401298464324817e-45) (f32.neg (local.get $b))))
    (drop (f32.add (local.get $a) (f32.neg (f32.const 1.401298464324817e-45))))
    (drop (f32.add (f32.const -1.401298464324817e-45) (f32.neg (local.get $b))))
    (drop (f32.add (local.get $a) (f32.neg (f32.const -1.401298464324817e-45))))
    ;; edge cases for x - (-y)
    (drop (f32.sub (f32.const 1.401298464324817e-45) (f32.neg (local.get $b))))
    (drop (f32.sub (local.get $a) (f32.neg (f32.const 1.401298464324817e-45))))
    (drop (f32.sub (f32.const -1.401298464324817e-45) (f32.neg (local.get $b))))
    (drop (f32.sub (local.get $a) (f32.neg (f32.const -1.401298464324817e-45))))
  )
  ;; CHECK:      (func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.add
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i64.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ge_s
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i64.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.lt_s
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.sub
  ;; CHECK-NEXT:    (f64.const -0)
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i64.eq
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const -1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64)
    (drop (i32.sub
      (local.get $x)
      (i32.const -1)
    ))
    (drop (i64.sub
      (local.get $y)
      (i64.const -1)
    ))
    ;; (unsigned)x > -1   ==>   0
    (drop (i32.gt_u
      (local.get $x)
      (i32.const -1)
    ))
    (drop (i32.gt_u
      (i32.load
        (i32.const 0)
      )
      (i32.const -1)
    ))
    (drop (i64.gt_u
      (local.get $y)
      (i64.const -1)
    ))
    (drop (i64.gt_u
      (i64.load
        (i32.const 0)
      )
      (i64.const -1)
    ))
    (drop (i32.gt_s
      (local.get $x)
      (i32.const -1)
    ))
    (drop (i64.gt_s
      (local.get $y)
      (i64.const -1)
    ))
    (drop (i64.extend_i32_s
      (i64.gt_u
        (i64.const 0)
        (i64.const -1)
      )
    ))
    ;; (unsigned)x <= -1   ==>   1
    (drop (i32.le_u
      (local.get $x)
      (i32.const -1)
    ))
    (drop (i32.le_u
      (i32.load
        (i32.const 0)
      )
      (i32.const -1)
    ))
    (drop (i64.le_u
      (local.get $y)
      (i64.const -1)
    ))
    (drop (i64.le_u
      (i64.load
        (i32.const 0)
      )
      (i64.const -1)
    ))
    (drop (i32.le_s
      (local.get $x)
      (i32.const -1)
    ))
    (drop (i64.le_s
      (local.get $y)
      (i64.const -1)
    ))
    ;; (unsigned)x >= -1   ==>   x == -1
    (drop (i32.ge_u
      (local.get $x)
      (i32.const -1)
    ))
    (drop (i64.ge_u
      (local.get $y)
      (i64.const -1)
    ))
    ;; (unsigned)x < -1   ==>   x != -1
    (drop (i32.lt_u
      (local.get $x)
      (i32.const -1)
    ))
    (drop (i64.lt_u
      (local.get $y)
      (i64.const -1)
    ))
    ;; x * -1
    (drop (i32.mul
      (local.get $x)
      (i32.const -1)
    ))
    (drop (i64.mul
      (local.get $y)
      (i64.const -1)
    ))
    (drop (f32.mul    ;; skip
      (local.get $fx)
      (f32.const -1)
    ))
    (drop (f64.mul    ;; skip
      (local.get $fy)
      (f64.const -1)
    ))
    ;; (unsigned)x / -1
    (drop (i32.div_u
      (local.get $x)
      (i32.const -1)
    ))
    (drop (i64.div_u
      (local.get $y)
      (i64.const -1)
    ))
  )
  ;; CHECK:      (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.div_u
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i64.eq
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const -9223372036854775808)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.div_s
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i64)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i64.div_u
  ;; CHECK-NEXT:      (i64.const 0)
  ;; CHECK-NEXT:      (i64.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 31)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.div_u
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i64.eq
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const -1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shr_u
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 63)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i64)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i64.div_u
  ;; CHECK-NEXT:      (i64.const 0)
  ;; CHECK-NEXT:      (i64.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.eqz
  ;; CHECK-NEXT:      (i32.load
  ;; CHECK-NEXT:       (i32.const 0)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i64)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i64.extend_i32_u
  ;; CHECK-NEXT:      (i64.eqz
  ;; CHECK-NEXT:       (i64.load
  ;; CHECK-NEXT:        (i32.const 0)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i64.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i64.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (block (result i32)
  ;; CHECK-NEXT:      (i32.store
  ;; CHECK-NEXT:       (i32.const 0)
  ;; CHECK-NEXT:       (i32.const 0)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i64.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (block (result i64)
  ;; CHECK-NEXT:      (i64.store
  ;; CHECK-NEXT:       (i32.const 0)
  ;; CHECK-NEXT:       (i64.const 0)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (i64.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 9223372036854775807)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -9223372036854775808)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const -9223372036854775808)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 9223372036854775807)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const -0)
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:    (f64.const 2.1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:    (f64.const -2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.div
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:    (f32.const -inf)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:    (f64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (f64.const -5)
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.sub
  ;; CHECK-NEXT:    (f32.const 3.5)
  ;; CHECK-NEXT:    (local.get $fx)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.sub
  ;; CHECK-NEXT:    (f64.const 5)
  ;; CHECK-NEXT:    (local.get $fy)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64)
    ;; signed divs
    ;; i32(x) / -2147483648  ->  x == -2147483648
    (drop (i32.div_s
      (local.get $x)
      (i32.const -2147483648)
    ))
    ;; i32(0) / i32(0) => i32(0) but still traps
    (drop (i32.div_s
      (i32.const 0)
      (i32.const 0)
    ))
    ;; i64(x) / -9223372036854775808  ->  x == -9223372036854775808
    (drop (i64.div_s
      (local.get $y)
      (i64.const -9223372036854775808)
    ))
    ;; skip
    (drop (i64.div_s
      (local.get $y)
      (i64.const -2147483648)
    ))
    ;; i64(0) / i64(0) => i64(0) but still traps
    (drop (i64.div_s
      (i64.const 0)
      (i64.const 0)
    ))

    ;; unsigned divs
    ;; u32(x) / -2  =>  x >= -2
    (drop (i32.div_u
      (local.get $x)
      (i32.const -2)
    ))
    ;; u32(x) / -1  =>  x == -1
    (drop (i32.div_u
      (local.get $x)
      (i32.const -1)
    ))
    ;; u32(x) / (i32.min + 1)
    (drop (i32.div_u
      (local.get $x)
      (i32.const -2147483647)
    ))
    ;; u32(x) / i32.min  =>  x >>> 31
    (drop (i32.div_u
      (local.get $x)
      (i32.const -2147483648)
    ))
    ;; i32(0) / i32(0) => i32(0) but still traps
    (drop (i32.div_u
      (i32.const 0)
      (i32.const 0)
    ))
    ;; u64(x) / -1  =>  u64(x == -1)
    (drop (i64.div_u
      (local.get $y)
      (i64.const -1)
    ))
    ;; u64(x) / i64.min  =>  x >>> 63
    (drop (i64.div_u
      (local.get $y)
      (i64.const -9223372036854775808)
    ))
    ;; i64(0) / i64(0) => i64(0) but still traps
    (drop (i64.div_u
      (i64.const 0)
      (i64.const 0)
    ))

    ;; bool(x) | 1  ==>  1
    (drop (i32.or
      (i32.eqz
        (local.get $x)
      )
      (i32.const 1)
    ))
    (drop (i32.or
      (i32.eqz
        (i32.load
          (i32.const 0)
        )
      )
      (i32.const 1)
    ))
    (drop (i64.or
      (i64.extend_i32_u
        (i64.eqz
          (local.get $y)
        )
      )
      (i64.const 1)
    ))
    (drop (i64.or
      (i64.extend_i32_u
        (i64.eqz
          (i64.load
            (i32.const 0)
          )
        )
      )
      (i64.const 1)
    ))

    ;; (unsigned)x >= 0  =>  i32(1)
    (drop (i32.ge_u
      (local.get $x)
      (i32.const 0)
    ))
    (drop (i32.ge_u
      (i32.load
       (i32.const 0)
      )
      (i32.const 0)
    ))
    (drop (i64.ge_u
      (local.get $y)
      (i64.const 0)
    ))
    (drop (i64.ge_u
      (i64.load
       (i32.const 0)
      )
      (i64.const 0)
    ))

    ;; (unsigned)x < 0  =>  i32(0)
    (drop (i32.lt_u
      (local.get $x)
      (i32.const 0)
    ))
    (drop (i32.lt_u
      (i32.load
       (i32.const 0)
      )
      (i32.const 0)
    ))
    (drop (i64.lt_u
      (local.get $y)
      (i64.const 0)
    ))
    (drop (i64.lt_u
      (i64.load
       (i32.const 0)
      )
      (i64.const 0)
    ))
    (drop (i32.lt_u
        (i32.load
          (i32.const 0)
        )
        (block (result i32)
          (i32.store
            (i32.const 0)
            (i32.const 0)
          )
          (i32.const 0)
        )
      )
    )
    (drop (i64.lt_u
        (i64.load
          (i32.const 0)
        )
        (block (result i64)
          (i64.store
            (i32.const 0)
            (i64.const 0)
          )
          (i64.const 0)
        )
      )
    )


    ;; (unsigned)x > 0  =>  x != 0
    (drop (i32.gt_u
      (local.get $x)
      (i32.const 0)
    ))
    (drop (i64.gt_u
      (local.get $y)
      (i64.const 0)
    ))

    ;; (unsigned)x <= 0  =>  x == 0
    (drop (i32.le_u
      (local.get $x)
      (i32.const 0)
    ))
    (drop (i64.le_u
      (local.get $y)
      (i64.const 0)
    ))

    ;; i32(x) <= 0x7fffffff  =>  i32(1)
    (drop (i32.le_s
      (local.get $x)
      (i32.const 0x7fffffff)
    ))
    ;; i64(x) <= 0x7fffffffffffffff  =>  i32(1)
    (drop (i64.le_s
      (local.get $y)
      (i64.const 0x7fffffffffffffff)
    ))

    ;; i32(x) >= 0x80000000  =>  i32(1)
    (drop (i32.ge_s
      (local.get $x)
      (i32.const 0x80000000)
    ))
    ;; i64(x) >= 0x8000000000000000  =>  i32(1)
    (drop (i64.ge_s
      (local.get $y)
      (i64.const 0x8000000000000000)
    ))

    ;; i32(x) < 0x80000000  =>  0
    (drop (i32.lt_s
      (local.get $x)
      (i32.const 0x80000000)
    ))
    ;; i64(x) < 0x8000000000000000  =>  0
    (drop (i64.lt_s
      (local.get $y)
      (i64.const 0x8000000000000000)
    ))

    ;; i32(x) > 0x7fffffff  =>  0
    (drop (i32.gt_s
      (local.get $x)
      (i32.const 0x7fffffff)
    ))
    ;; i64(x) > 0x7fffffffffffffff  =>  0
    (drop (i64.gt_s
      (local.get $y)
      (i64.const 0x7fffffffffffffff)
    ))

    ;; i32(x) < 0x7fffffff  =>  x != 0x7fffffff
    (drop (i32.lt_s
      (local.get $x)
      (i32.const 0x7fffffff)
    ))
    ;; i64(x) < 0x7fffffffffffffff  =>  x != 0x7fffffffffffffff
    (drop (i64.lt_s
      (local.get $y)
      (i64.const 0x7fffffffffffffff)
    ))

    ;; i32(x) > 0x80000000  =>  x != 0x80000000
    (drop (i32.gt_s
      (local.get $x)
      (i32.const 0x80000000)
    ))
    ;; i64(x) > 0x8000000000000000  =>  x != 0x8000000000000000
    (drop (i64.gt_s
      (local.get $y)
      (i64.const 0x8000000000000000)
    ))

    ;; i32(x) <= 0x80000000  =>  x == 0x80000000
    (drop (i32.le_s
      (local.get $x)
      (i32.const 0x80000000)
    ))
    ;; i64(x) <= 0x8000000000000000  =>  x == 0x8000000000000000
    (drop (i64.le_s
      (local.get $y)
      (i64.const 0x8000000000000000)
    ))

    ;; i32(x) >= 0x7fffffff  =>  x == 0x7fffffff
    (drop (i32.ge_s
      (local.get $x)
      (i32.const 0x7fffffff)
    ))
    ;; i64(x) >= 0x7fffffffffffffff  =>  x == 0x7fffffffffffffff
    (drop (i64.ge_s
      (local.get $y)
      (i64.const 0x7fffffffffffffff)
    ))

    ;; -x * 1  =>  x * -1
    (drop (f32.mul
      (f32.neg
        (local.get $fx)
      )
      (f32.const 1)
    ))
    ;; -x * -2.1  =>  x * 2.1
    (drop (f64.mul
      (f64.neg
        (local.get $fy)
      )
      (f64.const -2.1)
    ))
    ;; 2 * -x  =>  x * -2
    (drop (f64.mul
      (f64.const 2)
      (f64.neg
        (local.get $fy)
      )
    ))
    ;; -x / inf  =>  x / -inf
    (drop (f32.div
      (f32.neg
        (local.get $fx)
      )
      (f32.const inf)
    ))
    ;; -x / -0.0  =>  x / 0.0
    (drop (f64.div
      (f64.neg
        (local.get $fy)
      )
      (f64.const -0.0)
    ))
    ;; -x / nan  =>  x / -nan
    (drop (f64.div
      (f64.neg
        (local.get $fy)
      )
      (f64.const nan)
    ))
    ;; 5.0 / -x  =>  -5 / x
    (drop (f64.div
      (f64.const 5)
      (f64.neg
        (local.get $fy)
      )
    ))

    ;; -x + C   ->   C - x
    (drop (f32.add
      (f32.neg
        (local.get $fx)
      )
      (f32.const 3.5)
    ))
    (drop (f64.sub
      (f64.neg
        (local.get $fy)
      )
      (f64.const -5)
    ))
  )
  ;; CHECK:      (func $rhs-is-const-nan (param $x f32) (param $y f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.const nan:0x400000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.const nan:0x8000000000000)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.copysign
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const nan:0x400000)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.copysign
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (f32.const nan:0x200000)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.copysign
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (f64.const -nan:0x8000000000000)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $rhs-is-const-nan (param $x f32) (param $y f64)

    ;; arithmetic ops

    ;; x + nan'   =>   nan'
    (drop (f32.add (local.get $x) (f32.const nan)))
    (drop (f32.add (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.add (local.get $y) (f64.const -nan)))
    ;; x - nan'   =>   nan'
    (drop (f32.sub (local.get $x) (f32.const nan)))
    (drop (f32.sub (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.sub (local.get $y) (f64.const -nan)))
    ;; x * nan'   =>   nan'
    (drop (f32.mul (local.get $x) (f32.const nan)))
    (drop (f32.mul (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.mul (local.get $y) (f64.const -nan)))
    ;; x / nan'   =>   nan'
    (drop (f32.div (local.get $x) (f32.const nan)))
    (drop (f32.div (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.div (local.get $y) (f64.const -nan)))

    ;; min / max ops

    ;; min(x, nan')   =>   nan'
    (drop (f32.min (local.get $x) (f32.const nan)))
    (drop (f32.min (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.min (local.get $y) (f64.const -nan)))
    ;; max(x, nan')   =>   nan'
    (drop (f32.max (local.get $x) (f32.const nan)))
    (drop (f32.max (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.max (local.get $y) (f64.const -nan)))

    ;; copysign ops (should be skipped)

    ;; copysign(x, nan)   =>  skip
    (drop (f32.copysign (local.get $x) (f32.const nan)))
    (drop (f32.copysign (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.copysign (local.get $y) (f64.const -nan)))

    ;; relational ops

    ;; x != nan   =>   1
    (drop (f32.ne (local.get $x) (f32.const nan)))
    (drop (f32.ne (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.ne (local.get $y) (f64.const -nan)))
    ;; x == nan   =>   0
    (drop (f32.eq (local.get $x) (f32.const nan)))
    (drop (f32.eq (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.eq (local.get $y) (f64.const -nan)))
    ;; x >  nan   =>   0
    (drop (f32.gt (local.get $x) (f32.const nan)))
    (drop (f32.gt (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.gt (local.get $y) (f64.const -nan)))
    ;; x >= nan   =>   0
    (drop (f32.ge (local.get $x) (f32.const nan)))
    (drop (f32.ge (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.ge (local.get $y) (f64.const -nan)))
    ;; x <  nan   =>   0
    (drop (f32.lt (local.get $x) (f32.const nan)))
    (drop (f32.lt (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.lt (local.get $y) (f64.const -nan)))
    ;; x <= nan   =>   0
    (drop (f32.le (local.get $x) (f32.const nan)))
    (drop (f32.le (local.get $x) (f32.const nan:0x200000)))
    (drop (f64.le (local.get $y) (f64.const -nan)))
  )
  ;; CHECK:      (func $lhs-is-neg-one (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const -1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $lhs-is-neg-one (param $x i32) (param $y i64)
    ;; -1 >> x  ==>   -1
    (drop (i32.shr_s
      (i32.const -1)
      (local.get $x)
    ))
    (drop (i64.shr_s
      (i64.const -1)
      (local.get $y)
    ))
    ;; rotl(-1, x)  ==>   -1
    (drop (i32.rotl
      (i32.const -1)
      (local.get $x)
    ))
    (drop (i64.rotl
      (i64.const -1)
      (local.get $y)
    ))
    ;; rotr(-1, x)  ==>   -1
    (drop (i32.rotr
      (i32.const -1)
      (local.get $x)
    ))
    (drop (i64.rotr
      (i64.const -1)
      (local.get $y)
    ))
    ;; skip
    (drop (i32.shr_s
      (i32.const -1)
      (call $ne0) ;; side effect
    ))
    ;; skip
    (drop (i32.shr_u
      (i32.const -1)
      (local.get $x)
    ))
  )
  ;; CHECK:      (func $lhs-is-const (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.const -2)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (i64.const -2)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $lhs-is-const (param $x i32) (param $y i64)
    ;; 0 - (x - 1)
    (drop (i32.sub
      (i32.const 0)
      (i32.sub
        (local.get $x)
        (i32.const 1)
      )
    ))
    (drop (i64.sub
      (i64.const 0)
      (i64.sub
        (local.get $y)
        (i64.const 1)
      )
    ))
    ;; -1 - (x + 1)
    (drop (i32.sub
      (i32.const -1)
      (i32.add
        (local.get $x)
        (i32.const 1)
      )
    ))
    (drop (i64.sub
      (i64.const -1)
      (i64.add
        (local.get $y)
        (i64.const 1)
      )
    ))
    ;; 1 - (2 - x)
    (drop (i32.sub
      (i32.const 1)
      (i32.sub
        (i32.const 2)
        (local.get $x)
      )
    ))
    (drop (i64.sub
      (i64.const 1)
      (i64.sub
        (i64.const 2)
        (local.get $y)
      )
    ))
    ;; 0 - (0x80000000 - x)
    (drop (i32.sub
      (i32.const 0)
      (i32.sub
        (i32.const 0x80000000)
        (local.get $x)
      )
    ))
  )
  ;; CHECK:      (func $pre-combine-or (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.gt_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.gt_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.gt_s
  ;; CHECK-NEXT:     (call $ne0)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (call $ne0)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.lt_s
  ;; CHECK-NEXT:     (call $ne0)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (call $ne0)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $pre-combine-or (param $x i32) (param $y i32)
    (drop (i32.or
      (i32.gt_s
        (local.get $x)
        (local.get $y)
      )
      (i32.eq
        (local.get $y) ;; ordering should not stop us
        (local.get $x)
      )
    ))
    (drop (i32.or
      (i32.eq ;; ordering should not stop us
        (local.get $y)
        (local.get $x)
      )
      (i32.gt_s
        (local.get $x)
        (local.get $y)
      )
    ))
    (drop (i32.or
      (i32.gt_s
        (local.get $x)
        (local.get $y)
      )
      (i32.eq
        (local.get $x)
        (i32.const 1) ;; not equal
      )
    ))
    (drop (i32.or
      (i32.gt_s
        (local.get $x)
        (i32.const 1) ;; not equal
      )
      (i32.eq
        (local.get $x)
        (local.get $y)
      )
    ))
    (drop (i32.or
      (i32.gt_s
        (call $ne0) ;; side effects
        (local.get $y)
      )
      (i32.eq
        (call $ne0)
        (local.get $y)
      )
    ))
    (drop (i32.or
      (i32.gt_s
        (local.get $y)
        (call $ne0) ;; side effects
      )
      (i32.eq
        (local.get $y)
        (call $ne0)
      )
    ))
  )
  ;; CHECK:      (func $combine-or (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $combine-or (param $x i32) (param $y i32)
    (drop (i32.or
      (i32.gt_s
        (local.get $x)
        (local.get $y)
      )
      (i32.eq
        (local.get $x)
        (local.get $y)
      )
    ))
    ;; TODO: more stuff here
  )
  ;; CHECK:      (func $select-into-arms (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-into-arms (param $x i32) (param $y i32)
    (if
      (select
        (i32.eqz (i32.eqz (local.get $x)))
        (i32.eqz (i32.eqz (local.get $y)))
        (local.get $y)
      )
      (then
        (unreachable)
      )
    )
  )
  ;; CHECK:      (func $select-with-same-arm-and-cond-32 (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-with-same-arm-and-cond-32 (param $x i32)
    ;; i32(x) ? i32(x) : 0  ==>  x
    (drop (select
      (local.get $x)
      (i32.const 0)
      (local.get $x)
    ))
    ;; i32(x) ? 0 : i32(x)  ==>  {x, 0}
    (drop (select
      (i32.const 0)
      (local.get $x)
      (local.get $x)
    ))
    ;; i32(x) == 0 ? i32(x) : 0  ==>  {x, 0}
    (drop (select
      (local.get $x)
      (i32.const 0)
      (i32.eqz (local.get $x))
    ))
  )

  ;; CHECK:      (func $select-with-same-arm-and-cond-64 (param $x i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i64)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i64)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i64)
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-with-same-arm-and-cond-64 (param $x i64)
    ;; i64(x) != 0 ? i64(x) : 0  ==>  x
    (drop (select
      (local.get $x)
      (i64.const 0)
      (i64.ne
        (local.get $x)
        (i64.const 0)
      )
    ))
    ;; i64(x) == 0 ? 0 : i64(x)  ==>  x
    (drop (select
      (i64.const 0)
      (local.get $x)
      (i64.eqz
        (local.get $x)
      )
    ))
    ;; i64(x) != 0 ? 0 : i64(x)  ==>  0
    (drop (select
      (i64.const 0)
      (local.get $x)
      (i64.ne
        (local.get $x)
        (i64.const 0)
      )
    ))
    ;; i64(x) == 0 ? i64(x) : 0  ==>  {x, 0}
    (drop (select
      (local.get $x)
      (i64.const 0)
      (i64.eqz
        (local.get $x)
      )
    ))
    (drop (select
      (local.get $x)
      (i64.const 0)
      (i64.eq
        (local.get $x)
        (i64.const 0)
      )
    ))
  )

  ;; CHECK:      (func $select-with-same-arm-and-cond-skips (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (i32.wrap_i64
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.ne
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:    (i64.eq
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-with-same-arm-and-cond-skips (param $x i32) (param $y i64)
    ;; skip not equals
    (drop (select
      (local.get $x)
      (i32.const 0)
      (i32.wrap_i64 (local.get $y))
    ))
    (drop (select
      (i32.const 0)
      (i32.sub (i32.const 0) (local.get $x))
      (local.get $x)
    ))

    ;; skip not zero
    (drop (select
      (local.get $x)
      (i32.const -1)
      (local.get $x)
    ))
    (drop (select
      (i32.const -1)
      (local.get $x)
      (local.get $x)
    ))
    (drop (select
      (i64.const -1)
      (local.get $y)
      (i64.ne
        (local.get $y)
        (i64.const 0)
      )
    ))
    (drop (select
      (i64.const 0)
      (local.get $y)
      (i64.ne
        (local.get $y)
        (i64.const 1)
      )
    ))
  )

  ;; CHECK:      (func $select-with-same-arm-and-cond-skips-side-effects (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.div_u
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (i32.div_u
  ;; CHECK-NEXT:     (i32.const 10)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (call $select-sign-64-lt
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:    (i64.eqz
  ;; CHECK-NEXT:     (call $select-sign-64-lt
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:    (call $select-sign-64-lt
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.eqz
  ;; CHECK-NEXT:     (call $select-sign-64-lt
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $select-with-same-arm-and-cond-skips-side-effects (param $x i32) (param $y i64)
    ;; skip with side effects
    (drop (select
      (i32.div_u (i32.const 10) (local.get $x))
      (i32.const 0)
      (i32.div_u (i32.const 10) (local.get $x))
    ))
    (drop (select
      (i32.const 0)
      (call $ne0)
      (call $ne0)
    ))
    (drop (select
      (call $select-sign-64-lt (local.get $y))
      (i64.const 0)
      (i64.eqz
        (call $select-sign-64-lt (local.get $y))
      )
    ))
    (drop (select
      (i64.const 0)
      (call $select-sign-64-lt (local.get $y))
      (i64.eqz
        (call $select-sign-64-lt (local.get $y))
      )
    ))
  )
  ;; CHECK:      (func $optimize-boolean-context (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-boolean-context (param $x i32) (param $y i32)
    ;; 0 - x   ==>   x
    (if
      (i32.sub
        (i32.const 0)
        (local.get $x)
      )
      (then
        (unreachable)
      )
    )
    (drop (select
      (local.get $x)
      (local.get $y)
      (i32.sub
        (i32.const 0)
        (local.get $x)
      )
    ))
  )

  ;; CHECK:      (func $optimize-combined-by-and-equals-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (i64.or
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-combined-by-and-equals-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
    ;; (i32(x) == 0) & (i32(y) == 0)   ==>   i32(x | y) == 0
    (drop (i32.and
      (i32.eq (local.get $x) (i32.const 0))
      (i32.eq (local.get $y) (i32.const 0))
    ))
    ;; (i64(x) == 0) & (i64(y) == 0)   ==>   i64(x | y) == 0
    (drop (i32.and
      (i64.eq (local.get $a) (i64.const 0))
      (i64.eq (local.get $b) (i64.const 0))
    ))
  )
  ;; CHECK:      (func $optimize-combined-by-or-noequal-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (i64.or
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-combined-by-or-noequal-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
    ;; (i32(x) != 0) | (i32(y) != 0)   ==>   i32(x | y) != 0
    (drop (i32.or
      (i32.ne (local.get $x) (i32.const 0))
      (i32.ne (local.get $y) (i32.const 0))
    ))
    ;; (i64(x) != 0) | (i64(y) != 0)   ==>   i64(x | y) != 0
    (drop (i32.or
      (i64.ne (local.get $a) (i64.const 0))
      (i64.ne (local.get $b) (i64.const 0))
    ))
  )
  ;; CHECK:      (func $optimize-combined-by-or-gt-or-eq-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ge_s
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.ge_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.ge_s
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (i64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-combined-by-or-gt-or-eq-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
    ;; (i32(x) >= 0) | (i32(y) >= 0)   ==>   i32(x & y) >= 0
    (drop (i32.or
      (i32.ge_s (local.get $x) (i32.const 0))
      (i32.ge_s (local.get $y) (i32.const 0))
    ))
    ;; (i64(x) >= 0) | (i64(y) >= 0)   ==>   i64(x & y) >= 0
    (drop (i32.or
      (i64.ge_s (local.get $a) (i64.const 0))
      (i64.ge_s (local.get $b) (i64.const 0))
    ))

    ;; skips
    ;; (i32(x) >= 0) | (i64(y) >= 0)   ==>   skip
    (drop (i32.or
      (i32.ge_s (local.get $x) (i32.const 0))
      (i64.ge_s (local.get $a) (i64.const 0))
    ))
  )
  ;; CHECK:      (func $optimize-combined-by-or-ne-to-minus-one (param $x i32) (param $y i32) (param $a i64) (param $b i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.ne
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const -1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.ne
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (i64.const -1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-combined-by-or-ne-to-minus-one (param $x i32) (param $y i32) (param $a i64) (param $b i64)
    ;; (i32(x) != -1) | (i32(y) != -1)   ==>   i32(x & y) != -1
    (drop (i32.or
      (i32.ne (local.get $x) (i32.const -1))
      (i32.ne (local.get $y) (i32.const -1))
    ))
    ;; (i64(x) != -1) | (i64(y) == -1)   ==>   i64(x & y) != -1
    (drop (i32.or
      (i64.ne (local.get $a) (i64.const -1))
      (i64.ne (local.get $b) (i64.const -1))
    ))

    ;; skips
    ;; (i32(x) != -1) | (i64(y) != -1)   ==>   skip
    (drop (i32.or
      (i32.ne (local.get $x) (i32.const -1))
      (i64.ne (local.get $a) (i64.const -1))
    ))
  )
  ;; CHECK:      (func $optimize-combined-by-or-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.lt_s
  ;; CHECK-NEXT:    (i64.or
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.lt_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.lt_s
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (i64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.lt_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.le_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.lt_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.le_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-combined-by-or-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
    ;; (i32(x) < 0) | (i32(y) < 0)   ==>   i32(x | y) < 0
    (drop (i32.or
      (i32.lt_s (local.get $x) (i32.const 0))
      (i32.lt_s (local.get $y) (i32.const 0))
    ))
    ;; (i64(x) < 0) | (i64(y) < 0)   ==>   i64(x | y) < 0
    (drop (i32.or
      (i64.lt_s (local.get $a) (i64.const 0))
      (i64.lt_s (local.get $b) (i64.const 0))
    ))

    ;; skips
    ;; (i32(x) < 0) | (i64(a) < 0)   ==>   skip
    (drop (i32.or
      (i32.lt_s (local.get $x) (i32.const 0))
      (i64.lt_s (local.get $a) (i64.const 0))
    ))
    ;; (i32(x) <= 0) | (i32(y) < 0)   ==>   skip
    (drop (i32.or
      (i32.le_s (local.get $x) (i32.const 0))
      (i32.lt_s (local.get $y) (i32.const 0))
    ))
    ;; (i32(x) < 1) | (i32(y) < 0)   ==>   skip
    (drop (i32.or
      (i32.lt_s (local.get $x) (i32.const 1))
      (i32.lt_s (local.get $y) (i32.const 0))
    ))
  )
  ;; CHECK:      (func $optimize-combined-by-and-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.lt_s
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-combined-by-and-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
    ;; (i32(x) < 0) & (i32(y) < 0)   ==>   i32(x & y) < 0
    (drop (i32.and
      (i32.lt_s (local.get $x) (i32.const 0))
      (i32.lt_s (local.get $y) (i32.const 0))
    ))
    ;; (i64(x) < 0) & (i64(y) < 0)   ==>   i64(x & y) < 0
    (drop (i32.and
      (i64.lt_s (local.get $a) (i64.const 0))
      (i64.lt_s (local.get $b) (i64.const 0))
    ))
  )
  ;; CHECK:      (func $optimize-combined-by-and-greatequal-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ge_s
  ;; CHECK-NEXT:    (i64.or
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.ge_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.ge_s
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (i64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-combined-by-and-greatequal-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64)
    ;; (i32(x) >= 0) & (i32(y) >= 0)   ==>   i32(x | y) >= 0
    (drop (i32.and
      (i32.ge_s (local.get $x) (i32.const 0))
      (i32.ge_s (local.get $y) (i32.const 0))
    ))
    ;; (i64(x) >= 0) & (i64(y) >= 0)   ==>   i64(x | y) >= 0
    (drop (i32.and
      (i64.ge_s (local.get $a) (i64.const 0))
      (i64.ge_s (local.get $b) (i64.const 0))
    ))

    ;; skips
    ;; (i32(x) >= 0) & (i64(y) >= 0)   ==>   skip
    (drop (i32.and
      (i32.ge_s (local.get $x) (i32.const 0))
      (i64.ge_s (local.get $a) (i64.const 0))
    ))
  )
  ;; CHECK:      (func $optimize-combined-by-and-equal-neg-one (param $x i32) (param $y i32) (param $a i64) (param $b i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.eq
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const -1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.eq
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (i64.const -1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-combined-by-and-equal-neg-one (param $x i32) (param $y i32) (param $a i64) (param $b i64)
    ;; (i32(x) == -1) & (i32(y) == -1)   ==>   i32(x & y) == -1
    (drop (i32.and
      (i32.eq (local.get $x) (i32.const -1))
      (i32.eq (local.get $y) (i32.const -1))
    ))
    ;; (i64(x) == -1) & (i64(y) == -1)   ==>   i64(x & y) == -1
    (drop (i32.and
      (i64.eq (local.get $a) (i64.const -1))
      (i64.eq (local.get $b) (i64.const -1))
    ))

    ;; skips
    ;; (i32(x) == -1) & (i64(y) == -1)   ==>   skip
    (drop (i32.and
      (i32.eq (local.get $x) (i32.const -1))
      (i64.eq (local.get $a) (i64.const -1))
    ))
  )
  ;; CHECK:      (func $optimize-relationals (param $x i32) (param $y i32) (param $X i64) (param $Y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (local.get $X)
  ;; CHECK-NEXT:    (local.get $Y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (local.get $X)
  ;; CHECK-NEXT:    (local.get $Y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.ne
  ;; CHECK-NEXT:    (local.get $X)
  ;; CHECK-NEXT:    (local.get $Y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_s
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.le_s
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const -2147483648)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const -2147483648)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_s
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (block (result i32)
  ;; CHECK-NEXT:      (i32.const -2147483648)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_s
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (block (result i32)
  ;; CHECK-NEXT:      (i32.const -2147483648)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-relationals (param $x i32) (param $y i32) (param $X i64) (param $Y i64)
    ;; eqz(x + 0x7FFFFFFF)  ->  x == -2147483647
    (drop (i32.eqz
      (i32.add
        (local.get $x)
        (i32.const 0x7FFFFFFF)
      )
    ))
    ;; eqz(x + 0x80000000)  ->  x == -2147483648
    (drop (i32.eqz
      (i32.add
        (local.get $x)
        (i32.const 0x80000000)
      )
    ))
    ;; eqz(x + 0x80000001)  ->  x == 2147483647
    (drop (i32.eqz
      (i32.add
        (local.get $x)
        (i32.const 0x80000001)
      )
    ))
    ;; eqz(x - y)
    (drop (i32.eqz
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
    ))
    (drop (i64.eqz
      (i64.sub
        (local.get $X)
        (local.get $Y)
      )
    ))
    ;; x - y == 0
    (drop (i32.eq
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    (drop (i64.eq
      (i64.sub
        (local.get $X)
        (local.get $Y)
      )
      (i64.const 0)
    ))
    ;; x - y != 0
    (drop (i32.ne
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    (drop (i64.ne
      (i64.sub
        (local.get $X)
        (local.get $Y)
      )
      (i64.const 0)
    ))
    ;; i32(x - y) > 0  ->  x > y
    (drop (i32.gt_s
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    ;; i32(x - y) >= 0  ->  x >= y
    (drop (i32.ge_s
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    ;; u32(x - y) > 0  ->  x != y
    (drop (i32.gt_u
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    ;; u32(x - y) >= 0  ->  1
    (drop (i32.ge_u
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    ;; u64(x - y) >= 0  ->  i32(1)
    (drop (i64.ge_u
      (i64.sub
        (local.get $X)
        (local.get $Y)
      )
      (i64.const 0)
    ))
    ;; i32(x - y) < 0  ->  x < y
    (drop (i32.lt_s
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    ;; i32(x - y) <= 0  ->  x <= y
    (drop (i32.le_s
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    ;; u32(x - y) < 0  ->  0
    (drop (i32.lt_u
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    ;; u64(x - y) < 0  ->  i32(0)
    (drop (i64.lt_u
      (i64.sub
        (local.get $X)
        (local.get $Y)
      )
      (i64.const 0)
    ))
    ;; u32(x - y) <= 0  ->  x == y
    (drop (i32.le_u
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
      (i32.const 0)
    ))
    ;; i32(x - 0x80000000) == 0  ->  x == 0x80000000
    (drop (i32.eq
      (i32.sub
        (local.get $x)
        (i32.const 0x80000000)
      )
      (i32.const 0)
    ))
    ;; i32(x - 0x80000000) != 0  ->  x == 0x80000000
    (drop (i32.ne
      (i32.sub
        (local.get $x)
        (i32.const 0x80000000)
      )
      (i32.const 0)
    ))
    ;; i32(x - { 0x80000000 }) < 0  ->  skip
    (drop (i32.lt_s
      (i32.sub
        (local.get $x)
        (i32.const 0x80000000)
      )
      (i32.const 0)
    ))
    ;; i32(x - { 0x80000000 }) >= 0  ->  skip
    (drop (i32.ge_s
      (i32.sub
        (local.get $x)
        (i32.const 0x80000000)
      )
      (i32.const 0)
    ))
    ;; i32(x - { 0x80000000 }) > 0  ->  skip
    (drop (i32.gt_s
      (i32.sub
        (local.get $x)
        (block (result i32)
          (i32.const 0x80000000)
        )
      )
      (i32.const 0)
    ))
    ;; i32(x - { 0x80000000 }) <= 0  ->  skip
    (drop (i32.gt_s
      (i32.sub
        (local.get $x)
        (block (result i32)
          (i32.const 0x80000000)
        )
      )
      (i32.const 0)
    ))
  )
  ;; CHECK:      (func $unsigned-context (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.div_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2147483647)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 3)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.div_s
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2147483647)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const -3)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shr_u
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 9223372036854775807)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.div_s
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i64.const 9223372036854775807)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.rem_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2147483647)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 3)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2147483647)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 7)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 2147483647)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 7)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $unsigned-context (param $x i32) (param $y i64)
    (drop (i32.div_s
      (i32.and
        (local.get $x)
        (i32.const 0x7fffffff)
      )
      (i32.const 3)
    ))
    (drop (i32.div_s
      (i32.and
        (local.get $x)
        (i32.const 0x7fffffff)
      )
      (i32.const -3) ;; skip
    ))
    (drop (i32.div_s
      (i32.and
        (local.get $x)
        (i32.const 0x7fffffff)
      )
      (i32.const 0x80000000) ;; skip
    ))
    (drop (i64.div_s
      (i64.and
        (local.get $y)
        (i64.const 0x7fffffffffffffff)
      )
      (i64.const 2)
    ))
     (drop (i64.div_s
      (i64.and
        (local.get $y)
        (i64.const 0x7fffffffffffffff)
      )
      (i64.const -1) ;; skip
    ))
    (drop (i32.rem_s
      (i32.and
        (local.get $x)
        (i32.const 0x7fffffff)
      )
      (i32.const 3)
    ))
    (drop (i32.shr_s
      (i32.and
        (local.get $x)
        (i32.const 0x7fffffff)
      )
      (i32.const 7)
    ))
    (drop (i32.ge_s
      (i32.and
        (local.get $x)
        (i32.const 0x7fffffff)
      )
      (i32.const 7)
    ))
    (drop (i32.ge_s
      (i32.and
        (local.get $x)
        (i32.const 0x7fffffff)
      )
      (i32.const -7) ;; skip
    ))
  )
  ;; CHECK:      (func $optimize-float-mul-by-two (param $0 f64) (param $1 f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.add
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.add
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (call $tee-with-unreachable-value)
  ;; CHECK-NEXT:    (f64.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (f64.const -2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-float-mul-by-two (param $0 f64) (param $1 f32)
    (drop (f64.mul
      (local.get $0)
      (f64.const 2)
    ))
    (drop (f32.mul
      (local.get $1)
      (f32.const 2)
    ))

    (drop (f64.mul
      (call $tee-with-unreachable-value) ;; side effect
      (f64.const 2)
    ))
    (drop (f64.mul
      (f64.neg (local.get $0)) ;; complex expression
      (f64.const 2)
    ))
  )
  ;; CHECK:      (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.ceil
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.floor
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.trunc
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.nearest
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.nearest
  ;; CHECK-NEXT:    (f64.trunc
  ;; CHECK-NEXT:     (local.get $w)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.trunc
  ;; CHECK-NEXT:    (f64.nearest
  ;; CHECK-NEXT:     (local.get $w)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $w)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.neg
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $w)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 2)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.rem_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.rem_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (call $ne0)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (call $ne0)
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (call $ne0)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.rem_s
  ;; CHECK-NEXT:    (i32.rem_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.rem_u
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:    (i32.rem_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (local.tee $x
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.or
  ;; CHECK-NEXT:    (i32.or
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.tee $x
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.xor
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.xor
  ;; CHECK-NEXT:     (local.tee $x
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.xor
  ;; CHECK-NEXT:    (i32.xor
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.tee $x
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64)
    ;; unary
    (drop (f64.abs (f64.abs (local.get $w))))
    (drop (f64.ceil (f64.ceil (local.get $w))))
    (drop (f64.floor (f64.floor (local.get $w))))
    (drop (f64.trunc (f64.trunc (local.get $w))))
    (drop (f64.nearest (f64.nearest (local.get $w))))

    (drop (f64.nearest (f64.trunc (local.get $w)))) ;; skip
    (drop (f64.trunc (f64.nearest (local.get $w)))) ;; skip

    (drop (f64.neg (f64.neg (local.get $w))))
    (drop (f64.neg (f64.neg (f64.neg (local.get $w)))))
    (drop (f64.neg (f64.neg (f64.neg (f64.neg (local.get $w))))))

    (drop (i32.eqz (i32.eqz (local.get $x)))) ;; skip
    (drop (i32.eqz (i32.eqz (i32.eqz (local.get $x)))))
    (drop (i32.eqz (i32.eqz (i64.eqz (i64.const 1)))))
    (drop (i32.eqz (i32.eqz (i32.ne (local.get $x) (i32.const 2)))))

    (drop (i32.eqz
      (i32.eqz
        (i32.and
          (local.get $x)
          (i32.const 1)
        )
      )
    ))

    ;; binary
    ;; ((signed)x % y) % y
    (drop (i32.rem_s
      (i32.rem_s
        (local.get $x)
        (local.get $y)
      )
      (local.get $y)
    ))
    ;; ((unsigned)x % y) % y
    (drop (i32.rem_u
      (i32.rem_u
        (local.get $x)
        (local.get $y)
      )
      (local.get $y)
    ))
    ;; 0 - (0 - y)
    (drop (i32.sub
      (i32.const 0)
      (i32.sub
        (i32.const 0)
        (local.get $y)
      )
    ))
    ;; x - (x - y)
    (drop (i32.sub
      (local.get $x)
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
    ))
    ;; y - (x - y)   -   skip
    (drop (i32.sub
      (local.get $y)
      (i32.sub
        (local.get $x)
        (local.get $y)
      )
    ))
    ;; x ^ (x ^ y)
    (drop (i32.xor
      (local.get $x)
      (i32.xor
        (local.get $x)
        (local.get $y)
      )
    ))
    ;; x ^ (y ^ x)
    (drop (i32.xor
      (local.get $x)
      (i32.xor
        (local.get $y)
        (local.get $x)
      )
    ))
    ;; (x ^ y) ^ x
    (drop (i32.xor
      (i32.xor
        (local.get $x)
        (local.get $y)
      )
      (local.get $x)
    ))
    ;; (y ^ x) ^ x
    (drop (i32.xor
      (i32.xor
        (local.get $y)
        (local.get $x)
      )
      (local.get $x)
    ))
    ;; x ^ (x ^ x)
    (drop (i32.xor
      (local.get $x)
      (i32.xor
        (local.get $x)
        (local.get $x)
      )
    ))
    ;; x & (x & y)
    (drop (i32.and
      (local.get $x)
      (i32.and
        (local.get $x)
        (local.get $y)
      )
    ))
    ;; x & (y & x)
    (drop (i32.and
      (local.get $x)
      (i32.and
        (local.get $y)
        (local.get $x)
      )
    ))
    ;; (x & y) & x
    (drop (i32.and
      (i32.and
        (local.get $x)
        (local.get $y)
      )
      (local.get $x)
    ))
    ;; (y & x) & x
    (drop (i32.and
      (i32.and
        (local.get $y)
        (local.get $x)
      )
      (local.get $x)
    ))
    ;; x | (x | y)
    (drop (i32.or
      (local.get $x)
      (i32.or
        (local.get $x)
        (local.get $y)
      )
    ))
    ;; x | (y | x)
    (drop (i32.or
      (local.get $x)
      (i32.or
        (local.get $y)
        (local.get $x)
      )
    ))
    ;; (x | y) | x
    (drop (i32.or
      (i32.or
        (local.get $x)
        (local.get $y)
      )
      (local.get $x)
    ))
    ;; (y | x) | x
    (drop (i32.or
      (i32.or
        (local.get $y)
        (local.get $x)
      )
      (local.get $x)
    ))
    ;; (y | x) | z   -   skip
    (drop (i32.or
      (i32.or
        (local.get $y)
        (local.get $x)
      )
      (local.get $z)
    ))
    ;; (z | x) | y   -   skip
    (drop (i32.or
      (i32.or
        (local.get $z)
        (local.get $x)
      )
      (local.get $y)
    ))
    ;; (SE() | x) | x
    (drop (i32.or
      (i32.or
        (call $ne0) ;; side effect
        (local.get $x)
      )
      (local.get $x)
    ))
    ;; (x | SE()) | SE()   -   skip
    (drop (i32.or
      (i32.or
        (local.get $x)
        (call $ne0) ;; side effect
      )
      (call $ne0) ;; side effect
    ))
    ;; x | (SE() | x)
    (drop (i32.or
      (local.get $x)
      (i32.or
        (local.get $x)
        (call $ne0) ;; side effect
      )
    ))
    ;; SE() | (x | SE())   -   skip
    (drop (i32.or
      (call $ne0) ;; side effect
      (i32.or
        (call $ne0) ;; side effect
        (local.get $x)
      )
    ))
    ;; (y % x) % y   -   skip
    (drop (i32.rem_s
      (i32.rem_s
        (local.get $y)
        (local.get $x)
      )
      (local.get $y)
    ))
    ;; y % (x % y)   -   skip
    (drop (i32.rem_u
      (local.get $y)
      (i32.rem_u
        (local.get $x)
        (local.get $y)
      )
    ))
    ;; x | (y | x)   where x and y cannot be reordered  -  skip
    (drop
      (i32.or
        (local.get $x)
        (i32.or
          (local.tee $x
            (i32.const 1)
          )
          (local.get $x)
        )
      )
    )
    (drop
      (i32.or
        (i32.or
          (local.get $x)
          (local.tee $x
            (i32.const 1)
          )
        )
        (local.get $x)
      )
    )
    ;; x ^ (y ^ x)   where x and y cannot be reordered  -  skip
    (drop
      (i32.xor
        (local.get $x)
        (i32.xor
          (local.tee $x
            (i32.const 1)
          )
          (local.get $x)
        )
      )
    )
    (drop
      (i32.xor
        (i32.xor
          (local.get $x)
          (local.tee $x
            (i32.const 1)
          )
        )
        (local.get $x)
      )
    )
  )

  ;; i32.wrap_i64(i64.extend_i32_s(x))  ==>  x
  ;; i32.wrap_i64(i64.extend_i32_u(x))  ==>  x

  ;; CHECK:      (func $sign-and-zero-extention-elimination-1 (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sign-and-zero-extention-elimination-1 (param $x i32)
    (drop (i32.wrap_i64 (i64.extend_i32_s (local.get $x))))
    (drop (i32.wrap_i64 (i64.extend_i32_u (local.get $x))))
  )
  ;; i64.extend_i32_u(i32.wrap_i64(x))  =>  x,  where maxBits(x) <= 32
  ;; i64.extend_i32_s(i32.wrap_i64(x))  =>  x,  where maxBits(x) <= 31

  ;; CHECK:      (func $sign-and-zero-extention-elimination-2 (param $x i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i64.const 4294967295)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i64.const 2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i32.wrap_i64
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_s
  ;; CHECK-NEXT:    (i32.wrap_i64
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_s
  ;; CHECK-NEXT:    (i32.wrap_i64
  ;; CHECK-NEXT:     (i64.and
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:      (i64.const 4294967295)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $sign-and-zero-extention-elimination-2 (param $x i64)
    (drop (i64.extend_i32_u (i32.wrap_i64 (i64.and (local.get $x) (i64.const 0x00000000FFFFFFFF)))))
    (drop (i64.extend_i32_s (i32.wrap_i64 (i64.and (local.get $x) (i64.const 0x000000007FFFFFFF)))))

    (drop (i64.extend_i32_u (i32.wrap_i64 (local.get $x)))) ;; skip
    (drop (i64.extend_i32_s (i32.wrap_i64 (local.get $x)))) ;; skip
    (drop (i64.extend_i32_s (i32.wrap_i64 (i64.and (local.get $x) (i64.const 0x00000000FFFFFFFF))))) ;; skip
  )
  ;; CHECK:      (func $optimize-shifts (param $x i32) (param $y i32) (param $z i64) (param $w i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shl
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (local.get $y)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shl
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shl
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shr_s
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shr_u
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shl
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $w)
  ;; CHECK-NEXT:     (i64.const 32)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.shr_u
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $w)
  ;; CHECK-NEXT:     (i64.const 31)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-shifts (param $x i32) (param $y i32) (param $z i64) (param $w i64)
    ;; i32
    (drop (i32.shl
      (local.get $x)
      (i32.const 32)
    ))
    (drop (i32.shr_s
      (local.get $x)
      (i32.const 32)
    ))
    (drop (i32.shr_u
      (local.get $x)
      (i32.const 64)
    ))
    (drop (i32.rotl
      (local.get $x)
      (i32.const 64)
    ))
    (drop (i32.rotr
      (local.get $x)
      (i32.const 64)
    ))
    ;; i64
    (drop (i64.shl
      (local.get $z)
      (i64.const 64)
    ))
    (drop (i64.shr_s
      (local.get $z)
      (i64.const 64)
    ))
    (drop (i64.shr_u
      (local.get $z)
      (i64.const 128)
    ))
    (drop (i64.rotl
      (local.get $z)
      (i64.const 128)
    ))
    (drop (i64.rotr
      (local.get $z)
      (i64.const 128)
    ))

    ;; i32
    (drop (i32.shl
      (local.get $x)
      (i32.and
        (local.get $y)
        (i32.const 31)
      )
    ))
    (drop (i32.shl
      (local.get $x)
      (i32.and
        (local.get $y)
        (i32.const 63)
      )
    ))
    (drop (i32.shr_s
      (local.get $x)
      (i32.and
        (local.get $y)
        (i32.const 31)
      )
    ))
    (drop (i32.shr_u
      (local.get $x)
      (i32.and
        (local.get $y)
        (i32.const 31)
      )
    ))
    ;; i64
    (drop (i64.shl
      (local.get $z)
      (i64.and
        (local.get $w)
        (i64.const 63)
      )
    ))
    (drop (i64.shl
      (local.get $z)
      (i64.and
        (local.get $w)
        (i64.const 127)
      )
    ))
    (drop (i64.shr_s
      (local.get $z)
      (i64.and
        (local.get $w)
        (i64.const 63)
      )
    ))
    (drop (i64.shr_u
      (local.get $z)
      (i64.and
        (local.get $w)
        (i64.const 63)
      )
    ))
    ;; i32(x) >> (y & 32)  ->  x
    (drop (i32.shr_u
      (local.get $x)
      (i32.and
        (local.get $y)
        (i32.const 32)
      )
    ))
    ;; i64(x) >> (y & 64)  ->  x
    (drop (i64.shr_u
      (local.get $z)
      (i64.and
        (local.get $w)
        (i64.const 128)
      )
    ))

    ;; skip
    (drop (i64.shl
      (local.get $z)
      (i64.and
        (local.get $w)
        (i64.const 32)
      )
    ))
    ;; skip
    (drop (i64.shr_u
      (local.get $z)
      (i64.and
        (local.get $w)
        (i64.const 31)
      )
    ))
  )
  ;; CHECK:      (func $optimize-float-points (param $x0 f64) (param $x1 f64) (param $y0 f32) (param $y1 f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x0)
  ;; CHECK-NEXT:    (local.get $x0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $y0)
  ;; CHECK-NEXT:    (local.get $y0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (f64.add
  ;; CHECK-NEXT:     (local.get $x0)
  ;; CHECK-NEXT:     (local.get $x1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (f64.add
  ;; CHECK-NEXT:     (local.get $x0)
  ;; CHECK-NEXT:     (local.get $x1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.mul
  ;; CHECK-NEXT:     (local.get $x0)
  ;; CHECK-NEXT:     (local.get $x1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.abs
  ;; CHECK-NEXT:    (f32.mul
  ;; CHECK-NEXT:     (local.get $y1)
  ;; CHECK-NEXT:     (local.get $y0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.mul
  ;; CHECK-NEXT:     (local.get $x0)
  ;; CHECK-NEXT:     (f64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.abs
  ;; CHECK-NEXT:    (f32.mul
  ;; CHECK-NEXT:     (f32.const 0)
  ;; CHECK-NEXT:     (local.get $y0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.mul
  ;; CHECK-NEXT:     (f64.add
  ;; CHECK-NEXT:      (local.get $x0)
  ;; CHECK-NEXT:      (local.get $x1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (f64.add
  ;; CHECK-NEXT:      (local.get $x0)
  ;; CHECK-NEXT:      (local.get $x0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (local.get $x0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.abs
  ;; CHECK-NEXT:    (local.get $y0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.sub
  ;; CHECK-NEXT:     (f64.const 0)
  ;; CHECK-NEXT:     (local.get $x0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.abs
  ;; CHECK-NEXT:    (f32.sub
  ;; CHECK-NEXT:     (f32.const 0)
  ;; CHECK-NEXT:     (local.get $y0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (local.get $x0)
  ;; CHECK-NEXT:    (local.get $x0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.div
  ;; CHECK-NEXT:    (local.get $y0)
  ;; CHECK-NEXT:    (local.get $y0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (f64.add
  ;; CHECK-NEXT:     (local.get $x0)
  ;; CHECK-NEXT:     (local.get $x1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (f64.add
  ;; CHECK-NEXT:     (local.get $x0)
  ;; CHECK-NEXT:     (local.get $x1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.div
  ;; CHECK-NEXT:     (local.get $x0)
  ;; CHECK-NEXT:     (local.get $x1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.abs
  ;; CHECK-NEXT:    (f32.div
  ;; CHECK-NEXT:     (local.get $y1)
  ;; CHECK-NEXT:     (local.get $y0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (local.get $x0)
  ;; CHECK-NEXT:    (local.get $x0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (local.get $y0)
  ;; CHECK-NEXT:    (local.get $y0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.mul
  ;; CHECK-NEXT:     (call $get-f64)
  ;; CHECK-NEXT:     (call $get-f64)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.div
  ;; CHECK-NEXT:    (local.get $x0)
  ;; CHECK-NEXT:    (local.get $x0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.div
  ;; CHECK-NEXT:    (local.get $y0)
  ;; CHECK-NEXT:    (local.get $y0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.div
  ;; CHECK-NEXT:     (local.get $x0)
  ;; CHECK-NEXT:     (f64.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.abs
  ;; CHECK-NEXT:    (f32.div
  ;; CHECK-NEXT:     (f32.const 0)
  ;; CHECK-NEXT:     (local.get $y0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.div
  ;; CHECK-NEXT:     (f64.add
  ;; CHECK-NEXT:      (local.get $x0)
  ;; CHECK-NEXT:      (local.get $x1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (f64.add
  ;; CHECK-NEXT:      (local.get $x0)
  ;; CHECK-NEXT:      (local.get $x0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-float-points (param $x0 f64) (param $x1 f64) (param $y0 f32) (param $y1 f32)
    ;; abs(x) * abs(x)   ==>   x * x
    (drop (f64.mul
      (f64.abs (local.get $x0))
      (f64.abs (local.get $x0))
    ))
    (drop (f32.mul
      (f32.abs (local.get $y0))
      (f32.abs (local.get $y0))
    ))
    (drop (f64.mul
      (f64.abs (f64.add (local.get $x0) (local.get $x1)))
      (f64.abs (f64.add (local.get $x0) (local.get $x1)))
    ))

    ;; abs(x) * abs(y)   ==>   abs(x * y)
    (drop (f64.mul
      (f64.abs (local.get $x0))
      (f64.abs (local.get $x1))
    ))
    (drop (f32.mul
      (f32.abs (local.get $y1))
      (f32.abs (local.get $y0))
    ))

    (drop (f64.mul
      (f64.abs (local.get $x0))
      (f64.abs (f64.const 0)) ;; skip
    ))
    (drop (f32.mul
      (f32.abs (f32.const 0)) ;; skip
      (f32.abs (local.get $y0))
    ))
    (drop (f64.mul
      (f64.abs (f64.add (local.get $x0) (local.get $x1)))
      (f64.abs (f64.add (local.get $x0) (local.get $x0)))
    ))


    ;; abs(-x)   ==>   abs(x)
    (drop (f64.abs
      (f64.neg (local.get $x0))
    ))
    (drop (f32.abs
      (f32.neg (local.get $y0))
    ))

    ;; abs(0 - x)   ==>   skip for non-fast math
    (drop (f64.abs
      (f64.sub
        (f64.const 0)
        (local.get $x0)
      )
    ))
    (drop (f32.abs
      (f32.sub
        (f32.const 0)
        (local.get $y0)
      )
    ))

    ;; abs(x) / abs(x)   ==>   x / x
    (drop (f64.div
      (f64.abs (local.get $x0))
      (f64.abs (local.get $x0))
    ))
    (drop (f32.div
      (f32.abs (local.get $y0))
      (f32.abs (local.get $y0))
    ))
    (drop (f64.div
      (f64.abs (f64.add (local.get $x0) (local.get $x1)))
      (f64.abs (f64.add (local.get $x0) (local.get $x1)))
    ))

    ;; abs(x) / abs(y)   ==>   abs(x / y)
    (drop (f64.div
      (f64.abs (local.get $x0))
      (f64.abs (local.get $x1))
    ))
    (drop (f32.div
      (f32.abs (local.get $y1))
      (f32.abs (local.get $y0))
    ))

    ;; abs(x * x)   ==>   x * x
    (drop (f64.abs
      (f64.mul
        (local.get $x0)
        (local.get $x0)
      )
    ))
    (drop (f32.abs
      (f32.mul
        (local.get $y0)
        (local.get $y0)
      )
    ))
    ;; This one cannot be optimized as the runtime values may differ: the calls
    ;; are "generative" in that identical syntactic calls may emit different
    ;; results.
    (drop (f64.abs
      (f64.mul
        (call $get-f64)
        (call $get-f64)
      )
    ))

    ;; abs(x / x)   ==>   x / x
    (drop (f64.abs
      (f64.div
        (local.get $x0)
        (local.get $x0)
      )
    ))
    (drop (f32.abs
      (f32.div
        (local.get $y0)
        (local.get $y0)
      )
    ))

    (drop (f64.div
      (f64.abs (local.get $x0))
      (f64.abs (f64.const 0)) ;; skip
    ))
    (drop (f32.div
      (f32.abs (f32.const 0)) ;; skip
      (f32.abs (local.get $y0))
    ))
    (drop (f64.div
      (f64.abs (f64.add (local.get $x0) (local.get $x1)))
      (f64.abs (f64.add (local.get $x0) (local.get $x0)))
    ))
  )

  ;; CHECK:      (func $optimize-float-points-fallthrough (param $x f64) (param $xb f64) (param $y f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.mul
  ;; CHECK-NEXT:    (block (result f32)
  ;; CHECK-NEXT:     (call $set-i32
  ;; CHECK-NEXT:      (i32.const 42)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (block (result f32)
  ;; CHECK-NEXT:     (call $set-i32
  ;; CHECK-NEXT:      (i32.const 1337)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-float-points-fallthrough (param $x f64) (param $xb f64) (param $y f32)
    ;; abs(x * x)   ==>   x * x  , as in the previous function.
    ;;
    ;; The fallthrough values here are identical, so we can optimize away the
    ;; f32.abs despite the effects in both (and even different-looking effects).
    (drop (f32.abs
      (f32.mul
        (block (result f32)
          (call $set-i32
            (i32.const 42)
          )
          (local.get $y)
        )
        (block (result f32)
          (call $set-i32
            (i32.const 1337)
          )
          (local.get $y)
        )
      )
    ))
  )
  ;; CHECK:      (func $optimize-float-points-fallthrough-b (param $x f64) (param $xb f64) (param $y f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.mul
  ;; CHECK-NEXT:     (block (result f64)
  ;; CHECK-NEXT:      (call $set-i32
  ;; CHECK-NEXT:       (i32.const 42)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (call $get-f64)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (block (result f64)
  ;; CHECK-NEXT:      (call $set-i32
  ;; CHECK-NEXT:       (i32.const 1337)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (call $get-f64)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-float-points-fallthrough-b (param $x f64) (param $xb f64) (param $y f32)
    ;; But generative effects in the fallthrough values themselves block us.
    (drop (f64.abs
      (f64.mul
        (block (result f64)
          (call $set-i32
            (i32.const 42)
          )
          (call $get-f64) ;; this changed
        )
        (block (result f64)
          (call $set-i32
            (i32.const 1337)
          )
          (call $get-f64) ;; this changed
        )
      )
    ))
  )
  ;; CHECK:      (func $optimize-float-points-fallthrough-c (param $x f64) (param $xb f64) (param $y f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.mul
  ;; CHECK-NEXT:     (block (result f64)
  ;; CHECK-NEXT:      (call $set-i32
  ;; CHECK-NEXT:       (i32.const 42)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (local.tee $x
  ;; CHECK-NEXT:       (f64.const 12.34)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (block (result f64)
  ;; CHECK-NEXT:      (call $set-i32
  ;; CHECK-NEXT:       (i32.const 1337)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-float-points-fallthrough-c (param $x f64) (param $xb f64) (param $y f32)
    ;; local.tee/get pairs are ok, but atm we don't look at the fallthrough of
    ;; the right side (we'd need to consider effects). TODO
    (drop (f64.abs
      (f64.mul
        (block (result f64)
          (call $set-i32
            (i32.const 42)
          )
          (local.tee $x         ;; this changed
            (f64.const 12.34)
          )
        )
        (block (result f64)
          (call $set-i32
            (i32.const 1337)
          )
          (local.get $x)        ;; this changed
        )
      )
    ))
  )
  ;; CHECK:      (func $optimize-float-points-fallthrough-cb (param $x f64) (param $xb f64) (param $y f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.mul
  ;; CHECK-NEXT:     (block (result f64)
  ;; CHECK-NEXT:      (call $set-i32
  ;; CHECK-NEXT:       (i32.const 42)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (local.tee $x
  ;; CHECK-NEXT:       (f64.const 12.34)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (block (result f64)
  ;; CHECK-NEXT:      (local.set $x
  ;; CHECK-NEXT:       (f64.const 13.37)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-float-points-fallthrough-cb (param $x f64) (param $xb f64) (param $y f32)
    ;; A conflicting set in the middle is a problem: here we cannot optimize.
    (drop (f64.abs
      (f64.mul
        (block (result f64)
          (call $set-i32
            (i32.const 42)
          )
          (local.tee $x
            (f64.const 12.34)
          )
        )
        (block (result f64)
          (local.set $x         ;; this changed
            (f64.const 13.37)
          )
          (local.get $x)
        )
      )
    ))
  )
  ;; CHECK:      (func $optimize-float-points-fallthrough-cc (param $x f64) (param $xb f64) (param $y f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.mul
  ;; CHECK-NEXT:    (block (result f64)
  ;; CHECK-NEXT:     (call $set-i32
  ;; CHECK-NEXT:      (i32.const 42)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.tee $x
  ;; CHECK-NEXT:      (f64.const 12.34)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-float-points-fallthrough-cc (param $x f64) (param $xb f64) (param $y f32)
    ;; Removing the local.set and the block on the right lets us optimize using
    ;; the tee/get pair.
    (drop (f64.abs
      (f64.mul
        (block (result f64)
          (call $set-i32
            (i32.const 42)
          )
          (local.tee $x
            (f64.const 12.34)
          )
        )
        (local.get $x)         ;; this moved out
      )
    ))
  )
  ;; CHECK:      (func $optimize-float-points-fallthrough-d (param $x f64) (param $xb f64) (param $y f32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.abs
  ;; CHECK-NEXT:    (f64.mul
  ;; CHECK-NEXT:     (block (result f64)
  ;; CHECK-NEXT:      (call $set-i32
  ;; CHECK-NEXT:       (i32.const 42)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (local.tee $x
  ;; CHECK-NEXT:       (f64.const 12.34)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (block (result f64)
  ;; CHECK-NEXT:      (call $set-i32
  ;; CHECK-NEXT:       (i32.const 1337)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (local.get $xb)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $optimize-float-points-fallthrough-d (param $x f64) (param $xb f64) (param $y f32)
    ;; The wrong local index means we fail again.
    (drop (f64.abs
      (f64.mul
        (block (result f64)
          (call $set-i32
            (i32.const 42)
          )
          (local.tee $x
            (f64.const 12.34)
          )
        )
        (block (result f64)
          (call $set-i32
            (i32.const 1337)
          )
          (local.get $xb) ;; this changed
        )
      )
    ))
  )
  ;; CHECK:      (func $ternary (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (select
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (select
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (select
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (select
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (if (result i32)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary (param $x i32) (param $y i32)
    (drop
      (select
        (i32.const 0)
        (i32.eqz
          (local.get $y)
        )
        (local.get $x)
      )
    )
    (drop
      (select
        (i32.const 1)
        (i32.eqz
          (local.get $y)
        )
        (local.get $x)
      )
    )
    (drop
      (select
        (i32.eqz
          (local.get $y)
        )
        (i32.const 0)
        (local.get $x)
      )
    )
    (drop
      (select
        (i32.eqz
          (local.get $y)
        )
        (i32.const 1)
        (local.get $x)
      )
    )
    ;; if works too
    (drop
      (if (result i32)
        (local.get $x)
        (then
          (i32.eqz
            (local.get $y)
          )
        )
        (else
          (i32.const 1)
        )
      )
    )
  )
  ;; CHECK:      (func $ternary-i64-0 (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (if (result i64)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (i64.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-i64-0 (param $x i32) (param $y i64)
    (drop
      (if (result i32)
        (local.get $x)
        (then
          (i32.const 0)
        )
        (else
          (i64.eqz
            (local.get $y)
          )
        )
      )
    )
  )
  ;; CHECK:      (func $ternary-i64-1 (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eqz
  ;; CHECK-NEXT:    (if (result i64)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (i64.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-i64-1 (param $x i32) (param $y i64)
    (drop
      (if (result i32)
        (local.get $x)
        (then
          (i64.eqz
            (local.get $y)
          )
        )
        (else
          (i32.const 1)
        )
      )
    )
  )
  ;; CHECK:      (func $ternary-no (param $x i32) (param $y i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const 2)
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-no (param $x i32) (param $y i32)
    (drop
      (select
        (i32.const 2) ;; only 0 and 1 work
        (i32.eqz
          (local.get $y)
        )
        (local.get $x)
      )
    )
  )
  ;; CHECK:      (func $ternary-no-unreachable-1 (param $x i32) (result i32)
  ;; CHECK-NEXT:  (if (result i32)
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (unreachable)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-no-unreachable-1 (param $x i32) (result i32)
    (if (result i32)
      (local.get $x)
      ;; one arm is an eqz, the other is 0 or 1, so we can put an eqz on the
      ;; outside in theory, but we'd need to be careful with the unreachable
      ;; type here. ignore this case, as DCE is the proper optimization anyhow.
      (then
        (i32.eqz
          (unreachable)
        )
      )
      (else
        (i32.const 0)
      )
    )
  )
  ;; CHECK:      (func $ternary-no-unreachable-2 (param $x i32) (result i32)
  ;; CHECK-NEXT:  (if (result i32)
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (unreachable)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-no-unreachable-2 (param $x i32) (result i32)
    (if (result i32)
      (local.get $x)
      ;; as before, but flipped
      (then
        (i32.const 0)
      )
      (else
        (i32.eqz
          (unreachable)
        )
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms (param $x i32) (param $y i32) (param $z i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (select
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms (param $x i32) (param $y i32) (param $z i32)
    (drop
      (select
        (i32.eqz (local.get $x))
        (i32.eqz (local.get $y))
        (local.get $z)
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-if (param $x i32) (param $y i32) (param $z i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (if (result i32)
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-if (param $x i32) (param $y i32) (param $z i32)
    (drop
      (if (result i32)
        (local.get $z)
        (then
          (i32.eqz (local.get $x))
        )
        (else
          (i32.eqz (local.get $y))
        )
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-type-change (param $x f64) (param $y f64) (param $z i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.demote_f64
  ;; CHECK-NEXT:    (f64.floor
  ;; CHECK-NEXT:     (if (result f64)
  ;; CHECK-NEXT:      (local.get $z)
  ;; CHECK-NEXT:      (then
  ;; CHECK-NEXT:       (local.get $x)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (else
  ;; CHECK-NEXT:       (local.get $y)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-type-change (param $x f64) (param $y f64) (param $z i32)
    (drop
      ;; the if's type begins as f32, but after moving code out it will be
      ;; f64
      (if (result f32)
        (local.get $z)
        (then
          (f32.demote_f64 (f64.floor (local.get $x)))
        )
        (else
          (f32.demote_f64 (f64.floor (local.get $y)))
        )
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-more (param $x f32) (param $y f32) (param $z i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.floor
  ;; CHECK-NEXT:    (f32.neg
  ;; CHECK-NEXT:     (select
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:      (local.get $z)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-more (param $x f32) (param $y f32) (param $z i32)
    (drop
      (select
        (f32.floor (f32.neg (local.get $x)))
        (f32.floor (f32.neg (local.get $y)))
        (local.get $z)
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-morer (param $x f32) (param $y f32) (param $z i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.abs
  ;; CHECK-NEXT:    (f32.floor
  ;; CHECK-NEXT:     (f32.neg
  ;; CHECK-NEXT:      (select
  ;; CHECK-NEXT:       (local.get $x)
  ;; CHECK-NEXT:       (local.get $y)
  ;; CHECK-NEXT:       (local.get $z)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-morer (param $x f32) (param $y f32) (param $z i32)
    (drop
      (select
        (f32.abs (f32.floor (f32.neg (local.get $x))))
        (f32.abs (f32.floor (f32.neg (local.get $y))))
        (local.get $z)
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-tee (param $param i32)
  ;; CHECK-NEXT:  (local $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (local.tee $x
  ;; CHECK-NEXT:     (local.get $param)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (call $send-i32
  ;; CHECK-NEXT:      (i32.const 42)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block (result i32)
  ;; CHECK-NEXT:    (call $send-i32
  ;; CHECK-NEXT:     (i32.const 1337)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.tee $x
  ;; CHECK-NEXT:     (local.get $param)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.tee $x
  ;; CHECK-NEXT:    (local.get $param)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-tee (param $param i32)
    (local $x i32)
    ;; The select's ifTrue and condition are equal (as a tee/get pair with
    ;; only a const in between), but there is a side effect too, that prevents
    ;; optimization atm TODO
    (drop
      (select
        (local.tee $x
          (local.get $param)
        )
        (i32.const 0)
        (block (result i32)
          (call $send-i32
            (i32.const 42)
          )
          (local.get $x)
        )
      )
    )
    ;; Side effect on the ifTrue - we handle this case, as we can easily see
    ;; that those effects are not a problem. We keep those effects around, of
    ;; course.
    (drop
      (select
        (block (result i32)
          (call $send-i32
            (i32.const 1337)
          )
          (local.tee $x
            (local.get $param)
          )
        )
        (i32.const 0)
        (local.get $x)
      )
    )
    ;; When there are no blocks or things and just a local.tee/get, we can
    ;; optimize.
    (drop
      (select
        (local.tee $x
          (local.get $param)
        )
        (i32.const 0)
        (local.get $x)
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-and-type-is-none (param $x i32) (param $y i32) (param $z i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (if (result i32)
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-and-type-is-none (param $x i32) (param $y i32) (param $z i32)
    (if
      (local.get $z)
      (then
        (drop (i32.eqz (local.get $x)))
      )
      (else
        (drop (i32.eqz (local.get $y)))
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-and-type-is-none-child-types-mismatch (param $x i32) (param $y i32) (param $z i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (f64.const 2.34)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-and-type-is-none-child-types-mismatch (param $x i32) (param $y i32) (param $z i32)
    (if
      (local.get $z)
      ;; the drop cannot be hoisted out, since the children's type mismatch
      ;; would not allow us to give a proper type to the if.
      (then
        (drop (i32.const 1))
      )
      (else
        (drop (f64.const 2.34))
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-but-block (param $x i32) (param $y i32) (param $z i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (i32.eqz
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (block (result i32)
  ;; CHECK-NEXT:     (i32.eqz
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-but-block (param $x i32) (param $y i32) (param $z i32)
    (drop
      (select
        ;; identical arms, but they are control flow structures
        (block (result i32)
          (i32.eqz (local.get $x))
        )
        (block (result i32)
          (i32.eqz (local.get $y))
        )
        (local.get $z)
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-but-binary (param $x i32) (param $y i32) (param $z i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-but-binary (param $x i32) (param $y i32) (param $z i32)
    (drop
      (select
        ;; identical arms, but they are binaries, not unaries
        (i32.add
          (local.get $x)
          (local.get $x)
        )
        (i32.add
          (local.get $y)
          (local.get $y)
        )
        (local.get $z)
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-br_if-same (param $x i32) (param $y i32) (param $z i32)
  ;; CHECK-NEXT:  (block $block
  ;; CHECK-NEXT:   (br_if $block
  ;; CHECK-NEXT:    (if (result i32)
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-br_if-same (param $x i32) (param $y i32) (param $z i32)
    (block $block
      (if
        (local.get $z)
        ;; two br_ifs with the same target are shallowly identical
        (then
          (br_if $block
            (local.get $x)
          )
        )
        (else
          (br_if $block
            (local.get $y)
          )
        )
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-br_if-different (param $x i32) (param $y i32) (param $z i32)
  ;; CHECK-NEXT:  (block $block1
  ;; CHECK-NEXT:   (block $block2
  ;; CHECK-NEXT:    (if
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (br_if $block1
  ;; CHECK-NEXT:       (local.get $x)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (br_if $block2
  ;; CHECK-NEXT:       (local.get $y)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-br_if-different (param $x i32) (param $y i32) (param $z i32)
    (block $block1
      (block $block2
        (if
          (local.get $z)
          ;; two br_ifs with different targets are not shallowly identical
          (then
            (br_if $block1
              (local.get $x)
            )
          )
          (else
            (br_if $block2
              (local.get $y)
            )
          )
        )
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-return (param $x i32) (param $y i32) (param $z i32) (result i32)
  ;; CHECK-NEXT:  (block $block
  ;; CHECK-NEXT:   (return
  ;; CHECK-NEXT:    (if (result i32)
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $y)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-return (param $x i32) (param $y i32) (param $z i32) (result i32)
    (block $block
      (if
        (local.get $z)
        (then
          (return
            (local.get $x)
          )
        )
        (else
          (return
            (local.get $y)
          )
        )
      )
    )
  )
  ;; CHECK:      (func $ternary-identical-arms-return-select (param $x i32) (param $y i32) (param $z i32) (result i32)
  ;; CHECK-NEXT:  (block $block
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (return
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (return
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-return-select (param $x i32) (param $y i32) (param $z i32) (result i32)
    (block $block
      ;; we cannot optimize a select currently as the return has side effects
      (select
        (return
          (local.get $x)
        )
        (return
          (local.get $y)
        )
        (local.get $z)
      )
    )
  )

  ;; CHECK:      (func $ternary-tee-with-identical-values (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.tee $x
  ;; CHECK-NEXT:     (i32.eqz
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.eqz
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-tee-with-identical-values (param $x i32)
    (drop
      ;; The tee's value, and the select's condition, are equal. If we just
      ;; look at them, we could think they are equal, and simplify this.
      ;; However, the tee modifies $x, so we cannot fold those two
      ;; expressions together while removing the select. (We can, though,
      ;; remove the select and the const, and use an and, but we do remain with
      ;; two copies of the eq, as those interact.)
      (select
        (local.tee $x
          (i32.eqz
            (local.get $x)
          )
        )
        (i32.const 0)
        (i32.eqz
          (local.get $x)
        )
      )
    )
  )

  ;; CHECK:      (func $send-i32 (param $0 i32)
  ;; CHECK-NEXT: )
  (func $send-i32 (param i32))
  ;; CHECK:      (func $ternary-identical-arms-call (param $x i32) (param $y i32) (param $z i32)
  ;; CHECK-NEXT:  (call $send-i32
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ternary-identical-arms-call (param $x i32) (param $y i32) (param $z i32)
    (if
      (local.get $z)
      (then
        (call $send-i32
          (local.get $x)
        )
      )
      (else
        (call $send-i32
          (local.get $y)
        )
      )
    )
  )
  ;; CHECK:      (func $if-unreachable-return-identical (param $x i32) (param $y i32) (param $z i32) (result i32)
  ;; CHECK-NEXT:  (return
  ;; CHECK-NEXT:   (if (result i32)
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (local.get $z)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-unreachable-return-identical (param $x i32) (param $y i32) (param $z i32) (result i32)
    ;; We can move the returns outside because we are already unreachable.
    (if (result i32)
      (local.get $x)
      (then
        (return
          (local.get $y)
        )
      )
      (else
        (return
          (local.get $z)
        )
      )
    )
  )

  ;; f32.reinterpret_i32(i32.load(x))  =>  f32.load(x)
  ;; f64.reinterpret_i64(i64.load(x))  =>  f64.load(x)
  ;; i32.reinterpret_f32(f32.load(x))  =>  i32.load(x)
  ;; i64.reinterpret_f64(f64.load(x))  =>  i64.load(x)

  ;; CHECK:      (func $simplify_reinterpret_and_load (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.load
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.load
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.load
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.load
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.reinterpret_i32
  ;; CHECK-NEXT:    (i32.load8_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.reinterpret_i64
  ;; CHECK-NEXT:    (i64.load32_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify_reinterpret_and_load (param $x i32)
    (drop (f32.reinterpret_i32 (i32.load (local.get $x))))
    (drop (f64.reinterpret_i64 (i64.load (local.get $x))))
    (drop (i32.reinterpret_f32 (f32.load (local.get $x))))
    (drop (i64.reinterpret_f64 (f64.load (local.get $x))))
    (drop (f32.reinterpret_i32 (i32.load8_s (local.get $x))))     ;; skip
    (drop (f64.reinterpret_i64 (i64.load32_u (local.get $x))))    ;; skip
  )

  ;; f32.store(y, f32.reinterpret_i32(x))  =>  i32.store(y, x)
  ;; f64.store(y, f64.reinterpret_i64(x))  =>  i64.store(y, x)
  ;; i32.store(y, i32.reinterpret_f32(x))  =>  f32.store(y, x)
  ;; i64.store(y, i64.reinterpret_f64(x))  =>  f64.store(y, x)

  ;; CHECK:      (func $simplify_store_and_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64)
  ;; CHECK-NEXT:  (i32.store
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i64.store
  ;; CHECK-NEXT:   (i32.const 16)
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (f32.store
  ;; CHECK-NEXT:   (i32.const 24)
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (f64.store
  ;; CHECK-NEXT:   (i32.const 32)
  ;; CHECK-NEXT:   (local.get $w)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.store8
  ;; CHECK-NEXT:   (i32.const 40)
  ;; CHECK-NEXT:   (i32.reinterpret_f32
  ;; CHECK-NEXT:    (local.get $z)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i64.store32
  ;; CHECK-NEXT:   (i32.const 44)
  ;; CHECK-NEXT:   (i64.reinterpret_f64
  ;; CHECK-NEXT:    (local.get $w)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify_store_and_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64)
    (f32.store (i32.const 8) (f32.reinterpret_i32 (local.get $x)))
    (f64.store (i32.const 16) (f64.reinterpret_i64 (local.get $y)))
    (i32.store (i32.const 24) (i32.reinterpret_f32 (local.get $z)))
    (i64.store (i32.const 32) (i64.reinterpret_f64 (local.get $w)))
    (i32.store8 (i32.const 40) (i32.reinterpret_f32 (local.get $z)))       ;; skip
    (i64.store32 (i32.const 44) (i64.reinterpret_f64 (local.get $w)))      ;; skip
  )

  ;; i32.reinterpret_f32(f32.reinterpret_i32(x))  =>  x
  ;; i64.reinterpret_f64(f64.reinterpret_i64(x))  =>  x
  ;; f32.reinterpret_i32(i32.reinterpret_f32(x))  =>  x
  ;; f64.reinterpret_i64(i64.reinterpret_f64(x))  =>  x

  ;; CHECK:      (func $eliminate_reinterpret_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $y)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $z)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $w)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eliminate_reinterpret_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64)
    (drop (i32.reinterpret_f32 (f32.reinterpret_i32 (local.get $x))))
    (drop (i64.reinterpret_f64 (f64.reinterpret_i64 (local.get $y))))
    (drop (f32.reinterpret_i32 (i32.reinterpret_f32 (local.get $z))))
    (drop (f64.reinterpret_i64 (i64.reinterpret_f64 (local.get $w))))
  )

  ;; CHECK:      (func $simplify_int_float_conversion_roundtrips (param $x i32) (param $y i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.trunc_f64_u
  ;; CHECK-NEXT:    (f64.convert_i32_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.trunc_f64_s
  ;; CHECK-NEXT:    (f64.convert_i32_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.trunc_f32_u
  ;; CHECK-NEXT:    (f32.convert_i32_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.trunc_f64_u
  ;; CHECK-NEXT:    (f64.convert_i64_u
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.trunc_f64_s
  ;; CHECK-NEXT:    (f64.convert_i64_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.trunc_f32_u
  ;; CHECK-NEXT:    (f32.convert_i32_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.trunc_f32_s
  ;; CHECK-NEXT:    (f32.convert_i64_s
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify_int_float_conversion_roundtrips (param $x i32) (param $y i64)
    (drop (i32.trunc_f64_u (f64.convert_i32_u (local.get $x))))
    (drop (i32.trunc_f64_s (f64.convert_i32_s (local.get $x))))

    ;; skips
    (drop (i32.trunc_f64_u (f64.convert_i32_s (local.get $x))))
    (drop (i32.trunc_f64_s (f64.convert_i32_u (local.get $x))))
    (drop (i32.trunc_f32_u (f32.convert_i32_u (local.get $x))))
    (drop (i32.trunc_f64_u (f64.convert_i64_u (local.get $y))))
    (drop (i64.trunc_f64_s (f64.convert_i64_s (local.get $y))))
    (drop (i64.trunc_f32_u (f32.convert_i32_s (local.get $x))))
    (drop (i64.trunc_f32_s (f32.convert_i64_s (local.get $y))))
  )

  ;; CHECK:      (func $simplify_rounding_after_conversions_i32_to_f64 (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i32_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i32_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i32_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i32_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i32_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i32_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i32_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i32_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify_rounding_after_conversions_i32_to_f64 (param $x i32)
    (drop (f64.ceil (f64.convert_i32_u (local.get $x))))
    (drop (f64.ceil (f64.convert_i32_s (local.get $x))))

    (drop (f64.floor (f64.convert_i32_u (local.get $x))))
    (drop (f64.floor (f64.convert_i32_s (local.get $x))))

    (drop (f64.trunc (f64.convert_i32_u (local.get $x))))
    (drop (f64.trunc (f64.convert_i32_s (local.get $x))))

    (drop (f64.nearest (f64.convert_i32_u (local.get $x))))
    (drop (f64.nearest (f64.convert_i32_s (local.get $x))))
  )

  ;; CHECK:      (func $simplify_rounding_after_conversions_i32_to_f32 (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i32_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i32_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i32_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i32_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i32_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i32_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i32_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i32_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify_rounding_after_conversions_i32_to_f32 (param $x i32)
    (drop (f32.ceil (f32.convert_i32_u (local.get $x))))
    (drop (f32.ceil (f32.convert_i32_s (local.get $x))))

    (drop (f32.floor (f32.convert_i32_u (local.get $x))))
    (drop (f32.floor (f32.convert_i32_s (local.get $x))))

    (drop (f32.trunc (f32.convert_i32_u (local.get $x))))
    (drop (f32.trunc (f32.convert_i32_s (local.get $x))))

    (drop (f32.nearest (f32.convert_i32_u (local.get $x))))
    (drop (f32.nearest (f32.convert_i32_s (local.get $x))))
  )

  ;; CHECK:      (func $simplify_rounding_after_conversions_i64_to_f64 (param $x i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i64_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i64_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i64_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i64_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i64_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i64_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i64_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f64.convert_i64_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify_rounding_after_conversions_i64_to_f64 (param $x i64)
    (drop (f64.ceil (f64.convert_i64_u (local.get $x))))
    (drop (f64.ceil (f64.convert_i64_s (local.get $x))))

    (drop (f64.floor (f64.convert_i64_u (local.get $x))))
    (drop (f64.floor (f64.convert_i64_s (local.get $x))))

    (drop (f64.trunc (f64.convert_i64_u (local.get $x))))
    (drop (f64.trunc (f64.convert_i64_s (local.get $x))))

    (drop (f64.nearest (f64.convert_i64_u (local.get $x))))
    (drop (f64.nearest (f64.convert_i64_s (local.get $x))))
  )

  ;; CHECK:      (func $simplify_rounding_after_conversions_i64_to_f32 (param $x i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i64_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i64_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i64_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i64_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i64_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i64_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i64_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (f32.convert_i64_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $simplify_rounding_after_conversions_i64_to_f32 (param $x i64)
    (drop (f32.ceil (f32.convert_i64_u (local.get $x))))
    (drop (f32.ceil (f32.convert_i64_s (local.get $x))))

    (drop (f32.floor (f32.convert_i64_u (local.get $x))))
    (drop (f32.floor (f32.convert_i64_s (local.get $x))))

    (drop (f32.trunc (f32.convert_i64_u (local.get $x))))
    (drop (f32.trunc (f32.convert_i64_s (local.get $x))))

    (drop (f32.nearest (f32.convert_i64_u (local.get $x))))
    (drop (f32.nearest (f32.convert_i64_s (local.get $x))))
  )

  ;; u64(i32.load(_8|_16)(_u|_s)(x))  =>  i64.load(_8|_16|_32)(_u|_s)(x)
  ;; except:
  ;;   i64.extend_i32_u(i32.load8_s(x)) and
  ;;   i64.extend_i32_u(i32.load16_s(x))

  ;; CHECK:      (func $combine_load_and_extend_u (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.load8_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.load16_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.load32_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i32.load8_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.extend_i32_u
  ;; CHECK-NEXT:    (i32.load16_s
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $combine_load_and_extend_u (param $x i32)
    (drop (i64.extend_i32_u (i32.load8_u (local.get $x))))
    (drop (i64.extend_i32_u (i32.load16_u (local.get $x))))
    (drop (i64.extend_i32_u (i32.load (local.get $x))))

    ;; skips
    (drop (i64.extend_i32_u (i32.load8_s (local.get $x))))
    (drop (i64.extend_i32_u (i32.load16_s (local.get $x))))
  )

  ;; i64(i32.load(_8|_16)(_u|_s)(x))  =>  i64.load(_8|_16|_32)(_u|_s)(x)

  ;; CHECK:      (func $combine_load_and_extend_s (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.load8_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.load16_u
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.load8_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.load16_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.load32_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $combine_load_and_extend_s (param $x i32)
    (drop (i64.extend_i32_s (i32.load8_u (local.get $x))))
    (drop (i64.extend_i32_s (i32.load16_u (local.get $x))))
    (drop (i64.extend_i32_s (i32.load8_s (local.get $x))))
    (drop (i64.extend_i32_s (i32.load16_s (local.get $x))))
    (drop (i64.extend_i32_s (i32.load (local.get $x))))
  )

  ;; CHECK:      (func $wrap-i64-to-i32-add (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.add
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $wrap-i64-to-i32-add (param $x i32) (result i32)
    ;; Rather than extend to 64 and add there, we can do all of this in i32.
    (i32.wrap_i64
      (i64.add
        (i64.extend_i32_u
          (local.get $x)
        )
        (i64.const 8)
      )
    )
  )

  ;; CHECK:      (func $wrap-i64-to-i32-sub (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.sub
  ;; CHECK-NEXT:   (i32.const 8)
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $wrap-i64-to-i32-sub (param $x i32) (result i32)
    (i32.wrap_i64
      (i64.sub
        (i64.const 8)
        (i64.extend_i32_u
          (local.get $x)
        )
      )
    )
  )

  ;; CHECK:      (func $wrap-i64-to-i32-mul (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (local.get $x)
  ;; CHECK-NEXT:   (i32.const 42)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $wrap-i64-to-i32-mul (param $x i32) (result i32)
    (i32.wrap_i64
      (i64.mul
        (i64.extend_i32_u
          (local.get $x)
        )
        (i64.const 42)
      )
    )
  )

  ;; CHECK:      (func $wrap-i64-to-i32-many (param $x i32) (param $y i32) (result i32)
  ;; CHECK-NEXT:  (i32.mul
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (i32.const -1)
  ;; CHECK-NEXT:     (local.get $y)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 42)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $wrap-i64-to-i32-many (param $x i32) (param $y i32) (result i32)
    ;; Multiple operations that all together can be turned into i32.
    (i32.wrap_i64
      (i64.mul
        (i64.add
          (i64.extend_i32_u
            (local.get $x)
          )
          (i64.sub
            (i64.const -1)
            (i64.extend_i32_u
              (local.get $y)
            )
          )
        )
        (i64.const 42)
      )
    )
  )

  ;; CHECK:      (func $wrap-i64-to-i32-div-no (param $x i32) (result i32)
  ;; CHECK-NEXT:  (i32.wrap_i64
  ;; CHECK-NEXT:   (i64.div_u
  ;; CHECK-NEXT:    (i64.extend_i32_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 42)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $wrap-i64-to-i32-div-no (param $x i32) (result i32)
    ;; We *cannot* optimize here, as division cares about i32/i64 differences.
    (i32.wrap_i64
      (i64.div_s
        (i64.extend_i32_u
          (local.get $x)
        )
        (i64.const 42)
      )
    )
  )

  ;; CHECK:      (func $wrap-i64-to-i32-tee-no (param $x i32) (result i32)
  ;; CHECK-NEXT:  (local $y i64)
  ;; CHECK-NEXT:  (i32.wrap_i64
  ;; CHECK-NEXT:   (i64.add
  ;; CHECK-NEXT:    (local.tee $y
  ;; CHECK-NEXT:     (i64.const 42)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.extend_i32_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $wrap-i64-to-i32-tee-no (param $x i32) (result i32)
    ;; The local.tee stops us from optimizing atm. TODO
    (local $y i64)
    (i32.wrap_i64
      (i64.add
        (i64.extend_i32_u
          (local.get $x)
        )
        (local.tee $y
          (i64.const 42)
        )
      )
    )
  )

  ;; CHECK:      (func $wrap-i64-to-i32-local-no (param $x i64) (result i32)
  ;; CHECK-NEXT:  (i32.wrap_i64
  ;; CHECK-NEXT:   (i64.div_s
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i64.const 42)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $wrap-i64-to-i32-local-no (param $x i64) (result i32)
    ;; We do not optimize here for now as an input ($x) is an i64. TODO
    (i32.wrap_i64
      (i64.div_s
        (local.get $x)
        (i64.const 42)
      )
    )
  )

  ;; CHECK:      (func $gt_u-added-constant (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_u
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 6)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $gt_u-added-constant (param $x i32)
    ;; x + C1 > C2  =>  x > (C2-C1), iff x+C1 and C2-C1 don't over/underflow
    (drop
      (i32.gt_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 5)
        )
        (i32.const 11)
      )
    )
    ;; We can optimize even if the constants are equal.
    (drop
      (i32.gt_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 5)
        )
        (i32.const 5)
      )
    )
    ;; x + C1 > C2  =>  x + (C1-C2) > 0, iff x+C1 and C1-C2 don't over/underflow
    ;; After doing that, further optimizations are possible here.
    (drop
      (i32.gt_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 6)
        )
        (i32.const 5)
      )
    )
  )

  ;; CHECK:      (func $gt_u-added-constant-no (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_u
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 11)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_u
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (i32.shr_u
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const -2147483648)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 11)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_u
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (i32.shr_u
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 11)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $gt_u-added-constant-no (param $x i32)
    ;; As above, but without the shr_u, A is big enough for a possible overflow,
    ;; and we cannot optimize.
    (drop
      (i32.gt_u
        (i32.add
          (local.get $x)
          (i32.const 5)
        )
        (i32.const 11)
      )
    )
    ;; With the added constant too big, it might overflow, and we cannot
    ;; optimize.
    (drop
      (i32.gt_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 0x80000000)
        )
        (i32.const 11)
      )
    )
    (drop
      (i32.gt_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 0xffffffff)
        )
        (i32.const 11)
      )
    )
  )

  ;; CHECK:      (func $ge_u-added-constant (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 6)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ge_u-added-constant (param $x i32)
    ;; As above, but with ge rather than gt. We can optimize here.
    (drop
      (i32.ge_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 5)
        )
        (i32.const 11)
      )
    )
    (drop
      (i32.ge_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 5)
        )
        (i32.const 5)
      )
    )
    (drop
      (i32.ge_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 6)
        )
        (i32.const 5)
      )
    )
  )

  ;; CHECK:      (func $ge_u-added-constant-no (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 11)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (i32.shr_u
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const -2147483648)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 11)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (i32.sub
  ;; CHECK-NEXT:     (i32.shr_u
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 11)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ge_u-added-constant-no (param $x i32)
    ;; As above, but with ge rather than gt. We cannot optimize here.
    (drop
      (i32.ge_u
        (i32.add
          (local.get $x)
          (i32.const 5)
        )
        (i32.const 11)
      )
    )
    (drop
      (i32.ge_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 0x80000000)
        )
        (i32.const 11)
      )
    )
    (drop
      (i32.ge_u
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 0xffffffff)
        )
        (i32.const 11)
      )
    )
  )

  ;; CHECK:      (func $eq-added-constant (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 6)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $eq-added-constant (param $x i32)
    ;; As above, but with eq rather than gt. We can optimize here.
    (drop
      (i32.eq
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 5)
        )
        (i32.const 11)
      )
    )
  )

  ;; CHECK:      (func $ne-added-constant (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 6)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ne-added-constant (param $x i32)
    ;; As above, but with ne rather than gt. We can optimize here.
    (drop
      (i32.ne
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 5)
        )
        (i32.const 11)
      )
    )
  )

  ;; CHECK:      (func $lt-added-constant (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_s
  ;; CHECK-NEXT:    (i32.add
  ;; CHECK-NEXT:     (i32.shr_u
  ;; CHECK-NEXT:      (local.get $x)
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 5)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 11)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $lt-added-constant (param $x i32)
    ;; As above, but with lt_s rather than gt_u. We can optimize here.
    (drop
      (i32.lt_s
        (i32.add
          (i32.shr_u
            (local.get $x)
            (i32.const 1)
          )
          (i32.const 5)
        )
        (i32.const 11)
      )
    )
  )

  ;; CHECK:      (func $too-few-bits (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $too-few-bits (param $x i32)
    ;; Comparison of something with at most 8 bits to something with more than
    ;; 8. These must all be false.
    (drop
      (i32.eq
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
    (drop
      (i32.gt_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
    (drop
      (i32.gt_u
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
    (drop
      (i32.ge_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
    (drop
      (i32.ge_u
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
    ;; These are all true.
    (drop
      (i32.ne
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
    (drop
      (i32.lt_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
    (drop
      (i32.lt_u
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
    (drop
      (i32.le_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
    (drop
      (i32.le_u
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 256)
      )
    )
  )

  ;; CHECK:      (func $too-few-bits-no (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.lt_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.le_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.le_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.gt_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ge_u
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i32.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $too-few-bits-no (param $x i32)
    ;; Identical to the above, but the constant is changed from 256 to 255. We
    ;; cannot optimize here: the number of bits is the same and we can't infer
    ;; anything.
    (drop
      (i32.eq
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.ne
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.lt_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.lt_u
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.le_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.le_u
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.gt_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.gt_u
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.ge_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
    (drop
      (i32.ge_u
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 255)
      )
    )
  )

  ;; CHECK:      (func $too-few-bits-signed (param $x i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.ne
  ;; CHECK-NEXT:    (local.get $x)
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $too-few-bits-signed (param $x i32)
    ;; As above, but now using only signed operations and the constant on the
    ;; right has the sign bit set. The left side is non-negative, which lets us
    ;; infer the results here.
    ;; These are all false:
    (drop
      (i32.lt_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 0x80000000) ;; -2147483648
      )
    )
    (drop
      (i32.le_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 0x80000000) ;; -2147483648
      )
    )
    ;; These are all true:
    (drop
      (i32.gt_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 0x80000000) ;; -2147483648
      )
    )
    (drop
      (i32.ge_s
        (i32.and
          (local.get $x)
          (i32.const 255)
        )
        (i32.const 0x80000000) ;; -2147483648
      )
    )
    ;; This cannot be inferred, as the left has too many possible bits (so it
    ;; may have the sign bit set).
    (drop
      (i32.gt_s
        (local.get $x)
        (i32.const 0x80000000) ;; -2147483648
      )
    )
  )

  ;; CHECK:      (func $too-few-bits-i64 (param $x i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.eq
  ;; CHECK-NEXT:    (i64.and
  ;; CHECK-NEXT:     (local.get $x)
  ;; CHECK-NEXT:     (i64.const 255)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 255)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $too-few-bits-i64 (param $x i64)
    ;; As above, but with i64 values. We can infer 0 here.
    (drop
      (i64.eq
        (i64.and
          (local.get $x)
          (i64.const 255)
        )
        (i64.const 256)
      )
    )
    ;; The constant is now 255 and we cannot optimize here.
    (drop
      (i64.eq
        (i64.and
          (local.get $x)
          (i64.const 255)
        )
        (i64.const 255)
      )
    )
  )

  ;; CHECK:      (func $skip-added-constants-overflow (result i32)
  ;; CHECK-NEXT:  (i32.ge_s
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const -2147483648)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $skip-added-constants-overflow (result i32)
    ;; If we subtracted 0x80000000 - 1 we'd get something that changes sign if
    ;; the comparison is signed (as the sign bit is no longer set). To avoid
    ;; that we skip optimizing cases where subtracting the constants might lead
    ;; to an overflow.
    (i32.ge_s
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 1)
        )
        (i32.const 1)
      )
      (i32.const 0x80000000)
    )
  )

  ;; CHECK:      (func $skip-added-constants-overflow-unsigned (result i32)
  ;; CHECK-NEXT:  (i32.ge_u
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (i32.load
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 2147483647)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $skip-added-constants-overflow-unsigned (result i32)
    ;; As above, but unsigned. This is ok for us to optimize.
    (i32.ge_u
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 1)
        )
        (i32.const 1)
      )
      (i32.const 0x80000000)
    )
  )

  ;; CHECK:      (func $skip-added-constants-zero (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (i32.load
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 1)
  ;; CHECK-NEXT: )
  (func $skip-added-constants-zero (result i32)
    ;; A zero in either constant means we should not optimize using an added
    ;; constant. However, other optimizations kick in here, as adding zero does
    ;; nothing, and we end up with [max 31 bits] >=_s MIN_INT which is true.
    (i32.ge_s
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 1)
        )
        (i32.const 0)
      )
      (i32.const 0x80000000)
    )
  )

  ;; CHECK:      (func $skip-added-constants-zero-a (result i32)
  ;; CHECK-NEXT:  (i32.ge_s
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $skip-added-constants-zero-a (result i32)
    ;; A zero in the last constant means we should not optimize.
    (i32.ge_s
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 1)
        )
        (i32.const 0x80000000)
      )
      (i32.const 0)
    )
  )

  ;; CHECK:      (func $skip-added-constants-zero-b (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.add
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 1)
  ;; CHECK-NEXT: )
  (func $skip-added-constants-zero-b (result i32)
    ;; Parallel case to the above, with a zero in the added constant, but we
    ;; do optimize the outer i32.ge_u away.
    (i32.ge_u
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 1)
        )
        (i32.const 1)
      )
      (i32.const 0)
    )
  )

  ;; CHECK:      (func $skip-added-constants-negative (result i32)
  ;; CHECK-NEXT:  (i32.ge_s
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const -20)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $skip-added-constants-negative (result i32)
    ;; Reasonable negative constants can be optimized. But the add is
    ;; canoncalized into a sub, and atm we do not optimize such added constants.
    (i32.ge_s
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 1)
        )
        (i32.const -10)
      )
      (i32.const -20)
    )
  )

  ;; CHECK:      (func $skip-added-constants-negative-flip (result i32)
  ;; CHECK-NEXT:  (i32.ge_s
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 20)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const -10)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $skip-added-constants-negative-flip (result i32)
    ;; As above, but flipped. The add is canoncalized into a sub, and atm we do
    ;; not optimize such added constants.
    (i32.ge_s
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 1)
        )
        (i32.const -20)
      )
      (i32.const -10)
    )
  )

  ;; CHECK:      (func $skip-added-constants-mix (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (i32.load
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 1)
  ;; CHECK-NEXT: )
  (func $skip-added-constants-mix (result i32)
    ;; A case of one negative and one positive constant. Here we have
    ;; [max 16 bits] + 10 >=_s -20 which is always true.
    (i32.ge_s
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 16)
        )
        (i32.const 10)
      )
      (i32.const -20)
    )
  )

  ;; CHECK:      (func $skip-added-constants-mix-flip (result i32)
  ;; CHECK-NEXT:  (i32.ge_s
  ;; CHECK-NEXT:   (i32.sub
  ;; CHECK-NEXT:    (i32.shr_u
  ;; CHECK-NEXT:     (i32.load
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.const 16)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 20)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i32.const 10)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $skip-added-constants-mix-flip (result i32)
    ;; As above, but with sign flipped. The add is canoncalized into a sub, and
    ;; atm we do not optimize such added constants.
    (i32.ge_s
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 16)
        )
        (i32.const -20)
      )
      (i32.const 10)
    )
  )

  ;; CHECK:      (func $skip-added-constants-mix-flip-other (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.shr_u
  ;; CHECK-NEXT:    (i32.load
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.const 16)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 1)
  ;; CHECK-NEXT: )
  (func $skip-added-constants-mix-flip-other (result i32)
    ;; As above, but with the sign the same while the absolute values are
    ;; flipped. Here we have [max 16 bits] + 20 >=_s -10 which is always true.
    (i32.ge_s
      (i32.add
        (i32.shr_u
          (i32.load
            (i32.const 0)
          )
          (i32.const 16)
        )
        (i32.const 20)
      )
      (i32.const -10)
    )
  )

  ;; CHECK:      (func $skip-added-constants-signed-overflow (result i32)
  ;; CHECK-NEXT:  (i64.lt_s
  ;; CHECK-NEXT:   (i64.add
  ;; CHECK-NEXT:    (i64.or
  ;; CHECK-NEXT:     (i64.const 0)
  ;; CHECK-NEXT:     (i64.const 9223372036854775807)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (i64.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $skip-added-constants-signed-overflow (result i32)
    ;; Adding 1 to 0x7fffffffffffffff turns it into 0x8000000000000000, which
    ;; when signed is -1, that is, we overflow. So we can't subtract 1 from the
    ;; gt_s arms.
    ;; (The i64.or is needed to avoid other opts.)
    (i64.gt_s
      (i64.const 2)
      (i64.add
        (i64.const 1)
        (i64.or
          (i64.const 0)
          (i64.const 0x7fffffffffffffff)
        )
      )
    )
  )

  ;; CHECK:      (func $added-constants-unsigned (result i32)
  ;; CHECK-NEXT:  (i64.eqz
  ;; CHECK-NEXT:   (i64.or
  ;; CHECK-NEXT:    (i64.const 0)
  ;; CHECK-NEXT:    (i64.const 9223372036854775807)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $added-constants-unsigned (result i32)
    ;; As above, but unsigned. This is ok, as it can't overflow as unsigned.
    (i64.gt_u
      (i64.const 2)
      (i64.add
        (i64.const 1)
        (i64.or
          (i64.const 0)
          (i64.const 0x7fffffffffffffff)
        )
      )
    )
  )

  ;; CHECK:      (func $added-constants-remaining-constant (result i32)
  ;; CHECK-NEXT:  (i32.const 32)
  ;; CHECK-NEXT: )
  (func $added-constants-remaining-constant (result i32)
    ;; optimizeAddedConstants will simplify this step by step and end up with
    ;; both an accumulated value and a constant to add it to (the 1 at the
    ;; bottom). We should not hit an assert here and return the proper value,
    ;; 32. (This is tricky for optimizeAddedConstants because of the shift that
    ;; does nothing, which it correctly ignores, but it also leads to having
    ;; something to add at the very end of the process.)
    (i32.sub              ;; This subtracts 33 by 1 to get 32.
      (i32.add            ;; This adds 1 to 32 to get 33.
        (i32.shl          ;; This shift by 32 does nothing, so it is 1.
         (i32.const 1)
         (i32.add         ;; This is 32
           (i32.const 0)
           (i32.const 32)
         )
       )
       (i32.const 32)
      )
      (i32.const 1)
    )
  )
  ;; CHECK:      (func $add-op-no-overlapping-bits-corner-case (param $0 i32) (param $1 i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $add-op-no-overlapping-bits-corner-case (param $0 i32) (param $1 i64)
    ;; optimizeAndNoOverlappingBits simplifies AND operations where
    ;;  - the left value covers bits in [0, n)
    ;;  - the right operand is a constant with no bits in [0, n)
    ;; Result is simplified to zero.
    ;; No bit overlaps, so we optimize.
    (drop
      (i32.and
        (i32.const 1)
        (i32.const 2)
      )
    )
    (drop
      (i64.and
        (i64.const 1)
        (i64.const 2)
      )
    )
    (drop
      (i64.and
        (i64.const 0x7fffffff)
        (i64.const 0x80000000)
      )
    )
    ;; We know something (but not constant) about the bits
    ;; on the left, so we can optimize.
    (drop
      (i32.and
        (i32.and
          (local.get $0)
          (i32.const 0xff)
        )
        (i32.const 0xff00)
      )
    )
    (drop
      (i64.and
        (i64.and
          (local.get $1)
          (i64.const 0xff)
        )
        (i64.const 0xff00)
      )
    )
  )
  ;; CHECK:      (func $add-op-overlapping-bits-corner-case
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const 2147483647)
  ;; CHECK-NEXT:    (i32.const -2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (i64.const 2147483647)
  ;; CHECK-NEXT:    (i64.const 2147483649)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $add-op-overlapping-bits-corner-case
    ;; One bit overlaps, so we cannot optimize.
    (drop
      (i32.and
        (i32.const 0x7fffffff)
        (i32.const 0x80000001)
      )
    )
    (drop
      (i64.and
        (i64.const 0x7fffffff)
        (i64.const 0x80000001)
      )
    )
  )
  ;; CHECK:      (func $add-op-no-overlapping-skipped
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const 2)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (i64.const 2)
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (i64.const 2147483648)
  ;; CHECK-NEXT:    (i64.const 2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $add-op-no-overlapping-skipped
    ;; Both-constant cases which do not meet the condition (mask of left has no
    ;; overlap with right) is left for Precompute.
    (drop
      (i32.and
        (i32.const 2)
        (i32.const 1)
      )
    )
    (drop
      (i64.and
        (i64.const 2)
        (i64.const 1)
      )
    )
    (drop
      (i64.and
        (i64.const 0x80000000)
        (i64.const 0x7fffffff)
      )
    )
  )
  ;; CHECK:      (func $add-op-unknown-useful (param $0 i32) (param $1 i64)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (i32.const -2147483648)
  ;; CHECK-NEXT:    (i32.const 2147483647)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (i64.const -9223372036854775808)
  ;; CHECK-NEXT:    (i64.const 9223372036854775807)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i64.and
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:    (i64.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $add-op-unknown-useful (param $0 i32) (param $1 i64)
    ;; We know nothing useful about the bits on the left, so we cannot optimize.
    (drop
      (i32.and
        (i32.const 0x80000000)
        (i32.const 0x7fffffff)
      )
    )
    (drop
      (i64.and
        (i64.const 0x8000000000000000)
        (i64.const 0x7fffffffffffffff)
      )
    )
    (drop
      (i32.and
        (local.get $0)
        (i32.const 1)
      )
    )
    (drop
      (i64.and
        (local.get $1)
        (i64.const 1)
      )
    )
  )

  ;; CHECK:      (func $local-unreachable-size-matters
  ;; CHECK-NEXT:  (local $temp i32)
  ;; CHECK-NEXT:  (local.set $temp
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.and
  ;; CHECK-NEXT:    (local.get $temp)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.tee $temp
  ;; CHECK-NEXT:   (unreachable)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $local-unreachable-size-matters
    ;; The local is written 1, then later down we have an unreachable. That
    ;; should not confuse us as to the max bits in the local. This is a test for
    ;; a bug where any local with an unreachable set got assigned 64 bits, which
    ;; is wrong in this case and led to a misoptimization of the |and|. We
    ;; should not optimize it away to a 0 (we could in theory optimize it to a
    ;; 1, but this pass does not infer locals that precisely).
    (local $temp i32)
    (local.set $temp
      (i32.const 1)
    )
    (drop
      (i32.and
        (local.get $temp)
        (i32.const 1)
      )
    )
    (local.tee $temp
      (unreachable)
    )
  )
)
