diff options
author | George Burgess IV <george.burgess.iv@gmail.com> | 2016-03-23 18:31:55 +0000 |
---|---|---|
committer | George Burgess IV <george.burgess.iv@gmail.com> | 2016-03-23 18:31:55 +0000 |
commit | 0e4898685f8654b8a01e1580cc9a14497cb3f794 (patch) | |
tree | aeea6bfeb96a96510c64f77e993e6735fa9bd7de /llvm/lib/Transforms | |
parent | 12b79aa0f1b7aa6e792a0b65d219a969f4ea8f0b (diff) | |
download | bcm5719-llvm-0e4898685f8654b8a01e1580cc9a14497cb3f794.tar.gz bcm5719-llvm-0e4898685f8654b8a01e1580cc9a14497cb3f794.zip |
Fix bugs in the MemorySSA walker.
There are a few bugs in the walker that this patch addresses.
Primarily:
- Caching can break when we have multiple BBs without phis
- We weren't optimizing some phis properly
- Because of how the DFS iterator works, there were times where we
wouldn't cache any results of our DFS
I left the test cases with FIXMEs in, because I'm not sure how much
effort it will take to get those to work (read: We'll probably
ultimately have to end up redoing the walker, or we'll have to come up
with some creative caching tricks), and more test coverage = better.
Differential Revision: http://reviews.llvm.org/D18065
llvm-svn: 264180
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Utils/MemorySSA.cpp | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/llvm/lib/Transforms/Utils/MemorySSA.cpp b/llvm/lib/Transforms/Utils/MemorySSA.cpp index a794406da15..f667bce04e3 100644 --- a/llvm/lib/Transforms/Utils/MemorySSA.cpp +++ b/llvm/lib/Transforms/Utils/MemorySSA.cpp @@ -898,11 +898,22 @@ MemoryAccessPair CachingMemorySSAWalker::UpwardsDFSWalk( continue; } +#ifndef NDEBUG + // The loop below visits the phi's children for us. Because phis are the + // only things with multiple edges, skipping the children should always lead + // us to the end of the loop. + // + // Use a copy of DFI because skipChildren would kill our search stack, which + // would make caching anything on the way back impossible. + auto DFICopy = DFI; + assert(DFICopy.skipChildren() == DFE && + "Skipping phi's children doesn't end the DFS?"); +#endif + // Recurse on PHI nodes, since we need to change locations. // TODO: Allow graphtraits on pairs, which would turn this whole function // into a normal single depth first walk. MemoryAccess *FirstDef = nullptr; - DFI = DFI.skipChildren(); const MemoryAccessPair PHIPair(CurrAccess, Loc); bool VisitedOnlyOne = true; for (auto MPI = upward_defs_begin(PHIPair), MPE = upward_defs_end(); @@ -932,32 +943,39 @@ MemoryAccessPair CachingMemorySSAWalker::UpwardsDFSWalk( VisitedOnlyOne = false; } - // The above loop determines if all arguments of the phi node reach the - // same place. However we skip arguments that are cyclically dependent - // only on the value of this phi node. This means in some cases, we may - // only visit one argument of the phi node, and the above loop will - // happily say that all the arguments are the same. However, in that case, - // we still can't walk past the phi node, because that argument still - // kills the access unless we hit the top of the function when walking - // that argument. - if (VisitedOnlyOne && FirstDef && !MSSA->isLiveOnEntryDef(FirstDef)) - ModifyingAccess = CurrAccess; + // If we exited the loop early, go with the result it gave us. + if (!ModifyingAccess) { + // The above loop determines if all arguments of the phi node reach the + // same place. However we skip arguments that are cyclically dependent + // only on the value of this phi node. This means in some cases, we may + // only visit one argument of the phi node, and the above loop will + // happily say that all the arguments are the same. However, in that case, + // we still can't walk past the phi node, because that argument still + // kills the access unless we hit the top of the function when walking + // that argument. + if (VisitedOnlyOne && !(FirstDef && MSSA->isLiveOnEntryDef(FirstDef))) { + ModifyingAccess = CurrAccess; + } else { + assert(FirstDef && "Visited multiple phis, but FirstDef isn't set?"); + ModifyingAccess = FirstDef; + } + } + break; } if (!ModifyingAccess) return {MSSA->getLiveOnEntryDef(), Q.StartingLoc}; - const BasicBlock *OriginalBlock = Q.OriginalAccess->getBlock(); + const BasicBlock *OriginalBlock = StartingAccess->getBlock(); unsigned N = DFI.getPathLength(); - MemoryAccess *FinalAccess = ModifyingAccess; for (; N != 0; --N) { - ModifyingAccess = DFI.getPath(N - 1); - BasicBlock *CurrBlock = ModifyingAccess->getBlock(); + MemoryAccess *CacheAccess = DFI.getPath(N - 1); + BasicBlock *CurrBlock = CacheAccess->getBlock(); if (!FollowingBackedge) - doCacheInsert(ModifyingAccess, FinalAccess, Q, Loc); + doCacheInsert(CacheAccess, ModifyingAccess, Q, Loc); if (DT->dominates(CurrBlock, OriginalBlock) && (CurrBlock != OriginalBlock || !FollowingBackedge || - MSSA->locallyDominates(ModifyingAccess, Q.OriginalAccess))) + MSSA->locallyDominates(CacheAccess, StartingAccess))) break; } |