From 23bb4735cad4027c55ca45f2fc8a06fd4341065f Mon Sep 17 00:00:00 2001 From: OCHyams Date: Wed, 9 Nov 2022 11:39:29 +0000 Subject: [PATCH] [Assignment Tracking][10/*] salvageDebugInfo for dbg.assign intrinsics The Assignment Tracking debug-info feature is outlined in this RFC: https://discourse.llvm.org/t/ rfc-assignment-tracking-a-better-way-of-specifying-variable-locations-in-ir Plumb in salvaging for the address part of dbg.assign intrinsics. Reviewed By: jmorse Differential Revision: https://reviews.llvm.org/D133293 --- llvm/lib/Transforms/Utils/Local.cpp | 49 ++++++++++++++- .../Generic/assignment-tracking/salvage-value.ll | 69 ++++++++++++++++++++++ 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 llvm/test/DebugInfo/Generic/assignment-tracking/salvage-value.ll diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index f3c2371..bef22ff 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1790,6 +1790,40 @@ void llvm::salvageDebugInfo(Instruction &I) { salvageDebugInfoForDbgValues(I, DbgUsers); } +/// Salvage the address component of \p DAI. +static void salvageDbgAssignAddress(DbgAssignIntrinsic *DAI) { + Instruction *I = dyn_cast(DAI->getAddress()); + // Only instructions can be salvaged at the moment. + if (!I) + return; + + assert(!DAI->getAddressExpression()->getFragmentInfo().has_value() && + "address-expression shouldn't have fragment info"); + + // The address component of a dbg.assign cannot be variadic. + uint64_t CurrentLocOps = 0; + SmallVector AdditionalValues; + SmallVector Ops; + Value *NewV = salvageDebugInfoImpl(*I, CurrentLocOps, Ops, AdditionalValues); + + // Check if the salvage failed. + if (!NewV) + return; + + DIExpression *SalvagedExpr = DIExpression::appendOpsToArg( + DAI->getAddressExpression(), Ops, 0, /*StackValue=*/false); + assert(!SalvagedExpr->getFragmentInfo().has_value() && + "address-expression shouldn't have fragment info"); + + // Salvage succeeds if no additional values are required. + if (AdditionalValues.empty()) { + DAI->setAddress(NewV); + DAI->setAddressExpression(SalvagedExpr); + } else { + DAI->setAddress(UndefValue::get(I->getType())); + } +} + void llvm::salvageDebugInfoForDbgValues( Instruction &I, ArrayRef DbgUsers) { // These are arbitrary chosen limits on the maximum number of values and the @@ -1800,6 +1834,15 @@ void llvm::salvageDebugInfoForDbgValues( bool Salvaged = false; for (auto *DII : DbgUsers) { + if (auto *DAI = dyn_cast(DII)) { + if (DAI->getAddress() == &I) { + salvageDbgAssignAddress(DAI); + Salvaged = true; + } + if (DAI->getValue() != &I) + continue; + } + // Do not add DW_OP_stack_value for DbgDeclare and DbgAddr, because they // are implicitly pointing out the value as a DWARF memory location // description. @@ -1836,13 +1879,15 @@ void llvm::salvageDebugInfoForDbgValues( bool IsValidSalvageExpr = SalvagedExpr->getNumElements() <= MaxExpressionSize; if (AdditionalValues.empty() && IsValidSalvageExpr) { DII->setExpression(SalvagedExpr); - } else if (isa(DII) && IsValidSalvageExpr && + } else if (isa(DII) && !isa(DII) && + IsValidSalvageExpr && DII->getNumVariableLocationOps() + AdditionalValues.size() <= MaxDebugArgs) { DII->addVariableLocationOps(AdditionalValues, SalvagedExpr); } else { // Do not salvage using DIArgList for dbg.addr/dbg.declare, as it is - // currently only valid for stack value expressions. + // currently only valid for stack value expressions. Do not salvage + // using DIArgList for dbg.assign yet. FIXME: support this. // Also do not salvage if the resulting DIArgList would contain an // unreasonably large number of values. Value *Undef = UndefValue::get(I.getOperand(0)->getType()); diff --git a/llvm/test/DebugInfo/Generic/assignment-tracking/salvage-value.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/salvage-value.ll new file mode 100644 index 0000000..c3bffa4 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/assignment-tracking/salvage-value.ll @@ -0,0 +1,69 @@ +; RUN: opt %s -S -o - -passes=instcombine -experimental-assignment-tracking \ +; RUN: | FileCheck %s --implicit-check-not="call void @llvm.dbg" + +;; Hand-written (the debug info doesn't necessarily make sense and isn't fully +;; formed). Test salvaging a dbg.assign value and address. Checks and comments +;; are inline. + +define dso_local void @fun(i32 %x, i32 %y, ptr %p) !dbg !7 { +entry: + %add = add nsw i32 %x, 1, !dbg !22 + call void @llvm.dbg.assign(metadata i32 %add, metadata !14, metadata !DIExpression(), metadata !28, metadata ptr %p, metadata !DIExpression()), !dbg !16 +;; %add is salvaged. +; CHECK: call void @llvm.dbg.assign(metadata i32 %x,{{.+}}metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value),{{.+}}, metadata ptr %p, metadata !DIExpression()) + + %add1 = add nsw i32 %x, %y, !dbg !29 + call void @llvm.dbg.assign(metadata i32 %add1, metadata !14, metadata !DIExpression(), metadata !31, metadata ptr %p, metadata !DIExpression()), !dbg !16 +;; %add1 is not salvaged as it requires two values and DIArgList is +;; not (yet) supported for dbg.assigns. +; CHECK-NEXT: call void @llvm.dbg.assign(metadata i32 undef,{{.+}}, metadata !DIExpression(),{{.+}}, metadata ptr %p, metadata !DIExpression()) + + %arrayidx0 = getelementptr inbounds i32, ptr %p, i32 0 + call void @llvm.dbg.assign(metadata i32 %x, metadata !14, metadata !DIExpression(), metadata !17, metadata ptr %arrayidx0, metadata !DIExpression()), !dbg !16 +;; %arrayidx0 is salvaged (zero offset, so the gep is just replaced with %p). +; CHECK-NEXT: call void @llvm.dbg.assign(metadata i32 %x,{{.+}}, metadata !DIExpression(),{{.+}}, metadata ptr %p, metadata !DIExpression()) + + %arrayidx1 = getelementptr inbounds i32, ptr %p, i32 1 + call void @llvm.dbg.assign(metadata i32 %x, metadata !14, metadata !DIExpression(), metadata !18, metadata ptr %arrayidx1, metadata !DIExpression()), !dbg !16 +;; %arrayidx1 is salvaged. +; CHECK-NEXT: call void @llvm.dbg.assign(metadata i32 %x,{{.+}}, metadata !DIExpression(),{{.+}}, metadata ptr %p, metadata !DIExpression(DW_OP_plus_uconst, 4)) + + %arrayidx2 = getelementptr inbounds i32, ptr %p, i32 %x + call void @llvm.dbg.assign(metadata i32 %x, metadata !14, metadata !DIExpression(), metadata !19, metadata ptr %arrayidx2, metadata !DIExpression()), !dbg !16 +;; Variadic DIExpressions for dbg.assign address component is not supported - +;; set undef. +; CHECK-NEXT: call void @llvm.dbg.assign(metadata i32 %x,{{.+}}, metadata !DIExpression(),{{.+}}, metadata ptr undef, metadata !DIExpression()) + + ret void +} + +declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.cpp", directory: "/") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 7, !"uwtable", i32 1} +!6 = !{!"clang version 14.0.0"} +!7 = distinct !DISubprogram(name: "fun", linkageName: "fun", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{null, !10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13, !14} +!12 = !DILocalVariable(name: "x", arg: 1, scope: !7, file: !1, line: 2, type: !10) +!13 = !DILocalVariable(name: "y", arg: 2, scope: !7, file: !1, line: 2, type: !10) +!14 = !DILocalVariable(name: "Local", scope: !7, file: !1, line: 3, type: !10) +!16 = !DILocation(line: 0, scope: !7) +!17 = distinct !DIAssignID() +!18 = distinct !DIAssignID() +!19 = distinct !DIAssignID() +!21 = !DILocation(line: 3, column: 3, scope: !7) +!22 = !DILocation(line: 3, column: 17, scope: !7) +!28 = distinct !DIAssignID() +!29 = !DILocation(line: 4, column: 13, scope: !7) +!31 = distinct !DIAssignID() -- 2.7.4