Skip to content

Commit 945d348

Browse files
committed
add test
1 parent 981e052 commit 945d348

File tree

8 files changed

+292
-4
lines changed

8 files changed

+292
-4
lines changed

src/passes/TailCall.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
#include "ir/properties.h"
3+
#include "ir/utils.h"
34
#include "pass.h"
45
#include "wasm-traversal.h"
56
#include "wasm.h"
@@ -50,6 +51,14 @@ struct Finder : TryDepthWalker<Finder> {
5051
} else if (auto* ifElse = target->dynCast<If>()) {
5152
workList.push(ifElse->ifTrue);
5253
workList.push(ifElse->ifFalse);
54+
} else if (auto* tryy = target->dynCast<Try>()) {
55+
for (Expression* catchBody : tryy->catchBodies) {
56+
workList.push(catchBody);
57+
}
58+
} else if (auto* block = target->dynCast<Block>()) {
59+
if (!block->list.empty()) {
60+
workList.push(block->list.back());
61+
}
5362
} else {
5463
Expression* const next = Properties::getImmediateFallthrough(
5564
target, passOptions, *getModule());
@@ -77,15 +86,14 @@ struct TailCallOptimizer : public Pass {
7786
for (Call* call : finder.tailCalls) {
7887
if (!call->isReturn) {
7988
call->isReturn = true;
80-
call->finalize();
8189
}
8290
}
8391
for (CallIndirect* call : finder.tailCallIndirects) {
8492
if (!call->isReturn) {
8593
call->isReturn = true;
86-
call->finalize();
8794
}
8895
}
96+
ReFinalize{}.walkFunctionInModule(function, module);
8997
}
9098
};
9199

src/passes/pass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,9 @@ void PassRegistry::registerPasses() {
558558
registerPass("strip-target-features",
559559
"strip the wasm target features section",
560560
createStripTargetFeaturesPass);
561-
registerPass(
562-
"tail-call", "transform call to return call", createTailCallPass);
561+
registerPass("tail-call-optimization",
562+
"transform call to return call",
563+
createTailCallPass);
563564
registerPass("translate-to-new-eh",
564565
"deprecated; same as translate-to-exnref",
565566
createTranslateToExnrefPass);

test/lit/help/wasm-metadce.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,8 @@
530530
;; CHECK-NEXT:
531531
;; CHECK-NEXT: --table64-lowering alias for memory64-lowering
532532
;; CHECK-NEXT:
533+
;; CHECK-NEXT: --tail-call-optimization transform call to return call
534+
;; CHECK-NEXT:
533535
;; CHECK-NEXT: --trace-calls instrument the build with code
534536
;; CHECK-NEXT: to intercept specific function
535537
;; CHECK-NEXT: calls

test/lit/help/wasm-opt.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@
554554
;; CHECK-NEXT:
555555
;; CHECK-NEXT: --table64-lowering alias for memory64-lowering
556556
;; CHECK-NEXT:
557+
;; CHECK-NEXT: --tail-call-optimization transform call to return call
558+
;; CHECK-NEXT:
557559
;; CHECK-NEXT: --trace-calls instrument the build with code
558560
;; CHECK-NEXT: to intercept specific function
559561
;; CHECK-NEXT: calls

test/lit/help/wasm2js.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@
494494
;; CHECK-NEXT:
495495
;; CHECK-NEXT: --table64-lowering alias for memory64-lowering
496496
;; CHECK-NEXT:
497+
;; CHECK-NEXT: --tail-call-optimization transform call to return call
498+
;; CHECK-NEXT:
497499
;; CHECK-NEXT: --trace-calls instrument the build with code
498500
;; CHECK-NEXT: to intercept specific function
499501
;; CHECK-NEXT: calls
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; RUN: foreach %s %t wasm-opt --tail-call-optimization --enable-tail-call --enable-exception-handling --optimize-level 2 --shrink-level 0 -S -o - | filecheck %s
4+
5+
;; Tests for tail call optimization with exception handling
6+
7+
(module $exception
8+
;; CHECK: (type $0 (func (result i32)))
9+
10+
;; CHECK: (type $1 (func))
11+
12+
;; CHECK: (tag $empty (type $1))
13+
(tag $empty)
14+
;; CHECK: (func $f (result i32)
15+
;; CHECK-NEXT: (i32.const 0)
16+
;; CHECK-NEXT: )
17+
(func $f (result i32)
18+
i32.const 0
19+
)
20+
;; CHECK: (func $in_try (result i32)
21+
;; CHECK-NEXT: (try (result i32)
22+
;; CHECK-NEXT: (do
23+
;; CHECK-NEXT: (call $f)
24+
;; CHECK-NEXT: )
25+
;; CHECK-NEXT: (catch $empty
26+
;; CHECK-NEXT: (return_call $f)
27+
;; CHECK-NEXT: )
28+
;; CHECK-NEXT: )
29+
;; CHECK-NEXT: )
30+
(func $in_try (result i32)
31+
try (result i32)
32+
call $f
33+
catch $empty
34+
call $f
35+
end
36+
)
37+
;; CHECK: (func $out_try (result i32)
38+
;; CHECK-NEXT: (try
39+
;; CHECK-NEXT: (do
40+
;; CHECK-NEXT: )
41+
;; CHECK-NEXT: (catch $empty
42+
;; CHECK-NEXT: )
43+
;; CHECK-NEXT: )
44+
;; CHECK-NEXT: (return_call $f)
45+
;; CHECK-NEXT: )
46+
(func $out_try (result i32)
47+
try
48+
catch $empty
49+
end
50+
call $f
51+
)
52+
;; CHECK: (func $in_catch (result i32)
53+
;; CHECK-NEXT: (try
54+
;; CHECK-NEXT: (do
55+
;; CHECK-NEXT: )
56+
;; CHECK-NEXT: (catch $empty
57+
;; CHECK-NEXT: (return
58+
;; CHECK-NEXT: (return_call $f)
59+
;; CHECK-NEXT: )
60+
;; CHECK-NEXT: )
61+
;; CHECK-NEXT: )
62+
;; CHECK-NEXT: (i32.const 0)
63+
;; CHECK-NEXT: )
64+
(func $in_catch (result i32)
65+
try
66+
catch $empty
67+
call $f
68+
return
69+
end
70+
i32.const 0
71+
)
72+
;; CHECK: (func $implicit_in_catch (result i32)
73+
;; CHECK-NEXT: (try (result i32)
74+
;; CHECK-NEXT: (do
75+
;; CHECK-NEXT: (i32.const 0)
76+
;; CHECK-NEXT: )
77+
;; CHECK-NEXT: (catch $empty
78+
;; CHECK-NEXT: (return_call $f)
79+
;; CHECK-NEXT: )
80+
;; CHECK-NEXT: (catch_all
81+
;; CHECK-NEXT: (return_call $f)
82+
;; CHECK-NEXT: )
83+
;; CHECK-NEXT: )
84+
;; CHECK-NEXT: )
85+
(func $implicit_in_catch (result i32)
86+
try (result i32)
87+
i32.const 0
88+
catch $empty
89+
call $f
90+
catch_all
91+
call $f
92+
end
93+
)
94+
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; RUN: foreach %s %t wasm-opt --tail-call-optimization --enable-tail-call --optimize-level 0 --shrink-level 2 -S -o - | filecheck %s
4+
5+
;; Tests for tail call optimization
6+
7+
(module
8+
;; CHECK: (type $0 (func (result i32)))
9+
10+
;; CHECK: (func $f (result i32)
11+
;; CHECK-NEXT: (i32.const 0)
12+
;; CHECK-NEXT: )
13+
(func $f (result i32)
14+
i32.const 0
15+
)
16+
;; CHECK: (func $implicit_return (result i32)
17+
;; CHECK-NEXT: (call $f)
18+
;; CHECK-NEXT: )
19+
(func $implicit_return (result i32)
20+
call $f
21+
)
22+
)

test/lit/tail-call-optimization.wast

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; RUN: foreach %s %t wasm-opt --tail-call-optimization --enable-tail-call --optimize-level 2 --shrink-level 0 -S -o - | filecheck %s
4+
5+
;; Tests for tail call optimization
6+
7+
(module
8+
;; CHECK: (type $0 (func (result i32)))
9+
10+
;; CHECK: (type $1 (func (param i32) (result i32)))
11+
12+
;; CHECK: (func $f (result i32)
13+
;; CHECK-NEXT: (i32.const 0)
14+
;; CHECK-NEXT: )
15+
(func $f (result i32)
16+
i32.const 0
17+
)
18+
;; CHECK: (func $implicit_return (result i32)
19+
;; CHECK-NEXT: (return_call $f)
20+
;; CHECK-NEXT: )
21+
(func $implicit_return (result i32)
22+
call $f
23+
)
24+
;; CHECK: (func $explicit_return (result i32)
25+
;; CHECK-NEXT: (return_call $f)
26+
;; CHECK-NEXT: )
27+
(func $explicit_return (result i32)
28+
call $f
29+
)
30+
;; CHECK: (func $return_through_tee (param $0 i32) (result i32)
31+
;; CHECK-NEXT: (local.tee $0
32+
;; CHECK-NEXT: (return_call $f)
33+
;; CHECK-NEXT: )
34+
;; CHECK-NEXT: )
35+
(func $return_through_tee (param $0 i32) (result i32)
36+
call $f
37+
local.tee $0
38+
)
39+
;; CHECK: (func $return_through_block (result i32)
40+
;; CHECK-NEXT: (return_call $f)
41+
;; CHECK-NEXT: )
42+
(func $return_through_block (result i32)
43+
block (result i32)
44+
call $f
45+
end
46+
)
47+
;; CHECK: (func $return_through_loop (result i32)
48+
;; CHECK-NEXT: (loop
49+
;; CHECK-NEXT: (return_call $f)
50+
;; CHECK-NEXT: )
51+
;; CHECK-NEXT: )
52+
(func $return_through_loop (result i32)
53+
loop (result i32)
54+
call $f
55+
end
56+
)
57+
;; CHECK: (func $return_through_if_then (param $0 i32) (result i32)
58+
;; CHECK-NEXT: (if (result i32)
59+
;; CHECK-NEXT: (local.get $0)
60+
;; CHECK-NEXT: (then
61+
;; CHECK-NEXT: (return_call $f)
62+
;; CHECK-NEXT: )
63+
;; CHECK-NEXT: (else
64+
;; CHECK-NEXT: (i32.const 0)
65+
;; CHECK-NEXT: )
66+
;; CHECK-NEXT: )
67+
;; CHECK-NEXT: )
68+
(func $return_through_if_then (param $0 i32) (result i32)
69+
local.get $0
70+
if (result i32)
71+
call $f
72+
else
73+
i32.const 0
74+
end
75+
)
76+
;; CHECK: (func $return_through_if_else (param $0 i32) (result i32)
77+
;; CHECK-NEXT: (if (result i32)
78+
;; CHECK-NEXT: (local.get $0)
79+
;; CHECK-NEXT: (then
80+
;; CHECK-NEXT: (i32.const 0)
81+
;; CHECK-NEXT: )
82+
;; CHECK-NEXT: (else
83+
;; CHECK-NEXT: (return_call $f)
84+
;; CHECK-NEXT: )
85+
;; CHECK-NEXT: )
86+
;; CHECK-NEXT: )
87+
(func $return_through_if_else (param $0 i32) (result i32)
88+
local.get $0
89+
if (result i32)
90+
i32.const 0
91+
else
92+
call $f
93+
end
94+
)
95+
;; CHECK: (func $return_through_if_both (param $0 i32) (result i32)
96+
;; CHECK-NEXT: (if
97+
;; CHECK-NEXT: (local.get $0)
98+
;; CHECK-NEXT: (then
99+
;; CHECK-NEXT: (return_call $f)
100+
;; CHECK-NEXT: )
101+
;; CHECK-NEXT: (else
102+
;; CHECK-NEXT: (return_call $f)
103+
;; CHECK-NEXT: )
104+
;; CHECK-NEXT: )
105+
;; CHECK-NEXT: )
106+
(func $return_through_if_both (param $0 i32) (result i32)
107+
local.get $0
108+
if (result i32)
109+
call $f
110+
else
111+
call $f
112+
end
113+
)
114+
;; CHECK: (func $return_through_br_if (param $0 i32) (result i32)
115+
;; CHECK-NEXT: (block $block
116+
;; CHECK-NEXT: (block
117+
;; CHECK-NEXT: (return_call $f)
118+
;; CHECK-NEXT: (drop
119+
;; CHECK-NEXT: (i32.const 1)
120+
;; CHECK-NEXT: )
121+
;; CHECK-NEXT: )
122+
;; CHECK-NEXT: )
123+
;; CHECK-NEXT: )
124+
(func $return_through_br_if (param $0 i32) (result i32)
125+
block (result i32)
126+
call $f
127+
i32.const 1
128+
br_if 0
129+
end
130+
)
131+
)
132+
133+
(module $NYI
134+
;; CHECK: (type $0 (func (result i32)))
135+
136+
;; CHECK: (type $1 (func (param i32) (result i32)))
137+
138+
;; CHECK: (func $f (result i32)
139+
;; CHECK-NEXT: (i32.const 0)
140+
;; CHECK-NEXT: )
141+
(func $f (result i32)
142+
i32.const 0
143+
)
144+
;; CHECK: (func $return_through_br (param $0 i32) (result i32)
145+
;; CHECK-NEXT: (block $block (result i32)
146+
;; CHECK-NEXT: (br $block
147+
;; CHECK-NEXT: (call $f)
148+
;; CHECK-NEXT: )
149+
;; CHECK-NEXT: )
150+
;; CHECK-NEXT: )
151+
(func $return_through_br (param $0 i32) (result i32)
152+
block (result i32)
153+
call $f
154+
br 0
155+
end
156+
)
157+
)

0 commit comments

Comments
 (0)