@@ -97,31 +97,30 @@ void RedundantAssignEliminator::operator()(FunctionDefinition const& _functionDe
97
97
{
98
98
std::set<YulString> outerDeclaredVariables;
99
99
TrackedAssignments outerAssignments;
100
+ ForLoopInfo forLoopInfo;
100
101
swap (m_declaredVariables, outerDeclaredVariables);
101
102
swap (m_assignments, outerAssignments);
103
+ swap (m_forLoopInfo, forLoopInfo);
102
104
103
105
(*this )(_functionDefinition.body );
104
106
105
107
for (auto const & param: _functionDefinition.parameters )
106
- {
107
- changeUndecidedTo (param.name , State::Unused);
108
- finalize (param.name );
109
- }
108
+ finalize (param.name , State::Unused);
110
109
for (auto const & retParam: _functionDefinition.returnVariables )
111
- {
112
- changeUndecidedTo (retParam.name , State::Used);
113
- finalize (retParam.name );
114
- }
110
+ finalize (retParam.name , State::Used);
115
111
116
112
swap (m_declaredVariables, outerDeclaredVariables);
117
113
swap (m_assignments, outerAssignments);
114
+ swap (m_forLoopInfo, forLoopInfo);
118
115
}
119
116
120
117
void RedundantAssignEliminator::operator ()(ForLoop const & _forLoop)
121
118
{
122
- // This will set all variables that are declared in this
123
- // block to "unused" when it is destroyed.
124
- BlockScope scope (*this );
119
+ ForLoopInfo outerForLoopInfo;
120
+ swap (outerForLoopInfo, m_forLoopInfo);
121
+
122
+ set<YulString> outerDeclaredVariables;
123
+ swap (m_declaredVariables, outerDeclaredVariables);
125
124
126
125
// We need to visit the statements directly because of the
127
126
// scoping rules.
@@ -133,9 +132,6 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
133
132
134
133
visit (*_forLoop.condition );
135
134
136
- ForLoopInfo outerForLoopInfo;
137
- swap (outerForLoopInfo, m_forLoopInfo);
138
-
139
135
TrackedAssignments zeroRuns{m_assignments};
140
136
141
137
(*this )(_forLoop.body );
@@ -150,6 +146,7 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
150
146
(*this )(_forLoop.body );
151
147
152
148
merge (m_assignments, move (m_forLoopInfo.pendingContinueStmts ));
149
+ m_forLoopInfo.pendingContinueStmts = {};
153
150
(*this )(_forLoop.post );
154
151
155
152
visit (*_forLoop.condition );
@@ -159,27 +156,37 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
159
156
merge (m_assignments, move (zeroRuns));
160
157
merge (m_assignments, move (m_forLoopInfo.pendingBreakStmts ));
161
158
162
- // Oestore potential outer for-loop states.
159
+ for (auto const & var: m_declaredVariables)
160
+ finalize (var, State::Unused);
161
+ swap (m_declaredVariables, outerDeclaredVariables);
162
+
163
+ // Restore potential outer for-loop states.
163
164
swap (m_forLoopInfo, outerForLoopInfo);
164
165
}
165
166
166
167
void RedundantAssignEliminator::operator ()(Break const &)
167
168
{
168
- m_forLoopInfo.pendingBreakStmts .push_back (m_assignments);
169
+ m_forLoopInfo.pendingBreakStmts .emplace_back (move (m_assignments));
170
+ m_assignments.clear ();
169
171
}
170
172
171
173
void RedundantAssignEliminator::operator ()(Continue const &)
172
174
{
173
- m_forLoopInfo.pendingContinueStmts .push_back (m_assignments);
175
+ m_forLoopInfo.pendingContinueStmts .emplace_back (move (m_assignments));
176
+ m_assignments.clear ();
174
177
}
175
178
176
179
void RedundantAssignEliminator::operator ()(Block const & _block)
177
180
{
178
- // This will set all variables that are declared in this
179
- // block to "unused" when it is destroyed.
180
- BlockScope scope (*this );
181
+ set<YulString> outerDeclaredVariables;
182
+ swap (m_declaredVariables, outerDeclaredVariables);
181
183
182
184
ASTWalker::operator ()(_block);
185
+
186
+ for (auto const & var: m_declaredVariables)
187
+ finalize (var, State::Unused);
188
+
189
+ swap (m_declaredVariables, outerDeclaredVariables);
183
190
}
184
191
185
192
void RedundantAssignEliminator::run (Dialect const & _dialect, Block& _ast)
@@ -239,21 +246,38 @@ void RedundantAssignEliminator::merge(TrackedAssignments& _target, vector<Tracke
239
246
void RedundantAssignEliminator::changeUndecidedTo (YulString _variable, RedundantAssignEliminator::State _newState)
240
247
{
241
248
for (auto & assignment: m_assignments[_variable])
242
- if (assignment.second == State{State ::Undecided} )
249
+ if (assignment.second == State::Undecided)
243
250
assignment.second = _newState;
244
251
}
245
252
246
- void RedundantAssignEliminator::finalize (YulString _variable)
253
+ void RedundantAssignEliminator::finalize (YulString _variable, RedundantAssignEliminator::State _finalState )
247
254
{
248
- for (auto & assignment: m_assignments[_variable])
255
+ finalize (m_assignments, _variable, _finalState);
256
+ for (auto & assignments: m_forLoopInfo.pendingBreakStmts )
257
+ finalize (assignments, _variable, _finalState);
258
+ for (auto & assignments: m_forLoopInfo.pendingContinueStmts )
259
+ finalize (assignments, _variable, _finalState);
260
+ }
261
+
262
+ void RedundantAssignEliminator::finalize (
263
+ TrackedAssignments& _assignments,
264
+ YulString _variable,
265
+ RedundantAssignEliminator::State _finalState
266
+ )
267
+ {
268
+ for (auto const & assignment: _assignments[_variable])
249
269
{
250
- assertThrow (assignment.second != State::Undecided, OptimizerException, " " );
251
- if (assignment.second == State{State::Unused} && MovableChecker{*m_dialect, *assignment.first ->value }.movable ())
270
+ State state = assignment.second ;
271
+ if (state == State::Undecided)
272
+ state = _finalState;
273
+
274
+ assertThrow (state != State::Undecided, OptimizerException, " " );
275
+ if (state == State::Unused && MovableChecker{*m_dialect, *assignment.first ->value }.movable ())
252
276
// TODO the only point where we actually need this
253
277
// to be a set is for the for loop
254
278
m_pendingRemovals.insert (assignment.first );
255
279
}
256
- m_assignments .erase (_variable);
280
+ _assignments .erase (_variable);
257
281
}
258
282
259
283
void AssignmentRemover::operator ()(Block& _block)
0 commit comments