diff options
author | Alina Sbirlea <asbirlea@google.com> | 2018-09-10 20:13:01 +0000 |
---|---|---|
committer | Alina Sbirlea <asbirlea@google.com> | 2018-09-10 20:13:01 +0000 |
commit | 7980099adbcc41dd473c0b4d8c87b7c25d86d822 (patch) | |
tree | 616ff4410ec807e70d07a1286b7579f98be1f274 /llvm/lib/Analysis/MemorySSA.cpp | |
parent | a3dc9484e3588f55907e87f0d36e605b9989a4d5 (diff) | |
download | llvm-7980099adbcc41dd473c0b4d8c87b7c25d86d822.zip llvm-7980099adbcc41dd473c0b4d8c87b7c25d86d822.tar.gz llvm-7980099adbcc41dd473c0b4d8c87b7c25d86d822.tar.bz2 |
API to update MemorySSA for cloned blocks and added CFG edges.
Summary:
End goal is to update MemorySSA in all loop passes. LoopUnswitch clones all blocks in a loop. SimpleLoopUnswitch clones some blocks. LoopRotate clones some instructions.
Some of these loop passes also make CFG changes.
This is an API based on what I found needed in LoopUnswitch, SimpleLoopUnswitch, LoopRotate, LoopInstSimplify, LoopSimplifyCFG.
Adding dependent patches using this API for context.
Reviewers: george.burgess.iv, dberlin
Subscribers: sanjoy, jlebar, Prazek, llvm-commits
Differential Revision: https://reviews.llvm.org/D45299
llvm-svn: 341855
Diffstat (limited to 'llvm/lib/Analysis/MemorySSA.cpp')
-rw-r--r-- | llvm/lib/Analysis/MemorySSA.cpp | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp index 2126d84..e720682 100644 --- a/llvm/lib/Analysis/MemorySSA.cpp +++ b/llvm/lib/Analysis/MemorySSA.cpp @@ -1542,9 +1542,10 @@ MemoryPhi *MemorySSA::createMemoryPhi(BasicBlock *BB) { } MemoryUseOrDef *MemorySSA::createDefinedAccess(Instruction *I, - MemoryAccess *Definition) { + MemoryAccess *Definition, + const MemoryUseOrDef *Template) { assert(!isa<PHINode>(I) && "Cannot create a defined access for a PHI"); - MemoryUseOrDef *NewAccess = createNewAccess(I); + MemoryUseOrDef *NewAccess = createNewAccess(I, Template); assert( NewAccess != nullptr && "Tried to create a memory access for a non-memory touching instruction"); @@ -1567,7 +1568,8 @@ static inline bool isOrdered(const Instruction *I) { } /// Helper function to create new memory accesses -MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I) { +MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I, + const MemoryUseOrDef *Template) { // The assume intrinsic has a control dependency which we model by claiming // that it writes arbitrarily. Ignore that fake memory dependency here. // FIXME: Replace this special casing with a more accurate modelling of @@ -1576,18 +1578,31 @@ MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I) { if (II->getIntrinsicID() == Intrinsic::assume) return nullptr; - // Find out what affect this instruction has on memory. - ModRefInfo ModRef = AA->getModRefInfo(I, None); - // The isOrdered check is used to ensure that volatiles end up as defs - // (atomics end up as ModRef right now anyway). Until we separate the - // ordering chain from the memory chain, this enables people to see at least - // some relative ordering to volatiles. Note that getClobberingMemoryAccess - // will still give an answer that bypasses other volatile loads. TODO: - // Separate memory aliasing and ordering into two different chains so that we - // can precisely represent both "what memory will this read/write/is clobbered - // by" and "what instructions can I move this past". - bool Def = isModSet(ModRef) || isOrdered(I); - bool Use = isRefSet(ModRef); + bool Def, Use; + if (Template) { + Def = dyn_cast_or_null<MemoryDef>(Template) != nullptr; + Use = dyn_cast_or_null<MemoryUse>(Template) != nullptr; +#if !defined(NDEBUG) + ModRefInfo ModRef = AA->getModRefInfo(I, None); + bool DefCheck, UseCheck; + DefCheck = isModSet(ModRef) || isOrdered(I); + UseCheck = isRefSet(ModRef); + assert(Def == DefCheck && (Def || Use == UseCheck) && "Invalid template"); +#endif + } else { + // Find out what affect this instruction has on memory. + ModRefInfo ModRef = AA->getModRefInfo(I, None); + // The isOrdered check is used to ensure that volatiles end up as defs + // (atomics end up as ModRef right now anyway). Until we separate the + // ordering chain from the memory chain, this enables people to see at least + // some relative ordering to volatiles. Note that getClobberingMemoryAccess + // will still give an answer that bypasses other volatile loads. TODO: + // Separate memory aliasing and ordering into two different chains so that + // we can precisely represent both "what memory will this read/write/is + // clobbered by" and "what instructions can I move this past". + Def = isModSet(ModRef) || isOrdered(I); + Use = isRefSet(ModRef); + } // It's possible for an instruction to not modify memory at all. During // construction, we ignore them. |