diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index 9fdcfe5ec3d..d9261ac5a1d 100644 --- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -23,6 +23,7 @@ #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/ADT/DenseMap.h" @@ -163,6 +164,7 @@ namespace { std::vector Allocas; DominatorTree &DT; DominanceFrontier &DF; + DIFactory *DIF; /// AST - An AliasSetTracker object to update. If null, don't update it. /// @@ -199,7 +201,7 @@ namespace { public: PromoteMem2Reg(const std::vector &A, DominatorTree &dt, DominanceFrontier &df, AliasSetTracker *ast) - : Allocas(A), DT(dt), DF(df), AST(ast) {} + : Allocas(A), DT(dt), DF(df), DIF(0), AST(ast) {} void run(); @@ -241,8 +243,9 @@ namespace { LargeBlockInfo &LBI); void PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, LargeBlockInfo &LBI); - - + void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, StoreInst* SI, + uint64_t Offset); + void RenamePass(BasicBlock *BB, BasicBlock *Pred, RenamePassData::ValVector &IncVals, std::vector &Worklist); @@ -306,6 +309,19 @@ namespace { } // end of anonymous namespace +/// Finds the llvm.dbg.declare intrinsic corresponding to an alloca if any. +static DbgDeclareInst *findDbgDeclare(AllocaInst *AI) { + Function *F = AI->getParent()->getParent(); + for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); + BI != BE; ++BI) + if (DbgDeclareInst *DDI = dyn_cast(BI)) + if (DDI->getAddress() == AI) + return DDI; + + return 0; +} + void PromoteMem2Reg::run() { Function &F = *DF.getRoot()->getParent(); @@ -344,6 +360,8 @@ void PromoteMem2Reg::run() { // Finally, after the scan, check to see if the store is all that is left. if (Info.UsingBlocks.empty()) { + // Record debuginfo for the store before removing it. + ConvertDebugDeclareToDebugValue(findDbgDeclare(AI), Info.OnlyStore, 0); // Remove the (now dead) store and alloca. Info.OnlyStore->eraseFromParent(); LBI.deleteValue(Info.OnlyStore); @@ -370,8 +388,11 @@ void PromoteMem2Reg::run() { if (Info.UsingBlocks.empty()) { // Remove the (now dead) stores and alloca. + DbgDeclareInst *DDI = findDbgDeclare(AI); while (!AI->use_empty()) { StoreInst *SI = cast(AI->use_back()); + // Record debuginfo for the store before removing it. + ConvertDebugDeclareToDebugValue(DDI, SI, 0); SI->eraseFromParent(); LBI.deleteValue(SI); } @@ -833,6 +854,18 @@ void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, } } +// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value +// that has an associated llvm.dbg.decl intrinsic. +void PromoteMem2Reg::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, + StoreInst* SI, + uint64_t Offset) { + if (!DDI) return; + + if (!DIF) + DIF = new DIFactory(*SI->getParent()->getParent()->getParent()); + DIF->InsertDbgValueIntrinsic(SI->getOperand(0), Offset, + DIVariable(DDI->getVariable()), SI); +} // QueuePhiNode - queues a phi-node to be added to a basic-block for a specific // Alloca returns true if there wasn't already a phi-node for that variable @@ -946,6 +979,8 @@ NextIteration: // what value were we writing? IncomingVals[ai->second] = SI->getOperand(0); + // Record debuginfo for the store before removing it. + ConvertDebugDeclareToDebugValue(findDbgDeclare(Dest), SI, 0); BB->getInstList().erase(SI); } } diff --git a/test/Transforms/Mem2Reg/ConvertDebugInfo.ll b/test/Transforms/Mem2Reg/ConvertDebugInfo.ll new file mode 100644 index 00000000000..8e309c0901e --- /dev/null +++ b/test/Transforms/Mem2Reg/ConvertDebugInfo.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -mem2reg -S | FileCheck %s + +target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" + +define double @testfunc(i32 %i, double %j) { + %I = alloca i32 ; [#uses=4] + call void @llvm.dbg.declare(metadata !{i32* %I}, metadata !0) + %J = alloca double ; [#uses=2] + call void @llvm.dbg.declare(metadata !{double* %J}, metadata !1) +; CHECK: call void @llvm.dbg.value(metadata !{i32 %i}, i64 0, metadata !0) + store i32 %i, i32* %I +; CHECK: call void @llvm.dbg.value(metadata !{double %j}, i64 0, metadata !1) + store double %j, double* %J + %t1 = load i32* %I ; [#uses=1] + %t2 = add i32 %t1, 1 ; [#uses=1] + store i32 %t2, i32* %I + %t3 = load i32* %I ; [#uses=1] + %t4 = sitofp i32 %t3 to double ; [#uses=1] + %t5 = load double* %J ; [#uses=1] + %t6 = fmul double %t4, %t5 ; [#uses=1] + ret double %t6 +} + +declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone + +!bar = !{!0} +!foo = !{!2} + +!0 = metadata !{i32 459008, metadata !1, metadata !"foo", metadata !2, i32 5, metadata !"foo"} ; [ DW_TAG_auto_variable ] +!1 = metadata !{i32 459008, metadata !1, metadata !"foo", metadata !0, i32 5, metadata !1} ; [ DW_TAG_auto_variable ] +!2 = metadata !{i32 458804, i32 0, metadata !2, metadata !"foo", metadata !"bar", metadata !"bar", metadata !2, i32 3, metadata !0, i1 false, i1 true} ; [ DW_TAG_variable ]