summaryrefslogtreecommitdiff
path: root/src/passes/Precompute.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/Precompute.cpp')
-rw-r--r--src/passes/Precompute.cpp58
1 files changed, 27 insertions, 31 deletions
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index 176642fd6..0a4a691f2 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -47,7 +47,7 @@ static const Name NOTPRECOMPUTABLE_FLOW("Binaryen|notprecomputable");
// helpful to avoid platform differences in native stack sizes.
static const Index MAX_DEPTH = 50;
-typedef std::unordered_map<LocalGet*, Literal> GetValues;
+typedef std::unordered_map<LocalGet*, Literals> GetValues;
// Precomputes an expression. Errors if we hit anything that can't be
// precomputed.
@@ -89,9 +89,9 @@ public:
Flow visitLocalGet(LocalGet* curr) {
auto iter = getValues.find(curr);
if (iter != getValues.end()) {
- auto value = iter->second;
- if (value.isConcrete()) {
- return Flow(value);
+ auto values = iter->second;
+ if (values.isConcrete()) {
+ return Flow(std::move(values));
}
}
return Flow(NOTPRECOMPUTABLE_FLOW);
@@ -188,10 +188,6 @@ struct Precompute
}
// try to evaluate this into a const
Flow flow = precomputeExpression(curr);
- if (flow.values.size() > 1) {
- // TODO: handle multivalue types
- return;
- }
if (flow.getType().hasVector()) {
return;
}
@@ -203,7 +199,7 @@ struct Precompute
// this expression causes a return. if it's already a return, reuse the
// node
if (auto* ret = curr->dynCast<Return>()) {
- if (flow.values.size() > 0) {
+ if (flow.values.isConcrete()) {
// reuse a const value if there is one
if (ret->value && flow.values.size() == 1) {
if (auto* value = ret->value->dynCast<Const>()) {
@@ -219,8 +215,8 @@ struct Precompute
} else {
Builder builder(*getModule());
replaceCurrent(builder.makeReturn(
- flow.values.size() > 0 ? flow.getConstExpression(*getModule())
- : nullptr));
+ flow.values.isConcrete() ? flow.getConstExpression(*getModule())
+ : nullptr));
}
return;
}
@@ -229,7 +225,7 @@ struct Precompute
if (auto* br = curr->dynCast<Break>()) {
br->name = flow.breakTo;
br->condition = nullptr;
- if (flow.values.size() > 0) {
+ if (flow.values.isConcrete()) {
// reuse a const value if there is one
if (br->value && flow.values.size() == 1) {
if (auto* value = br->value->dynCast<Const>()) {
@@ -248,13 +244,13 @@ struct Precompute
Builder builder(*getModule());
replaceCurrent(builder.makeBreak(
flow.breakTo,
- flow.values.size() > 0 ? flow.getConstExpression(*getModule())
- : nullptr));
+ flow.values.isConcrete() ? flow.getConstExpression(*getModule())
+ : nullptr));
}
return;
}
// this was precomputed
- if (flow.getType().isConcrete()) {
+ if (flow.values.isConcrete()) {
replaceCurrent(flow.getConstExpression(*getModule()));
worked = true;
} else {
@@ -287,14 +283,14 @@ private:
// (local.tee (i32.const 1))
// will have value 1 which we can optimize here, but in precomputeExpression
// we could not do anything.
- Literal precomputeValue(Expression* curr) {
+ Literals precomputeValue(Expression* curr) {
// Note that we set replaceExpression to false, as we just care about
// the value here.
Flow flow = precomputeExpression(curr, false /* replaceExpression */);
if (flow.breaking()) {
- return Literal();
+ return {};
}
- return flow.getSingleValue();
+ return flow.values;
}
// Propagates values around. Returns whether we propagated.
@@ -315,7 +311,7 @@ private:
work.insert(curr);
}
// the constant value, or none if not a constant
- std::unordered_map<LocalSet*, Literal> setValues;
+ std::unordered_map<LocalSet*, Literals> setValues;
// propagate constant values
while (!work.empty()) {
auto iter = work.begin();
@@ -328,30 +324,30 @@ private:
if (setValues[set].isConcrete()) {
continue; // already known constant
}
- auto value = setValues[set] =
+ auto values = setValues[set] =
precomputeValue(Properties::getFallthrough(
set->value, getPassOptions(), getModule()->features));
- if (value.isConcrete()) {
+ if (values.isConcrete()) {
for (auto* get : localGraph.setInfluences[set]) {
work.insert(get);
}
}
} else {
auto* get = curr->cast<LocalGet>();
- if (getValues[get].isConcrete()) {
+ if (getValues[get].size() >= 1) {
continue; // already known constant
}
// for this get to have constant value, all sets must agree
- Literal value;
+ Literals values;
bool first = true;
for (auto* set : localGraph.getSetses[get]) {
- Literal curr;
+ Literals curr;
if (set == nullptr) {
if (getFunction()->isVar(get->index)) {
curr = Literal::makeZero(getFunction()->getLocalType(get->index));
} else {
// it's a param, so it's hopeless
- value = Literal();
+ values = {};
break;
}
} else {
@@ -359,25 +355,25 @@ private:
}
if (curr.isNone()) {
// not a constant, give up
- value = Literal();
+ values = {};
break;
}
// we found a concrete value. compare with the current one
if (first) {
- value = curr; // this is the first
+ values = curr; // this is the first
first = false;
} else {
- if (value != curr) {
+ if (values != curr) {
// not the same, give up
- value = Literal();
+ values = {};
break;
}
}
}
// we may have found a value
- if (value.isConcrete()) {
+ if (values.isConcrete()) {
// we did!
- getValues[get] = value;
+ getValues[get] = values;
for (auto* set : localGraph.getInfluences[get]) {
work.insert(set);
}