summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast_utils.h66
-rw-r--r--src/pass.h4
-rw-r--r--src/passes/CodePushing.cpp19
-rw-r--r--src/passes/MergeBlocks.cpp10
-rw-r--r--src/passes/OptimizeInstructions.cpp8
-rw-r--r--src/passes/RemoveUnusedBrs.cpp27
-rw-r--r--src/passes/SimplifyLocals.cpp10
-rw-r--r--src/passes/Vacuum.cpp24
-rw-r--r--src/tools/optimization-options.h13
9 files changed, 121 insertions, 60 deletions
diff --git a/src/ast_utils.h b/src/ast_utils.h
index 2a151d8f7..35ad96987 100644
--- a/src/ast_utils.h
+++ b/src/ast_utils.h
@@ -71,11 +71,13 @@ struct BreakSeeker : public PostWalker<BreakSeeker, Visitor<BreakSeeker>> {
// TODO: optimize
struct EffectAnalyzer : public PostWalker<EffectAnalyzer, Visitor<EffectAnalyzer>> {
- EffectAnalyzer() {}
- EffectAnalyzer(Expression *ast) {
- analyze(ast);
+ EffectAnalyzer(PassOptions& passOptions, Expression *ast = nullptr) {
+ ignoreImplicitTraps = passOptions.ignoreImplicitTraps;
+ if (ast) analyze(ast);
}
+ bool ignoreImplicitTraps;
+
void analyze(Expression *ast) {
breakNames.clear();
walk(ast);
@@ -91,12 +93,18 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer, Visitor<EffectAnalyzer
std::set<Name> globalsWritten;
bool readsMemory = false;
bool writesMemory = false;
+ bool implicitTrap = false; // a load or div/rem, which may trap. we ignore trap
+ // differences, so it is ok to reorder these, and we
+ // also allow reordering them with other effects
+ // (so a trap may occur later or earlier, if it is
+ // going to occur anyhow), but we can't remove them,
+ // they count as side effects
bool accessesLocal() { return localsRead.size() + localsWritten.size() > 0; }
bool accessesGlobal() { return globalsRead.size() + globalsWritten.size() > 0; }
bool accessesMemory() { return calls || readsMemory || writesMemory; }
- bool hasSideEffects() { return calls || localsWritten.size() > 0 || writesMemory || branches || globalsWritten.size() > 0; }
- bool hasAnything() { return branches || calls || accessesLocal() || readsMemory || writesMemory || accessesGlobal(); }
+ bool hasSideEffects() { return calls || localsWritten.size() > 0 || writesMemory || branches || globalsWritten.size() > 0 || implicitTrap; }
+ bool hasAnything() { return branches || calls || accessesLocal() || readsMemory || writesMemory || accessesGlobal() || implicitTrap; }
// checks if these effects would invalidate another set (e.g., if we write, we invalidate someone that reads, they can't be moved past us)
bool invalidates(EffectAnalyzer& other) {
@@ -124,6 +132,10 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer, Visitor<EffectAnalyzer
for (auto global : globalsRead) {
if (other.globalsWritten.count(global)) return true;
}
+ // we are ok to reorder implicit traps, but not conditionalize them
+ if ((implicitTrap && other.branches) || (other.implicitTrap && branches)) {
+ return true;
+ }
return false;
}
@@ -189,8 +201,48 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer, Visitor<EffectAnalyzer
void visitSetGlobal(SetGlobal *curr) {
globalsWritten.insert(curr->name);
}
- void visitLoad(Load *curr) { readsMemory = true; }
- void visitStore(Store *curr) { writesMemory = true; }
+ void visitLoad(Load *curr) {
+ readsMemory = true;
+ if (!ignoreImplicitTraps) implicitTrap = true;
+ }
+ void visitStore(Store *curr) {
+ writesMemory = true;
+ if (!ignoreImplicitTraps) implicitTrap = true;
+ }
+ void visitUnary(Unary *curr) {
+ if (!ignoreImplicitTraps) {
+ switch (curr->op) {
+ case TruncSFloat32ToInt32:
+ case TruncSFloat32ToInt64:
+ case TruncUFloat32ToInt32:
+ case TruncUFloat32ToInt64:
+ case TruncSFloat64ToInt32:
+ case TruncSFloat64ToInt64:
+ case TruncUFloat64ToInt32:
+ case TruncUFloat64ToInt64: {
+ implicitTrap = true;
+ }
+ default: {}
+ }
+ }
+ }
+ void visitBinary(Binary *curr) {
+ if (!ignoreImplicitTraps) {
+ switch (curr->op) {
+ case DivSInt32:
+ case DivUInt32:
+ case RemSInt32:
+ case RemUInt32:
+ case DivSInt64:
+ case DivUInt64:
+ case RemSInt64:
+ case RemUInt64: {
+ implicitTrap = true;
+ }
+ default: {}
+ }
+ }
+ }
void visitReturn(Return *curr) { branches = true; }
void visitHost(Host *curr) { calls = true; }
void visitUnreachable(Unreachable *curr) { branches = true; }
diff --git a/src/pass.h b/src/pass.h
index dc9159aa0..74579e162 100644
--- a/src/pass.h
+++ b/src/pass.h
@@ -200,6 +200,10 @@ public:
return runner;
}
+ PassOptions& getPassOptions() {
+ return runner->options;
+ }
+
void setPassRunner(PassRunner* runner_) {
runner = runner_;
}
diff --git a/src/passes/CodePushing.cpp b/src/passes/CodePushing.cpp
index f4beff1a8..55b15ac9d 100644
--- a/src/passes/CodePushing.cpp
+++ b/src/passes/CodePushing.cpp
@@ -83,9 +83,10 @@ class Pusher {
ExpressionList& list;
LocalAnalyzer& analyzer;
std::vector<Index>& numGetsSoFar;
+ PassOptions& passOptions;
public:
- Pusher(Block* block, LocalAnalyzer& analyzer, std::vector<Index>& numGetsSoFar) : list(block->list), analyzer(analyzer), numGetsSoFar(numGetsSoFar) {
+ Pusher(Block* block, LocalAnalyzer& analyzer, std::vector<Index>& numGetsSoFar, PassOptions& passOptions) : list(block->list), analyzer(analyzer), numGetsSoFar(numGetsSoFar), passOptions(passOptions) {
// Find an optimization segment: from the first pushable thing, to the first
// point past which we want to push. We then push in that range before
// continuing forward.
@@ -119,7 +120,7 @@ private:
// but also have no side effects, as it may not execute if pushed.
if (analyzer.isSFA(index) &&
numGetsSoFar[index] == analyzer.getNumGets(index) &&
- !EffectAnalyzer(set->value).hasSideEffects()) {
+ !EffectAnalyzer(passOptions, set->value).hasSideEffects()) {
return set;
}
return nullptr;
@@ -146,8 +147,8 @@ private:
// of earlier ones. Once we know all we can push, we push it all
// in one pass, keeping the order of the pushables intact.
assert(firstPushable != Index(-1) && pushPoint != Index(-1) && firstPushable < pushPoint);
- EffectAnalyzer cumulativeEffects; // everything that matters if you want
- // to be pushed past the pushPoint
+ EffectAnalyzer cumulativeEffects(passOptions); // everything that matters if you want
+ // to be pushed past the pushPoint
cumulativeEffects.analyze(list[pushPoint]);
cumulativeEffects.branches = false; // it is ok to ignore the branching here,
// that is the crucial point of this opt
@@ -158,9 +159,13 @@ private:
if (pushable) {
auto iter = pushableEffects.find(pushable);
if (iter == pushableEffects.end()) {
- pushableEffects.emplace(pushable, pushable);
+ iter = pushableEffects.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(pushable),
+ std::forward_as_tuple(passOptions, pushable)
+ ).first;
}
- auto& effects = pushableEffects[pushable];
+ auto& effects = iter->second;
if (cumulativeEffects.invalidates(effects)) {
// we can't push this, so further pushables must pass it
cumulativeEffects.mergeIn(effects);
@@ -248,7 +253,7 @@ struct CodePushing : public WalkerPass<PostWalker<CodePushing, Visitor<CodePushi
// ordering invalidation issue, since if this isn't a loop, it's fine (we're not
// used outside), and if it is, we hit the assign before any use (as we can't
// push it past a use).
- Pusher pusher(curr, analyzer, numGetsSoFar);
+ Pusher pusher(curr, analyzer, numGetsSoFar, getPassOptions());
}
};
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index 383837beb..f8d044212 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -216,9 +216,9 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks, Visitor<MergeBloc
if (!child) return outer;
if ((dependency1 && *dependency1) || (dependency2 && *dependency2)) {
// there are dependencies, things we must be reordered through. make sure no problems there
- EffectAnalyzer childEffects(child);
- if (dependency1 && *dependency1 && EffectAnalyzer(*dependency1).invalidates(childEffects)) return outer;
- if (dependency2 && *dependency2 && EffectAnalyzer(*dependency2).invalidates(childEffects)) return outer;
+ EffectAnalyzer childEffects(getPassOptions(), child);
+ if (dependency1 && *dependency1 && EffectAnalyzer(getPassOptions(), *dependency1).invalidates(childEffects)) return outer;
+ if (dependency2 && *dependency2 && EffectAnalyzer(getPassOptions(), *dependency2).invalidates(childEffects)) return outer;
}
if (auto* block = child->dynCast<Block>()) {
if (!block->name.is() && block->list.size() >= 2) {
@@ -278,7 +278,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks, Visitor<MergeBloc
void handleCall(T* curr, Block* outer = nullptr) {
for (Index i = 0; i < curr->operands.size(); i++) {
outer = optimize(curr, curr->operands[i], outer);
- if (EffectAnalyzer(curr->operands[i]).hasSideEffects()) return;
+ if (EffectAnalyzer(getPassOptions(), curr->operands[i]).hasSideEffects()) return;
}
}
@@ -292,7 +292,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks, Visitor<MergeBloc
void visitCallIndirect(CallIndirect* curr) {
auto* outer = optimize(curr, curr->target);
- if (EffectAnalyzer(curr->target).hasSideEffects()) return;
+ if (EffectAnalyzer(getPassOptions(), curr->target).hasSideEffects()) return;
handleCall(curr, outer);
}
};
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 5c1aa5fc3..f94285930 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -317,8 +317,8 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
auto* condition = select->condition->dynCast<Unary>();
if (condition && condition->op == EqZInt32) {
// flip select to remove eqz, if we can reorder
- EffectAnalyzer ifTrue(select->ifTrue);
- EffectAnalyzer ifFalse(select->ifFalse);
+ EffectAnalyzer ifTrue(getPassOptions(), select->ifTrue);
+ EffectAnalyzer ifFalse(getPassOptions(), select->ifFalse);
if (!ifTrue.invalidates(ifFalse)) {
select->condition = condition->value;
std::swap(select->ifTrue, select->ifFalse);
@@ -408,8 +408,8 @@ private:
auto* left = binary->left;
auto* right = binary->right;
if (!Properties::emitsBoolean(left) || !Properties::emitsBoolean(right)) return nullptr;
- auto leftEffects = EffectAnalyzer(left).hasSideEffects();
- auto rightEffects = EffectAnalyzer(right).hasSideEffects();
+ auto leftEffects = EffectAnalyzer(getPassOptions(), left).hasSideEffects();
+ auto rightEffects = EffectAnalyzer(getPassOptions(), right).hasSideEffects();
if (leftEffects && rightEffects) return nullptr; // both must execute
// canonicalize with side effects, if any, happening on the left
if (rightEffects) {
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 69a7c4ff1..b4b188416 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -28,11 +28,11 @@ namespace wasm {
// to turn an if into a br-if, we must be able to reorder the
// condition and possible value, and the possible value must
// not have side effects (as they would run unconditionally)
-static bool canTurnIfIntoBrIf(Expression* ifCondition, Expression* brValue) {
+static bool canTurnIfIntoBrIf(Expression* ifCondition, Expression* brValue, PassOptions& options) {
if (!brValue) return true;
- EffectAnalyzer value(brValue);
+ EffectAnalyzer value(options, brValue);
if (value.hasSideEffects()) return false;
- return !EffectAnalyzer(ifCondition).invalidates(value);
+ return !EffectAnalyzer(options, ifCondition).invalidates(value);
}
struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<RemoveUnusedBrs>>> {
@@ -146,7 +146,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
// if without an else. try to reduce if (condition) br => br_if (condition)
Break* br = curr->ifTrue->dynCast<Break>();
if (br && !br->condition) { // TODO: if there is a condition, join them
- if (canTurnIfIntoBrIf(curr->condition, br->value)) {
+ if (canTurnIfIntoBrIf(curr->condition, br->value, getPassOptions())) {
br->condition = curr->condition;
br->finalize();
replaceCurrent(Builder(*getModule()).dropIfConcretelyTyped(br));
@@ -263,7 +263,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
return false;
}
// if there is control flow, we must stop looking
- if (EffectAnalyzer(curr).branches) {
+ if (EffectAnalyzer(getPassOptions(), curr).branches) {
return false;
}
if (i == 0) return false;
@@ -394,6 +394,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
// perform some final optimizations
struct FinalOptimizer : public PostWalker<FinalOptimizer, Visitor<FinalOptimizer>> {
bool selectify;
+ PassOptions& passOptions;
+
+ FinalOptimizer(PassOptions& passOptions) : passOptions(passOptions) {}
void visitBlock(Block* curr) {
// if a block has an if br else br, we can un-conditionalize the latter, allowing
@@ -406,7 +409,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
auto* iff = list[i]->dynCast<If>();
if (!iff || !iff->ifFalse || isConcreteWasmType(iff->type)) continue; // if it lacked an if-false, it would already be a br_if, as that's the easy case
auto* ifTrueBreak = iff->ifTrue->dynCast<Break>();
- if (ifTrueBreak && !ifTrueBreak->condition && canTurnIfIntoBrIf(iff->condition, ifTrueBreak->value)) {
+ if (ifTrueBreak && !ifTrueBreak->condition && canTurnIfIntoBrIf(iff->condition, ifTrueBreak->value, passOptions)) {
// we are an if-else where the ifTrue is a break without a condition, so we can do this
ifTrueBreak->condition = iff->condition;
ifTrueBreak->finalize();
@@ -416,7 +419,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
}
// otherwise, perhaps we can flip the if
auto* ifFalseBreak = iff->ifFalse->dynCast<Break>();
- if (ifFalseBreak && !ifFalseBreak->condition && canTurnIfIntoBrIf(iff->condition, ifFalseBreak->value)) {
+ if (ifFalseBreak && !ifFalseBreak->condition && canTurnIfIntoBrIf(iff->condition, ifFalseBreak->value, passOptions)) {
ifFalseBreak->condition = Builder(*getModule()).makeUnary(EqZInt32, iff->condition);
ifFalseBreak->finalize();
list[i] = Builder(*getModule()).dropIfConcretelyTyped(ifFalseBreak);
@@ -435,7 +438,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
if (!br2 || !br2->condition) continue;
if (br1->name == br2->name) {
assert(!br1->value && !br2->value);
- if (!EffectAnalyzer(br2->condition).hasSideEffects()) {
+ if (!EffectAnalyzer(passOptions, br2->condition).hasSideEffects()) {
// it's ok to execute them both, do it
Builder builder(*getModule());
br1->condition = builder.makeBinary(OrInt32, br1->condition, br2->condition);
@@ -480,11 +483,11 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
if (curr->ifFalse && isConcreteWasmType(curr->ifTrue->type) && isConcreteWasmType(curr->ifFalse->type)) {
// if with else, consider turning it into a select if there is no control flow
// TODO: estimate cost
- EffectAnalyzer condition(curr->condition);
+ EffectAnalyzer condition(passOptions, curr->condition);
if (!condition.hasSideEffects()) {
- EffectAnalyzer ifTrue(curr->ifTrue);
+ EffectAnalyzer ifTrue(passOptions, curr->ifTrue);
if (!ifTrue.hasSideEffects()) {
- EffectAnalyzer ifFalse(curr->ifFalse);
+ EffectAnalyzer ifFalse(passOptions, curr->ifFalse);
if (!ifFalse.hasSideEffects()) {
auto* select = getModule()->allocator.alloc<Select>();
select->condition = curr->condition;
@@ -498,7 +501,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
}
}
};
- FinalOptimizer finalOptimizer;
+ FinalOptimizer finalOptimizer(getPassOptions());
finalOptimizer.setModule(getModule());
finalOptimizer.selectify = getPassRunner()->options.shrinkLevel > 0;
finalOptimizer.walkFunction(func);
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index 6509c9da5..8590fbe96 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -84,9 +84,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
Expression** item;
EffectAnalyzer effects;
- SinkableInfo(Expression** item) : item(item) {
- effects.walk(*item);
- }
+ SinkableInfo(Expression** item, PassOptions& passOptions) : item(item), effects(passOptions, *item) {}
};
// a list of sinkables in a linear execution trace
@@ -246,7 +244,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
static void visitPre(SimplifyLocals* self, Expression** currp) {
Expression* curr = *currp;
- EffectAnalyzer effects;
+ EffectAnalyzer effects(self->getPassOptions());
if (effects.checkPre(curr)) {
self->checkInvalidations(effects);
}
@@ -274,7 +272,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
}
}
- EffectAnalyzer effects;
+ EffectAnalyzer effects(self->getPassOptions());
if (effects.checkPost(*currp)) {
self->checkInvalidations(effects);
}
@@ -282,7 +280,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
if (set && self->canSink(set)) {
Index index = set->index;
assert(self->sinkables.count(index) == 0);
- self->sinkables.emplace(std::make_pair(index, SinkableInfo(currp)));
+ self->sinkables.emplace(std::make_pair(index, SinkableInfo(currp, self->getPassOptions())));
}
self->expressionStack.pop_back();
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index 8d9bb421c..38e607c24 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -74,22 +74,22 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
}
// for unary, binary, and select, we need to check their arguments for side effects
if (auto* unary = curr->dynCast<Unary>()) {
- if (EffectAnalyzer(unary->value).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), unary->value).hasSideEffects()) {
curr = unary->value;
continue;
} else {
return nullptr;
}
} else if (auto* binary = curr->dynCast<Binary>()) {
- if (EffectAnalyzer(binary->left).hasSideEffects()) {
- if (EffectAnalyzer(binary->right).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), binary->left).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), binary->right).hasSideEffects()) {
return curr; // leave them
} else {
curr = binary->left;
continue;
}
} else {
- if (EffectAnalyzer(binary->right).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), binary->right).hasSideEffects()) {
curr = binary->right;
continue;
} else {
@@ -99,11 +99,11 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
} else {
// TODO: if two have side effects, we could replace the select with say an add?
auto* select = curr->cast<Select>();
- if (EffectAnalyzer(select->ifTrue).hasSideEffects()) {
- if (EffectAnalyzer(select->ifFalse).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->ifTrue).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->ifFalse).hasSideEffects()) {
return curr; // leave them
} else {
- if (EffectAnalyzer(select->condition).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->condition).hasSideEffects()) {
return curr; // leave them
} else {
curr = select->ifTrue;
@@ -111,15 +111,15 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
}
}
} else {
- if (EffectAnalyzer(select->ifFalse).hasSideEffects()) {
- if (EffectAnalyzer(select->condition).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->ifFalse).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->condition).hasSideEffects()) {
return curr; // leave them
} else {
curr = select->ifFalse;
continue;
}
} else {
- if (EffectAnalyzer(select->condition).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->condition).hasSideEffects()) {
curr = select->condition;
continue;
} else {
@@ -174,7 +174,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
if (!curr->name.is()) {
if (list.size() == 1) {
// just one element. replace the block, either with it or with a nop if it's not needed
- if (isConcreteWasmType(curr->type) || EffectAnalyzer(list[0]).hasSideEffects()) {
+ if (isConcreteWasmType(curr->type) || EffectAnalyzer(getPassOptions(), list[0]).hasSideEffects()) {
replaceCurrent(list[0]);
} else {
if (curr->type == unreachable) {
@@ -307,7 +307,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
} else {
ExpressionManipulator::nop(curr->body);
}
- if (curr->result == none && !EffectAnalyzer(curr->body).hasSideEffects()) {
+ if (curr->result == none && !EffectAnalyzer(getPassOptions(), curr->body).hasSideEffects()) {
ExpressionManipulator::nop(curr->body);
}
}
diff --git a/src/tools/optimization-options.h b/src/tools/optimization-options.h
index 7f3936d35..368e319a7 100644
--- a/src/tools/optimization-options.h
+++ b/src/tools/optimization-options.h
@@ -23,7 +23,6 @@
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
passOptions.optimizeLevel = 2;
passOptions.shrinkLevel = 1;
- passOptions.ignoreImplicitTraps = true;
runOptimizationPasses = true;
})
.add("", "-O0", "execute no optimization passes",
@@ -31,14 +30,12 @@
[&passOptions](Options*, const std::string&) {
passOptions.optimizeLevel = 0;
passOptions.shrinkLevel = 0;
- passOptions.ignoreImplicitTraps = false;
})
.add("", "-O1", "execute -O1 optimization passes",
Options::Arguments::Zero,
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
passOptions.optimizeLevel = 1;
passOptions.shrinkLevel = 0;
- passOptions.ignoreImplicitTraps = true;
runOptimizationPasses = true;
})
.add("", "-O2", "execute -O2 optimization passes",
@@ -46,7 +43,6 @@
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
passOptions.optimizeLevel = 2;
passOptions.shrinkLevel = 0;
- passOptions.ignoreImplicitTraps = true;
runOptimizationPasses = true;
})
.add("", "-O3", "execute -O3 optimization passes",
@@ -54,7 +50,6 @@
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
passOptions.optimizeLevel = 3;
passOptions.shrinkLevel = 0;
- passOptions.ignoreImplicitTraps = true;
runOptimizationPasses = true;
})
.add("", "-Os", "execute default optimization passes, focusing on code size",
@@ -62,7 +57,6 @@
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
passOptions.optimizeLevel = 2;
passOptions.shrinkLevel = 1;
- passOptions.ignoreImplicitTraps = true;
runOptimizationPasses = true;
})
.add("", "-Oz", "execute default optimization passes, super-focusing on code size",
@@ -70,7 +64,6 @@
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
passOptions.optimizeLevel = 2;
passOptions.shrinkLevel = 2;
- passOptions.ignoreImplicitTraps = true;
runOptimizationPasses = true;
})
.add("--optimize-level", "-ol", "How much to focus on optimizing code",
@@ -83,3 +76,9 @@
[&passOptions](Options* o, const std::string& argument) {
passOptions.shrinkLevel = atoi(argument.c_str());
})
+ .add("--ignore-implicit-traps", "-iit", "Optimize under the helpful assumption that no surprising traps occur (from load, div/mod, etc.)",
+ Options::Arguments::Zero,
+ [&runOptimizationPasses, &passOptions](Options*, const std::string&) {
+ passOptions.ignoreImplicitTraps = true;
+ })
+