summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/DeadCodeElimination.cpp48
-rw-r--r--src/wasm/wasm.cpp7
2 files changed, 47 insertions, 8 deletions
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp
index 41012fccb..33a52a09a 100644
--- a/src/passes/DeadCodeElimination.cpp
+++ b/src/passes/DeadCodeElimination.cpp
@@ -51,12 +51,20 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
std::set<Name> reachableBreaks;
void addBreak(Name name) {
- assert(reachable);
- reachableBreaks.insert(name);
+ // we normally have already reduced unreachable code into (unreachable)
+ // nodes, so we would not get to this function at all anyhow, the breaking
+ // instruction itself would be removed. However, an exception are things
+ // like (block i32 (call $x) (unreachable)) , which has type i32
+ // despite not being exited.
+ // TODO: optimize such cases
+ if (reachable) {
+ reachableBreaks.insert(name);
+ }
}
- bool isDead(Expression* curr) {
- return curr && curr->is<Unreachable>();
+ // if a child is unreachable, we can replace ourselves with it
+ bool isDead(Expression* child) {
+ return child && child->type == unreachable;
}
// things that stop control flow
@@ -67,6 +75,19 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
replaceCurrent(curr->value);
return;
}
+ if (isDead(curr->condition)) {
+ if (curr->value) {
+ auto* block = getModule()->allocator.alloc<Block>();
+ block->list.resize(2);
+ block->list[0] = drop(curr->value);
+ block->list[1] = curr->condition;
+ block->finalize();
+ replaceCurrent(block);
+ } else {
+ replaceCurrent(curr->condition);
+ }
+ return;
+ }
addBreak(curr->name);
if (!curr->condition) {
reachable = false;
@@ -78,6 +99,19 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
replaceCurrent(curr->value);
return;
}
+ if (isDead(curr->condition)) {
+ if (curr->value) {
+ auto* block = getModule()->allocator.alloc<Block>();
+ block->list.resize(2);
+ block->list[0] = drop(curr->value);
+ block->list[1] = curr->condition;
+ block->finalize();
+ replaceCurrent(block);
+ } else {
+ replaceCurrent(curr->condition);
+ }
+ return;
+ }
for (auto target : curr->targets) {
addBreak(target);
}
@@ -137,7 +171,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
reachable = reachable || reachableBreaks.count(curr->name);
reachableBreaks.erase(curr->name);
}
- if (curr->list.size() == 1 && isDead(curr->list[0])) {
+ if (curr->list.size() == 1 && isDead(curr->list[0]) && !BreakSeeker::has(curr->list[0], curr->name)) {
replaceCurrent(curr->list[0]);
}
}
@@ -146,7 +180,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
if (curr->name.is()) {
reachableBreaks.erase(curr->name);
}
- if (isDead(curr->body)) {
+ if (isDead(curr->body) && !BreakSeeker::has(curr->body, curr->name)) {
replaceCurrent(curr->body);
return;
}
@@ -360,7 +394,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
}
void visitHost(Host* curr) {
- // TODO
+ handleCall(curr);
}
void visitFunction(Function* curr) {
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index a983fc943..36eff681f 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -409,7 +409,12 @@ void Host::finalize() {
break;
}
case GrowMemory: {
- type = i32;
+ // if the single operand is not reachable, so are we
+ if (operands[0]->type == unreachable) {
+ type = unreachable;
+ } else {
+ type = i32;
+ }
break;
}
default: abort();