;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: foreach %s %t wasm-opt -all --reorder-globals-always -S -o - | filecheck %s
;; RUN: foreach %s %t wasm-opt -all --reorder-globals-always --roundtrip -S -o - | filecheck %s

;; Also check roundtripping here, so verify we don't end up emitting invalid
;; binaries.

;; Global $b has more uses, so it should be sorted first.
(module

  ;; CHECK:      (global $b i32 (i32.const 20))

  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  (global $b i32 (i32.const 20))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $b)
    )
  )
)

;; As above, but now with global.sets. Again $b should be sorted first.
(module

  ;; CHECK:      (global $b (mut i32) (i32.const 20))

  ;; CHECK:      (global $a (mut i32) (i32.const 10))
  (global $a (mut i32) (i32.const 10))
  (global $b (mut i32) (i32.const 20))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (global.set $b
  ;; CHECK-NEXT:   (i32.const 30)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (global.set $b
  ;; CHECK-NEXT:   (i32.const 40)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $a)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (global.set $b
      (i32.const 30)
    )
    (global.set $b
      (i32.const 40)
    )
    (drop
      (global.get $a)
    )
  )
)

;; As above, but flipped so now $a has more, and should remain first.
(module
  ;; CHECK:      (global $a (mut i32) (i32.const 10))
  (global $a (mut i32) (i32.const 10))
  ;; CHECK:      (global $b (mut i32) (i32.const 20))
  (global $b (mut i32) (i32.const 20))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (global.set $a
  ;; CHECK-NEXT:   (i32.const 30)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (global.set $a
  ;; CHECK-NEXT:   (i32.const 40)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (global.set $a
      (i32.const 30)
    )
    (global.set $a
      (i32.const 40)
    )
    (drop
      (global.get $b)
    )
  )
)

;; $b has more uses, but it depends on $a and cannot be sorted before it.
(module
  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $b)
    )
  )
)

;; $c has more uses, but it depends on $b and $a and cannot be sorted before
;; them. Likewise $b cannot be before $a.
(module
  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))
  ;; CHECK:      (global $c i32 (global.get $b))
  (global $c i32 (global.get $b))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $b)
    )
    (drop
      (global.get $c)
    )
    (drop
      (global.get $c)
    )
  )
)

;; As above, but without dependencies, so now $c is first and then $b.
(module
  ;; CHECK:      (global $c i32 (i32.const 30))

  ;; CHECK:      (global $b i32 (i32.const 20))

  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  (global $b i32 (i32.const 20))
  (global $c i32 (i32.const 30))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $b)
    )
    (drop
      (global.get $c)
    )
    (drop
      (global.get $c)
    )
  )
)

;; As above, but a mixed case: $b depends on $a but $c has no dependencies, and
;; the counts are $c with the most, followed by $b, and then $a. $c can be
;; first here, but $b must follow $a.
(module
  ;; CHECK:      (global $c i32 (i32.const 30))

  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))
  (global $c i32 (i32.const 30))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    ;; ($a already has one use in the global $b)
    (drop
      (global.get $b)
    )
    (drop
      (global.get $b)
    )
    (drop
      (global.get $c)
    )
    (drop
      (global.get $c)
    )
    (drop
      (global.get $c)
    )
  )
)

;; As above, but with the counts adjusted: before we had $c, $b, $a from most to
;; least uses, and now $b, $c, $a.
;;
;; A greedy sort would do $c, $a, $b (as the first choice is between $c and $a,
;; and $c wins), but that leaves $b, the highest count, for the end. The
;; smoothed-out LEB costs (1 byte at the start, +1/128 each index later) are:
;;
;;  $c           $a               $b
;; 1 * 2  +  129/128 * 1  +  130/128 * 3  =  775/128
;;
;; The original sort is
;;
;;  $a           $b               $c
;; 1 * 1  +  129/128 * 3  +  130/128 * 2  =  775/128
;;
;; As they are equal we prefer the original order.
(module
  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))
  ;; CHECK:      (global $c i32 (i32.const 30))
  (global $c i32 (i32.const 30))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $b)
    )
    (drop
      (global.get $b)
    )
    (drop
      (global.get $b)
    )
    (drop
      (global.get $c)
    )
    (drop
      (global.get $c)
    )
  )
)

;; As above, but with the counts adjusted to $b, $a, $c.
(module
  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))
  ;; CHECK:      (global $c i32 (i32.const 30))
  (global $c i32 (i32.const 30))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $b)
    )
    (drop
      (global.get $b)
    )
  )
)

;; As above, but with the counts adjusted to $c, $a, $b.
(module
  ;; CHECK:      (global $c i32 (i32.const 30))

  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))
  (global $c i32 (i32.const 30))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $c)
    )
    (drop
      (global.get $c)
    )
  )
)

;; As above, but with the counts adjusted to $a, $b, $c.
(module
  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))
  ;; CHECK:      (global $c i32 (i32.const 30))
  (global $c i32 (i32.const 30))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $a)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $a)
    )
    (drop
      (global.get $b)
    )
  )
)

;; As above, but with the counts adjusted to $a, $c, $b.
(module
  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))
  ;; CHECK:      (global $c i32 (i32.const 30))

  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))
  (global $c i32 (i32.const 30))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $a)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $a)
    )
    (drop
      (global.get $c)
    )
  )
)

;; $b has more uses, but $a is an import and must remain first.
(module
  ;; CHECK:      (import "a" "b" (global $a i32))
  (import "a" "b" (global $a i32))
  ;; CHECK:      (global $b i32 (i32.const 10))
  (global $b i32 (i32.const 10))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $b)
    )
  )
)

;; As above, but with a and b's names flipped, to check that the names do not
;; matter, and we keep imports first.
(module
  ;; CHECK:      (import "a" "b" (global $b i32))
  (import "a" "b" (global $b i32))

  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $a)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    (drop
      (global.get $a)
    )
  )
)

;; Lower letters have lower counts: $a has the least, and $e has the most.
;;
;; Dependency graph (left depends on right):
;;
;;    $c - $a
;;   /
;; $e
;;   \
;;    $d - $b
;;
;; $e has the most uses, followed by $c and $d. $a and $b have a reverse
;; ordering from their dependers, so a naive topological sort will fail to
;; be optimal. There are multiple optimal orders however, including:
;;
;;   $b, $a, $c, $d, $e
;;   $b, $d, $a, $c, $e
;;
;; $b and $e must be at the edges, but there is no single way to sort the
;; others: the first sorting here puts $a before both $d (though $a has
;; lower count) while the second puts $d before $c. Our greedy algorithm
;; picks the second order here.
(module
  ;; CHECK:      (global $b i32 (i32.const 20))

  ;; CHECK:      (global $d i32 (global.get $b))

  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))

  (global $b i32 (i32.const 20))

  ;; CHECK:      (global $c i32 (global.get $a))
  (global $c i32 (global.get $a))

  (global $d i32 (global.get $b))

  ;; CHECK:      (global $e i32 (i32.add
  ;; CHECK-NEXT:  (global.get $c)
  ;; CHECK-NEXT:  (global.get $d)
  ;; CHECK-NEXT: ))
  (global $e i32 (i32.add
    (global.get $c)
    (global.get $d)
  ))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $d)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $d)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $d)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    ;; $a, $b, $c, $d each have one already from the globals. Add more so that
    ;; $a has the least, and $e has the most
    (drop (global.get $e))
    (drop (global.get $e))
    (drop (global.get $e))
    (drop (global.get $e))
    (drop (global.get $e))

    (drop (global.get $d))
    (drop (global.get $d))
    (drop (global.get $d))

    (drop (global.get $c))
    (drop (global.get $c))

    (drop (global.get $b))
  )
)

;; As above, but add a direct dep from $d to $a:
;;
;;    $c - $a
;;   /    /
;; $e    / <-- this was added
;;   \  /
;;    $d - $b
;;
;; This forces $a to appear before $d: the order goes from before, which was
;;   $b, $d, $a, $c, $e
;; to
;;   $b, $a, $d, $c, $e
(module
  ;; CHECK:      (global $b i32 (i32.const 20))

  ;; CHECK:      (global $a i32 (i32.const 10))
  (global $a i32 (i32.const 10))

  (global $b i32 (i32.const 20))

  ;; CHECK:      (global $d i32 (i32.add
  ;; CHECK-NEXT:  (global.get $b)
  ;; CHECK-NEXT:  (global.get $a)
  ;; CHECK-NEXT: ))

  ;; CHECK:      (global $c i32 (global.get $a))
  (global $c i32 (global.get $a))

  (global $d i32 (i32.add
    (global.get $b)
    (global.get $a) ;; this was added
  ))

  ;; CHECK:      (global $e i32 (i32.add
  ;; CHECK-NEXT:  (global.get $c)
  ;; CHECK-NEXT:  (global.get $d)
  ;; CHECK-NEXT: ))
  (global $e i32 (i32.add
    (global.get $c)
    (global.get $d)
  ))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $e)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $d)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $d)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $d)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $d)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $b)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    ;; $b, $c, $d each have one already from the globals, and $a has two. Add
    ;; more so that $a has the least, and $e has the most.
    (drop (global.get $e))
    (drop (global.get $e))
    (drop (global.get $e))
    (drop (global.get $e))
    (drop (global.get $e))
    (drop (global.get $e))

    (drop (global.get $d))
    (drop (global.get $d))
    (drop (global.get $d))
    (drop (global.get $d))

    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))

    (drop (global.get $b))
    (drop (global.get $b))
  )
)

;; A situation where the simple greedy sort fails to be optimal. We have a
;; chain and one more independent global
;;
;;  a <- b <- c
;;
;;  other
;;
;; The candidates for the first global emitted are a and other, as they have no
;; dependencies, and other has a higher count so greedy sorting would pick it.
;; however, c has the highest count by far, so it is worth being less greedy and
;; doing a just in order to be able to do b and then c, and to emit other last.
;; In other words, the original order is best.
(module
  ;; CHECK:      (global $a i32 (i32.const 0))
  (global $a i32 (i32.const 0))
  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))
  ;; CHECK:      (global $c i32 (global.get $b))
  (global $c i32 (global.get $b))

  ;; CHECK:      (global $other i32 (i32.const 1))
  (global $other i32 (i32.const 1))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $other)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $other)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    ;; Ten uses for $c, far more than all the rest combined.
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))

    ;; Two uses for other, which is more than $a's single use.
    (drop (global.get $other))
    (drop (global.get $other))
  )
)

;; As above, but with the original order a little different. This is again a
;; case where the greedy sort is unoptimal (see above), but now also the
;; original sort is unoptimal as well, and instead we use the "sum" sort, which
;; counts the sum of the uses of a global and all the things it depends on and
;; uses that as the count for that global (which in effect means that we take
;; into consideration not only its own size but the entire size that it may
;; unlock, which happens to work well here).
;;
;; The only change in the input compared to the previous test is that $other
;; was moved up to between $b and $c. Sum sort works well here because the
;; first comparison is $a and $other, and sum takes into account $b and $c in
;; $a's favor, so it wins. Likewise $b and $c win against $other as well, so
;; the order is $a, $b, $c, $other which is optimal here.
(module
  ;; CHECK:      (global $a i32 (i32.const 0))
  (global $a i32 (i32.const 0))
  ;; CHECK:      (global $b i32 (global.get $a))
  (global $b i32 (global.get $a))

  ;; CHECK:      (global $c i32 (global.get $b))

  ;; CHECK:      (global $other i32 (i32.const 1))
  (global $other i32 (i32.const 1))

  (global $c i32 (global.get $b))

  ;; CHECK:      (func $uses (type $0)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $c)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $other)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (global.get $other)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $uses
    ;; Ten uses for $c, far more than all the rest combined.
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))
    (drop (global.get $c))

    ;; Two uses for other, which is more than $a's single use.
    (drop (global.get $other))
    (drop (global.get $other))
  )
)

