summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp98
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h16
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp1
-rw-r--r--llvm/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll2
-rw-r--r--llvm/test/DebugInfo/X86/sdag-ir-salvage.ll56
5 files changed, 154 insertions, 19 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 23655a87dbf..5b62a568197 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -108,6 +108,7 @@
#include "llvm/Target/TargetIntrinsicInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/Utils/Local.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -1131,6 +1132,13 @@ void SelectionDAGBuilder::dropDanglingDebugInfo(const DILocalVariable *Variable,
for (auto &DDIMI : DanglingDebugInfoMap) {
DanglingDebugInfoVector &DDIV = DDIMI.second;
+
+ // If debug info is to be dropped, run it through final checks to see
+ // whether it can be salvaged.
+ for (auto &DDI : DDIV)
+ if (isMatchingDbgValue(DDI))
+ salvageUnresolvedDbgValue(DDI);
+
DDIV.erase(remove_if(DDIV, isMatchingDbgValue), DDIV.end());
}
}
@@ -1179,12 +1187,73 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
} else
LLVM_DEBUG(dbgs() << "Resolved dangling debug info for " << *DI
<< "in EmitFuncArgumentDbgValue\n");
- } else
+ } else {
LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
+ auto Undef =
+ UndefValue::get(DDI.getDI()->getVariableLocation()->getType());
+ auto SDV =
+ DAG.getConstantDbgValue(Variable, Expr, Undef, dl, DbgSDNodeOrder);
+ DAG.AddDbgValue(SDV, nullptr, false);
+ }
}
DDIV.clear();
}
+void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
+ Value *V = DDI.getDI()->getValue();
+ DILocalVariable *Var = DDI.getDI()->getVariable();
+ DIExpression *Expr = DDI.getDI()->getExpression();
+ DebugLoc DL = DDI.getdl();
+ DebugLoc InstDL = DDI.getDI()->getDebugLoc();
+ unsigned SDOrder = DDI.getSDNodeOrder();
+
+ // Currently we consider only dbg.value intrinsics -- we tell the salvager
+ // that DW_OP_stack_value is desired.
+ assert(isa<DbgValueInst>(DDI.getDI()));
+ bool StackValue = true;
+
+ // Can this Value can be encoded without any further work?
+ if (handleDebugValue(V, Var, Expr, DL, InstDL, SDOrder))
+ return;
+
+ // Attempt to salvage back through as many instructions as possible. Bail if
+ // a non-instruction is seen, such as a constant expression or global
+ // variable. FIXME: Further work could recover those too.
+ while (isa<Instruction>(V)) {
+ Instruction &VAsInst = *cast<Instruction>(V);
+ DIExpression *NewExpr = salvageDebugInfoImpl(VAsInst, Expr, StackValue);
+
+ // If we cannot salvage any further, and haven't yet found a suitable debug
+ // expression, bail out.
+ if (!NewExpr)
+ break;
+
+ // New value and expr now represent this debuginfo.
+ V = VAsInst.getOperand(0);
+ Expr = NewExpr;
+
+ // Some kind of simplification occurred: check whether the operand of the
+ // salvaged debug expression can be encoded in this DAG.
+ if (handleDebugValue(V, Var, Expr, DL, InstDL, SDOrder)) {
+ LLVM_DEBUG(dbgs() << "Salvaged debug location info for:\n "
+ << DDI.getDI() << "\nBy stripping back to:\n " << V);
+ return;
+ }
+ }
+
+ // This was the final opportunity to salvage this debug information, and it
+ // couldn't be done. Place an undef DBG_VALUE at this location to terminate
+ // any earlier variable location.
+ auto Undef = UndefValue::get(DDI.getDI()->getVariableLocation()->getType());
+ auto SDV = DAG.getConstantDbgValue(Var, Expr, Undef, DL, SDNodeOrder);
+ DAG.AddDbgValue(SDV, nullptr, false);
+
+ LLVM_DEBUG(dbgs() << "Dropping debug value info for:\n " << DDI.getDI()
+ << "\n");
+ LLVM_DEBUG(dbgs() << " Last seen at:\n " << *DDI.getDI()->getOperand(0)
+ << "\n");
+}
+
bool SelectionDAGBuilder::handleDebugValue(const Value *V, DILocalVariable *Var,
DIExpression *Expr, DebugLoc dl,
DebugLoc InstDL, unsigned Order) {
@@ -1277,6 +1346,14 @@ bool SelectionDAGBuilder::handleDebugValue(const Value *V, DILocalVariable *Var,
return false;
}
+void SelectionDAGBuilder::resolveOrClearDbgInfo() {
+ // Try to fixup any remaining dangling debug info -- and drop it if we can't.
+ for (auto &Pair : DanglingDebugInfoMap)
+ for (auto &DDI : Pair.getSecond())
+ salvageUnresolvedDbgValue(DDI);
+ clearDanglingDebugInfo();
+}
+
/// getCopyFromRegs - If there was virtual register allocated for the value V
/// emit CopyFromReg of the specified type Ty. Return empty SDValue() otherwise.
SDValue SelectionDAGBuilder::getCopyFromRegs(const Value *V, Type *Ty) {
@@ -5552,21 +5629,12 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
SDNodeOrder))
return nullptr;
- // TODO: When we get here we will either drop the dbg.value completely, or
- // we try to move it forward by letting it dangle for awhile. So we should
- // probably add an extra DbgValue to the DAG here, with a reference to
- // "noreg", to indicate that we have lost the debug location for the
- // variable.
-
- if (!V->use_empty() ) {
- // Do not call getValue(V) yet, as we don't want to generate code.
- // Remember it for later.
- DanglingDebugInfoMap[V].emplace_back(&DI, dl, SDNodeOrder);
- return nullptr;
- }
+ // TODO: Dangling debug info will eventually either be resolved or produce
+ // an Undef DBG_VALUE. However in the resolution case, a gap may appear
+ // between the original dbg.value location and its resolved DBG_VALUE, which
+ // we should ideally fill with an extra Undef DBG_VALUE.
- LLVM_DEBUG(dbgs() << "Dropping debug location info for:\n " << DI << "\n");
- LLVM_DEBUG(dbgs() << " Last seen at:\n " << *V << "\n");
+ DanglingDebugInfoMap[V].emplace_back(&DI, dl, SDNodeOrder);
return nullptr;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index 2b0a5f891c0..e84214dbf5e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -676,16 +676,24 @@ public:
void dropDanglingDebugInfo(const DILocalVariable *Variable,
const DIExpression *Expr);
- // If we saw an earlier dbg_value referring to V, generate the debug data
- // structures now that we've seen its definition.
+ /// If we saw an earlier dbg_value referring to V, generate the debug data
+ /// structures now that we've seen its definition.
void resolveDanglingDebugInfo(const Value *V, SDValue Val);
- // For a given Value, attempt to create and record a SDDbgValue in the
- // SelectionDAG.
+ /// For the given dangling debuginfo record, perform last-ditch efforts to
+ /// resolve the debuginfo to something that is represented in this DAG. If
+ /// this cannot be done, produce an Undef debug value record.
+ void salvageUnresolvedDbgValue(DanglingDebugInfo &DDI);
+
+ /// For a given Value, attempt to create and record a SDDbgValue in the
+ /// SelectionDAG.
bool handleDebugValue(const Value *V, DILocalVariable *Var,
DIExpression *Expr, DebugLoc CurDL,
DebugLoc InstDL, unsigned Order);
+ /// Evict any dangling debug information, attempting to salvage it first.
+ void resolveOrClearDbgInfo();
+
SDValue getValue(const Value *V);
bool findValue(const Value *V) const;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 4eabab45e28..173919378ae 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -691,6 +691,7 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin,
// Make sure the root of the DAG is up-to-date.
CurDAG->setRoot(SDB->getControlRoot());
HadTailCall = SDB->HasTailCall;
+ SDB->resolveOrClearDbgInfo();
SDB->clear();
// Final step, emit the lowered DAG as machine code.
diff --git a/llvm/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll b/llvm/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll
index ca7cfb82571..34c97f7a4c0 100644
--- a/llvm/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll
+++ b/llvm/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll
@@ -101,6 +101,7 @@ entry3:
; Verify that the def comes before the for bar4.
define i32 @test4() local_unnamed_addr #0 !dbg !40 {
; CHECK-LABEL: bb.0.entry4
+; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[FOO4]], !DIExpression()
; CHECK-NEXT: DBG_VALUE 0, $noreg, ![[FOO4]], !DIExpression()
; CHECK-NEXT: [[REG4:%[0-9]+]]:gr64 =
; CHECK-NEXT: DBG_VALUE [[REG4]], $noreg, ![[BAR4]], !DIExpression()
@@ -114,6 +115,7 @@ entry4:
; Verify that we do not get a DBG_VALUE that maps foo5 to @S here.
define i32 @test5() local_unnamed_addr #0 !dbg !47 {
; CHECK-LABEL: bb.0.entry5:
+; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[FOO5]], !DIExpression()
; CHECK-NEXT: DBG_VALUE 0, $noreg, ![[FOO5]], !DIExpression()
; CHECK-NEXT: [[REG5:%[0-9]+]]:gr64 =
; CHECK-NEXT: DBG_VALUE [[REG5]], $noreg, ![[BAR5]], !DIExpression()
diff --git a/llvm/test/DebugInfo/X86/sdag-ir-salvage.ll b/llvm/test/DebugInfo/X86/sdag-ir-salvage.ll
new file mode 100644
index 00000000000..0bd5f18dd17
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/sdag-ir-salvage.ll
@@ -0,0 +1,56 @@
+; RUN: llc -mtriple=x86_64-unknown-unknown -start-after=codegenprepare -stop-before expand-isel-pseudos %s -o - | FileCheck %s
+
+; Test that the dbg.value for %baz, which doesn't exist in the 'next' bb,
+; can be salvaged back to the underlying argument vreg.
+
+; CHECK: ![[AAAVAR:.*]] = !DILocalVariable(name: "aaa",
+; CHECK-LABEL: bb.1.next:
+; CHECK: DBG_VALUE %{{[0-9]+}}, $noreg, ![[AAAVAR]]
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-linux-gnu"
+
+define i8 @f(i32* %foo) local_unnamed_addr !dbg !6 {
+entry:
+ %bar = getelementptr i32, i32* %foo, i32 4
+ %baz = bitcast i32* %bar to i8*
+ %quux = load i8, i8* %baz
+ br label %next
+
+next: ; preds = %entry
+ tail call void @llvm.dbg.value(metadata i8* %baz, metadata !15, metadata !DIExpression()), !dbg !30
+ %xyzzy = add i8 %quux, 123
+ br label %fin
+
+fin: ; preds = %next
+ %trains = getelementptr i32, i32* %foo, i32 3
+ %planes = bitcast i32* %trains to i8*
+ %cars = load i8, i8* %planes
+ %ret = add i8 %xyzzy, %cars
+ ret i8 %ret
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!25, !26, !27, !28}
+!llvm.ident = !{!29}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "test.c", directory: ".")
+!2 = !{}
+!6 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 18, type: !7, scopeLine: 19, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_unsigned)
+!14 = !{!15}
+!15 = !DILocalVariable(name: "aaa", scope: !6, file: !1, line: 18, type: !13)
+!25 = !{i32 2, !"Dwarf Version", i32 4}
+!26 = !{i32 2, !"Debug Info Version", i32 3}
+!27 = !{i32 1, !"wchar_size", i32 4}
+!28 = !{i32 7, !"PIC Level", i32 2}
+!29 = !{!"clang"}
+!30 = !DILocation(line: 18, column: 14, scope: !6)
OpenPOWER on IntegriCloud