Skip to content

Commit 981e052

Browse files
committed
use getImmediateFallthrough
1 parent 5dd3bca commit 981e052

File tree

1 file changed

+41
-33
lines changed

1 file changed

+41
-33
lines changed

src/passes/TailCall.cpp

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,63 @@
11

2+
#include "ir/properties.h"
23
#include "pass.h"
34
#include "wasm-traversal.h"
45
#include "wasm.h"
6+
#include <stack>
57
#include <vector>
68

79
namespace wasm {
810

911
namespace {
1012

1113
struct Finder : TryDepthWalker<Finder> {
14+
explicit Finder(const PassOptions& passOptions)
15+
: TryDepthWalker<Finder>(), passOptions(passOptions) {}
16+
const PassOptions& passOptions;
1217
std::vector<Call*> tailCalls;
1318
std::vector<CallIndirect*> tailCallIndirects;
14-
void visitFunction(Function* curr) { checkTailCall(curr->body); }
15-
void visitReturn(Return* curr) { checkTailCall(curr->value); }
16-
17-
private:
18-
void checkTailCall(Expression* expr) {
19-
if (expr == nullptr) {
19+
void visitFunction(Function* curr) {
20+
if (passOptions.shrinkLevel > 0 && passOptions.optimizeLevel == 0) {
21+
// When we more force on the binary size, add return_call will increase
22+
// the code size.
2023
return;
2124
}
25+
checkTailCall(curr->body);
26+
}
27+
void visitReturn(Return* curr) {
2228
if (tryDepth > 0) {
23-
// We are in a try block, so we cannot optimize tail calls.
24-
return;
25-
}
26-
if (auto* call = expr->dynCast<Call>()) {
27-
if (!call->isReturn && call->type == getFunction()->getResults()) {
28-
tailCalls.push_back(call);
29-
}
30-
return;
31-
}
32-
if (auto* call = expr->dynCast<CallIndirect>()) {
33-
if (!call->isReturn && call->type == getFunction()->getResults()) {
34-
tailCallIndirects.push_back(call);
35-
}
36-
return;
37-
}
38-
if (auto* block = expr->dynCast<Block>()) {
39-
return checkTailCall(block->list);
40-
}
41-
if (auto* ifElse = expr->dynCast<If>()) {
42-
checkTailCall(ifElse->ifTrue);
43-
checkTailCall(ifElse->ifFalse);
29+
// (return (call ...)) is not equal to (return_call ...) in try block
4430
return;
4531
}
32+
checkTailCall(curr->value);
4633
}
47-
void checkTailCall(ExpressionList const& exprs) {
48-
if (exprs.empty()) {
49-
return;
34+
35+
private:
36+
void checkTailCall(Expression* const curr) {
37+
std::stack<Expression*> workList{};
38+
workList.push(curr);
39+
while (!workList.empty()) {
40+
Expression* const target = workList.top();
41+
workList.pop();
42+
if (auto* call = target->dynCast<Call>()) {
43+
if (!call->isReturn && call->type == getFunction()->getResults()) {
44+
tailCalls.push_back(call);
45+
}
46+
} else if (auto* call = target->dynCast<CallIndirect>()) {
47+
if (!call->isReturn && call->type == getFunction()->getResults()) {
48+
tailCallIndirects.push_back(call);
49+
}
50+
} else if (auto* ifElse = target->dynCast<If>()) {
51+
workList.push(ifElse->ifTrue);
52+
workList.push(ifElse->ifFalse);
53+
} else {
54+
Expression* const next = Properties::getImmediateFallthrough(
55+
target, passOptions, *getModule());
56+
if (next != target) {
57+
workList.push(next);
58+
}
59+
}
5060
}
51-
checkTailCall(exprs.back());
52-
return;
5361
}
5462
};
5563

@@ -64,7 +72,7 @@ struct TailCallOptimizer : public Pass {
6472
if (!module->features.hasTailCall()) {
6573
return;
6674
}
67-
Finder finder{};
75+
Finder finder{getPassOptions()};
6876
finder.walkFunctionInModule(function, module);
6977
for (Call* call : finder.tailCalls) {
7078
if (!call->isReturn) {

0 commit comments

Comments
 (0)