|
18 | 18 | #include "llvm/Analysis/MemorySSA.h" |
19 | 19 | #include "llvm/IR/BasicBlock.h" |
20 | 20 | #include "llvm/IR/Dominators.h" |
| 21 | +#include "llvm/Support/CommandLine.h" |
21 | 22 | #include "llvm/Support/Debug.h" |
22 | 23 | #include <algorithm> |
23 | 24 |
|
24 | 25 | #define DEBUG_TYPE "memoryssa" |
25 | 26 | using namespace llvm; |
26 | 27 |
|
| 28 | +static cl::opt<uint32_t> TrivialPhiProcessingLimit( |
| 29 | + "mssaupdater-processing-limit", cl::Hidden, cl::init(20), |
| 30 | + cl::desc("The worklist limit for trivial phi removal (default = 20)")); |
| 31 | + |
27 | 32 | // This is the marker algorithm from "Simple and Efficient Construction of |
28 | 33 | // Static Single Assignment Form" |
29 | 34 | // The simple, non-marker algorithm places phi nodes at any join |
@@ -181,18 +186,6 @@ MemoryAccess *MemorySSAUpdater::getPreviousDefFromEnd( |
181 | 186 |
|
182 | 187 | return getPreviousDefRecursive(BB, CachedPreviousDef); |
183 | 188 | } |
184 | | -// Recurse over a set of phi uses to eliminate the trivial ones |
185 | | -MemoryAccess *MemorySSAUpdater::recursePhi(MemoryAccess *Phi) { |
186 | | - if (!Phi) |
187 | | - return nullptr; |
188 | | - TrackingVH<MemoryAccess> Res(Phi); |
189 | | - SmallVector<TrackingVH<Value>, 8> Uses; |
190 | | - std::copy(Phi->user_begin(), Phi->user_end(), std::back_inserter(Uses)); |
191 | | - for (auto &U : Uses) |
192 | | - if (MemoryPhi *UsePhi = dyn_cast<MemoryPhi>(&*U)) |
193 | | - tryRemoveTrivialPhi(UsePhi); |
194 | | - return Res; |
195 | | -} |
196 | 189 |
|
197 | 190 | // Eliminate trivial phis |
198 | 191 | // Phis are trivial if they are defined either by themselves, or all the same |
@@ -230,9 +223,61 @@ MemoryAccess *MemorySSAUpdater::tryRemoveTrivialPhi(MemoryPhi *Phi, |
230 | 223 | removeMemoryAccess(Phi); |
231 | 224 | } |
232 | 225 |
|
233 | | - // We should only end up recursing in case we replaced something, in which |
234 | | - // case, we may have made other Phis trivial. |
235 | | - return recursePhi(Same); |
| 226 | + // Continue traversal in a DFS worklist approach, in case we might find |
| 227 | + // other trivial Phis. |
| 228 | + if (!Same) |
| 229 | + return nullptr; |
| 230 | + |
| 231 | + TrackingVH<MemoryAccess> Result(Same); |
| 232 | + |
| 233 | + // Worklist approach to recursively removing trivial Phis. |
| 234 | + SmallVector<TrackingVH<Value>, 5> Worklist; |
| 235 | + |
| 236 | + for (auto U : Same->users()) { |
| 237 | + if (dyn_cast<MemoryPhi>(&*U)) |
| 238 | + Worklist.push_back(TrackingVH<Value>(U)); |
| 239 | + } |
| 240 | + |
| 241 | + while (!Worklist.empty() || Worklist.size() > TrivialPhiProcessingLimit) { |
| 242 | + MemoryPhi *RecPhi = dyn_cast<MemoryPhi>(&*(Worklist[Worklist.size() - 1])); |
| 243 | + Worklist.pop_back(); |
| 244 | + |
| 245 | + if (!RecPhi) |
| 246 | + continue; |
| 247 | + auto RecOperands = RecPhi->operands(); |
| 248 | + |
| 249 | + // Repeat above algorithm. |
| 250 | + if (NonOptPhis.count(RecPhi)) |
| 251 | + continue; |
| 252 | + |
| 253 | + bool nextone = false; |
| 254 | + MemoryAccess *RecSame = nullptr; |
| 255 | + for (auto &Op : RecOperands) { |
| 256 | + if (Op == RecPhi || Op == RecSame) |
| 257 | + continue; |
| 258 | + if (RecSame) { |
| 259 | + nextone = true; |
| 260 | + break; |
| 261 | + } |
| 262 | + RecSame = cast<MemoryAccess>(&*Op); |
| 263 | + } |
| 264 | + |
| 265 | + // Move on to the next Phi in the worklist. |
| 266 | + if (nextone || RecSame == nullptr) |
| 267 | + continue; |
| 268 | + |
| 269 | + if (RecPhi) { |
| 270 | + RecPhi->replaceAllUsesWith(RecSame); |
| 271 | + removeMemoryAccess(RecPhi); |
| 272 | + } |
| 273 | + |
| 274 | + for (auto U : RecSame->users()) { |
| 275 | + if (dyn_cast<MemoryPhi>(&*U)) |
| 276 | + Worklist.push_back(TrackingVH<Value>(U)); |
| 277 | + } |
| 278 | + } |
| 279 | + |
| 280 | + return Result; |
236 | 281 | } |
237 | 282 |
|
238 | 283 | void MemorySSAUpdater::insertUse(MemoryUse *MU, bool RenameUses) { |
|
0 commit comments