@@ -41,19 +41,22 @@ template<typename P, typename T>
4141class MemoryAccessOptimizer {
4242public:
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
97101private:
@@ -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
269287private:
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