Skip to content

Commit 1863c45

Browse files
committed
[ReorderFunctions] Count ref.func uses in bodies and globals
ReorderFunctions ordered functions using calls, plus exports, start and element segments. It did not count ref.func, so a function that is only used through a reference could be sorted as if it were unused. Count ref.func in function bodies, and in global initializers, as well. The size effect is small, but the counts now match how functions are actually used.
1 parent b71b29e commit 1863c45

3 files changed

Lines changed: 79 additions & 1 deletion

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Current Trunk
2222
- Reject non-natural alignment for atomic memory operations at parse time (#8962)
2323
- Note that fast-math mode can ignore the difference between negative zero and
2424
zero (like clang and gcc). (#9056)
25+
- reorder-functions now counts ref.func uses in function bodies and global
26+
initializers. (#9160)
2527

2628
v132
2729
----

‎src/passes/ReorderFunctions.cpp‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <memory>
3131

3232
#include <ir/element-utils.h>
33+
#include <ir/find_all.h>
3334
#include <pass.h>
3435
#include <wasm.h>
3536

@@ -54,6 +55,12 @@ struct CallCountScanner : public WalkerPass<PostWalker<CallCountScanner>> {
5455
(*counts)[curr->target]++;
5556
}
5657

58+
void visitRefFunc(RefFunc* curr) {
59+
// can't add a new element in parallel
60+
assert(counts->count(curr->func) > 0);
61+
(*counts)[curr->func]++;
62+
}
63+
5764
private:
5865
NameCountMap* counts;
5966
};
@@ -82,7 +89,16 @@ struct ReorderFunctions : public Pass {
8289
}
8390
ElementUtils::iterAllElementFunctionNames(
8491
module, [&](Name name) { counts[name]++; });
85-
// TODO: count all RefFunc as well
92+
// find counts on ref.funcs in globals (those in element segments are
93+
// counted above, and those in functions by the scanner)
94+
for (auto& global : module->globals) {
95+
if (!global->init) {
96+
continue;
97+
}
98+
for (auto* refFunc : FindAll<RefFunc>(global->init).list) {
99+
counts[refFunc->func]++;
100+
}
101+
}
86102
// TODO: count the declaration section as well, which adds another mention
87103
// sort
88104
std::sort(module->functions.begin(),
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
;; RUN: foreach %s %t wasm-opt --all-features --reorder-functions -S -o - | filecheck %s
3+
4+
;; Check that ref.func references count towards a function's usage, both in
5+
;; function bodies and in global initializers. The expected order is $c (two
6+
;; ref.func uses and a call), $a (one ref.func use in a function and one in a
7+
;; global), then $b (a single call).
8+
9+
(module
10+
;; CHECK: (type $0 (func (result i32)))
11+
12+
;; CHECK: (global $g funcref (ref.func $a))
13+
14+
;; CHECK: (elem declare func $a $c)
15+
16+
;; CHECK: (func $c (type $0) (result i32)
17+
;; CHECK-NEXT: (i32.const 3)
18+
;; CHECK-NEXT: )
19+
20+
;; CHECK: (func $a (type $0) (result i32)
21+
;; CHECK-NEXT: (i32.const 1)
22+
;; CHECK-NEXT: )
23+
(func $a (result i32)
24+
(i32.const 1)
25+
)
26+
;; CHECK: (func $b (type $0) (result i32)
27+
;; CHECK-NEXT: (i32.const 2)
28+
;; CHECK-NEXT: )
29+
(func $b (result i32)
30+
(i32.const 2)
31+
)
32+
(func $c (result i32)
33+
(i32.const 3)
34+
)
35+
(global $g funcref
36+
(ref.func $a)
37+
)
38+
;; CHECK: (func $use (type $0) (result i32)
39+
;; CHECK-NEXT: (drop
40+
;; CHECK-NEXT: (ref.func $a)
41+
;; CHECK-NEXT: )
42+
;; CHECK-NEXT: (drop
43+
;; CHECK-NEXT: (ref.func $c)
44+
;; CHECK-NEXT: )
45+
;; CHECK-NEXT: (drop
46+
;; CHECK-NEXT: (ref.func $c)
47+
;; CHECK-NEXT: )
48+
;; CHECK-NEXT: (drop
49+
;; CHECK-NEXT: (call $c)
50+
;; CHECK-NEXT: )
51+
;; CHECK-NEXT: (call $b)
52+
;; CHECK-NEXT: )
53+
(func $use (result i32)
54+
(drop (ref.func $a))
55+
(drop (ref.func $c))
56+
(drop (ref.func $c))
57+
(drop (call $c))
58+
(call $b)
59+
)
60+
)

0 commit comments

Comments
 (0)