Skip to content

Commit 3ef8d19

Browse files
authored
Look at fallthrough when deleting branch hints (#8630)
The DeleteBranchHints pass looks at the conditions of branches to find the ID operands of logging calls to determine which branch hints to remove. It previously expected the logging call to be the condition of the branch, but in the presence of stacky code it is possible for the parser to create a block around the logging call. Handle this pattern by looking for the logging call at the condition's fallthrough value.
1 parent 604f547 commit 3ef8d19

File tree

2 files changed

+60
-20
lines changed

2 files changed

+60
-20
lines changed

src/passes/InstrumentBranchHints.cpp

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898

9999
#include "ir/effects.h"
100100
#include "ir/names.h"
101+
#include "ir/properties.h"
101102
#include "ir/utils.h"
102103
#include "pass.h"
103104
#include "support/string.h"
@@ -231,18 +232,6 @@ struct InstrumentationProcessor : public WalkerPass<PostWalker<Sub>> {
231232

232233
Super::doWalkModule(module);
233234
}
234-
235-
// Helpers
236-
237-
// Check if an expression's condition is instrumented, and return the
238-
// instrumentation call if so. Otherwise return null.
239-
Call* getInstrumentation(Expression* condition) {
240-
auto* call = condition->dynCast<Call>();
241-
if (!call || call->target != logBranch) {
242-
return nullptr;
243-
}
244-
return call;
245-
}
246235
};
247236

248237
struct DeleteBranchHints : public InstrumentationProcessor<DeleteBranchHints> {
@@ -251,15 +240,27 @@ struct DeleteBranchHints : public InstrumentationProcessor<DeleteBranchHints> {
251240
// The set of IDs to delete.
252241
std::unordered_set<Index> idsToDelete;
253242

243+
std::optional<uint32_t> getBranchID(Expression* condition,
244+
const PassOptions& passOptions,
245+
Module& wasm) {
246+
auto* call =
247+
Properties::getFallthrough(condition, getPassOptions(), *getModule())
248+
->dynCast<Call>();
249+
if (!call || call->target != logBranch || call->operands.size() != 3) {
250+
return std::nullopt;
251+
}
252+
auto* c = call->operands[2]->dynCast<Const>();
253+
if (!c || c->type != Type::i32) {
254+
return std::nullopt;
255+
}
256+
return c->value.geti32();
257+
}
258+
254259
template<typename T> void processCondition(T* curr) {
255-
if (auto* call = getInstrumentation(curr->condition)) {
256-
if (auto* c = call->operands[2]->template dynCast<Const>()) {
257-
auto id = c->value.geti32();
258-
if (idsToDelete.contains(id)) {
259-
// Remove the branch hint.
260-
getFunction()->codeAnnotations[curr].branchLikely = {};
261-
}
262-
}
260+
if (auto id = getBranchID(curr->condition, getPassOptions(), *getModule());
261+
id && idsToDelete.contains(*id)) {
262+
// Remove the branch hint.
263+
getFunction()->codeAnnotations[curr].branchLikely = std::nullopt;
263264
}
264265
}
265266

test/lit/passes/delete-branch-hints.wast

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
;; CHECK: (type $1 (func (param i32 i32 i32) (result i32)))
99

10+
;; CHECK: (type $2 (func (param i32) (result i32)))
11+
1012
;; CHECK: (import "fuzzing-support" "log-branch" (func $log (type $1) (param i32 i32 i32) (result i32)))
1113
(import "fuzzing-support" "log-branch" (func $log (param i32 i32 i32) (result i32)))
1214

@@ -118,4 +120,41 @@
118120
)
119121
)
120122
)
123+
124+
;; CHECK: (func $stacky (type $2) (param $c i32) (result i32)
125+
;; CHECK-NEXT: (block $l (result i32)
126+
;; CHECK-NEXT: (br_if $l
127+
;; CHECK-NEXT: (i32.const 42)
128+
;; CHECK-NEXT: (block (result i32)
129+
;; CHECK-NEXT: (nop)
130+
;; CHECK-NEXT: (call $log
131+
;; CHECK-NEXT: (local.get $c)
132+
;; CHECK-NEXT: (i32.const 1)
133+
;; CHECK-NEXT: (i32.const 10)
134+
;; CHECK-NEXT: )
135+
;; CHECK-NEXT: )
136+
;; CHECK-NEXT: )
137+
;; CHECK-NEXT: )
138+
;; CHECK-NEXT: )
139+
(func $stacky (param $c i32) (result i32)
140+
block $l (result i32)
141+
i32.const 42
142+
;; Because the parser greedily pulls previous none-typed expressions into
143+
;; block, this condition will be parsed as this:
144+
;;
145+
;; (block
146+
;; (nop)
147+
;; (call $log-branch ...))
148+
;; )
149+
;;
150+
;; We must be able to find and handle this pattern to remove the hint.
151+
nop
152+
local.get $c
153+
i32.const 1
154+
i32.const 10
155+
call $log
156+
(@metadata.code.branch_hint "\01")
157+
br_if $l
158+
end
159+
)
121160
)

0 commit comments

Comments
 (0)