MemoryUseOrDef *MemorySSA::createDefinedAccess(Instruction *I,
MemoryAccess *Definition,
- const MemoryUseOrDef *Template) {
+ const MemoryUseOrDef *Template,
+ bool CreationMustSucceed) {
assert(!isa<PHINode>(I) && "Cannot create a defined access for a PHI");
MemoryUseOrDef *NewAccess = createNewAccess(I, AA, Template);
- assert(
- NewAccess != nullptr &&
- "Tried to create a memory access for a non-memory touching instruction");
- NewAccess->setDefiningAccess(Definition);
+ if (CreationMustSucceed)
+ assert(NewAccess != nullptr && "Tried to create a memory access for a "
+ "non-memory touching instruction");
+ if (NewAccess)
+ NewAccess->setDefiningAccess(Definition);
return NewAccess;
}
}
}
+static MemoryAccess *getNewDefiningAccessForClone(MemoryAccess *MA,
+ const ValueToValueMapTy &VMap,
+ PhiToDefMap &MPhiMap,
+ bool CloneWasSimplified,
+ MemorySSA *MSSA) {
+ MemoryAccess *InsnDefining = MA;
+ if (MemoryDef *DefMUD = dyn_cast<MemoryDef>(InsnDefining)) {
+ if (!MSSA->isLiveOnEntryDef(DefMUD)) {
+ Instruction *DefMUDI = DefMUD->getMemoryInst();
+ assert(DefMUDI && "Found MemoryUseOrDef with no Instruction.");
+ if (Instruction *NewDefMUDI =
+ cast_or_null<Instruction>(VMap.lookup(DefMUDI))) {
+ InsnDefining = MSSA->getMemoryAccess(NewDefMUDI);
+ if (!CloneWasSimplified)
+ assert(InsnDefining && "Defining instruction cannot be nullptr.");
+ else if (!InsnDefining || isa<MemoryUse>(InsnDefining)) {
+ // The clone was simplified, it's no longer a MemoryDef, look up.
+ auto DefIt = DefMUD->getDefsIterator();
+ // Since simplified clones only occur in single block cloning, a
+ // previous definition must exist, otherwise NewDefMUDI would not
+ // have been found in VMap.
+ assert(DefIt != MSSA->getBlockDefs(DefMUD->getBlock())->begin() &&
+ "Previous def must exist");
+ InsnDefining = getNewDefiningAccessForClone(
+ &*(--DefIt), VMap, MPhiMap, CloneWasSimplified, MSSA);
+ }
+ }
+ }
+ } else {
+ MemoryPhi *DefPhi = cast<MemoryPhi>(InsnDefining);
+ if (MemoryAccess *NewDefPhi = MPhiMap.lookup(DefPhi))
+ InsnDefining = NewDefPhi;
+ }
+ assert(InsnDefining && "Defining instruction cannot be nullptr.");
+ return InsnDefining;
+}
+
void MemorySSAUpdater::cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB,
const ValueToValueMapTy &VMap,
PhiToDefMap &MPhiMap,
bool CloneWasSimplified) {
- auto GetNewDefiningAccess = [&](MemoryAccess *MA) -> MemoryAccess * {
- MemoryAccess *InsnDefining = MA;
- if (MemoryUseOrDef *DefMUD = dyn_cast<MemoryUseOrDef>(InsnDefining)) {
- if (!MSSA->isLiveOnEntryDef(DefMUD)) {
- Instruction *DefMUDI = DefMUD->getMemoryInst();
- assert(DefMUDI && "Found MemoryUseOrDef with no Instruction.");
- if (Instruction *NewDefMUDI =
- cast_or_null<Instruction>(VMap.lookup(DefMUDI)))
- InsnDefining = MSSA->getMemoryAccess(NewDefMUDI);
- }
- } else {
- MemoryPhi *DefPhi = cast<MemoryPhi>(InsnDefining);
- if (MemoryAccess *NewDefPhi = MPhiMap.lookup(DefPhi))
- InsnDefining = NewDefPhi;
- }
- assert(InsnDefining && "Defining instruction cannot be nullptr.");
- return InsnDefining;
- };
-
const MemorySSA::AccessList *Acc = MSSA->getBlockAccesses(BB);
if (!Acc)
return;
if (Instruction *NewInsn =
dyn_cast_or_null<Instruction>(VMap.lookup(Insn))) {
MemoryAccess *NewUseOrDef = MSSA->createDefinedAccess(
- NewInsn, GetNewDefiningAccess(MUD->getDefiningAccess()),
- CloneWasSimplified ? nullptr : MUD);
- MSSA->insertIntoListsForBlock(NewUseOrDef, NewBB, MemorySSA::End);
+ NewInsn,
+ getNewDefiningAccessForClone(MUD->getDefiningAccess(), VMap,
+ MPhiMap, CloneWasSimplified, MSSA),
+ /*Template=*/CloneWasSimplified ? nullptr : MUD,
+ /*CreationMustSucceed=*/CloneWasSimplified ? false : true);
+ if (NewUseOrDef)
+ MSSA->insertIntoListsForBlock(NewUseOrDef, NewBB, MemorySSA::End);
}
}
}
--- /dev/null
+; RUN: opt -verify-memoryssa -enable-mssa-loop-dependency -loop-rotate %s -S | FileCheck %s
+; REQUIRES: asserts
+
+; CHECK-LABEL: @test()
+define dso_local void @test() {
+entry:
+ br label %preheader
+
+preheader:
+ br label %l39
+
+l39:
+ %v40 = phi float (float)* [ @foo, %preheader ], [ %v43, %crit_edge ]
+ %v41 = call float %v40(float undef)
+ %v42 = load i32, i32* undef, align 8
+ br i1 undef, label %crit_edge, label %loopexit
+
+crit_edge:
+ %v43 = load float (float)*, float (float)** undef, align 8
+ br label %l39
+
+loopexit:
+ unreachable
+}
+
+; Function Attrs: readnone
+declare dso_local float @foo(float) #0 align 32
+
+attributes #0 = { readnone }