Index: llvm/trunk/lib/CodeGen/SelectionDAG/InstrEmitter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -694,6 +694,20 @@ assert(cast(Var)->isValidLocationForIntrinsic(DL) && "Expected inlined-at fields to agree"); + SD->setIsEmitted(); + + if (SD->isInvalidated()) { + // An invalidated SDNode must generate an undef DBG_VALUE: although the + // original value is no longer computed, earlier DBG_VALUEs live ranges + // must not leak into later code. + auto MIB = BuildMI(*MF, DL, TII->get(TargetOpcode::DBG_VALUE)); + MIB.addReg(0U); + MIB.addReg(0U, RegState::Debug); + MIB.addMetadata(Var); + MIB.addMetadata(Expr); + return &*MIB; + } + if (SD->getKind() == SDDbgValue::FRAMEIX) { // Stack address; this needs to be lowered in target-dependent fashion. // EmitTargetCodeForFrameDebugValue is responsible for allocation. Index: llvm/trunk/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h +++ llvm/trunk/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h @@ -53,6 +53,7 @@ enum DbgValueKind kind; bool IsIndirect; bool Invalid = false; + bool Emitted = false; public: /// Constructor for non-constants. @@ -126,6 +127,15 @@ void setIsInvalidated() { Invalid = true; } bool isInvalidated() const { return Invalid; } + /// setIsEmitted / isEmitted - Getter/Setter for flag indicating that this + /// SDDbgValue has been emitted to an MBB. + void setIsEmitted() { Emitted = true; } + bool isEmitted() const { return Emitted; } + + /// clearIsEmitted - Reset Emitted flag, for certain special cases where + /// dbg.addr is emitted twice. + void clearIsEmitted() { Emitted = false; } + LLVM_DUMP_METHOD void dump(raw_ostream &OS) const; }; Index: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp @@ -776,11 +776,9 @@ if (N->getHasDebugValue()) { MachineBasicBlock::iterator InsertPos = Emitter.getInsertPos(); for (auto DV : DAG->GetDbgValues(N)) { - if (DV->isInvalidated()) - continue; - if (auto *DbgMI = Emitter.EmitDbgValue(DV, VRBaseMap)) - BB->insert(InsertPos, DbgMI); - DV->setIsInvalidated(); + if (!DV->isEmitted()) + if (auto *DbgMI = Emitter.EmitDbgValue(DV, VRBaseMap)) + BB->insert(InsertPos, DbgMI); } } } Index: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -722,7 +722,7 @@ MachineBasicBlock *BB = Emitter.getBlock(); MachineBasicBlock::iterator InsertPos = Emitter.getInsertPos(); for (auto DV : DAG->GetDbgValues(N)) { - if (DV->isInvalidated()) + if (DV->isEmitted()) continue; unsigned DVOrder = DV->getOrder(); if (!Order || DVOrder == Order) { @@ -731,7 +731,6 @@ Orders.push_back({DVOrder, DbgMI}); BB->insert(InsertPos, DbgMI); } - DV->setIsInvalidated(); } } } @@ -822,8 +821,12 @@ SDDbgInfo::DbgIterator PDE = DAG->ByvalParmDbgEnd(); for (; PDI != PDE; ++PDI) { MachineInstr *DbgMI= Emitter.EmitDbgValue(*PDI, VRBaseMap); - if (DbgMI) + if (DbgMI) { BB->insert(InsertPos, DbgMI); + // We re-emit the dbg_value closer to its use, too, after instructions + // are emitted to the BB. + (*PDI)->clearIsEmitted(); + } } } @@ -889,7 +892,7 @@ for (; DI != DE; ++DI) { if ((*DI)->getOrder() < LastOrder || (*DI)->getOrder() >= Order) break; - if ((*DI)->isInvalidated()) + if ((*DI)->isEmitted()) continue; MachineInstr *DbgMI = Emitter.EmitDbgValue(*DI, VRBaseMap); @@ -911,7 +914,7 @@ // some of them before one or more conditional branches? SmallVector DbgMIs; for (; DI != DE; ++DI) { - if ((*DI)->isInvalidated()) + if ((*DI)->isEmitted()) continue; assert((*DI)->getOrder() >= LastOrder && "emitting DBG_VALUE out of order"); Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -7740,8 +7740,11 @@ Dbg->getDebugLoc(), Dbg->getOrder()); ClonedDVs.push_back(Clone); - if (InvalidateDbg) + if (InvalidateDbg) { + // Invalidate value and indicate the SDDbgValue should not be emitted. Dbg->setIsInvalidated(); + Dbg->setIsEmitted(); + } } for (SDDbgValue *Dbg : ClonedDVs) @@ -7778,6 +7781,7 @@ DV->isIndirect(), DV->getDebugLoc(), DV->getOrder()); ClonedDVs.push_back(Clone); DV->setIsInvalidated(); + DV->setIsEmitted(); LLVM_DEBUG(dbgs() << "SALVAGE: Rewriting"; N0.getNode()->dumprFull(this); dbgs() << " into " << *DIExpr << '\n'); Index: llvm/trunk/test/CodeGen/X86/pr39896.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/pr39896.ll +++ llvm/trunk/test/CodeGen/X86/pr39896.ll @@ -0,0 +1,54 @@ +; RUN: llc %s -start-after=codegenprepare -stop-after=expand-isel-pseudos -o - | FileCheck %s + +; PR39896: When code such as %conv below is dropped by SelectionDAG for having +; no users, don't just drop the dbg.value record associated with it. Instead, +; the corresponding variable should receive a "DBG_VALUE" undef to terminate +; earlier variable live ranges. + +; ModuleID = 'run.c' +source_filename = "run.c" +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +@a = global i8 25, align 1, !dbg !0 + +define signext i16 @b() !dbg !12 { +entry: +; CHECK: DBG_VALUE 23680, $noreg, ![[VARNUM:[0-9]+]], + call void @llvm.dbg.value(metadata i16 23680, metadata !17, metadata !DIExpression()), !dbg !18 + %0 = load i8, i8* @a, align 1, !dbg !18 + %conv = sext i8 %0 to i16, !dbg !18 +; CHECK: DBG_VALUE $noreg, $noreg, ![[VARNUM]], + call void @llvm.dbg.value(metadata i16 %conv, metadata !17, metadata !DIExpression()), !dbg !18 + %call = call i32 (...) @optimize_me_not(), !dbg !18 + %1 = load i8, i8* @a, align 1, !dbg !18 + %conv1 = sext i8 %1 to i16, !dbg !18 + ret i16 %conv1, !dbg !18 +} +declare i32 @optimize_me_not(...) + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9, !10} +!llvm.ident = !{!11} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 348101) (llvm/trunk 348109)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: GNU) +!3 = !DIFile(filename: "run.c", directory: "/Users/dcci/work/llvm/build-debug/bin") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{i32 7, !"PIC Level", i32 2} +!11 = !{!"clang version something"} +!12 = distinct !DISubprogram(name: "b", scope: !3, file: !3, line: 2, type: !13, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !16) +!13 = !DISubroutineType(types: !14) +!14 = !{!15} +!15 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed) +!16 = !{!17} +!17 = !DILocalVariable(name: "i", scope: !12, file: !3, line: 3, type: !15) +!18 = !DILocation(line: 3, scope: !12) Index: llvm/trunk/test/DebugInfo/NVPTX/debug-info.ll =================================================================== --- llvm/trunk/test/DebugInfo/NVPTX/debug-info.ll +++ llvm/trunk/test/DebugInfo/NVPTX/debug-info.ll @@ -687,12 +687,12 @@ ; CHECK: // } ; CHECK: // .section .debug_info ; CHECK: // { -; CHECK: // .b32 10025 // Length of Unit +; CHECK: // .b32 10030 // Length of Unit ; CHECK: // .b8 2 // DWARF version number ; CHECK: // .b8 0 ; CHECK: // .b32 .debug_abbrev // Offset Into Abbrev. Section ; CHECK: // .b8 8 // Address Size (in bytes) -; CHECK: // .b8 1 // Abbrev [1] 0xb:0x2722 DW_TAG_compile_unit +; CHECK: // .b8 1 // Abbrev [1] 0xb:0x2727 DW_TAG_compile_unit ; CHECK: // .b8 0 // DW_AT_producer ; CHECK: // .b8 4 // DW_AT_language ; CHECK: // .b8 0 @@ -4719,7 +4719,7 @@ ; CHECK: // .b8 3 // DW_AT_decl_line ; CHECK: // .b32 3345 // DW_AT_type ; CHECK: // .b8 0 // End Of Children Mark -; CHECK: // .b8 40 // Abbrev [40] 0x2671:0xbb DW_TAG_subprogram +; CHECK: // .b8 40 // Abbrev [40] 0x2671:0xc0 DW_TAG_subprogram ; CHECK: // .b64 Lfunc_begin0 // DW_AT_low_pc ; CHECK: // .b64 Lfunc_end0 // DW_AT_high_pc ; CHECK: // .b8 1 // DW_AT_frame_base @@ -4779,7 +4779,7 @@ ; CHECK: // .b64 Ltmp3 // DW_AT_high_pc ; CHECK: // .b8 12 // DW_AT_call_file ; CHECK: // .b8 6 // DW_AT_call_line -; CHECK: // .b8 43 // Abbrev [43] 0x270e:0x1d DW_TAG_inlined_subroutine +; CHECK: // .b8 43 // Abbrev [43] 0x270e:0x22 DW_TAG_inlined_subroutine ; CHECK: // .b32 9791 // DW_AT_abstract_origin ; CHECK: // .b64 Ltmp8 // DW_AT_low_pc ; CHECK: // .b64 Ltmp9 // DW_AT_high_pc Index: llvm/trunk/test/DebugInfo/X86/dbg-value-inlined-parameter.ll =================================================================== --- llvm/trunk/test/DebugInfo/X86/dbg-value-inlined-parameter.ll +++ llvm/trunk/test/DebugInfo/X86/dbg-value-inlined-parameter.ll @@ -32,10 +32,10 @@ ;CHECK-NEXT: DW_AT_call_line ;CHECK: DW_TAG_formal_parameter -;FIXME: Linux shouldn't drop this parameter either... ;CHECK-NOT: DW_TAG -;DARWIN: DW_AT_abstract_origin {{.*}} "sp" -;DARWIN: DW_TAG_formal_parameter +;CHECK: DW_AT_abstract_origin {{.*}} "sp" +;CHECK: DW_TAG_formal_parameter +;CHECK-NOT: DW_TAG ;CHECK: DW_AT_abstract_origin {{.*}} "nums" ;CHECK-NOT: DW_TAG_formal_parameter Index: llvm/trunk/test/DebugInfo/X86/pieces-3.ll =================================================================== --- llvm/trunk/test/DebugInfo/X86/pieces-3.ll +++ llvm/trunk/test/DebugInfo/X86/pieces-3.ll @@ -40,8 +40,8 @@ call void @llvm.dbg.value(metadata i32 %outer.sroa.1.8.extract.trunc, metadata !34, metadata !35), !dbg !33 %outer.sroa.1.12.extract.shift = lshr i64 %outer.coerce1, 32, !dbg !33 %outer.sroa.1.12.extract.trunc = trunc i64 %outer.sroa.1.12.extract.shift to i32, !dbg !33 - call void @llvm.dbg.value(metadata i64 %outer.sroa.1.12.extract.shift, metadata !34, metadata !35), !dbg !33 - call void @llvm.dbg.value(metadata i32 %outer.sroa.1.12.extract.trunc, metadata !34, metadata !35), !dbg !33 + call void @llvm.dbg.value(metadata i64 %outer.sroa.1.12.extract.shift, metadata !34, metadata !37), !dbg !33 + call void @llvm.dbg.value(metadata i32 %outer.sroa.1.12.extract.trunc, metadata !34, metadata !37), !dbg !33 call void @llvm.dbg.declare(metadata !{null}, metadata !34, metadata !35), !dbg !33 ret i32 %outer.sroa.1.8.extract.trunc, !dbg !36 } @@ -99,3 +99,4 @@ !34 = !DILocalVariable(name: "i1", line: 11, scope: !4, file: !5, type: !14) !35 = !DIExpression(DW_OP_LLVM_fragment, 0, 32) !36 = !DILocation(line: 12, scope: !4) +!37 = !DIExpression(DW_OP_LLVM_fragment, 32, 32)