summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp62
1 files changed, 40 insertions, 22 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index ef7c17000..90abed825 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -330,6 +330,7 @@ struct OptimizeInstructions
// Optimizations that don't yet fit in the pattern DSL, but could be
// eventually maybe
Expression* handOptimize(Expression* curr) {
+ FeatureSet features = getModule()->features;
// if this contains dead code, don't bother trying to optimize it, the type
// might change (if might not be unreachable if just one arm is, for
// example). this optimization pass focuses on actually executing code. the
@@ -472,7 +473,7 @@ struct OptimizeInstructions
if (auto* subZero = sub->left->dynCast<Const>()) {
if (subZero->value.geti32() == 0) {
if (EffectAnalyzer::canReorder(
- getPassOptions(), sub->right, binary->right)) {
+ getPassOptions(), features, sub->right, binary->right)) {
sub->left = binary->right;
return sub;
}
@@ -630,7 +631,8 @@ struct OptimizeInstructions
}
// finally, try more expensive operations on the binary in
// the case that they have no side effects
- if (!EffectAnalyzer(getPassOptions(), binary->left).hasSideEffects()) {
+ if (!EffectAnalyzer(getPassOptions(), features, binary->left)
+ .hasSideEffects()) {
if (ExpressionAnalyzer::equal(binary->left, binary->right)) {
return optimizeBinaryWithEqualEffectlessChildren(binary);
}
@@ -750,7 +752,8 @@ struct OptimizeInstructions
// if we can replace the if with one arm, and no side effects in the
// condition, do that
auto needCondition =
- EffectAnalyzer(getPassOptions(), iff->condition).hasSideEffects();
+ EffectAnalyzer(getPassOptions(), features, iff->condition)
+ .hasSideEffects();
auto isSubType = Type::isSubType(iff->ifTrue->type, iff->type);
if (isSubType && !needCondition) {
return iff->ifTrue;
@@ -781,8 +784,8 @@ struct OptimizeInstructions
auto* condition = select->condition->dynCast<Unary>();
if (condition && condition->op == EqZInt32) {
// flip select to remove eqz, if we can reorder
- EffectAnalyzer ifTrue(getPassOptions(), select->ifTrue);
- EffectAnalyzer ifFalse(getPassOptions(), select->ifFalse);
+ EffectAnalyzer ifTrue(getPassOptions(), features, select->ifTrue);
+ EffectAnalyzer ifFalse(getPassOptions(), features, select->ifFalse);
if (!ifTrue.invalidates(ifFalse)) {
select->condition = condition->value;
std::swap(select->ifTrue, select->ifFalse);
@@ -792,7 +795,7 @@ struct OptimizeInstructions
// constant condition, we can just pick the right side (barring side
// effects)
if (c->value.getInteger()) {
- if (!EffectAnalyzer(getPassOptions(), select->ifFalse)
+ if (!EffectAnalyzer(getPassOptions(), features, select->ifFalse)
.hasSideEffects()) {
return select->ifTrue;
} else {
@@ -800,7 +803,7 @@ struct OptimizeInstructions
// local, which is bad
}
} else {
- if (!EffectAnalyzer(getPassOptions(), select->ifTrue)
+ if (!EffectAnalyzer(getPassOptions(), features, select->ifTrue)
.hasSideEffects()) {
return select->ifFalse;
} else {
@@ -812,7 +815,7 @@ struct OptimizeInstructions
}
if (ExpressionAnalyzer::equal(select->ifTrue, select->ifFalse)) {
// sides are identical, fold
- EffectAnalyzer value(getPassOptions(), select->ifTrue);
+ EffectAnalyzer value(getPassOptions(), features, select->ifTrue);
if (value.hasSideEffects()) {
// at best we don't need the condition, but need to execute the value
// twice. a block is larger than a select by 2 bytes, and
@@ -820,7 +823,8 @@ struct OptimizeInstructions
// so it's not clear this is worth it, TODO
} else {
// value has no side effects
- EffectAnalyzer condition(getPassOptions(), select->condition);
+ EffectAnalyzer condition(
+ getPassOptions(), features, select->condition);
if (!condition.hasSideEffects()) {
return select->ifTrue;
} else {
@@ -887,14 +891,15 @@ private:
// write more concise pattern matching code elsewhere.
void canonicalize(Binary* binary) {
assert(Properties::isSymmetric(binary));
+ FeatureSet features = getModule()->features;
auto swap = [&]() {
assert(EffectAnalyzer::canReorder(
- getPassOptions(), binary->left, binary->right));
+ getPassOptions(), features, binary->left, binary->right));
std::swap(binary->left, binary->right);
};
auto maybeSwap = [&]() {
if (EffectAnalyzer::canReorder(
- getPassOptions(), binary->left, binary->right)) {
+ getPassOptions(), features, binary->left, binary->right)) {
swap();
}
};
@@ -1064,6 +1069,7 @@ private:
ZeroRemover(PassOptions& passOptions) : passOptions(passOptions) {}
void visitBinary(Binary* curr) {
+ FeatureSet features = getModule()->features;
auto* left = curr->left->dynCast<Const>();
auto* right = curr->right->dynCast<Const>();
if (curr->op == AddInt32) {
@@ -1086,7 +1092,8 @@ private:
// shift has side effects
if (((left && left->value.geti32() == 0) ||
(right && Bits::getEffectiveShifts(right) == 0)) &&
- !EffectAnalyzer(passOptions, curr->right).hasSideEffects()) {
+ !EffectAnalyzer(passOptions, features, curr->right)
+ .hasSideEffects()) {
replaceCurrent(curr->left);
return;
}
@@ -1094,12 +1101,14 @@ private:
// multiplying by zero is a zero, unless the other side has side
// effects
if (left && left->value.geti32() == 0 &&
- !EffectAnalyzer(passOptions, curr->right).hasSideEffects()) {
+ !EffectAnalyzer(passOptions, features, curr->right)
+ .hasSideEffects()) {
replaceCurrent(left);
return;
}
if (right && right->value.geti32() == 0 &&
- !EffectAnalyzer(passOptions, curr->left).hasSideEffects()) {
+ !EffectAnalyzer(passOptions, features, curr->left)
+ .hasSideEffects()) {
replaceCurrent(right);
return;
}
@@ -1107,7 +1116,9 @@ private:
}
};
Expression* walked = binary;
- ZeroRemover(getPassOptions()).walk(walked);
+ ZeroRemover remover(getPassOptions());
+ remover.setModule(getModule());
+ remover.walk(walked);
if (constant == 0) {
return walked; // nothing more to do
}
@@ -1142,8 +1153,9 @@ private:
if (!Properties::emitsBoolean(left) || !Properties::emitsBoolean(right)) {
return nullptr;
}
- auto leftEffects = EffectAnalyzer(getPassOptions(), left);
- auto rightEffects = EffectAnalyzer(getPassOptions(), right);
+ FeatureSet features = getModule()->features;
+ auto leftEffects = EffectAnalyzer(getPassOptions(), features, left);
+ auto rightEffects = EffectAnalyzer(getPassOptions(), features, right);
auto leftHasSideEffects = leftEffects.hasSideEffects();
auto rightHasSideEffects = rightEffects.hasSideEffects();
if (leftHasSideEffects && rightHasSideEffects) {
@@ -1189,13 +1201,16 @@ private:
// (x > y) | (x == y) ==> x >= y
Expression* combineOr(Binary* binary) {
assert(binary->op == OrInt32);
+ FeatureSet features = getModule()->features;
if (auto* left = binary->left->dynCast<Binary>()) {
if (auto* right = binary->right->dynCast<Binary>()) {
if (left->op != right->op &&
ExpressionAnalyzer::equal(left->left, right->left) &&
ExpressionAnalyzer::equal(left->right, right->right) &&
- !EffectAnalyzer(getPassOptions(), left->left).hasSideEffects() &&
- !EffectAnalyzer(getPassOptions(), left->right).hasSideEffects()) {
+ !EffectAnalyzer(getPassOptions(), features, left->left)
+ .hasSideEffects() &&
+ !EffectAnalyzer(getPassOptions(), features, left->right)
+ .hasSideEffects()) {
switch (left->op) {
// (x > y) | (x == y) ==> x >= y
case EqInt32: {
@@ -1296,6 +1311,7 @@ private:
// is a constant
// TODO: templatize on type?
Expression* optimizeWithConstantOnRight(Binary* binary) {
+ FeatureSet features = getModule()->features;
auto type = binary->right->type;
auto* right = binary->right->cast<Const>();
if (type.isInteger()) {
@@ -1309,7 +1325,7 @@ private:
return binary->left;
} else if ((binary->op == Abstract::getBinary(type, Abstract::Mul) ||
binary->op == Abstract::getBinary(type, Abstract::And)) &&
- !EffectAnalyzer(getPassOptions(), binary->left)
+ !EffectAnalyzer(getPassOptions(), features, binary->left)
.hasSideEffects()) {
return binary->right;
} else if (binary->op == EqInt64) {
@@ -1323,7 +1339,7 @@ private:
if (binary->op == Abstract::getBinary(type, Abstract::And)) {
return binary->left;
} else if (binary->op == Abstract::getBinary(type, Abstract::Or) &&
- !EffectAnalyzer(getPassOptions(), binary->left)
+ !EffectAnalyzer(getPassOptions(), features, binary->left)
.hasSideEffects()) {
return binary->right;
}
@@ -1381,7 +1397,9 @@ private:
if ((binary->op == Abstract::getBinary(type, Abstract::Shl) ||
binary->op == Abstract::getBinary(type, Abstract::ShrU) ||
binary->op == Abstract::getBinary(type, Abstract::ShrS)) &&
- !EffectAnalyzer(getPassOptions(), binary->right).hasSideEffects()) {
+ !EffectAnalyzer(
+ getPassOptions(), getModule()->features, binary->right)
+ .hasSideEffects()) {
return binary->left;
}
}