Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -116,9 +116,12 @@ unsigned getSDNodeOrder() { return SDNodeOrder; } }; + /// DanglingDebugInfoVector - Helper type for DanglingDebugInfoMap. + typedef SmallVector DanglingDebugInfoVector; + /// DanglingDebugInfoMap - Keeps track of dbg_values for which we have not /// yet seen the referent. We defer handling these until we do see it. - DenseMap DanglingDebugInfoMap; + DenseMap DanglingDebugInfoMap; public: /// PendingLoads - Loads are not emitted to the program immediately. We bunch Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1080,62 +1080,59 @@ void SelectionDAGBuilder::dropDanglingDebugInfo(const DILocalVariable *Variable, const DIExpression *Expr) { - SmallVector ToRemove; - for (auto &DMI : DanglingDebugInfoMap) { - DanglingDebugInfo &DDI = DMI.second; - if (DDI.getDI()) { - const DbgValueInst *DI = DDI.getDI(); - DIVariable *DanglingVariable = DI->getVariable(); - DIExpression *DanglingExpr = DI->getExpression(); - if (DanglingVariable == Variable && - Expr->fragmentsOverlap(DanglingExpr)) { - DEBUG(dbgs() << "Dropping dangling debug info for " << *DI << "\n"); - ToRemove.push_back(DMI.first); + for (auto &DDIMI : DanglingDebugInfoMap) + for (auto &DDI : DDIMI.second) + if (DDI.getDI()) { + const DbgValueInst *DI = DDI.getDI(); + DIVariable *DanglingVariable = DI->getVariable(); + DIExpression *DanglingExpr = DI->getExpression(); + if (DanglingVariable == Variable && + Expr->fragmentsOverlap(DanglingExpr)) { + DEBUG(dbgs() << "Dropping dangling debug info for " << *DI << "\n"); + DDI = DanglingDebugInfo(); + } } - } - } - - for (auto V : ToRemove) - DanglingDebugInfoMap[V] = DanglingDebugInfo(); } // resolveDanglingDebugInfo - if we saw an earlier dbg_value referring to V, // generate the debug data structures now that we've seen its definition. void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V, SDValue Val) { - DanglingDebugInfo &DDI = DanglingDebugInfoMap[V]; - if (!DDI.getDI()) - return; - const DbgValueInst *DI = DDI.getDI(); - DebugLoc dl = DDI.getdl(); - unsigned ValSDNodeOrder = Val.getNode()->getIROrder(); - unsigned DbgSDNodeOrder = DDI.getSDNodeOrder(); - DILocalVariable *Variable = DI->getVariable(); - DIExpression *Expr = DI->getExpression(); - assert(Variable->isValidLocationForIntrinsic(dl) && - "Expected inlined-at fields to agree"); - SDDbgValue *SDV; - if (Val.getNode()) { - if (!EmitFuncArgumentDbgValue(V, Variable, Expr, dl, false, Val)) { - DEBUG(dbgs() << "Resolve dangling debug info [order=" << DbgSDNodeOrder - << "] for:\n " << *DI << "\n"); - DEBUG(dbgs() << " By mapping to:\n "; Val.dump()); - // Increase the SDNodeOrder for the DbgValue here to make sure it is - // inserted after the definition of Val when emitting the instructions - // after ISel. An alternative could be to teach - // ScheduleDAGSDNodes::EmitSchedule to delay the insertion properly. - DEBUG(if (ValSDNodeOrder > DbgSDNodeOrder) - dbgs() << "changing SDNodeOrder from " << DbgSDNodeOrder - << " to " << ValSDNodeOrder << "\n"); - SDV = getDbgValue(Val, Variable, Expr, dl, - std::max(DbgSDNodeOrder, ValSDNodeOrder)); - DAG.AddDbgValue(SDV, Val.getNode(), false); + DanglingDebugInfoVector &DDIV = DanglingDebugInfoMap[V]; + for (auto &DDI : DDIV) { + if (!DDI.getDI()) + continue; + const DbgValueInst *DI = DDI.getDI(); + DebugLoc dl = DDI.getdl(); + unsigned ValSDNodeOrder = Val.getNode()->getIROrder(); + unsigned DbgSDNodeOrder = DDI.getSDNodeOrder(); + DILocalVariable *Variable = DI->getVariable(); + DIExpression *Expr = DI->getExpression(); + assert(Variable->isValidLocationForIntrinsic(dl) && + "Expected inlined-at fields to agree"); + SDDbgValue *SDV; + if (Val.getNode()) { + if (!EmitFuncArgumentDbgValue(V, Variable, Expr, dl, false, Val)) { + DEBUG(dbgs() << "Resolve dangling debug info [order=" << DbgSDNodeOrder + << "] for:\n " << *DI << "\n"); + DEBUG(dbgs() << " By mapping to:\n "; Val.dump()); + // Increase the SDNodeOrder for the DbgValue here to make sure it is + // inserted after the definition of Val when emitting the instructions + // after ISel. An alternative could be to teach + // ScheduleDAGSDNodes::EmitSchedule to delay the insertion properly. + DEBUG(if (ValSDNodeOrder > DbgSDNodeOrder) + dbgs() << "changing SDNodeOrder from " << DbgSDNodeOrder + << " to " << ValSDNodeOrder << "\n"); + SDV = getDbgValue(Val, Variable, Expr, dl, + std::max(DbgSDNodeOrder, ValSDNodeOrder)); + DAG.AddDbgValue(SDV, Val.getNode(), false); + } else + DEBUG(dbgs() << "Resolved dangling debug info for " << *DI + << "in EmitFuncArgumentDbgValue\n"); } else - DEBUG(dbgs() << "Resolved dangling debug info for " << *DI - << "in EmitFuncArgumentDbgValue\n"); - } else - DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n"); - DanglingDebugInfoMap[V] = DanglingDebugInfo(); + DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n"); + } + DanglingDebugInfoMap[V].clear(); } /// getCopyFromRegs - If there was virtual register allocated for the value V @@ -5330,7 +5327,7 @@ // Do not call getValue(V) yet, as we don't want to generate code. // Remember it for later. DanglingDebugInfo DDI(&DI, dl, SDNodeOrder); - DanglingDebugInfoMap[V] = DDI; + DanglingDebugInfoMap[V].push_back(DDI); return nullptr; } Index: test/DebugInfo/X86/sdag-dangling-dbgvalue.ll =================================================================== --- test/DebugInfo/X86/sdag-dangling-dbgvalue.ll +++ test/DebugInfo/X86/sdag-dangling-dbgvalue.ll @@ -50,8 +50,8 @@ ; CHECK: ![[BAR3:.*]] = !DILocalVariable(name: "foo3" ; CHECK: ![[FOO4:.*]] = !DILocalVariable(name: "foo4" ; CHECK: ![[BAR4:.*]] = !DILocalVariable(name: "bar4" -; CHECK: ![[FOO5:.*]] = !DILocalVariable(name: "bar5" -; CHECK: ![[BAR5:.*]] = !DILocalVariable(name: "foo5" +; CHECK: ![[BAR5:.*]] = !DILocalVariable(name: "bar5" +; CHECK: ![[FOO5:.*]] = !DILocalVariable(name: "foo5" source_filename = "sdag-dangling-dbgvalue.c" @@ -74,13 +74,11 @@ ret i32 ptrtoint (%struct.SS* @S to i32), !dbg !25 } -; Verify that the def comes before the debug-use for bar2. -; TODO: Currently dbg.value for foo2 is dropped. Seems to be a bug. The -; SelectionDAGBuilder should support several dangling dbg.value for the -; same value. +; Verify that the def comes before the debug-use for foo2 and bar2. define i32 @test2() local_unnamed_addr #0 !dbg !26 { ; CHECK-LABEL: bb.0.entry2 ; CHECK-NEXT: [[REG2:%[0-9]+]]:gr64 = +; CHECK-NEXT: DBG_VALUE debug-use [[REG2]], debug-use $noreg, ![[FOO2]], !DIExpression() ; CHECK-NEXT: DBG_VALUE debug-use [[REG2]], debug-use $noreg, ![[BAR2]], !DIExpression() entry2: call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !28, metadata !DIExpression()), !dbg !30 @@ -88,13 +86,11 @@ ret i32 add (i32 ptrtoint (%struct.SS* @S to i32), i32 ptrtoint (%struct.SS* @S to i32)), !dbg !32 } -; Verify that the def comes before the debug-use for foo3. -; TODO: Currently dbg.value for bar3 is dropped. Seems to be a bug. The -; SelectionDAGBuilder should support several dangling dbg.value for the -; same value. +; Verify that the def comes before the debug-use for foo3 and bar3. define i32 @test3() local_unnamed_addr #0 !dbg !33 { ; CHECK-LABEL: bb.0.entry3 ; CHECK-NEXT: [[REG3:%[0-9]+]]:gr64 = +; CHECK-NEXT: DBG_VALUE debug-use [[REG3]], debug-use $noreg, ![[BAR3]], !DIExpression() ; CHECK-NEXT: DBG_VALUE debug-use [[REG3]], debug-use $noreg, ![[FOO3]], !DIExpression() entry3: call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !36, metadata !DIExpression()), !dbg !38 @@ -118,15 +114,13 @@ } ; Verify that we do not get a DBG_VALUE that maps foo5 to @S here. -; TODO: At the moment we do not get any DBG_VALUE at all here. If -; SelectionDAGBuilder should support several dangling dbg.value for the -; same value it would be possible to at least get a DBG_VALUE for -; bar5. ; TODO: foo5 is set to null, and it is not really used. Just like in test1 it ; can be discussed if there should be a DBG_VALUE for foo5 here. define i32 @test5() local_unnamed_addr #0 !dbg !47 { ; CHECK-LABEL: bb.0.entry5: -; CHECK-NOT: DBG_VALUE +; CHECK-NEXT: [[REG5:%[0-9]+]]:gr64 = +; CHECK-NEXT: DBG_VALUE debug-use [[REG5]], debug-use $noreg, ![[BAR5]], !DIExpression() +; CHECK-NOT: DBG_VALUE debug-use [[REG5]], debug-use $noreg, ![[FOO5]], !DIExpression() ; CHECK: RET entry5: call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !49, metadata !DIExpression()), !dbg !51