Index: include/llvm/Analysis/MemorySSAUpdater.h =================================================================== --- include/llvm/Analysis/MemorySSAUpdater.h +++ include/llvm/Analysis/MemorySSAUpdater.h @@ -60,6 +60,7 @@ MemorySSA *MSSA; SmallVector InsertedPHIs; SmallPtrSet VisitedBlocks; + SmallPtrSet NonOptPhis; public: MemorySSAUpdater(MemorySSA *MSSA) : MSSA(MSSA) {} Index: lib/Analysis/MemorySSA.cpp =================================================================== --- lib/Analysis/MemorySSA.cpp +++ lib/Analysis/MemorySSA.cpp @@ -1415,7 +1415,7 @@ auto *Defs = getOrCreateDefsList(BB); // If we got asked to insert at the end, we have an easy job, just shove it // at the end. If we got asked to insert before an existing def, we also get - // an terator. If we got asked to insert before a use, we have to hunt for + // an iterator. If we got asked to insert before a use, we have to hunt for // the next def. if (WasEnd) { Defs->push_back(*What); @@ -1434,7 +1434,7 @@ BlockNumberingValid.erase(BB); } -// Move What before Where in the IR. The end result is taht What will belong to +// Move What before Where in the IR. The end result is that What will belong to // the right lists and have the right Block set, but will not otherwise be // correct. It will not have the right defining access, and if it is a def, // things below it will not properly be updated. Index: lib/Analysis/MemorySSAUpdater.cpp =================================================================== --- lib/Analysis/MemorySSAUpdater.cpp +++ lib/Analysis/MemorySSAUpdater.cpp @@ -165,6 +165,10 @@ template MemoryAccess *MemorySSAUpdater::tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands) { + // Bail out on non-opt Phis. + if (NonOptPhis.count(Phi)) + return Phi; + // Detect equal or self arguments MemoryAccess *Same = nullptr; for (auto &Op : Operands) { @@ -307,6 +311,11 @@ auto *Defs = MSSA->getWritableBlockDefs(NewDef->getBlock()); auto DefIter = NewDef->getDefsIterator(); + // The temporary Phi is being fixed, unmark it for not to optimize. + if (MemoryPhi *Phi = dyn_cast_or_null(NewDef)) + if (NonOptPhis.count(Phi)) + NonOptPhis.erase(Phi); + // If there is a local def after us, we only have to rename that. if (++DefIter != Defs->end()) { cast(DefIter)->setDefiningAccess(NewDef); @@ -366,6 +375,11 @@ template void MemorySSAUpdater::moveTo(MemoryUseOrDef *What, BasicBlock *BB, WhereType Where) { + // Mark MemoryPhi users of What not to be optimized. + for (auto *U : What->users()) + if (MemoryPhi *PhiUser = dyn_cast_or_null(U)) + NonOptPhis.insert(PhiUser); + // Replace all our users with our defining access. What->replaceAllUsesWith(What->getDefiningAccess()); Index: test/Transforms/GVNHoist/non-trivial-phi.ll =================================================================== --- /dev/null +++ test/Transforms/GVNHoist/non-trivial-phi.ll @@ -0,0 +1,34 @@ +; RUN: opt -gvn-hoist %s -S -o - | FileCheck %s + +; CHECK: store +; CHECK-NOT: store + +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" + +define void @f(i8* %p) { +entry: + switch i4 undef, label %if.then30 [ + i4 4, label %if.end + i4 0, label %if.end + ] + +if.end: + br label %if.end19 + +if.end19: + br i1 undef, label %e, label %e.thread + +e.thread: + store i8 0, i8* %p, align 4 + br label %if.then30 + +if.then30: + call void @g() + unreachable + +e: + store i8 0, i8* %p, align 4 + unreachable +} + +declare void @g()