Skip to content

Commit 22fe326

Browse files
committed
Run multiple iterations in OptimizeAddedConstants
Multiple propagations may be possible in some cases, like nested structs in C.
1 parent 56fc114 commit 22fe326

12 files changed

Lines changed: 13766 additions & 13757 deletions

src/passes/OptimizeAddedConstants.cpp

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,22 @@ template<typename P, typename T>
4141
class MemoryAccessOptimizer {
4242
public:
4343
MemoryAccessOptimizer(P* parent, T* curr, Module* module, LocalGraph* localGraph) :
44-
parent(parent), curr(curr), module(module), localGraph(localGraph) {
44+
parent(parent), curr(curr), module(module), localGraph(localGraph) {}
45+
46+
// Tries to optimize, and returns whether we propagated a change.
47+
bool optimize() {
4548
// The pointer itself may be a constant, if e.g. it was precomputed or
4649
// a get that we propagated.
4750
if (curr->ptr->template is<Const>()) {
4851
optimizeConstantPointer();
49-
return;
52+
return false;
5053
}
5154
if (auto* add = curr->ptr->template dynCast<Binary>()) {
5255
if (add->op == AddInt32) {
5356
// Look for a constant on both sides.
5457
if (tryToOptimizeConstant(add->right, add->left) ||
5558
tryToOptimizeConstant(add->left, add->right)) {
56-
return;
59+
return false;
5760
}
5861
}
5962
}
@@ -84,14 +87,15 @@ class MemoryAccessOptimizer {
8487
// old value.
8588
if (tryToOptimizePropagatedAdd(add->right, add->left, get, set) ||
8689
tryToOptimizePropagatedAdd(add->left, add->right, get, set)) {
87-
return;
90+
return true;
8891
}
8992
}
9093
}
9194
}
9295
}
9396
}
9497
}
98+
return false;
9599
}
96100

97101
private:
@@ -233,23 +237,37 @@ struct OptimizeAddedConstants : public WalkerPass<PostWalker<OptimizeAddedConsta
233237
std::unique_ptr<LocalGraph> localGraph;
234238

235239
void visitLoad(Load* curr) {
236-
MemoryAccessOptimizer<OptimizeAddedConstants, Load>(this, curr, getModule(), localGraph.get());
240+
MemoryAccessOptimizer<OptimizeAddedConstants, Load> optimizer(this, curr, getModule(), localGraph.get());
241+
if (optimizer.optimize()) {
242+
propagated = true;
243+
}
237244
}
238245

239246
void visitStore(Store* curr) {
240-
MemoryAccessOptimizer<OptimizeAddedConstants, Store>(this, curr, getModule(), localGraph.get());
247+
MemoryAccessOptimizer<OptimizeAddedConstants, Store> optimizer(this, curr, getModule(), localGraph.get());
248+
if (optimizer.optimize()) {
249+
propagated = true;
250+
}
241251
}
242252

243253
void doWalkFunction(Function* func) {
244254
// This pass is only valid under the assumption of unused low memory.
245255
assert(getPassOptions().lowMemoryUnused);
246-
if (propagate) {
247-
localGraph = make_unique<LocalGraph>(func);
248-
localGraph->computeSSAIndexes();
249-
}
250-
super::doWalkFunction(func);
251-
if (!helperIndexes.empty()) {
252-
createHelperIndexes();
256+
// Multiple passes may be needed if we have x + 4 + 8 etc. (nested structs in C
257+
// can cause this, but it's rare). Note that we only need that for the propagation
258+
// case (as 4 + 8 would be optimized directly if it were adjacent).
259+
while (1) {
260+
propagated = false;
261+
if (propagate) {
262+
localGraph = make_unique<LocalGraph>(func);
263+
localGraph->computeSSAIndexes();
264+
}
265+
super::doWalkFunction(func);
266+
if (!helperIndexes.empty()) {
267+
createHelperIndexes();
268+
helperIndexes.clear();
269+
}
270+
if (!propagated) return;
253271
}
254272
}
255273

@@ -269,6 +287,8 @@ struct OptimizeAddedConstants : public WalkerPass<PostWalker<OptimizeAddedConsta
269287
private:
270288
std::map<SetLocal*, Index> helperIndexes;
271289

290+
bool propagated;
291+
272292
void createHelperIndexes() {
273293
struct Creator : public PostWalker<Creator> {
274294
std::map<SetLocal*, Index>& helperIndexes;

0 commit comments

Comments
 (0)