forked from OSchip/llvm-project
[MemorySSA] Don't use template when the clone is a simplified instruction.
Summary: LoopRotate doesn't create a faithful clone of an instruction, it may simplify it beforehand. Hence the clone of an instruction that has a MemoryDef associated may not be a definition, but a use or not a memory alternig instruction. Don't rely on the template when the clone may be simplified. Reviewers: george.burgess.iv Subscribers: jlebar, Prazek, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63355 llvm-svn: 363597
This commit is contained in:
parent
49537bbf74
commit
7a0098aa6e
|
@ -287,8 +287,14 @@ private:
|
|||
// not necessarily be MemoryPhis themselves, they may be MemoryDefs. As such,
|
||||
// the map is between MemoryPhis and MemoryAccesses, where the MemoryAccesses
|
||||
// may be MemoryPhis or MemoryDefs and not MemoryUses.
|
||||
// If CloneWasSimplified = true, the clone was exact. Otherwise, assume that
|
||||
// the clone involved simplifications that may have: (1) turned a MemoryUse
|
||||
// into an instruction that MemorySSA has no representation for, or (2) turned
|
||||
// a MemoryDef into a MemoryUse or an instruction that MemorySSA has no
|
||||
// representation for. No other cases are supported.
|
||||
void cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB,
|
||||
const ValueToValueMapTy &VMap, PhiToDefMap &MPhiMap);
|
||||
const ValueToValueMapTy &VMap, PhiToDefMap &MPhiMap,
|
||||
bool CloneWasSimplified = false);
|
||||
template <typename Iter>
|
||||
void privateUpdateExitBlocksForClonedLoop(ArrayRef<BasicBlock *> ExitBlocks,
|
||||
Iter ValuesBegin, Iter ValuesEnd,
|
||||
|
|
|
@ -482,7 +482,8 @@ void MemorySSAUpdater::removeDuplicatePhiEdgesBetween(const BasicBlock *From,
|
|||
|
||||
void MemorySSAUpdater::cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB,
|
||||
const ValueToValueMapTy &VMap,
|
||||
PhiToDefMap &MPhiMap) {
|
||||
PhiToDefMap &MPhiMap,
|
||||
bool CloneWasSimplified) {
|
||||
auto GetNewDefiningAccess = [&](MemoryAccess *MA) -> MemoryAccess * {
|
||||
MemoryAccess *InsnDefining = MA;
|
||||
if (MemoryUseOrDef *DefMUD = dyn_cast<MemoryUseOrDef>(InsnDefining)) {
|
||||
|
@ -512,10 +513,14 @@ void MemorySSAUpdater::cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB,
|
|||
// instructions. This occurs in LoopRotate when cloning instructions
|
||||
// from the old header to the old preheader. The cloned instruction may
|
||||
// also be a simplified Value, not an Instruction (see LoopRotate).
|
||||
// Also in LoopRotate, even when it's an instruction, due to it being
|
||||
// simplified, it may be a Use rather than a Def, so we cannot use MUD as
|
||||
// template. Calls coming from updateForClonedBlockIntoPred, ensure this.
|
||||
if (Instruction *NewInsn =
|
||||
dyn_cast_or_null<Instruction>(VMap.lookup(Insn))) {
|
||||
MemoryAccess *NewUseOrDef = MSSA->createDefinedAccess(
|
||||
NewInsn, GetNewDefiningAccess(MUD->getDefiningAccess()), MUD);
|
||||
NewInsn, GetNewDefiningAccess(MUD->getDefiningAccess()),
|
||||
CloneWasSimplified ? nullptr : MUD);
|
||||
MSSA->insertIntoListsForBlock(NewUseOrDef, NewBB, MemorySSA::End);
|
||||
}
|
||||
}
|
||||
|
@ -645,10 +650,13 @@ void MemorySSAUpdater::updateForClonedBlockIntoPred(
|
|||
// Defs from BB being used in BB will be replaced with the cloned defs from
|
||||
// VM. The uses of BB's Phi (if it exists) in BB will be replaced by the
|
||||
// incoming def into the Phi from P1.
|
||||
// Instructions cloned into the predecessor are in practice sometimes
|
||||
// simplified, so disable the use of the template, and create an access from
|
||||
// scratch.
|
||||
PhiToDefMap MPhiMap;
|
||||
if (MemoryPhi *MPhi = MSSA->getMemoryAccess(BB))
|
||||
MPhiMap[MPhi] = MPhi->getIncomingValueForBlock(P1);
|
||||
cloneUsesAndDefs(BB, P1, VM, MPhiMap);
|
||||
cloneUsesAndDefs(BB, P1, VM, MPhiMap, /*CloneWasSimplified=*/true);
|
||||
}
|
||||
|
||||
template <typename Iter>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
; RUN: opt -disable-output -loop-rotate -enable-mssa-loop-dependency -verify-memoryssa %s
|
||||
; REQUIRES: asserts
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define dso_local void @bar() local_unnamed_addr #0 align 32 {
|
||||
entry:
|
||||
br label %looplabel.exit.i
|
||||
|
||||
looplabel.exit.i: ; preds = %if.end.i, %entry
|
||||
%0 = phi i1 (i32*, i32*)* [ @foo, %entry ], [ undef, %if.end.i ]
|
||||
%call3.i.i = call zeroext i1 %0(i32* nonnull dereferenceable(16) undef, i32* nonnull undef)
|
||||
br i1 %call3.i.i, label %if.end.i, label %label.exit
|
||||
|
||||
if.end.i: ; preds = %looplabel.exit.i
|
||||
%tobool.i = icmp eq i32* undef, null
|
||||
br label %looplabel.exit.i
|
||||
|
||||
label.exit: ; preds = %looplabel.exit.i
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: readonly
|
||||
declare dso_local i1 @foo(i32*, i32*) #1 align 32
|
||||
|
||||
attributes #0 = { nounwind }
|
||||
attributes #1 = { readonly }
|
||||
|
Loading…
Reference in New Issue