Skip to content

Commit d81f5bb

Browse files
authored
MergeSimilarFunctions: Do a return_call when possible (#7350)
This patch makes MergeSimilarFunctions do a return_call when the module has tail-call enabled. This is not merely an optimization, but is crucial for correctness when optimizing wasm modules produced by GHC that relies on tail-call to do control flow transfers. Previously, -Oz would break tail-call enabled modules by making the control stack grow where it shouldn't.
1 parent bc47696 commit d81f5bb

File tree

3 files changed

+18
-11
lines changed

3 files changed

+18
-11
lines changed

src/passes/MergeSimilarFunctions.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ struct EquivalentClass {
165165
Function* target,
166166
Function* shared,
167167
const std::vector<ParamInfo>& params,
168-
const std::vector<Expression*>& extraArgs);
168+
const std::vector<Expression*>& extraArgs,
169+
bool isReturn);
169170

170171
bool deriveParams(Module* module,
171172
std::vector<ParamInfo>& params,
@@ -480,7 +481,12 @@ void EquivalentClass::merge(Module* module,
480481
for (auto& param : params) {
481482
extraArgs.push_back(param.lowerToExpression(builder, module, i));
482483
}
483-
replaceWithThunk(builder, func, sharedFn, params, extraArgs);
484+
replaceWithThunk(builder,
485+
func,
486+
sharedFn,
487+
params,
488+
extraArgs,
489+
module->features.hasTailCall());
484490
}
485491
return;
486492
}
@@ -617,7 +623,8 @@ EquivalentClass::replaceWithThunk(Builder& builder,
617623
Function* target,
618624
Function* shared,
619625
const std::vector<ParamInfo>& params,
620-
const std::vector<Expression*>& extraArgs) {
626+
const std::vector<Expression*>& extraArgs,
627+
bool isReturn) {
621628
std::vector<Expression*> callOperands;
622629
Type targetParams = target->getParams();
623630
for (Index i = 0; i < targetParams.size(); i++) {
@@ -628,8 +635,8 @@ EquivalentClass::replaceWithThunk(Builder& builder,
628635
callOperands.push_back(value);
629636
}
630637

631-
// TODO: make a return_call when possible?
632-
auto ret = builder.makeCall(shared->name, callOperands, target->getResults());
638+
auto ret = builder.makeCall(
639+
shared->name, callOperands, target->getResults(), isReturn);
633640
target->vars.clear();
634641
target->body = ret;
635642
return target;

test/lit/passes/merge-similar-functions_all-features.wast

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
;; CHECK: (elem declare func $return_a $return_b)
104104

105105
;; CHECK: (func $return_call_a (type $0) (result i32)
106-
;; CHECK-NEXT: (call $byn$mgfn-shared$return_call_a
106+
;; CHECK-NEXT: (return_call $byn$mgfn-shared$return_call_a
107107
;; CHECK-NEXT: (ref.func $return_a)
108108
;; CHECK-NEXT: )
109109
;; CHECK-NEXT: )
@@ -115,7 +115,7 @@
115115
)
116116

117117
;; CHECK: (func $return_call_b (type $0) (result i32)
118-
;; CHECK-NEXT: (call $byn$mgfn-shared$return_call_a
118+
;; CHECK-NEXT: (return_call $byn$mgfn-shared$return_call_a
119119
;; CHECK-NEXT: (ref.func $return_b)
120120
;; CHECK-NEXT: )
121121
;; CHECK-NEXT: )

test/lit/passes/merge-similar-functions_types.wast

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
;; CHECK: (elem declare func $2 $3)
1818

1919
;; CHECK: (func $0 (type $type$0)
20-
;; CHECK-NEXT: (call $byn$mgfn-shared$0
20+
;; CHECK-NEXT: (return_call $byn$mgfn-shared$0
2121
;; CHECK-NEXT: (ref.func $2)
2222
;; CHECK-NEXT: )
2323
;; CHECK-NEXT: )
@@ -41,7 +41,7 @@
4141
(nop)
4242
)
4343
;; CHECK: (func $1 (type $type$0)
44-
;; CHECK-NEXT: (call $byn$mgfn-shared$0
44+
;; CHECK-NEXT: (return_call $byn$mgfn-shared$0
4545
;; CHECK-NEXT: (ref.func $3)
4646
;; CHECK-NEXT: )
4747
;; CHECK-NEXT: )
@@ -126,7 +126,7 @@
126126
;; CHECK: (elem declare func $2 $3)
127127

128128
;; CHECK: (func $0 (type $type$0)
129-
;; CHECK-NEXT: (call $byn$mgfn-shared$0
129+
;; CHECK-NEXT: (return_call $byn$mgfn-shared$0
130130
;; CHECK-NEXT: (ref.func $2)
131131
;; CHECK-NEXT: )
132132
;; CHECK-NEXT: )
@@ -150,7 +150,7 @@
150150
(nop)
151151
)
152152
;; CHECK: (func $1 (type $type$0)
153-
;; CHECK-NEXT: (call $byn$mgfn-shared$0
153+
;; CHECK-NEXT: (return_call $byn$mgfn-shared$0
154154
;; CHECK-NEXT: (ref.func $3)
155155
;; CHECK-NEXT: )
156156
;; CHECK-NEXT: )

0 commit comments

Comments
 (0)