class MemorySSAUpdater {
private:
MemorySSA *MSSA;
- SmallVector<MemoryPhi *, 8> InsertedPHIs;
+
+ /// We use WeakVH rather than a costly deletion to deal with dangling pointers.
+ /// MemoryPhis are created eagerly and sometimes get zapped shortly afterwards.
+ SmallVector<WeakVH, 16> InsertedPHIs;
+
SmallPtrSet<BasicBlock *, 8> VisitedBlocks;
SmallSet<AssertingVH<MemoryPhi>, 8> NonOptPhis;
MemoryAccess *recursePhi(MemoryAccess *Phi);
template <class RangeType>
MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands);
- void fixupDefs(const SmallVectorImpl<MemoryAccess *> &);
+ void fixupDefs(const SmallVectorImpl<WeakVH> &);
};
} // end namespace llvm
// above and reset ourselves.
MD->setDefiningAccess(DefBefore);
- SmallVector<MemoryAccess *, 8> FixupList(InsertedPHIs.begin(),
- InsertedPHIs.end());
+ SmallVector<WeakVH, 8> FixupList(InsertedPHIs.begin(), InsertedPHIs.end());
if (!DefBeforeSameBlock) {
// If there was a local def before us, we must have the same effect it
// did. Because every may-def is the same, any phis/etc we would create, it
fixupDefs(FixupList);
FixupList.clear();
// Put any new phis on the fixup list, and process them
- FixupList.append(InsertedPHIs.end() - StartingPHISize, InsertedPHIs.end());
+ FixupList.append(InsertedPHIs.begin() + StartingPHISize, InsertedPHIs.end());
}
// Now that all fixups are done, rename all uses if we are asked.
if (RenameUses) {
MSSA->renamePass(MD->getBlock(), FirstDef, Visited);
// We just inserted a phi into this block, so the incoming value will become
// the phi anyway, so it does not matter what we pass.
- for (auto *MP : InsertedPHIs)
- MSSA->renamePass(MP->getBlock(), nullptr, Visited);
+ for (auto &MP : InsertedPHIs) {
+ MemoryPhi *Phi = dyn_cast_or_null<MemoryPhi>(MP);
+ if (Phi)
+ MSSA->renamePass(Phi->getBlock(), nullptr, Visited);
+ }
}
}
-void MemorySSAUpdater::fixupDefs(const SmallVectorImpl<MemoryAccess *> &Vars) {
+void MemorySSAUpdater::fixupDefs(const SmallVectorImpl<WeakVH> &Vars) {
SmallPtrSet<const BasicBlock *, 8> Seen;
SmallVector<const BasicBlock *, 16> Worklist;
- for (auto *NewDef : Vars) {
+ for (auto &Var : Vars) {
+ MemoryAccess *NewDef = dyn_cast_or_null<MemoryAccess>(Var);
+ if (!NewDef)
+ continue;
// First, see if there is a local def after the operand.
auto *Defs = MSSA->getWritableBlockDefs(NewDef->getBlock());
auto DefIter = NewDef->getDefsIterator();
--- /dev/null
+; RUN: opt < %s -gvn-hoist -S | FileCheck %s
+
+define void @func() {
+; CHECK-LABEL: @func()
+; CHECK: bb6:
+; CHECK: store i64 0, i64* undef, align 8
+; CHECK: bb7:
+; CHECK-NOT: store i64 0, i64* undef, align 8
+; CHECK: bb8:
+; CHECK-NOT: store i64 0, i64* undef, align 8
+
+entry:
+ br label %bb1
+
+bb1:
+ br label %bb2
+
+bb2:
+ br label %bb3
+
+bb3:
+ br i1 undef, label %bb4, label %bb2
+
+bb4:
+ br i1 undef, label %bb5, label %bb3
+
+bb5:
+ br label %bb6
+
+bb6:
+ br i1 undef, label %bb7, label %bb8
+
+bb7:
+ store i64 0, i64* undef, align 8
+ unreachable
+
+bb8:
+ store i64 0, i64* undef, align 8
+ ret void
+}