Index: lib/Transforms/Utils/MemorySSA.cpp =================================================================== --- lib/Transforms/Utils/MemorySSA.cpp +++ lib/Transforms/Utils/MemorySSA.cpp @@ -170,6 +170,18 @@ } }; +static bool lifetimeEndsAt(MemoryDef *MD, const MemoryLocation &Loc, + AliasAnalysis &AA) { + Instruction *Inst = MD->getMemoryInst(); + if (IntrinsicInst *II = dyn_cast(Inst)) { + if (II->getIntrinsicID() == Intrinsic::lifetime_start) { + if (AA.isMustAlias(MemoryLocation(II->getArgOperand(1)), Loc)) + return true; + } + } + return false; +} + static bool instructionClobbersQuery(MemoryDef *MD, const MemoryLocation &UseLoc, const Instruction *UseInst, @@ -177,6 +189,21 @@ Instruction *DefInst = MD->getMemoryInst(); assert(DefInst && "Defining instruction not actually an instruction"); + if (const IntrinsicInst *II = dyn_cast(UseInst)) { + // These intrinsics will show up as affecting memory, but they are just + // markers. + switch (II->getIntrinsicID()) { + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::invariant_start: + case Intrinsic::invariant_end: + case Intrinsic::assume: + return false; + default: + break; + } + } + ImmutableCallSite UseCS(UseInst); if (UseCS) { ModRefInfo I = AA.getModRefInfo(DefInst, UseCS); @@ -501,7 +528,7 @@ if (Current == StopAt) return {Current, false, false}; - if (auto *MD = dyn_cast(Current)) + if (auto *MD = dyn_cast(Current)) { if (MSSA.isLiveOnEntryDef(MD) || instructionClobbersQuery(MD, Desc.Loc, Query->Inst, AA)) return {MD, true, false}; @@ -1307,7 +1334,14 @@ } MemoryDef *MD = cast(VersionStack[UpperBound]); - + // If the lifetime of the pointer ends at this instruction, it's live on + // entry. + if (!UseMLOC.IsCall && lifetimeEndsAt(MD, UseMLOC.getLoc(), *AA)) { + // Reset UpperBound to liveOnEntryDef's place in the stack + UpperBound = 0; + FoundClobberResult = true; + break; + } if (instructionClobbersQuery(MD, MU, UseMLOC, *AA)) { FoundClobberResult = true; break;