Skip to content

Commit cddfb78

Browse files
HerrCai0907atc-github
authored andcommitted
feat(gc): directly inlining tostack call (#127)
`tostack<{}>` will block subsequent constant propagation because it is block box for optimizer when it is not inlined. This PR will inline `tostack` during lowering to avoid this issue.
1 parent 4ed6a99 commit cddfb78

21 files changed

+327
-133
lines changed

passes/GC/OptLower.cpp

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#include <algorithm>
21
#include <cassert>
32
#include <cstddef>
43
#include <functional>
@@ -22,8 +21,6 @@
2221
#include "passes/passes.h"
2322
#include "support/name.h"
2423
#include "warpo/support/Opt.hpp"
25-
#include "wasm-builder.h"
26-
#include "wasm-type.h"
2724
#include "wasm.h"
2825

2926
#define PASS_NAME "GCOptLower"
@@ -59,43 +56,6 @@ static cli::Opt<bool> TestOnlyControlGroup{
5956
[](argparse::Argument &arg) { arg.flag().hidden(); },
6057
};
6158

62-
struct PostLower : public wasm::Pass {
63-
std::shared_ptr<StackPositions const> stackPosition_;
64-
explicit PostLower(std::shared_ptr<StackPositions const> stackPosition) : stackPosition_(stackPosition) {
65-
name = "PostLower";
66-
}
67-
void run(wasm::Module *m) override {
68-
wasm::Builder b{*m};
69-
wasm::Name const memoryName = m->memories.front()->name;
70-
wasm::Type const i32 = wasm::Type::i32;
71-
72-
addStackStackOperationFunction(m);
73-
uint32_t const maxShadowStackOffset = getMaxShadowStackOffset();
74-
for (size_t offset = 0U; offset <= maxShadowStackOffset; offset += 4U) {
75-
m->addFunction(b.makeFunction(
76-
ToStackReplacer::getToStackFunctionName(offset), wasm::Signature(i32, i32), {},
77-
b.makeBlock({
78-
b.makeStore(4, offset, 1, b.makeGlobalGet(VarStackPointer, i32), b.makeLocalGet(0, i32), i32, memoryName),
79-
b.makeLocalGet(0, i32),
80-
})));
81-
}
82-
83-
m->removeFunction(FnLocalToStack);
84-
m->removeFunction(FnTmpToStack);
85-
}
86-
87-
private:
88-
uint32_t getMaxShadowStackOffset() const {
89-
uint32_t maxOffset = 0;
90-
for (auto const &[_, offsets] : *stackPosition_) {
91-
for (auto const &offset : offsets) {
92-
maxOffset = std::max(maxOffset, offset.second);
93-
}
94-
}
95-
return maxOffset;
96-
}
97-
};
98-
9959
void OptLower::preprocess(wasm::PassRunner &runner) {
10060
// cleanup without changing the overall code structure
10161
runner.add("vacuum");
@@ -140,9 +100,12 @@ void OptLower::run(wasm::Module *m) {
140100
runner.add(std::unique_ptr<wasm::Pass>(
141101
new PrologEpilogInserter(stackInsertPositions, MaxShadowStackOffsetsFromStackPositions::create(stackPositions))));
142102
runner.add(std::unique_ptr<wasm::Pass>(new ToStackReplacer(stackPositions)));
143-
runner.add(std::unique_ptr<wasm::Pass>(new PostLower(stackPositions)));
144103

145104
runner.run();
105+
106+
m->removeFunction(FnLocalToStack);
107+
m->removeFunction(FnTmpToStack);
108+
addStackStackOperationFunction(m);
146109
}
147110

148111
} // namespace warpo::passes::gc

passes/GC/ToStackReplacer.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
#include <cstddef>
33
#include <map>
44
#include <memory>
5+
#include <optional>
56

67
#include "GCInfo.hpp"
78
#include "StackAssigner.hpp"
89
#include "ToStackReplacer.hpp"
10+
#include "support/index.h"
911
#include "support/name.h"
1012
#include "wasm-builder.h"
1113
#include "wasm-traversal.h"
14+
#include "wasm-type.h"
1215
#include "wasm.h"
1316

1417
#define PASS_NAME "ToStackReplacer"
@@ -23,24 +26,41 @@ void ToStackReplacer::runOnFunction(wasm::Module *m, wasm::Function *func) {
2326
void ToStackReplacer::replaceToStackCallExpr(wasm::Module *m, wasm::Function *func,
2427
StackPosition const &stackPosition) {
2528
struct CallReplacer : public wasm::PostWalker<CallReplacer> {
26-
wasm::Function *func;
29+
wasm::Function *func_;
2730
StackPosition const &stackPosition_;
28-
explicit CallReplacer(StackPosition const &input, wasm::Function *func) : stackPosition_(input), func(func) {}
31+
std::optional<wasm::Index> tempLocalIndex_;
32+
explicit CallReplacer(StackPosition const &input, wasm::Function *func) : stackPosition_(input), func_(func) {}
2933
void visitCall(wasm::Call *expr) {
3034
if (expr->target != FnLocalToStack && expr->target != FnTmpToStack)
3135
return;
36+
assert(expr->operands.size() == 1);
3237

3338
auto it = stackPosition_.find(expr);
3439
if (it == stackPosition_.end()) {
3540
// no need to tostack
36-
assert(expr->operands.size() == 1);
3741
replaceCurrent(expr->operands.front());
3842
} else {
43+
wasm::Module *const m = getModule();
3944
uint32_t const offset = it->second;
40-
wasm::Builder builder{*getModule()};
41-
expr->target = getToStackFunctionName(offset);
45+
wasm::Builder b{*m};
46+
wasm::Name const memoryName = m->memories.front()->name;
47+
wasm::Index const tempLocalIndex = ensureTempLocal();
48+
wasm::Block *const newExpr = b.makeBlock(
49+
{
50+
b.makeLocalSet(tempLocalIndex, expr->operands.front()),
51+
b.makeStore(4, offset, 1, b.makeGlobalGet(VarStackPointer, wasm::Type::i32),
52+
b.makeLocalGet(tempLocalIndex, wasm::Type::i32), wasm::Type::i32, memoryName),
53+
b.makeLocalGet(tempLocalIndex, wasm::Type::i32),
54+
},
55+
wasm::Type::i32);
56+
replaceCurrent(newExpr);
4257
}
4358
}
59+
wasm::Index ensureTempLocal() {
60+
if (!tempLocalIndex_)
61+
tempLocalIndex_ = wasm::Builder::addVar(func_, wasm::Type::i32);
62+
return *tempLocalIndex_;
63+
}
4464
};
4565
CallReplacer callReplacer{stackPosition, func};
4666
callReplacer.walkFunctionInModule(func, m);

passes/GC/ToStackReplacer.hpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ struct ToStackReplacer : public wasm::Pass {
2222
bool modifiesBinaryenIR() override { return true; }
2323
void runOnFunction(wasm::Module *m, wasm::Function *func) override;
2424

25-
static wasm::Name getToStackFunctionName(uint32_t offset) {
26-
return wasm::Name{fmt::format("~lib/rt/__tostack<{}>", offset)};
27-
}
28-
2925
private:
3026
void replaceToStackCallExpr(wasm::Module *m, wasm::Function *func, StackPosition const &stackPosition);
3127
};

tests/snapshot_diff/gc_lower_opt/base/global.diff.wat

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,3 @@
3232
end
3333
;; ====================
3434
)
35-
;; =========add========
36-
(func $~lib/rt/__tostack<0> (type $func.0 (func (param i32) (result i32)))
37-
block ;;i32
38-
global.get $~lib/memory/__stack_pointer
39-
local.get $0
40-
i32.store $0 align=1
41-
local.get $0
42-
end
43-
)

tests/snapshot_diff/gc_lower_opt/base/new_obj_with_conditional_use.diff.wat

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,26 @@
33
(local i32)
44
;; =========add========
55
(local i32)
6+
(local i32)
67
;; ====================
78
block ;;i32
89
;; =========add========
910
i32.const 4
1011
call $~lib/rt/__decrease_sp
1112
block ;;unreachable
13+
block ;;i32
1214
;; ====================
13-
i32.const 0
14-
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
15+
i32.const 0
16+
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
1517
;; ======remove=======
1618
;; call $~lib/rt/__localtostack
1719
;; =========add========
18-
call $~lib/rt/__tostack<0>
20+
local.set $2
21+
global.get $~lib/memory/__stack_pointer
22+
local.get $2
23+
i32.store $0 align=1
24+
local.get $2
25+
end
1926
;; ====================
2027
local.set $0
2128
if ;;unreachable

tests/snapshot_diff/gc_lower_opt/base/new_obj_with_directly_use.diff.wat

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
;; ====================
22
(func $tests/snapshot_diff/gc_lower_opt/base/new_obj_with_directly_use/_start (type $func.0 (func))
33
;; =========add========
4+
(local i32)
45
block ;;none
56
i32.const 4
67
call $~lib/rt/__decrease_sp
8+
block ;;i32
79
;; ====================
8-
i32.const 0
9-
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
10+
i32.const 0
11+
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
1012
;; ======remove=======
1113
;; call $~lib/rt/__tmptostack
1214
;; =========add========
13-
call $~lib/rt/__tostack<0>
15+
local.set $0
16+
global.get $~lib/memory/__stack_pointer
17+
local.get $0
18+
i32.store $0 align=1
19+
local.get $0
20+
end
1421
;; ====================
1522
call $tests/snapshot_diff/gc_lower_opt/base/new_obj_with_directly_use/foo
1623
;; =========add========

tests/snapshot_diff/gc_lower_opt/base/new_obj_with_loop_use.diff.wat

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,26 @@
22
(func $tests/snapshot_diff/gc_lower_opt/base/new_obj_with_loop_use/_start (type $func.0 (func))
33
(local i32)
44
(local i32)
5+
;; =========add========
6+
(local i32)
7+
;; ====================
58
block ;;none
69
;; =========add========
710
i32.const 8
811
call $~lib/rt/__decrease_sp
912
block ;;none
13+
block ;;i32
1014
;; ====================
11-
i32.const 0
15+
i32.const 0
1216
;; ======remove=======
1317
;; call $~lib/rt/__localtostack
1418
;; =========add========
15-
call $~lib/rt/__tostack<0>
19+
local.set $2
20+
global.get $~lib/memory/__stack_pointer
21+
local.get $2
22+
i32.store $0 align=1
23+
local.get $2
24+
end
1625
;; ====================
1726
local.set $0
1827
;; ======remove=======
@@ -26,12 +35,20 @@
2635
i32.const 0
2736
i32.eq
2837
local.set $1
29-
i32.const 0
30-
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
38+
;; =========add========
39+
block ;;i32
40+
;; ====================
41+
i32.const 0
42+
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
3143
;; ======remove=======
3244
;; call $~lib/rt/__localtostack
3345
;; =========add========
34-
call $~lib/rt/__tostack<4>
46+
local.set $2
47+
global.get $~lib/memory/__stack_pointer
48+
local.get $2
49+
i32.store $0 offset=4 align=1
50+
local.get $2
51+
end
3552
;; ====================
3653
local.set $0
3754
br $while-continue|0

tests/snapshot_diff/gc_lower_opt/base/new_obj_with_overwritten.diff.wat

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
(local i32)
44
;; =========add========
55
(local i32)
6+
(local i32)
67
;; ====================
78
block ;;i32
89
;; =========add========
@@ -15,12 +16,20 @@
1516
;; call $~lib/rt/__localtostack
1617
;; ====================
1718
local.set $0
18-
i32.const 0
19-
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
19+
;; =========add========
20+
block ;;i32
21+
;; ====================
22+
i32.const 0
23+
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
2024
;; ======remove=======
2125
;; call $~lib/rt/__localtostack
2226
;; =========add========
23-
call $~lib/rt/__tostack<0>
27+
local.set $2
28+
global.get $~lib/memory/__stack_pointer
29+
local.get $2
30+
i32.store $0 align=1
31+
local.get $2
32+
end
2433
;; ====================
2534
local.set $0
2635
;; =========add========

tests/snapshot_diff/gc_lower_opt/base/new_obj_with_use.diff.wat

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,26 @@
33
(local i32)
44
;; =========add========
55
(local i32)
6+
(local i32)
67
;; ====================
78
block ;;i32
89
;; =========add========
910
i32.const 4
1011
call $~lib/rt/__decrease_sp
1112
block ;;unreachable
13+
block ;;i32
1214
;; ====================
13-
i32.const 0
14-
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
15+
i32.const 0
16+
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
1517
;; ======remove=======
1618
;; call $~lib/rt/__localtostack
1719
;; =========add========
18-
call $~lib/rt/__tostack<0>
20+
local.set $2
21+
global.get $~lib/memory/__stack_pointer
22+
local.get $2
23+
i32.store $0 align=1
24+
local.get $2
25+
end
1926
;; ====================
2027
local.set $0
2128
;; =========add========

tests/snapshot_diff/gc_lower_opt/base/use_from_condition.diff.wat

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
(local i32)
44
;; =========add========
55
(local i32)
6+
(local i32)
67
;; ====================
78
block ;;i32
89
;; =========add========
@@ -12,20 +13,36 @@
1213
;; ====================
1314
if ;;none
1415
global.get $tests/snapshot_diff/gc_lower_opt/base/use_from_condition/v
15-
i32.const 0
16-
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
16+
;; =========add========
17+
block ;;i32
18+
;; ====================
19+
i32.const 0
20+
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
1721
;; ======remove=======
1822
;; call $~lib/rt/__localtostack
1923
;; =========add========
20-
call $~lib/rt/__tostack<0>
24+
local.set $2
25+
global.get $~lib/memory/__stack_pointer
26+
local.get $2
27+
i32.store $0 align=1
28+
local.get $2
29+
end
2130
;; ====================
2231
local.set $0
23-
i32.const 0
24-
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
32+
;; =========add========
33+
block ;;i32
34+
;; ====================
35+
i32.const 0
36+
call $tests/snapshot_diff/common_lib/normal/Normal#constructor
2537
;; ======remove=======
2638
;; call $~lib/rt/__localtostack
2739
;; =========add========
28-
call $~lib/rt/__tostack<4>
40+
local.set $2
41+
global.get $~lib/memory/__stack_pointer
42+
local.get $2
43+
i32.store $0 offset=4 align=1
44+
local.get $2
45+
end
2946
;; ====================
3047
local.set $0
3148
end

0 commit comments

Comments
 (0)