Index: include/llvm/CodeGen/MachineBasicBlock.h =================================================================== --- include/llvm/CodeGen/MachineBasicBlock.h +++ include/llvm/CodeGen/MachineBasicBlock.h @@ -455,10 +455,15 @@ iterator getFirstNonPHI(); /// Return the first instruction in MBB after I that is not a PHI or a label. - /// This is the correct point to insert copies at the beginning of a basic - /// block. + /// This is the correct point to insert lowered copies at the beginning of a + /// basic block that must be before any debugging information. iterator SkipPHIsAndLabels(iterator I); + /// Return the first instruction in MBB after I that is not a PHI, label or + /// debug. This is the correct point to insert copies at the beginning of a + /// basic block. + iterator SkipPHIsLabelsAndDebug(iterator I); + /// Returns an iterator to the first terminator instruction of this basic /// block. If a terminator does not exist, it returns end(). iterator getFirstTerminator(); Index: include/llvm/Transforms/Utils/Local.h =================================================================== --- include/llvm/Transforms/Utils/Local.h +++ include/llvm/Transforms/Utils/Local.h @@ -258,6 +258,11 @@ bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, LoadInst *LI, DIBuilder &Builder); +/// Inserts a llvm.dbg.value intrinsic after a phi of an alloca'd value +/// that has an associated llvm.dbg.decl intrinsic. +bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, + PHINode *LI, DIBuilder &Builder); + /// Lowers llvm.dbg.declare intrinsics into appropriate set of /// llvm.dbg.value intrinsics. bool LowerDbgDeclare(Function &F); Index: lib/CodeGen/InlineSpiller.cpp =================================================================== --- lib/CodeGen/InlineSpiller.cpp +++ lib/CodeGen/InlineSpiller.cpp @@ -377,7 +377,7 @@ MachineBasicBlock *MBB = LIS.getMBBFromIndex(SrcVNI->def); MachineBasicBlock::iterator MII; if (SrcVNI->isPHIDef()) - MII = MBB->SkipPHIsAndLabels(MBB->begin()); + MII = MBB->SkipPHIsLabelsAndDebug(MBB->begin()); else { MachineInstr *DefMI = LIS.getInstructionFromIndex(SrcVNI->def); assert(DefMI && "Defining instruction disappeared"); Index: lib/CodeGen/LiveDebugVariables.cpp =================================================================== --- lib/CodeGen/LiveDebugVariables.cpp +++ lib/CodeGen/LiveDebugVariables.cpp @@ -951,7 +951,7 @@ while (!(MI = LIS.getInstructionFromIndex(Idx))) { // We've reached the beginning of MBB. if (Idx == Start) { - MachineBasicBlock::iterator I = MBB->SkipPHIsAndLabels(MBB->begin()); + MachineBasicBlock::iterator I = MBB->SkipPHIsLabelsAndDebug(MBB->begin()); return I; } Idx = Idx.getPrevIndex(); Index: lib/CodeGen/MachineBasicBlock.cpp =================================================================== --- lib/CodeGen/MachineBasicBlock.cpp +++ lib/CodeGen/MachineBasicBlock.cpp @@ -149,12 +149,25 @@ MachineBasicBlock::iterator MachineBasicBlock::SkipPHIsAndLabels(MachineBasicBlock::iterator I) { iterator E = end(); + while (I != E && (I->isPHI() || I->isPosition())) + ++I; + // FIXME: This needs to change if we wish to bundle labels + // inside the bundle. + assert((I == E || !I->isInsideBundle()) && + "First non-phi / non-label instruction is inside a bundle!"); + return I; +} + +MachineBasicBlock::iterator +MachineBasicBlock::SkipPHIsLabelsAndDebug(MachineBasicBlock::iterator I) { + iterator E = end(); while (I != E && (I->isPHI() || I->isPosition() || I->isDebugValue())) ++I; // FIXME: This needs to change if we wish to bundle labels / dbg_values // inside the bundle. assert((I == E || !I->isInsideBundle()) && - "First non-phi / non-label instruction is inside a bundle!"); + "First non-phi / non-label / non-debug " + "instruction is inside a bundle!"); return I; } Index: lib/CodeGen/PHIEliminationUtils.cpp =================================================================== --- lib/CodeGen/PHIEliminationUtils.cpp +++ lib/CodeGen/PHIEliminationUtils.cpp @@ -54,6 +54,7 @@ ++InsertPoint; } - // Make sure the copy goes after any phi nodes however. + // Make sure the copy goes after any phi nodes but before + // any debug nodes. return MBB->SkipPHIsAndLabels(InsertPoint); } Index: lib/CodeGen/SplitKit.cpp =================================================================== --- lib/CodeGen/SplitKit.cpp +++ lib/CodeGen/SplitKit.cpp @@ -621,7 +621,7 @@ } VNInfo *VNI = defFromParent(0, ParentVNI, Start, MBB, - MBB.SkipPHIsAndLabels(MBB.begin())); + MBB.SkipPHIsLabelsAndDebug(MBB.begin())); RegAssign.insert(Start, VNI->def, OpenIdx); DEBUG(dump()); return VNI->def; Index: lib/Target/PowerPC/PPCEarlyReturn.cpp =================================================================== --- lib/Target/PowerPC/PPCEarlyReturn.cpp +++ lib/Target/PowerPC/PPCEarlyReturn.cpp @@ -58,7 +58,7 @@ bool Changed = false; MachineBasicBlock::iterator I = ReturnMBB.begin(); - I = ReturnMBB.SkipPHIsAndLabels(I); + I = ReturnMBB.SkipPHIsLabelsAndDebug(I); // The block must be essentially empty except for the blr. if (I == ReturnMBB.end() || Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1057,6 +1057,27 @@ return false; } +/// See if there is a dbg.value intrinsic for DIVar after I. +static bool PhiHasDebugValue(DILocalVariable *DIVar, DIExpression *DIExpr, + PHINode *I) { + // Since we can't guarantee that the original dbg.declare instrinsic + // is removed by LowerDbgDeclare(), we need to make sure that we are + // not inserting the same dbg.value intrinsic over and over. + llvm::BasicBlock::InstListType::iterator NextI(I); + while (NextI != I->getParent()->getInstList().end()) { + ++NextI; + if (DbgValueInst *DVI = dyn_cast(NextI)) { + if (DVI->getValue() == I && + DVI->getOffset() == 0 && + DVI->getVariable() == DIVar && + DVI->getExpression() == DIExpr) + return true; + } else + return false; + } + return false; +} + /// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value /// that has an associated llvm.dbg.decl intrinsic. bool llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, @@ -1124,6 +1145,23 @@ return true; } +/// Inserts a llvm.dbg.value intrinsic after a phi +/// that has an associated llvm.dbg.decl intrinsic. +bool llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, + PHINode *APN, DIBuilder &Builder) { + auto *DIVar = DDI->getVariable(); + auto *DIExpr = DDI->getExpression(); + assert(DIVar && "Missing variable"); + + if (PhiHasDebugValue(DIVar, DIExpr, APN)) + return true; + + Instruction *DbgValue = Builder.insertDbgValueIntrinsic( + APN, 0, DIVar, DIExpr, DDI->getDebugLoc(), (Instruction *)nullptr); + DbgValue->insertBefore(&*APN->getParent()->getFirstInsertionPt()); + return true; +} + /// Determine whether this alloca is either a VLA or an array. static bool isArray(AllocaInst *AI) { return AI->isArrayAllocation() || Index: lib/Transforms/Utils/PromoteMemoryToRegister.cpp =================================================================== --- lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -907,6 +907,8 @@ // The currently active variable for this block is now the PHI. IncomingVals[AllocaNo] = APN; + if (DbgDeclareInst *DDI = AllocaDbgDeclares[AllocaNo]) + ConvertDebugDeclareToDebugValue(DDI, APN, DIB); // Get the next phi node. ++PNI; Index: test/CodeGen/AArch64/phi-dbg.ll =================================================================== --- test/CodeGen/AArch64/phi-dbg.ll +++ test/CodeGen/AArch64/phi-dbg.ll @@ -0,0 +1,75 @@ +; RUN: llc -O0 %s -mtriple=aarch64 -o - | FileCheck %s + +; Test that a DEBUG_VALUE node is create for variable c after the phi has been +; converted to a ldr. The DEBUG_VALUE must be *after* the ldr and not before it. + +; Created from the C code, compiled with -O0 -g and then passed through opt -mem2reg: +; +; int func(int a) +; { +; int c = 1; +; if (a < 0 ) { +; c = 12; +; } +; return c; +; } +; +; Function Attrs: nounwind +define i32 @func(i32) #0 !dbg !8 { + call void @llvm.dbg.value(metadata i32 %0, i64 0, metadata !12, metadata !13), !dbg !14 + call void @llvm.dbg.value(metadata i32 1, i64 0, metadata !15, metadata !13), !dbg !16 + %2 = icmp slt i32 %0, 0, !dbg !17 + br i1 %2, label %3, label %4, !dbg !19 + +;