Skip to content

Commit 5327619

Browse files
committed
[ReorderFunctions] Count ref.func uses
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 uses in function bodies and in module code (global initializers, element segments, table initializers). The size effect is small, but the counts now match how functions are actually used.
1 parent eacbf23 commit 5327619

2 files changed

Lines changed: 68 additions & 5 deletions

File tree

‎src/passes/ReorderFunctions.cpp‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
#include <memory>
3131

32-
#include <ir/element-utils.h>
3332
#include <pass.h>
3433
#include <wasm.h>
3534

@@ -54,6 +53,12 @@ struct CallCountScanner : public WalkerPass<PostWalker<CallCountScanner>> {
5453
(*counts)[curr->target]++;
5554
}
5655

56+
void visitRefFunc(RefFunc* curr) {
57+
// can't add a new element in parallel
58+
assert(counts->count(curr->func) > 0);
59+
(*counts)[curr->func]++;
60+
}
61+
5762
private:
5863
NameCountMap* counts;
5964
};
@@ -69,8 +74,10 @@ struct ReorderFunctions : public Pass {
6974
for (auto& func : module->functions) {
7075
counts.try_emplace(func->name, 0);
7176
}
72-
// find counts on function calls
77+
// find counts on function calls and ref.funcs in function bodies
7378
CallCountScanner(&counts).run(getPassRunner(), module);
79+
// find counts on ref.funcs in module code: globals, element segments, etc.
80+
CallCountScanner(&counts).walkModuleCode(module);
7481
// find counts on global usages
7582
if (module->start.is()) {
7683
counts[module->start]++;
@@ -80,9 +87,6 @@ struct ReorderFunctions : public Pass {
8087
counts[*curr->getInternalName()]++;
8188
}
8289
}
83-
ElementUtils::iterAllElementFunctionNames(
84-
module, [&](Name name) { counts[name]++; });
85-
// TODO: count all RefFunc as well
8690
// TODO: count the declaration section as well, which adds another mention
8791
// sort
8892
std::sort(module->functions.begin(),
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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 module code (global initializers and element
6+
;; segments). The expected order is $c, then $a, then $b.
7+
8+
(module
9+
;; CHECK: (type $0 (func (result i32)))
10+
11+
;; CHECK: (global $g funcref (ref.func $a))
12+
13+
;; CHECK: (elem declare func $a $c)
14+
15+
;; CHECK: (func $c (type $0) (result i32)
16+
;; CHECK-NEXT: (i32.const 3)
17+
;; CHECK-NEXT: )
18+
19+
;; CHECK: (func $a (type $0) (result i32)
20+
;; CHECK-NEXT: (i32.const 1)
21+
;; CHECK-NEXT: )
22+
(func $a (result i32)
23+
(i32.const 1)
24+
)
25+
;; CHECK: (func $b (type $0) (result i32)
26+
;; CHECK-NEXT: (i32.const 2)
27+
;; CHECK-NEXT: )
28+
(func $b (result i32)
29+
(i32.const 2)
30+
)
31+
(func $c (result i32)
32+
(i32.const 3)
33+
)
34+
(global $g funcref
35+
(ref.func $a)
36+
)
37+
;; CHECK: (func $use (type $0) (result i32)
38+
;; CHECK-NEXT: (drop
39+
;; CHECK-NEXT: (ref.func $a)
40+
;; CHECK-NEXT: )
41+
;; CHECK-NEXT: (drop
42+
;; CHECK-NEXT: (ref.func $c)
43+
;; CHECK-NEXT: )
44+
;; CHECK-NEXT: (drop
45+
;; CHECK-NEXT: (ref.func $c)
46+
;; CHECK-NEXT: )
47+
;; CHECK-NEXT: (drop
48+
;; CHECK-NEXT: (call $c)
49+
;; CHECK-NEXT: )
50+
;; CHECK-NEXT: (call $b)
51+
;; CHECK-NEXT: )
52+
(func $use (result i32)
53+
(drop (ref.func $a))
54+
(drop (ref.func $c))
55+
(drop (ref.func $c))
56+
(drop (call $c))
57+
(call $b)
58+
)
59+
)

0 commit comments

Comments
 (0)