summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/block-utils.h7
-rw-r--r--src/ir/effects.h28
-rw-r--r--src/ir/properties.h2
-rw-r--r--src/passes/CodeFolding.cpp7
-rw-r--r--src/passes/DeadArgumentElimination.cpp2
-rw-r--r--src/passes/LocalCSE.cpp4
-rw-r--r--src/passes/LoopInvariantCodeMotion.cpp7
-rw-r--r--src/passes/MergeBlocks.cpp30
-rw-r--r--src/passes/OptimizeInstructions.cpp30
-rw-r--r--src/passes/RemoveUnusedBrs.cpp53
-rw-r--r--src/passes/SimplifyGlobals.cpp8
-rw-r--r--src/passes/SimplifyLocals.cpp22
-rw-r--r--src/passes/Vacuum.cpp12
-rw-r--r--src/wasm2js.h13
14 files changed, 115 insertions, 110 deletions
diff --git a/src/ir/block-utils.h b/src/ir/block-utils.h
index f8224186f..be24cf483 100644
--- a/src/ir/block-utils.h
+++ b/src/ir/block-utils.h
@@ -37,10 +37,9 @@ simplifyToContents(Block* block, T* parent, bool allowTypeChange = false) {
!BranchUtils::BranchSeeker::has(list[0], block->name)) {
// just one element. try to replace the block
auto* singleton = list[0];
- auto sideEffects = EffectAnalyzer(parent->getPassOptions(),
- parent->getModule()->features,
- singleton)
- .hasSideEffects();
+ auto sideEffects =
+ EffectAnalyzer(parent->getPassOptions(), *parent->getModule(), singleton)
+ .hasSideEffects();
if (!sideEffects && !singleton->type.isConcrete()) {
// no side effects, and singleton is not returning a value, so we can
// throw away the block and its contents, basically
diff --git a/src/ir/effects.h b/src/ir/effects.h
index e8fba8e3a..d34f8e5b2 100644
--- a/src/ir/effects.h
+++ b/src/ir/effects.h
@@ -31,7 +31,19 @@ public:
Expression* ast = nullptr)
: ignoreImplicitTraps(passOptions.ignoreImplicitTraps),
trapsNeverHappen(passOptions.trapsNeverHappen),
- debugInfo(passOptions.debugInfo), features(features) {
+ debugInfo(passOptions.debugInfo), module(nullptr), features(features) {
+ if (ast) {
+ walk(ast);
+ }
+ }
+
+ EffectAnalyzer(const PassOptions& passOptions,
+ Module& module,
+ Expression* ast = nullptr)
+ : ignoreImplicitTraps(passOptions.ignoreImplicitTraps),
+ trapsNeverHappen(passOptions.trapsNeverHappen),
+ debugInfo(passOptions.debugInfo), module(&module),
+ features(module.features) {
if (ast) {
walk(ast);
}
@@ -40,6 +52,7 @@ public:
bool ignoreImplicitTraps;
bool trapsNeverHappen;
bool debugInfo;
+ Module* module;
FeatureSet features;
// Walk an expression and all its children.
@@ -680,6 +693,15 @@ public:
return !aEffects.invalidates(bEffects);
}
+ static bool canReorder(const PassOptions& passOptions,
+ Module& module,
+ Expression* a,
+ Expression* b) {
+ EffectAnalyzer aEffects(passOptions, module, a);
+ EffectAnalyzer bEffects(passOptions, module, b);
+ return !aEffects.invalidates(bEffects);
+ }
+
// C-API
enum SideEffects : uint32_t {
@@ -767,9 +789,9 @@ private:
class ShallowEffectAnalyzer : public EffectAnalyzer {
public:
ShallowEffectAnalyzer(const PassOptions& passOptions,
- FeatureSet features,
+ Module& module,
Expression* ast = nullptr)
- : EffectAnalyzer(passOptions, features) {
+ : EffectAnalyzer(passOptions, module) {
if (ast) {
visit(ast);
}
diff --git a/src/ir/properties.h b/src/ir/properties.h
index dbf2715ef..2e3f94a06 100644
--- a/src/ir/properties.h
+++ b/src/ir/properties.h
@@ -250,6 +250,8 @@ inline Index getZeroExtBits(Expression* curr) {
// child of this expression. See getFallthrough for a method that looks all the
// way to the final value falling through, potentially through multiple
// intermediate expressions.
+//
+// TODO: Receive a Module instead of FeatureSet, to pass to EffectAnalyzer?
inline Expression* getImmediateFallthrough(Expression* curr,
const PassOptions& passOptions,
FeatureSet features) {
diff --git a/src/passes/CodeFolding.cpp b/src/passes/CodeFolding.cpp
index 5b7c88024..886b5b891 100644
--- a/src/passes/CodeFolding.cpp
+++ b/src/passes/CodeFolding.cpp
@@ -303,7 +303,7 @@ private:
return false;
}
if (getModule()->features.hasExceptionHandling()) {
- EffectAnalyzer effects(getPassOptions(), getModule()->features, item);
+ EffectAnalyzer effects(getPassOptions(), *getModule(), item);
// Pop instructions are pseudoinstructions used only after 'catch' to
// simulate its behavior. We cannot move expressions containing pops if
// they are not enclosed in a 'catch' body, because a pop instruction
@@ -591,9 +591,8 @@ private:
// TODO: this should not be a problem in
// *non*-terminating tails, but
// double-verify that
- if (EffectAnalyzer(getPassOptions(),
- getModule()->features,
- newItem)
+ if (EffectAnalyzer(
+ getPassOptions(), *getModule(), newItem)
.hasExternalBreakTargets()) {
return true;
}
diff --git a/src/passes/DeadArgumentElimination.cpp b/src/passes/DeadArgumentElimination.cpp
index 419ae1aca..afe9f19b7 100644
--- a/src/passes/DeadArgumentElimination.cpp
+++ b/src/passes/DeadArgumentElimination.cpp
@@ -395,7 +395,7 @@ struct DAE : public Pass {
bool callParamsAreValid =
std::none_of(calls.begin(), calls.end(), [&](Call* call) {
auto* operand = call->operands[i];
- return EffectAnalyzer(runner->options, module->features, operand)
+ return EffectAnalyzer(runner->options, *module, operand)
.hasSideEffects();
});
// The type must be valid for us to handle as a local (since we
diff --git a/src/passes/LocalCSE.cpp b/src/passes/LocalCSE.cpp
index a233517c5..863179e49 100644
--- a/src/passes/LocalCSE.cpp
+++ b/src/passes/LocalCSE.cpp
@@ -380,7 +380,7 @@ struct Checker
// Given the current expression, see what it invalidates of the currently-
// hashed expressions, if there are any.
if (!activeOriginals.empty()) {
- EffectAnalyzer effects(options, getModule()->features);
+ EffectAnalyzer effects(options, *getModule());
// We only need to visit this node itself, as we have already visited its
// children by the time we get here.
effects.visit(curr);
@@ -421,7 +421,7 @@ struct Checker
if (info.requests > 0) {
// This is an original. Compute its side effects, as we cannot optimize
// away repeated apperances if it has any.
- EffectAnalyzer effects(options, getModule()->features, curr);
+ EffectAnalyzer effects(options, *getModule(), curr);
// We can ignore traps here, as we replace a repeating expression with a
// single appearance of it, a store to a local, and gets in the other
diff --git a/src/passes/LoopInvariantCodeMotion.cpp b/src/passes/LoopInvariantCodeMotion.cpp
index a80e3a55d..1007e57b3 100644
--- a/src/passes/LoopInvariantCodeMotion.cpp
+++ b/src/passes/LoopInvariantCodeMotion.cpp
@@ -60,14 +60,13 @@ struct LoopInvariantCodeMotion
// Accumulate effects of things we can't move out - things
// we move out later must cross them, so we must verify it
// is ok to do so.
- FeatureSet features = getModule()->features;
- EffectAnalyzer effectsSoFar(getPassOptions(), features);
+ EffectAnalyzer effectsSoFar(getPassOptions(), *getModule());
// The loop's total effects also matter. For example, a store
// in the loop means we can't move a load outside.
// FIXME: we look at the loop "tail" area too, after the last
// possible branch back, which can cause false positives
// for bad effect interactions.
- EffectAnalyzer loopEffects(getPassOptions(), features, loop);
+ EffectAnalyzer loopEffects(getPassOptions(), *getModule(), loop);
// Note all the sets in each loop, and how many per index. Currently
// EffectAnalyzer can't do that, and we need it to know if we
// can move a set out of the loop (if there is another set
@@ -108,7 +107,7 @@ struct LoopInvariantCodeMotion
// a branch to it anyhow, so we would stop before that point anyhow.
}
// If this may branch, we are done.
- EffectAnalyzer effects(getPassOptions(), features, curr);
+ EffectAnalyzer effects(getPassOptions(), *getModule(), curr);
if (effects.transfersControlFlow()) {
break;
}
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index 7e8819309..b38f949e9 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -113,7 +113,7 @@ struct ProblemFinder
brIfs++;
}
// if the value has side effects, we can't remove it
- if (EffectAnalyzer(passOptions, getModule()->features, br->value)
+ if (EffectAnalyzer(passOptions, *getModule(), br->value)
.hasSideEffects()) {
foundProblem = true;
}
@@ -434,18 +434,17 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
if (!child) {
return outer;
}
- FeatureSet features = getModule()->features;
if ((dependency1 && *dependency1) || (dependency2 && *dependency2)) {
// there are dependencies, things we must be reordered through. make sure
// no problems there
- EffectAnalyzer childEffects(getPassOptions(), features, child);
+ EffectAnalyzer childEffects(getPassOptions(), *getModule(), child);
if (dependency1 && *dependency1 &&
- EffectAnalyzer(getPassOptions(), features, *dependency1)
+ EffectAnalyzer(getPassOptions(), *getModule(), *dependency1)
.invalidates(childEffects)) {
return outer;
}
if (dependency2 && *dependency2 &&
- EffectAnalyzer(getPassOptions(), features, *dependency2)
+ EffectAnalyzer(getPassOptions(), *getModule(), *dependency2)
.invalidates(childEffects)) {
return outer;
}
@@ -512,17 +511,19 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
Expression*& third) {
// TODO: for now, just stop when we see any side effect. instead, we could
// check effects carefully for reordering
- FeatureSet features = getModule()->features;
Block* outer = nullptr;
- if (EffectAnalyzer(getPassOptions(), features, first).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), *getModule(), first)
+ .hasSideEffects()) {
return;
}
outer = optimize(curr, first, outer);
- if (EffectAnalyzer(getPassOptions(), features, second).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), *getModule(), second)
+ .hasSideEffects()) {
return;
}
outer = optimize(curr, second, outer);
- if (EffectAnalyzer(getPassOptions(), features, third).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), *getModule(), third)
+ .hasSideEffects()) {
return;
}
optimize(curr, third, outer);
@@ -548,8 +549,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
template<typename T> void handleCall(T* curr) {
Block* outer = nullptr;
for (Index i = 0; i < curr->operands.size(); i++) {
- if (EffectAnalyzer(
- getPassOptions(), getModule()->features, curr->operands[i])
+ if (EffectAnalyzer(getPassOptions(), *getModule(), curr->operands[i])
.hasSideEffects()) {
return;
}
@@ -560,16 +560,15 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
void visitCall(Call* curr) { handleCall(curr); }
template<typename T> void handleNonDirectCall(T* curr) {
- FeatureSet features = getModule()->features;
Block* outer = nullptr;
for (Index i = 0; i < curr->operands.size(); i++) {
- if (EffectAnalyzer(getPassOptions(), features, curr->operands[i])
+ if (EffectAnalyzer(getPassOptions(), *getModule(), curr->operands[i])
.hasSideEffects()) {
return;
}
outer = optimize(curr, curr->operands[i], outer);
}
- if (EffectAnalyzer(getPassOptions(), features, curr->target)
+ if (EffectAnalyzer(getPassOptions(), *getModule(), curr->target)
.hasSideEffects()) {
return;
}
@@ -583,8 +582,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
void visitThrow(Throw* curr) {
Block* outer = nullptr;
for (Index i = 0; i < curr->operands.size(); i++) {
- if (EffectAnalyzer(
- getPassOptions(), getModule()->features, curr->operands[i])
+ if (EffectAnalyzer(getPassOptions(), *getModule(), curr->operands[i])
.hasSideEffects()) {
return;
}
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 2c4bdc905..22d53b151 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -275,7 +275,7 @@ struct OptimizeInstructions
}
EffectAnalyzer effects(Expression* expr) {
- return EffectAnalyzer(getPassOptions(), getModule()->features, expr);
+ return EffectAnalyzer(getPassOptions(), *getModule(), expr);
}
decltype(auto) pure(Expression** binder) {
@@ -284,8 +284,7 @@ struct OptimizeInstructions
}
bool canReorder(Expression* a, Expression* b) {
- return EffectAnalyzer::canReorder(
- getPassOptions(), getModule()->features, a, b);
+ return EffectAnalyzer::canReorder(getPassOptions(), *getModule(), a, b);
}
void visitBinary(Binary* curr) {
@@ -1379,7 +1378,8 @@ struct OptimizeInstructions
if (auto* child = ref->dynCast<RefCast>()) {
// Check if the casts are identical.
if (ExpressionAnalyzer::equal(curr->rtt, child->rtt) &&
- !EffectAnalyzer(passOptions, features, curr->rtt).hasSideEffects()) {
+ !EffectAnalyzer(passOptions, *getModule(), curr->rtt)
+ .hasSideEffects()) {
replaceCurrent(curr->ref);
return;
}
@@ -1545,9 +1545,9 @@ private:
// checking if we can remove the two inputs anyhow.)
auto passOptions = getPassOptions();
auto features = getModule()->features;
- if (EffectAnalyzer(passOptions, features, left)
+ if (EffectAnalyzer(passOptions, *getModule(), left)
.hasUnremovableSideEffects() ||
- EffectAnalyzer(passOptions, features, right)
+ EffectAnalyzer(passOptions, *getModule(), right)
.hasUnremovableSideEffects()) {
return false;
}
@@ -1916,7 +1916,6 @@ private:
if (!curr->type.isInteger()) {
return;
}
- FeatureSet features = getModule()->features;
auto type = curr->type;
auto* left = curr->left->dynCast<Const>();
auto* right = curr->right->dynCast<Const>();
@@ -1938,7 +1937,7 @@ private:
// shift has side effects
if (((left && left->value.isZero()) ||
(right && Bits::getEffectiveShifts(right) == 0)) &&
- !EffectAnalyzer(passOptions, features, curr->right)
+ !EffectAnalyzer(passOptions, *getModule(), curr->right)
.hasSideEffects()) {
replaceCurrent(curr->left);
return;
@@ -1947,13 +1946,13 @@ private:
// multiplying by zero is a zero, unless the other side has side
// effects
if (left && left->value.isZero() &&
- !EffectAnalyzer(passOptions, features, curr->right)
+ !EffectAnalyzer(passOptions, *getModule(), curr->right)
.hasSideEffects()) {
replaceCurrent(left);
return;
}
if (right && right->value.isZero() &&
- !EffectAnalyzer(passOptions, features, curr->left)
+ !EffectAnalyzer(passOptions, *getModule(), curr->left)
.hasSideEffects()) {
replaceCurrent(right);
return;
@@ -2687,8 +2686,7 @@ private:
if (type.isInteger()) {
if (auto* inner = outer->right->dynCast<Binary>()) {
if (outer->op == inner->op) {
- if (!EffectAnalyzer(
- getPassOptions(), getModule()->features, outer->left)
+ if (!EffectAnalyzer(getPassOptions(), *getModule(), outer->left)
.hasSideEffects()) {
if (ExpressionAnalyzer::equal(inner->left, outer->left)) {
// x - (x - y) ==> y
@@ -2730,8 +2728,7 @@ private:
}
if (auto* inner = outer->left->dynCast<Binary>()) {
if (outer->op == inner->op) {
- if (!EffectAnalyzer(
- getPassOptions(), getModule()->features, outer->right)
+ if (!EffectAnalyzer(getPassOptions(), *getModule(), outer->right)
.hasSideEffects()) {
if (ExpressionAnalyzer::equal(inner->right, outer->right)) {
// (x ^ y) ^ y ==> x
@@ -3263,9 +3260,8 @@ private:
// the side effects execute once, so there is no problem.
// TODO: handle certain side effects when possible in select
bool validEffects = std::is_same<T, If>::value ||
- !ShallowEffectAnalyzer(getPassOptions(),
- getModule()->features,
- curr->ifTrue)
+ !ShallowEffectAnalyzer(
+ getPassOptions(), *getModule(), curr->ifTrue)
.hasSideEffects();
// In addition, check for specific limitations of select.
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index f80f9ba39..ea8a66612 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -65,7 +65,7 @@ stealSlice(Builder& builder, Block* input, Index from, Index to) {
static bool canTurnIfIntoBrIf(Expression* ifCondition,
Expression* brValue,
PassOptions& options,
- FeatureSet features) {
+ Module& wasm) {
// if the if isn't even reached, this is all dead code anyhow
if (ifCondition->type == Type::unreachable) {
return false;
@@ -73,11 +73,11 @@ static bool canTurnIfIntoBrIf(Expression* ifCondition,
if (!brValue) {
return true;
}
- EffectAnalyzer value(options, features, brValue);
+ EffectAnalyzer value(options, wasm, brValue);
if (value.hasSideEffects()) {
return false;
}
- return !EffectAnalyzer(options, features, ifCondition).invalidates(value);
+ return !EffectAnalyzer(options, wasm, ifCondition).invalidates(value);
}
// Check if it is not worth it to run code unconditionally. This
@@ -329,13 +329,12 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
void visitIf(If* curr) {
- FeatureSet features = getModule()->features;
if (!curr->ifFalse) {
// if without an else. try to reduce
// if (condition) br => br_if (condition)
if (Break* br = curr->ifTrue->dynCast<Break>()) {
if (canTurnIfIntoBrIf(
- curr->condition, br->value, getPassOptions(), features)) {
+ curr->condition, br->value, getPassOptions(), *getModule())) {
if (!br->condition) {
br->condition = curr->condition;
} else {
@@ -360,7 +359,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
// Of course we can't do this if the br's condition has side
// effects, as we would then execute those unconditionally.
- if (EffectAnalyzer(getPassOptions(), features, br->condition)
+ if (EffectAnalyzer(getPassOptions(), *getModule(), br->condition)
.hasSideEffects()) {
return;
}
@@ -555,7 +554,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
return false;
}
// if there is control flow, we must stop looking
- if (EffectAnalyzer(getPassOptions(), getModule()->features, curr)
+ if (EffectAnalyzer(getPassOptions(), *getModule(), curr)
.transfersControlFlow()) {
return false;
}
@@ -851,7 +850,6 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// the if is dead
// * note that we do this at the end, because un-conditionalizing can
// interfere with optimizeLoop()ing.
- FeatureSet features = getModule()->features;
auto& list = curr->list;
for (Index i = 0; i < list.size(); i++) {
auto* iff = list[i]->dynCast<If>();
@@ -862,8 +860,10 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
auto* ifTrueBreak = iff->ifTrue->dynCast<Break>();
if (ifTrueBreak && !ifTrueBreak->condition &&
- canTurnIfIntoBrIf(
- iff->condition, ifTrueBreak->value, passOptions, features)) {
+ canTurnIfIntoBrIf(iff->condition,
+ ifTrueBreak->value,
+ passOptions,
+ *getModule())) {
// we are an if-else where the ifTrue is a break without a
// condition, so we can do this
ifTrueBreak->condition = iff->condition;
@@ -875,8 +875,10 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// otherwise, perhaps we can flip the if
auto* ifFalseBreak = iff->ifFalse->dynCast<Break>();
if (ifFalseBreak && !ifFalseBreak->condition &&
- canTurnIfIntoBrIf(
- iff->condition, ifFalseBreak->value, passOptions, features)) {
+ canTurnIfIntoBrIf(iff->condition,
+ ifFalseBreak->value,
+ passOptions,
+ *getModule())) {
ifFalseBreak->condition =
Builder(*getModule()).makeUnary(EqZInt32, iff->condition);
ifFalseBreak->finalize();
@@ -905,7 +907,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
if (shrink && br2->type != Type::unreachable) {
// Join adjacent br_ifs to the same target, making one br_if
// with a "selectified" condition that executes both.
- if (!EffectAnalyzer(passOptions, features, br2->condition)
+ if (!EffectAnalyzer(passOptions, *getModule(), br2->condition)
.hasSideEffects()) {
// it's ok to execute them both, do it
Builder builder(*getModule());
@@ -933,10 +935,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// This switch has just one target no matter what; replace with a br
// if we can (to do so, we must put the condition before a possible
// value).
- if (!curr->value || EffectAnalyzer::canReorder(passOptions,
- getModule()->features,
- curr->condition,
- curr->value)) {
+ if (!curr->value ||
+ EffectAnalyzer::canReorder(
+ passOptions, *getModule(), curr->condition, curr->value)) {
Builder builder(*getModule());
replaceCurrent(builder.makeSequence(
builder.makeDrop(curr->condition), // might have side effects
@@ -1002,12 +1003,11 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
} else {
// To use an if, the value must have no side effects, as in the
// if it may not execute.
- FeatureSet features = getModule()->features;
- if (!EffectAnalyzer(passOptions, features, br->value)
+ if (!EffectAnalyzer(passOptions, *getModule(), br->value)
.hasSideEffects()) {
// We also need to reorder the condition and the value.
if (EffectAnalyzer::canReorder(
- passOptions, features, br->condition, br->value)) {
+ passOptions, *getModule(), br->condition, br->value)) {
ExpressionManipulator::nop(list[0]);
replaceCurrent(
builder.makeIf(br->condition, br->value, curr));
@@ -1045,9 +1045,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// after ignoring the br_if.
list[0] = &nop;
auto canReorder = EffectAnalyzer::canReorder(
- passOptions, features, br->condition, curr);
+ passOptions, *getModule(), br->condition, curr);
auto hasSideEffects =
- EffectAnalyzer(passOptions, features, curr)
+ EffectAnalyzer(passOptions, *getModule(), curr)
.hasSideEffects();
list[0] = old;
if (canReorder && !hasSideEffects &&
@@ -1099,16 +1099,15 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
// Check if side effects allow this: we need to execute the two arms
// unconditionally, and also to make the condition run last.
- FeatureSet features = getModule()->features;
- EffectAnalyzer ifTrue(passOptions, features, iff->ifTrue);
+ EffectAnalyzer ifTrue(passOptions, *getModule(), iff->ifTrue);
if (ifTrue.hasSideEffects()) {
return nullptr;
}
- EffectAnalyzer ifFalse(passOptions, features, iff->ifFalse);
+ EffectAnalyzer ifFalse(passOptions, *getModule(), iff->ifFalse);
if (ifFalse.hasSideEffects()) {
return nullptr;
}
- EffectAnalyzer condition(passOptions, features, iff->condition);
+ EffectAnalyzer condition(passOptions, *getModule(), iff->condition);
if (condition.invalidates(ifTrue) || condition.invalidates(ifFalse)) {
return nullptr;
}
@@ -1363,7 +1362,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
// if the condition has side effects, we can't replace many
// appearances of it with a single one
- if (EffectAnalyzer(passOptions, getModule()->features, conditionValue)
+ if (EffectAnalyzer(passOptions, *getModule(), conditionValue)
.hasSideEffects()) {
start++;
continue;
diff --git a/src/passes/SimplifyGlobals.cpp b/src/passes/SimplifyGlobals.cpp
index 5a6337bd6..f162d50c5 100644
--- a/src/passes/SimplifyGlobals.cpp
+++ b/src/passes/SimplifyGlobals.cpp
@@ -108,8 +108,7 @@ struct GlobalUseScanner : public WalkerPass<PostWalker<GlobalUseScanner>> {
}
// See if reading a specific global is the only effect the condition has.
- EffectAnalyzer condition(
- getPassOptions(), getModule()->features, curr->condition);
+ EffectAnalyzer condition(getPassOptions(), *getModule(), curr->condition);
if (condition.globalsRead.size() != 1) {
return;
@@ -123,8 +122,7 @@ struct GlobalUseScanner : public WalkerPass<PostWalker<GlobalUseScanner>> {
// See if writing the same global is the only effect the body has. (Note
// that we don't need to care about the case where the body has no effects
// at all - other pass would handle that trivial situation.)
- EffectAnalyzer ifTrue(
- getPassOptions(), getModule()->features, curr->ifTrue);
+ EffectAnalyzer ifTrue(getPassOptions(), *getModule(), curr->ifTrue);
if (ifTrue.globalsWritten.size() != 1) {
return;
}
@@ -210,7 +208,7 @@ struct ConstantGlobalApplier
return;
}
// Otherwise, invalidate if we need to.
- EffectAnalyzer effects(getPassOptions(), getModule()->features);
+ EffectAnalyzer effects(getPassOptions(), *getModule());
effects.visit(curr);
assert(effects.globalsWritten.empty()); // handled above
if (effects.calls) {
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index 77b8f1a93..ee0459d7d 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -79,10 +79,8 @@ struct SimplifyLocals
Expression** item;
EffectAnalyzer effects;
- SinkableInfo(Expression** item,
- PassOptions& passOptions,
- FeatureSet features)
- : item(item), effects(passOptions, features, *item) {}
+ SinkableInfo(Expression** item, PassOptions& passOptions, Module& module)
+ : item(item), effects(passOptions, module, *item) {}
};
// a list of sinkables in a linear execution trace
@@ -315,7 +313,7 @@ struct SimplifyLocals
}
}
- EffectAnalyzer effects(self->getPassOptions(), self->getModule()->features);
+ EffectAnalyzer effects(self->getPassOptions(), *self->getModule());
if (effects.checkPre(curr)) {
self->checkInvalidations(effects);
}
@@ -401,8 +399,7 @@ struct SimplifyLocals
}
}
- FeatureSet features = self->getModule()->features;
- EffectAnalyzer effects(self->getPassOptions(), features);
+ EffectAnalyzer effects(self->getPassOptions(), *self->getModule());
if (effects.checkPost(original)) {
self->checkInvalidations(effects);
}
@@ -411,7 +408,8 @@ struct SimplifyLocals
Index index = set->index;
assert(self->sinkables.count(index) == 0);
self->sinkables.emplace(std::make_pair(
- index, SinkableInfo(currp, self->getPassOptions(), features)));
+ index,
+ SinkableInfo(currp, self->getPassOptions(), *self->getModule())));
}
if (!allowNesting) {
@@ -428,7 +426,7 @@ struct SimplifyLocals
// 'catch', because 'pop' should follow right after 'catch'.
FeatureSet features = this->getModule()->features;
if (features.hasExceptionHandling() &&
- EffectAnalyzer(this->getPassOptions(), features, set->value)
+ EffectAnalyzer(this->getPassOptions(), *this->getModule(), set->value)
.danglingPop) {
return false;
}
@@ -530,7 +528,6 @@ struct SimplifyLocals
// )
// )
// so we must check for that.
- FeatureSet features = this->getModule()->features;
for (size_t j = 0; j < breaks.size(); j++) {
// move break local.set's value to the break
auto* breakLocalSetPointer = breaks[j].sinkables.at(sharedIndex).item;
@@ -548,8 +545,9 @@ struct SimplifyLocals
Nop nop;
*breakLocalSetPointer = &nop;
EffectAnalyzer condition(
- this->getPassOptions(), features, br->condition);
- EffectAnalyzer value(this->getPassOptions(), features, set);
+ this->getPassOptions(), *this->getModule(), br->condition);
+ EffectAnalyzer value(
+ this->getPassOptions(), *this->getModule(), set);
*breakLocalSetPointer = set;
if (condition.invalidates(value)) {
// indeed, we can't do this, stop
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index 14a464297..dec4add01 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -69,7 +69,6 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
// i32.eqz returns the same type as it receives. But for an expression that
// returns a different type, if the type matters then we cannot replace it.
Expression* optimize(Expression* curr, bool resultUsed, bool typeMatters) {
- FeatureSet features = getModule()->features;
auto type = curr->type;
// If the type is none, then we can never replace it with another type.
if (type == Type::none) {
@@ -102,7 +101,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
return curr;
}
// Check if this expression itself has side effects, ignoring children.
- EffectAnalyzer self(getPassOptions(), features);
+ EffectAnalyzer self(getPassOptions(), *getModule());
self.visit(curr);
if (self.hasSideEffects()) {
return curr;
@@ -111,7 +110,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
// get rid of it. However, the children may have side effects.
SmallVector<Expression*, 1> childrenWithEffects;
for (auto* child : ChildIterator(curr)) {
- if (EffectAnalyzer(getPassOptions(), features, child)
+ if (EffectAnalyzer(getPassOptions(), *getModule(), child)
.hasSideEffects()) {
childrenWithEffects.push_back(child);
}
@@ -292,7 +291,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
// Note that we check the type here to avoid removing unreachable code - we
// leave that for DCE.
if (curr->type == Type::none &&
- !EffectAnalyzer(getPassOptions(), getModule()->features, curr)
+ !EffectAnalyzer(getPassOptions(), *getModule(), curr)
.hasUnremovableSideEffects()) {
ExpressionManipulator::nop(curr);
return;
@@ -361,8 +360,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
void visitTry(Try* curr) {
// If try's body does not throw, the whole try-catch can be replaced with
// the try's body.
- if (!EffectAnalyzer(getPassOptions(), getModule()->features, curr->body)
- .throws) {
+ if (!EffectAnalyzer(getPassOptions(), *getModule(), curr->body).throws) {
replaceCurrent(curr->body);
for (auto* catchBody : curr->catchBodies) {
typeUpdater.noteRecursiveRemoval(catchBody);
@@ -379,7 +377,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
ExpressionManipulator::nop(curr->body);
}
if (curr->getResults() == Type::none &&
- !EffectAnalyzer(getPassOptions(), getModule()->features, curr->body)
+ !EffectAnalyzer(getPassOptions(), *getModule(), curr->body)
.hasSideEffects()) {
ExpressionManipulator::nop(curr->body);
}
diff --git a/src/wasm2js.h b/src/wasm2js.h
index ad8e32647..3e264f98b 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -1298,12 +1298,11 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
// If the target has effects that interact with the operands, we must
// reorder it to the start.
bool mustReorder = false;
- EffectAnalyzer targetEffects(
- parent->options, module->features, curr->target);
+ EffectAnalyzer targetEffects(parent->options, *module, curr->target);
if (targetEffects.hasAnything()) {
for (auto* operand : curr->operands) {
if (targetEffects.invalidates(
- EffectAnalyzer(parent->options, module->features, operand))) {
+ EffectAnalyzer(parent->options, *module, operand))) {
mustReorder = true;
break;
}
@@ -1930,11 +1929,9 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
// side effects, as a JS conditional does not visit both sides.
bool useLocals = false;
EffectAnalyzer conditionEffects(
- parent->options, module->features, curr->condition);
- EffectAnalyzer ifTrueEffects(
- parent->options, module->features, curr->ifTrue);
- EffectAnalyzer ifFalseEffects(
- parent->options, module->features, curr->ifFalse);
+ parent->options, *module, curr->condition);
+ EffectAnalyzer ifTrueEffects(parent->options, *module, curr->ifTrue);
+ EffectAnalyzer ifFalseEffects(parent->options, *module, curr->ifFalse);
if (conditionEffects.invalidates(ifTrueEffects) ||
conditionEffects.invalidates(ifFalseEffects) ||
ifTrueEffects.hasSideEffects() || ifFalseEffects.hasSideEffects()) {