summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/CoalesceLocals.cpp51
1 files changed, 46 insertions, 5 deletions
diff --git a/src/passes/CoalesceLocals.cpp b/src/passes/CoalesceLocals.cpp
index 2063a20db..693a13131 100644
--- a/src/passes/CoalesceLocals.cpp
+++ b/src/passes/CoalesceLocals.cpp
@@ -198,6 +198,7 @@ struct CoalesceLocals : public WalkerPass<CFGWalker<CoalesceLocals, Visitor<Coal
void scanLivenessThroughActions(std::vector<Action>& actions, LocalSet& live);
void pickIndicesFromOrder(std::vector<Index>& order, std::vector<Index>& indices);
+ void pickIndicesFromOrder(std::vector<Index>& order, std::vector<Index>& indices, Index& removedCopies);
virtual void pickIndices(std::vector<Index>& indices); // returns a vector of oldIndex => newIndex
@@ -388,8 +389,38 @@ void CoalesceLocals::calculateInterferences(const LocalSet& locals) {
// Indices decision making
void CoalesceLocals::pickIndicesFromOrder(std::vector<Index>& order, std::vector<Index>& indices) {
+ Index removedCopies;
+ pickIndicesFromOrder(order, indices, removedCopies);
+}
+
+void CoalesceLocals::pickIndicesFromOrder(std::vector<Index>& order, std::vector<Index>& indices, Index& removedCopies) {
// simple greedy coloring
- // TODO: take into account eliminated copies
+#if CFG_DEBUG
+ std::cerr << "pickIndicesFromOrder on " << getFunction()->name << '\n';
+ std::cerr << "order:\n";
+ for (auto i : order) std::cerr << i << ' ';
+ std::cerr << '\n';
+ std::cerr << "interferences:\n";
+ for (Index i = 0; i < numLocals; i++) {
+ for (Index j = 0; j < i + 1; j++) {
+ std::cerr << " ";
+ }
+ for (Index j = i + 1; j < numLocals; j++) {
+ std::cerr << int(interferes(i, j)) << ' ';
+ }
+ std::cerr << '\n';
+ }
+ std::cerr << "copies:\n";
+ for (Index i = 0; i < numLocals; i++) {
+ for (Index j = 0; j < i + 1; j++) {
+ std::cerr << " ";
+ }
+ for (Index j = i + 1; j < numLocals; j++) {
+ std::cerr << int(getCopies(i, j)) << ' ';
+ }
+ std::cerr << '\n';
+ }
+#endif
// TODO: take into account distribution (99-1 is better than 50-50 with two registers, for gzip)
std::vector<WasmType> types;
std::vector<bool> newInterferences; // new index * numLocals => list of all interferences of locals merged to it
@@ -401,6 +432,7 @@ void CoalesceLocals::pickIndicesFromOrder(std::vector<Index>& order, std::vector
std::fill(newInterferences.begin(), newInterferences.end(), 0);
std::fill(newCopies.begin(), newCopies.end(), 0);
Index nextFree = 0;
+ removedCopies = 0;
// we can't reorder parameters, they are fixed in order, and cannot coalesce
auto numParams = getFunction()->getNumParams();
Index i = 0;
@@ -432,6 +464,9 @@ void CoalesceLocals::pickIndicesFromOrder(std::vector<Index>& order, std::vector
indices[actual] = found = nextFree;
types[found] = getFunction()->getLocalType(actual);
nextFree++;
+ removedCopies += newCopies[found * numLocals + actual];
+ } else {
+ removedCopies += foundCopies;
}
// merge new interferences and copies for the new index
for (Index k = i + 1; k < numLocals; k++) {
@@ -455,7 +490,8 @@ void CoalesceLocals::pickIndices(std::vector<Index>& indices) {
for (Index i = 0; i < numLocals; i++) {
order[i] = i;
}
- pickIndicesFromOrder(order, indices);
+ Index removedCopies;
+ pickIndicesFromOrder(order, indices, removedCopies);
auto maxIndex = *std::max_element(indices.begin(), indices.end());
// next try the reverse order. this both gives us anothe chance at something good,
// and also the very naturalness of the simple order may be quite suboptimal
@@ -464,9 +500,12 @@ void CoalesceLocals::pickIndices(std::vector<Index>& indices) {
order[i] = numParams + numLocals - 1 - i;
}
std::vector<Index> reverseIndices;
- pickIndicesFromOrder(order, reverseIndices);
+ Index reverseRemovedCopies;
+ pickIndicesFromOrder(order, reverseIndices, reverseRemovedCopies);
auto reverseMaxIndex = *std::max_element(reverseIndices.begin(), reverseIndices.end());
- if (reverseMaxIndex < maxIndex) {
+ // prefer to remove copies foremost, as it matters more for code size (minus gzip), and
+ // improves throughput.
+ if (reverseRemovedCopies > removedCopies || (reverseRemovedCopies == removedCopies && reverseMaxIndex < maxIndex)) {
indices.swap(reverseIndices);
}
}
@@ -553,7 +592,8 @@ void CoalesceLocalsWithLearning::pickIndices(std::vector<Index>& indices) {
void calculateFitness(Order* order) {
// apply the order
std::vector<Index> indices; // the phenotype
- parent->pickIndicesFromOrder(*order, indices);
+ Index removedCopies;
+ parent->pickIndicesFromOrder(*order, indices, removedCopies);
auto maxIndex = *std::max_element(indices.begin(), indices.end());
assert(maxIndex <= parent->numLocals);
// main part of fitness is the number of locals
@@ -563,6 +603,7 @@ void CoalesceLocalsWithLearning::pickIndices(std::vector<Index>& indices) {
for (Index i = 0; i < parent->numLocals; i++) {
if ((*order)[i] == i) fitness += fragment; // boost for each that wasn't moved
}
+ fitness = (100 * fitness) + removedCopies; // removing copies is a secondary concern
order->setFitness(fitness);
}