Skip to content

Commit 7fe2701

Browse files
authored
wasm2js: remove more code we don't need since we have flat IR (#2039)
Also run remove-unused-names which became more noticeably necessary after this change.
1 parent 831a774 commit 7fe2701

17 files changed

Lines changed: 269 additions & 637 deletions

src/passes/I64ToI32Lowering.cpp

Lines changed: 0 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
160160
if (!builder) builder = make_unique<Builder>(*getModule());
161161
indexMap.clear();
162162
highBitVars.clear();
163-
labelHighBitVars.clear();
164163
freeTemps.clear();
165164
Module temp;
166165
auto* oldFunc = ModuleUtils::copyFunction(func, temp);
@@ -221,124 +220,6 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
221220
}
222221
}
223222

224-
void visitBlock(Block* curr) {
225-
if (curr->list.size() == 0) return;
226-
if (handleUnreachable(curr)) return;
227-
if (curr->type == i64) curr->type = i32;
228-
auto highBitsIt = labelHighBitVars.find(curr->name);
229-
if (!hasOutParam(curr->list.back())) {
230-
if (highBitsIt != labelHighBitVars.end()) {
231-
setOutParam(curr, std::move(highBitsIt->second));
232-
}
233-
return;
234-
}
235-
TempVar lastHighBits = fetchOutParam(curr->list.back());
236-
if (highBitsIt == labelHighBitVars.end() ||
237-
highBitsIt->second == lastHighBits) {
238-
setOutParam(curr, std::move(lastHighBits));
239-
if (highBitsIt != labelHighBitVars.end()) {
240-
labelHighBitVars.erase(highBitsIt);
241-
}
242-
return;
243-
}
244-
TempVar highBits = std::move(highBitsIt->second);
245-
TempVar tmp = getTemp();
246-
labelHighBitVars.erase(highBitsIt);
247-
SetLocal* setLow = builder->makeSetLocal(tmp, curr->list.back());
248-
SetLocal* setHigh = builder->makeSetLocal(
249-
highBits,
250-
builder->makeGetLocal(lastHighBits, i32)
251-
);
252-
GetLocal* getLow = builder->makeGetLocal(tmp, i32);
253-
curr->list.back() = builder->blockify(setLow, setHigh, getLow);
254-
setOutParam(curr, std::move(highBits));
255-
}
256-
257-
void visitIf(If* curr) {
258-
if (!hasOutParam(curr->ifTrue)) return;
259-
assert(curr->ifFalse != nullptr && "Nullable ifFalse found");
260-
TempVar highBits = fetchOutParam(curr->ifTrue);
261-
TempVar falseBits = fetchOutParam(curr->ifFalse);
262-
TempVar tmp = getTemp();
263-
curr->type = i32;
264-
curr->ifFalse = builder->blockify(
265-
builder->makeSetLocal(tmp, curr->ifFalse),
266-
builder->makeSetLocal(
267-
highBits,
268-
builder->makeGetLocal(falseBits, i32)
269-
),
270-
builder->makeGetLocal(tmp, i32)
271-
);
272-
setOutParam(curr, std::move(highBits));
273-
}
274-
275-
void visitLoop(Loop* curr) {
276-
// TODO: in flat IR, no chance for an out param
277-
assert(labelHighBitVars.find(curr->name) == labelHighBitVars.end());
278-
if (curr->type != i64) return;
279-
curr->type = i32;
280-
setOutParam(curr, fetchOutParam(curr->body));
281-
}
282-
283-
void visitBreak(Break* curr) {
284-
// TODO: in flat IR, no chance for an out param
285-
if (!hasOutParam(curr->value)) return;
286-
assert(curr->value != nullptr);
287-
TempVar valHighBits = fetchOutParam(curr->value);
288-
auto blockHighBitsIt = labelHighBitVars.find(curr->name);
289-
if (blockHighBitsIt == labelHighBitVars.end()) {
290-
labelHighBitVars.emplace(curr->name, std::move(valHighBits));
291-
curr->type = i32;
292-
return;
293-
}
294-
TempVar blockHighBits = std::move(blockHighBitsIt->second);
295-
TempVar tmp = getTemp();
296-
SetLocal* setLow = builder->makeSetLocal(tmp, curr->value);
297-
SetLocal* setHigh = builder->makeSetLocal(
298-
blockHighBits,
299-
builder->makeGetLocal(valHighBits, i32)
300-
);
301-
curr->value = builder->makeGetLocal(tmp, i32);
302-
curr->type = i32;
303-
replaceCurrent(builder->blockify(setLow, setHigh, curr));
304-
}
305-
306-
void visitSwitch(Switch* curr) {
307-
// TODO: in flat IR, no chance for an out param
308-
if (!hasOutParam(curr->value)) return;
309-
TempVar outParam = fetchOutParam(curr->value);
310-
TempVar tmp = getTemp();
311-
Expression* result = curr;
312-
std::vector<Name> targets;
313-
size_t blockID = 0;
314-
auto processTarget = [&](Name target) -> Name {
315-
auto labelIt = labelHighBitVars.find(target);
316-
if (labelIt == labelHighBitVars.end()) {
317-
labelHighBitVars.emplace(target, getTemp());
318-
labelIt = labelHighBitVars.find(target);
319-
}
320-
Name newLabel("$i64toi32_" + std::string(target.c_str()) +
321-
"_" + std::to_string(blockID++));
322-
Block* trampoline = builder->makeBlock(newLabel, result);
323-
trampoline->type = i32;
324-
result = builder->blockify(
325-
builder->makeSetLocal(tmp, trampoline),
326-
builder->makeSetLocal(
327-
labelIt->second,
328-
builder->makeGetLocal(outParam, i32)
329-
),
330-
builder->makeBreak(target, builder->makeGetLocal(tmp, i32))
331-
);
332-
return newLabel;
333-
};
334-
for (auto target : curr->targets) {
335-
targets.push_back(processTarget(target));
336-
}
337-
curr->targets.set(targets);
338-
curr->default_ = processTarget(curr->default_);
339-
replaceCurrent(result);
340-
}
341-
342223
template<typename T>
343224
using BuilderFunc = std::function<T*(std::vector<Expression*>&, Type)>;
344225

@@ -1615,7 +1496,6 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
16151496
std::unordered_map<Index, Index> indexMap;
16161497
std::unordered_map<int, std::vector<Index>> freeTemps;
16171498
std::unordered_map<Expression*, TempVar> highBitVars;
1618-
std::unordered_map<Name, TempVar> labelHighBitVars;
16191499
std::unordered_map<Index, Type> tempTypes;
16201500
std::unordered_set<Name> originallyI64Globals;
16211501
Index nextTemp;

src/wasm2js.h

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,7 @@ class Wasm2JSBuilder {
136136

137137
// The second pass on an expression: process it fully, generating
138138
// JS
139-
// @param result Whether the context we are in receives a value,
140-
// and its type, or if not, then we can drop our return,
141-
// if we have one.
142-
Ref processFunctionBody(Module* m, Function* func, IString result);
139+
Ref processFunctionBody(Module* m, Function* func);
143140

144141
// Get a temp var.
145142
IString getTemp(Type type, Function* func) {
@@ -274,6 +271,7 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
274271
runner.add("flatten");
275272
runner.add("simplify-locals-notee-nostructure");
276273
runner.add("reorder-locals");
274+
runner.add("remove-unused-names");
277275
runner.add("vacuum");
278276
runner.add("remove-unused-module-elements");
279277
runner.setDebug(flags.debug);
@@ -632,6 +630,7 @@ Ref Wasm2JSBuilder::processFunction(Module* m, Function* func, bool standaloneFu
632630
runner.add("flatten");
633631
runner.add("simplify-locals-notee-nostructure");
634632
runner.add("reorder-locals");
633+
runner.add("remove-unused-names");
635634
runner.add("vacuum");
636635
runner.runOnFunction(func);
637636
}
@@ -665,7 +664,7 @@ Ref Wasm2JSBuilder::processFunction(Module* m, Function* func, bool standaloneFu
665664
size_t theVarIndex = ret[3]->size();
666665
ret[3]->push_back(theVar);
667666
// body
668-
flattenAppend(ret, processFunctionBody(m, func, NO_RESULT));
667+
flattenAppend(ret, processFunctionBody(m, func));
669668
// vars, including new temp vars
670669
for (Index i = func->getVarIndexBase(); i < func->getNumLocals(); i++) {
671670
ValueBuilder::appendToVar(
@@ -684,7 +683,7 @@ Ref Wasm2JSBuilder::processFunction(Module* m, Function* func, bool standaloneFu
684683
return ret;
685684
}
686685

687-
Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString result) {
686+
Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func) {
688687
struct ExpressionProcessor : public Visitor<ExpressionProcessor, Ref> {
689688
Wasm2JSBuilder* parent;
690689
IString result; // TODO: remove
@@ -741,14 +740,9 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString resul
741740
}
742741

743742
Ref visitAndAssign(Expression* curr, IString result) {
743+
assert(result != NO_RESULT);
744744
Ref ret = visit(curr, result);
745-
// if it's not already a statement, then it's an expression, and we need to assign it
746-
// (if it is a statement, it already assigns to the result var)
747-
if (result != NO_RESULT) {
748-
ret = ValueBuilder::makeStatement(
749-
ValueBuilder::makeBinary(ValueBuilder::makeName(result), SET, ret));
750-
}
751-
return ret;
745+
return ValueBuilder::makeStatement(ValueBuilder::makeBinary(ValueBuilder::makeName(result), SET, ret));
752746
}
753747

754748
Ref visitAndAssign(Expression* curr, ScopedTemp& temp) {
@@ -768,10 +762,6 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString resul
768762
return ret;
769763
}
770764

771-
// For spooky return-at-a-distance/break-with-result, this tells us
772-
// what the result var is for a specific label.
773-
std::map<Name, IString> breakResults;
774-
775765
// Breaks to the top of a loop should be emitted as continues, to that loop's main label
776766
std::unordered_set<Name> continueLabels;
777767

@@ -782,7 +772,6 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString resul
782772
// Visitors
783773

784774
Ref visitBlock(Block* curr) {
785-
breakResults[curr->name] = result;
786775
Ref ret = ValueBuilder::makeBlock();
787776
size_t size = curr->list.size();
788777
auto noResults = result == NO_RESULT ? size : size-1;
@@ -799,20 +788,13 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString resul
799788
}
800789

801790
Ref visitIf(If* curr) {
802-
IString temp;
803791
Ref condition = visit(curr->condition, EXPRESSION_RESULT);
804-
Ref ifTrue = ValueBuilder::makeStatement(visitAndAssign(curr->ifTrue, result));
792+
Ref ifTrue = visit(curr->ifTrue, NO_RESULT);
805793
Ref ifFalse;
806794
if (curr->ifFalse) {
807-
ifFalse = ValueBuilder::makeStatement(visitAndAssign(curr->ifFalse, result));
808-
}
809-
if (temp.isNull()) {
810-
return ValueBuilder::makeIf(condition, ifTrue, ifFalse); // simple if
795+
ifFalse = visit(curr->ifFalse, NO_RESULT);
811796
}
812-
condition = blockify(condition);
813-
// just add an if to the block
814-
condition[1]->push_back(ValueBuilder::makeIf(ValueBuilder::makeName(temp), ifTrue, ifFalse));
815-
return condition;
797+
return ValueBuilder::makeIf(condition, ifTrue, ifFalse); // simple if
816798
}
817799

818800
Ref visitLoop(Loop* curr) {
@@ -842,13 +824,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString resul
842824
fakeIf.ifTrue = &fakeBreak;
843825
return visit(&fakeIf, result);
844826
}
845-
Ref theBreak = makeBreakOrContinue(curr->name);
846-
if (!curr->value) return theBreak;
847-
// generate the value, including assigning to the result, and then do the break
848-
Ref ret = visitAndAssign(curr->value, breakResults[curr->name]);
849-
ret = blockify(ret);
850-
ret[1]->push_back(theBreak);
851-
return ret;
827+
return makeBreakOrContinue(curr->name);
852828
}
853829

854830
Expression* defaultBody = nullptr; // default must be last in asm.js
@@ -1141,7 +1117,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString resul
11411117
}
11421118

11431119
Ref visitDrop(Drop* curr) {
1144-
return visitAndAssign(curr->value, result);
1120+
return visit(curr->value, NO_RESULT);
11451121
}
11461122

11471123
Ref visitConst(Const* curr) {
@@ -1587,7 +1563,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString resul
15871563
}
15881564
};
15891565

1590-
return ExpressionProcessor(this, m, func).visit(func->body, result);
1566+
return ExpressionProcessor(this, m, func).visit(func->body, NO_RESULT);
15911567
}
15921568

15931569
void Wasm2JSBuilder::addMemoryGrowthFuncs(Ref ast, Module* wasm) {

test/passes/flatten_i64-to-i32-lowering.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@
206206
(local $1 i32)
207207
(local $1$hi i32)
208208
(local $i64toi32_i32$0 i32)
209-
(block
209+
(block $label$1
210210
(unreachable)
211211
(unreachable)
212212
)

test/wasm2js/block.2asm.js

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,19 @@ function asmFunc(global, env, buffer) {
3434
}
3535

3636
function $3() {
37-
block : {
38-
dummy();
39-
dummy();
40-
dummy();
41-
dummy();
42-
}
43-
block1 : {
44-
dummy();
45-
dummy();
46-
dummy();
47-
}
37+
dummy();
38+
dummy();
39+
dummy();
40+
dummy();
41+
dummy();
42+
dummy();
43+
dummy();
4844
return 8 | 0;
4945
}
5046

5147
function $4() {
52-
block : {
53-
dummy();
54-
dummy();
55-
}
48+
dummy();
49+
dummy();
5650
return 9 | 0;
5751
}
5852

test/wasm2js/br.2asm.js

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,37 +115,28 @@ function asmFunc(global, env, buffer) {
115115
function $13() {
116116
var $0 = 0, $1_1 = 0, $3_1 = 0;
117117
block : {
118-
loop_in : do {
119-
$0 = 3;
120-
break block;
121-
break loop_in;
122-
} while (1);
118+
$0 = 3;
119+
break block;
123120
}
124121
return $0 | 0;
125122
}
126123

127124
function $14() {
128125
var $0 = 0, $1_1 = 0, $3_1 = 0;
129126
block : {
130-
loop_in : do {
131-
dummy();
132-
$0 = 4;
133-
break block;
134-
break loop_in;
135-
} while (1);
127+
dummy();
128+
$0 = 4;
129+
break block;
136130
}
137131
return $0 | 0;
138132
}
139133

140134
function $15() {
141135
var $0 = 0;
142136
block : {
143-
loop_in : do {
144-
dummy();
145-
$0 = 5;
146-
break block;
147-
break loop_in;
148-
} while (1);
137+
dummy();
138+
$0 = 5;
139+
break block;
149140
}
150141
return $0 | 0;
151142
}

0 commit comments

Comments
 (0)