Skip to content

Commit aef3b1d

Browse files
Fix review
1 parent d673f1b commit aef3b1d

File tree

1 file changed

+43
-53
lines changed

1 file changed

+43
-53
lines changed

src/passes/SimplifyLocals.cpp

Lines changed: 43 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,15 @@ struct SimplifyLocals
9393

9494
// Reverse index: for each local L, tracks which sinkable keys have effects
9595
// that read L. This allows checkInvalidations to find conflicting sinkables
96-
// in O(|current effects|) instead of O(|all sinkables|).
96+
// in O(|current effects|) instead of O(|all sinkables|) when the current
97+
// expression only has local effects.
9798
std::unordered_map<Index, std::unordered_set<Index>> localReadBySinkable_;
9899

99100
// Reverse index: for each local L, tracks which sinkable keys have effects
100101
// that write L. A sinkable at key K always writes K, but may also write
101102
// other locals if its value contains nested local.sets.
102103
std::unordered_map<Index, std::unordered_set<Index>> localWrittenBySinkable_;
103104

104-
// Sinkable keys that have non-local ordering-relevant effects (calls,
105-
// memory, control flow, etc.). These need full orderedAfter checks when
106-
// the current expression also has non-local effects.
107-
std::unordered_set<Index> heavySinkables_;
108-
109105
void registerSinkable(Index key) {
110106
auto& effects = sinkables.at(key).effects;
111107
for (auto L : effects.localsRead) {
@@ -114,9 +110,6 @@ struct SimplifyLocals
114110
for (auto L : effects.localsWritten) {
115111
localWrittenBySinkable_[L].insert(key);
116112
}
117-
if (effects.hasNonLocalOrderingEffects()) {
118-
heavySinkables_.insert(key);
119-
}
120113
}
121114

122115
void unregisterSinkable(Index key) {
@@ -143,20 +136,17 @@ struct SimplifyLocals
143136
}
144137
}
145138
}
146-
heavySinkables_.erase(key);
147139
}
148140

149141
void clearSinkables() {
150142
sinkables.clear();
151143
localReadBySinkable_.clear();
152144
localWrittenBySinkable_.clear();
153-
heavySinkables_.clear();
154145
}
155146

156147
Sinkables takeSinkables() {
157148
localReadBySinkable_.clear();
158149
localWrittenBySinkable_.clear();
159-
heavySinkables_.clear();
160150
return std::move(sinkables);
161151
}
162152

@@ -384,56 +374,56 @@ struct SimplifyLocals
384374
}
385375

386376
void checkInvalidations(EffectAnalyzer& effects) {
387-
// Use targeted lookups instead of iterating all sinkables.
388-
// We collect candidate sinkable keys that *might* conflict, then verify.
389-
std::unordered_set<Index> candidates;
390-
391-
// Local conflicts via reverse indices.
392-
// When the current expression reads local L, any sinkable that writes L
393-
// has a write-read conflict.
394-
for (auto L : effects.localsRead) {
395-
auto it = localWrittenBySinkable_.find(L);
396-
if (it != localWrittenBySinkable_.end()) {
397-
candidates.insert(it->second.begin(), it->second.end());
377+
// If the current expression only has local effects, we can use reverse
378+
// indices to find exactly the conflicting sinkables in O(|locals|) instead
379+
// of iterating all sinkables. This is the common case for local.get,
380+
// local.set, const, and simple arithmetic expressions.
381+
if (!effects.hasNonLocalOrderingEffects()) {
382+
std::unordered_set<Index> candidates;
383+
// When the current expression reads local L, any sinkable that writes L
384+
// has a write-read conflict.
385+
for (auto L : effects.localsRead) {
386+
auto it = localWrittenBySinkable_.find(L);
387+
if (it != localWrittenBySinkable_.end()) {
388+
candidates.insert(it->second.begin(), it->second.end());
389+
}
398390
}
399-
}
400-
// When the current expression writes local L, any sinkable that reads L
401-
// (read-write conflict) or writes L (write-write conflict) is a candidate.
402-
for (auto L : effects.localsWritten) {
403-
auto it = localReadBySinkable_.find(L);
404-
if (it != localReadBySinkable_.end()) {
405-
candidates.insert(it->second.begin(), it->second.end());
391+
// When the current expression writes local L, any sinkable that reads L
392+
// (read-write conflict) or writes L (write-write conflict) is a
393+
// candidate.
394+
for (auto L : effects.localsWritten) {
395+
auto it = localReadBySinkable_.find(L);
396+
if (it != localReadBySinkable_.end()) {
397+
candidates.insert(it->second.begin(), it->second.end());
398+
}
399+
auto it2 = localWrittenBySinkable_.find(L);
400+
if (it2 != localWrittenBySinkable_.end()) {
401+
candidates.insert(it2->second.begin(), it2->second.end());
402+
}
406403
}
407-
auto it2 = localWrittenBySinkable_.find(L);
408-
if (it2 != localWrittenBySinkable_.end()) {
409-
candidates.insert(it2->second.begin(), it2->second.end());
404+
std::vector<Index> invalidated;
405+
for (auto key : candidates) {
406+
auto it = sinkables.find(key);
407+
if (it != sinkables.end() && effects.orderedAfter(it->second.effects)) {
408+
invalidated.push_back(key);
409+
}
410410
}
411-
}
412-
413-
// Non-local conflicts: if the current expression has non-local effects,
414-
// check sinkables that also have non-local effects.
415-
if (effects.hasNonLocalOrderingEffects()) {
416-
candidates.insert(heavySinkables_.begin(), heavySinkables_.end());
417-
}
418-
// If current transfers control flow, all sinkables with any side effects
419-
// (including local access) are invalidated. Since all sinkables access
420-
// locals, this means all of them.
421-
if (effects.transfersControlFlow()) {
422-
for (auto& [key, _] : sinkables) {
423-
candidates.insert(key);
411+
for (auto key : invalidated) {
412+
eraseSinkable(key);
424413
}
414+
return;
425415
}
426416

427-
// Verify candidates with the full ordering check and invalidate.
417+
// The current expression has non-local effects (memory, calls, control
418+
// flow, etc.), so we must check all sinkables.
428419
std::vector<Index> invalidated;
429-
for (auto key : candidates) {
430-
auto it = sinkables.find(key);
431-
if (it != sinkables.end() && effects.orderedAfter(it->second.effects)) {
432-
invalidated.push_back(key);
420+
for (auto& [index, info] : sinkables) {
421+
if (effects.orderedAfter(info.effects)) {
422+
invalidated.push_back(index);
433423
}
434424
}
435-
for (auto key : invalidated) {
436-
eraseSinkable(key);
425+
for (auto index : invalidated) {
426+
eraseSinkable(index);
437427
}
438428
}
439429

0 commit comments

Comments
 (0)