Skip to content

Commit c25a2e4

Browse files
authored
[Compilation Hints] Add binary format support for inline hints (#7596)
1 parent a150177 commit c25a2e4

File tree

4 files changed

+174
-5
lines changed

4 files changed

+174
-5
lines changed

src/wasm-binary.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,7 @@ class WasmBinaryWriter {
14111411
std::optional<BufferWithRandomAccess> writeCodeAnnotations();
14121412

14131413
std::optional<BufferWithRandomAccess> getBranchHintsBuffer();
1414+
std::optional<BufferWithRandomAccess> getInlineHintsBuffer();
14141415

14151416
// helpers
14161417
void writeInlineString(std::string_view name);
@@ -1692,6 +1693,11 @@ class WasmBinaryReader {
16921693
size_t branchHintsLen = 0;
16931694
void readBranchHints(size_t payloadLen);
16941695

1696+
// Like branch hints, we note where the section is to read it later.
1697+
size_t inlineHintsPos = 0;
1698+
size_t inlineHintsLen = 0;
1699+
void readInlineHints(size_t payloadLen);
1700+
16951701
Index readMemoryAccess(Address& alignment, Address& offset);
16961702
std::tuple<Name, Address, Address> getMemarg();
16971703
MemoryOrder getMemoryOrder(bool isRMW = false);

src/wasm/wasm-binary.cpp

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,7 @@ std::optional<BufferWithRandomAccess> WasmBinaryWriter::writeCodeAnnotations() {
15641564
};
15651565

15661566
append(getBranchHintsBuffer());
1567+
append(getInlineHintsBuffer());
15671568
return ret;
15681569
}
15691570

@@ -1683,6 +1684,28 @@ std::optional<BufferWithRandomAccess> WasmBinaryWriter::getBranchHintsBuffer() {
16831684
});
16841685
}
16851686

1687+
std::optional<BufferWithRandomAccess> WasmBinaryWriter::getInlineHintsBuffer() {
1688+
return writeExpressionHints(
1689+
Annotations::InlineHint,
1690+
[](const Function::CodeAnnotation& annotation) {
1691+
return annotation.inline_;
1692+
},
1693+
[](const Function::CodeAnnotation& annotation,
1694+
BufferWithRandomAccess& buffer) {
1695+
// Hint size, always 1 for now.
1696+
buffer << U32LEB(1);
1697+
1698+
// We must only emit hints that are present.
1699+
assert(annotation.inline_);
1700+
1701+
// Hint must fit in one byte.
1702+
assert(*annotation.inline_ <= 127);
1703+
1704+
// Hint contents: inline frequency count
1705+
buffer << U32LEB(*annotation.inline_);
1706+
});
1707+
}
1708+
16861709
void WasmBinaryWriter::writeData(const char* data, size_t size) {
16871710
for (size_t i = 0; i < size; i++) {
16881711
o << int8_t(data[i]);
@@ -1973,10 +1996,11 @@ void WasmBinaryReader::preScan() {
19731996
if (sectionCode == BinaryConsts::Section::Custom) {
19741997
auto sectionName = getInlineString();
19751998

1976-
if (sectionName == Annotations::BranchHint) {
1999+
if (sectionName == Annotations::BranchHint ||
2000+
sectionName == Annotations::InlineHint) {
19772001
// Code annotations require code locations.
1978-
// TODO: For Branch Hinting, we could note which functions require
1979-
// code locations, as an optimization.
2002+
// TODO: We could note which functions require code locations, as an
2003+
// optimization.
19802004
needCodeLocations = true;
19812005
} else if (DWARF && Debug::isDWARFSection(sectionName)) {
19822006
// DWARF sections contain code offsets.
@@ -2099,6 +2123,10 @@ void WasmBinaryReader::read() {
20992123
pos = branchHintsPos;
21002124
readBranchHints(branchHintsLen);
21012125
}
2126+
if (inlineHintsPos) {
2127+
pos = inlineHintsPos;
2128+
readInlineHints(inlineHintsLen);
2129+
}
21022130

21032131
validateBinary();
21042132
}
@@ -2124,6 +2152,9 @@ void WasmBinaryReader::readCustomSection(size_t payloadLen) {
21242152
// Only note the position and length, we read this later.
21252153
branchHintsPos = pos;
21262154
branchHintsLen = payloadLen;
2155+
} else if (sectionName == Annotations::InlineHint) {
2156+
inlineHintsPos = pos;
2157+
inlineHintsLen = payloadLen;
21272158
} else {
21282159
// an unfamiliar custom section
21292160
if (sectionName.equals(BinaryConsts::CustomSections::Linking)) {
@@ -5305,11 +5336,28 @@ void WasmBinaryReader::readBranchHints(size_t payloadLen) {
53055336
throwError("bad BranchHint value");
53065337
}
53075338

5308-
// Apply the valid hint.
53095339
annotation.branchLikely = likely;
53105340
});
53115341
}
53125342

5343+
void WasmBinaryReader::readInlineHints(size_t payloadLen) {
5344+
readExpressionHints(Annotations::InlineHint,
5345+
payloadLen,
5346+
[&](Function::CodeAnnotation& annotation) {
5347+
auto size = getU32LEB();
5348+
if (size != 1) {
5349+
throwError("bad InlineHint size");
5350+
}
5351+
5352+
uint8_t inline_ = getInt8();
5353+
if (inline_ > 127) {
5354+
throwError("bad InlineHint value");
5355+
}
5356+
5357+
annotation.inline_ = inline_;
5358+
});
5359+
}
5360+
53135361
Index WasmBinaryReader::readMemoryAccess(Address& alignment, Address& offset) {
53145362
auto rawAlignment = getU32LEB();
53155363
bool hasMemIdx = false;

test/lit/compilation-hints.wast renamed to test/lit/inline-hints.wast

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
;; RUN: wasm-opt -all %s -S -o - | filecheck %s
44

5-
;; TODO: wasm-opt -all --roundtrip %s -S -o - | filecheck %s --check-prefix=RTRIP
5+
;; RUN: wasm-opt -all --roundtrip %s -S -o - | filecheck %s --check-prefix=RTRIP
66

77
(module
88
;; CHECK: (type $func (func))
9+
;; RTRIP: (type $func (func))
910
(type $func (func))
1011

1112
;; CHECK: (table $table 10 20 funcref)
13+
;; RTRIP: (table $table 10 20 funcref)
1214
(table $table 10 20 funcref)
1315

1416
;; CHECK: (elem declare func $func)
@@ -24,6 +26,19 @@
2426
;; CHECK-NEXT: (call $func)
2527
;; CHECK-NEXT: (call $func)
2628
;; CHECK-NEXT: )
29+
;; RTRIP: (elem declare func $func)
30+
31+
;; RTRIP: (func $func (type $func)
32+
;; RTRIP-NEXT: (@metadata.code.inline "\00")
33+
;; RTRIP-NEXT: (call $func)
34+
;; RTRIP-NEXT: (@metadata.code.inline "\01")
35+
;; RTRIP-NEXT: (call $func)
36+
;; RTRIP-NEXT: (@metadata.code.inline "\7e")
37+
;; RTRIP-NEXT: (call $func)
38+
;; RTRIP-NEXT: (@metadata.code.inline "\7f")
39+
;; RTRIP-NEXT: (call $func)
40+
;; RTRIP-NEXT: (call $func)
41+
;; RTRIP-NEXT: )
2742
(func $func
2843
(@metadata.code.inline "\00")
2944
(call $func)
@@ -47,6 +62,16 @@
4762
;; CHECK-NEXT: (ref.func $func)
4863
;; CHECK-NEXT: )
4964
;; CHECK-NEXT: )
65+
;; RTRIP: (func $other-calls (type $func)
66+
;; RTRIP-NEXT: (@metadata.code.inline "\12")
67+
;; RTRIP-NEXT: (call_indirect $table (type $func)
68+
;; RTRIP-NEXT: (i32.const 0)
69+
;; RTRIP-NEXT: )
70+
;; RTRIP-NEXT: (@metadata.code.inline "\34")
71+
;; RTRIP-NEXT: (call_ref $func
72+
;; RTRIP-NEXT: (ref.func $func)
73+
;; RTRIP-NEXT: )
74+
;; RTRIP-NEXT: )
5075
(func $other-calls
5176
(@metadata.code.inline "\12")
5277
(call_indirect (type $func)

test/lit/multi-hints.wast

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; RUN: wasm-opt -all %s -S -o - | filecheck %s
4+
5+
;; RUN: wasm-opt -all --roundtrip %s -S -o - | filecheck %s --check-prefix=RTRIP
6+
7+
;; Check that separate code annotations do not interfere with each other, even
8+
;; in the same function.
9+
(module
10+
;; CHECK: (type $0 (func (param i32)))
11+
12+
;; CHECK: (type $func (func))
13+
;; RTRIP: (type $0 (func (param i32)))
14+
15+
;; RTRIP: (type $func (func))
16+
(type $func (func))
17+
18+
;; CHECK: (table $table 10 20 funcref)
19+
;; RTRIP: (table $table 10 20 funcref)
20+
(table $table 10 20 funcref)
21+
22+
;; CHECK: (func $inline (type $func)
23+
;; CHECK-NEXT: (@metadata.code.inline "\00")
24+
;; CHECK-NEXT: (call $inline)
25+
;; CHECK-NEXT: )
26+
;; RTRIP: (func $inline (type $func)
27+
;; RTRIP-NEXT: (@metadata.code.inline "\00")
28+
;; RTRIP-NEXT: (call $inline)
29+
;; RTRIP-NEXT: )
30+
(func $inline
31+
(@metadata.code.inline "\00")
32+
(call $inline)
33+
)
34+
35+
;; CHECK: (func $branch (type $0) (param $x i32)
36+
;; CHECK-NEXT: (block $out
37+
;; CHECK-NEXT: (@metadata.code.branch_hint "\01")
38+
;; CHECK-NEXT: (br_if $out
39+
;; CHECK-NEXT: (local.get $x)
40+
;; CHECK-NEXT: )
41+
;; CHECK-NEXT: )
42+
;; CHECK-NEXT: )
43+
;; RTRIP: (func $branch (type $0) (param $x i32)
44+
;; RTRIP-NEXT: (block $block
45+
;; RTRIP-NEXT: (@metadata.code.branch_hint "\01")
46+
;; RTRIP-NEXT: (br_if $block
47+
;; RTRIP-NEXT: (local.get $x)
48+
;; RTRIP-NEXT: )
49+
;; RTRIP-NEXT: )
50+
;; RTRIP-NEXT: )
51+
(func $branch (param $x i32)
52+
(block $out
53+
(@metadata.code.branch_hint "\01")
54+
(br_if $out
55+
(local.get $x)
56+
)
57+
)
58+
)
59+
60+
;; CHECK: (func $both (type $0) (param $x i32)
61+
;; CHECK-NEXT: (block $out
62+
;; CHECK-NEXT: (@metadata.code.inline "\02")
63+
;; CHECK-NEXT: (call $inline)
64+
;; CHECK-NEXT: (@metadata.code.branch_hint "\00")
65+
;; CHECK-NEXT: (br_if $out
66+
;; CHECK-NEXT: (local.get $x)
67+
;; CHECK-NEXT: )
68+
;; CHECK-NEXT: )
69+
;; CHECK-NEXT: )
70+
;; RTRIP: (func $both (type $0) (param $x i32)
71+
;; RTRIP-NEXT: (block $block
72+
;; RTRIP-NEXT: (@metadata.code.inline "\02")
73+
;; RTRIP-NEXT: (call $inline)
74+
;; RTRIP-NEXT: (@metadata.code.branch_hint "\00")
75+
;; RTRIP-NEXT: (br_if $block
76+
;; RTRIP-NEXT: (local.get $x)
77+
;; RTRIP-NEXT: )
78+
;; RTRIP-NEXT: )
79+
;; RTRIP-NEXT: )
80+
(func $both (param $x i32)
81+
(block $out
82+
(@metadata.code.inline "\02")
83+
(call $inline)
84+
(@metadata.code.branch_hint "\00")
85+
(br_if $out
86+
(local.get $x)
87+
)
88+
)
89+
)
90+
)

0 commit comments

Comments
 (0)