;; 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)) ) )