Skip to content

[SelectionDAG] Salvage debug info for non-constant ADDs #68981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 33 additions & 10 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
Expand Down Expand Up @@ -10781,8 +10782,11 @@ void SelectionDAG::salvageDebugInfo(SDNode &N) {
case ISD::ADD: {
SDValue N0 = N.getOperand(0);
SDValue N1 = N.getOperand(1);
if (!isa<ConstantSDNode>(N0) && isa<ConstantSDNode>(N1)) {
uint64_t Offset = N.getConstantOperandVal(1);
if (!isa<ConstantSDNode>(N0)) {
bool RHSConstant = isa<ConstantSDNode>(N1);
uint64_t Offset;
if (RHSConstant)
Offset = N.getConstantOperandVal(1);

// Rewrite an ADD constant node into a DIExpression. Since we are
// performing arithmetic to compute the variable's *value* in the
Expand All @@ -10791,27 +10795,46 @@ void SelectionDAG::salvageDebugInfo(SDNode &N) {
auto *DIExpr = DV->getExpression();
auto NewLocOps = DV->copyLocationOps();
bool Changed = false;
for (size_t i = 0; i < NewLocOps.size(); ++i) {
size_t OrigLocOpsSize = NewLocOps.size();
for (size_t i = 0; i < OrigLocOpsSize; ++i) {
// We're not given a ResNo to compare against because the whole
// node is going away. We know that any ISD::ADD only has one
// result, so we can assume any node match is using the result.
if (NewLocOps[i].getKind() != SDDbgOperand::SDNODE ||
NewLocOps[i].getSDNode() != &N)
continue;
NewLocOps[i] = SDDbgOperand::fromNode(N0.getNode(), N0.getResNo());
SmallVector<uint64_t, 3> ExprOps;
DIExpression::appendOffset(ExprOps, Offset);
DIExpr = DIExpression::appendOpsToArg(DIExpr, ExprOps, i, true);
if (RHSConstant) {
SmallVector<uint64_t, 3> ExprOps;
DIExpression::appendOffset(ExprOps, Offset);
DIExpr = DIExpression::appendOpsToArg(DIExpr, ExprOps, i, true);
} else {
// Convert to a variadic expression (if not already).
// convertToVariadicExpression() returns a const pointer, so we use
// a temporary const variable here.
const auto *TmpDIExpr =
DIExpression::convertToVariadicExpression(DIExpr);
SmallVector<uint64_t, 3> ExprOps;
ExprOps.push_back(dwarf::DW_OP_LLVM_arg);
ExprOps.push_back(NewLocOps.size());
ExprOps.push_back(dwarf::DW_OP_plus);
SDDbgOperand RHS =
SDDbgOperand::fromNode(N1.getNode(), N1.getResNo());
NewLocOps.push_back(RHS);
DIExpr = DIExpression::appendOpsToArg(TmpDIExpr, ExprOps, i, true);
}
Changed = true;
}
(void)Changed;
assert(Changed && "Salvage target doesn't use N");

bool IsVariadic =
DV->isVariadic() || OrigLocOpsSize != NewLocOps.size();
Copy link
Contributor

@KanRobert KanRobert Nov 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We changed the value of IsVariadic here and getDbgValueList(line 10835) would call constructor of SDDbgValue
https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h#L166

it seems the assertion assert(!(IsVariadic && IsIndirect)); in the constructor may fail. In fact, I did see such an error for x86 target.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


auto AdditionalDependencies = DV->getAdditionalDependencies();
SDDbgValue *Clone = getDbgValueList(DV->getVariable(), DIExpr,
NewLocOps, AdditionalDependencies,
DV->isIndirect(), DV->getDebugLoc(),
DV->getOrder(), DV->isVariadic());
SDDbgValue *Clone = getDbgValueList(
DV->getVariable(), DIExpr, NewLocOps, AdditionalDependencies,
DV->isIndirect(), DV->getDebugLoc(), DV->getOrder(), IsVariadic);
ClonedDVs.push_back(Clone);
DV->setIsInvalidated();
DV->setIsEmitted();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
# RUN: llc -mtriple=sparcv9 %s -start-before=sparc-isel -o - -stop-after=sparc-isel | FileCheck %s
--- |
target datalayout = "E-m:e-i64:64-n32:64-S128"
target triple = "sparcv9"

define void @pointer_add_unknown_offset(ptr %base, i32 %offset) !dbg !7 {
entry:
%idx.ext = sext i32 %offset to i64
%add.ptr = getelementptr inbounds i32, ptr %base, i64 %idx.ext
call void @llvm.dbg.value(metadata ptr %add.ptr, metadata !13, metadata !DIExpression()), !dbg !16
call void @llvm.dbg.value(metadata ptr %add.ptr, metadata !14, metadata !DIExpression(DW_OP_plus_uconst, 3, DW_OP_stack_value)), !dbg !16
call void @llvm.dbg.value(metadata !DIArgList(ptr %add.ptr, ptr %add.ptr), metadata !15, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)), !dbg !16
store i32 42, ptr %add.ptr, align 4
ret void
}

declare void @llvm.dbg.value(metadata, metadata, metadata)

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5}
!llvm.ident = !{!6}

!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "test.c", directory: "/tmp", checksumkind: CSK_MD5, checksum: "4321633e52cefeee6e307c697a82574f")
!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, !"debug-info-assignment-tracking", i1 true}
!6 = !{!"clang"}
!7 = distinct !DISubprogram(name: "pointer_add_unknown_offset", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
!8 = !DISubroutineType(types: !9)
!9 = !{null, !10, !11}
!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!12 = !{!13, !14, !15}
!13 = !DILocalVariable(name: "p", scope: !7, file: !1, line: 2, type: !10)
!14 = !DILocalVariable(name: "q", scope: !7, file: !1, line: 2, type: !10)
!15 = !DILocalVariable(name: "r", scope: !7, file: !1, line: 2, type: !10)
!16 = !DILocation(line: 0, scope: !7)
...
---
name: pointer_add_unknown_offset
alignment: 4
tracksRegLiveness: true
body: |
; CHECK-LABEL: name: pointer_add_unknown_offset
; CHECK: bb.0.entry:
; CHECK-NEXT: liveins: $i0, $i1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:i64regs = COPY $i1
; CHECK-NEXT: [[COPY1:%[0-9]+]]:i64regs = COPY $i0
; CHECK-NEXT: [[SRAri:%[0-9]+]]:i64regs = SRAri [[COPY]], 0
; CHECK-NEXT: [[SLLXri:%[0-9]+]]:i64regs = SLLXri killed [[SRAri]], 2
; CHECK-NEXT: DBG_VALUE_LIST !13, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_stack_value), [[COPY1]], [[SLLXri]], debug-location !16
; CHECK-NEXT: DBG_VALUE_LIST !14, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_plus_uconst, 3, DW_OP_stack_value), [[COPY1]], [[SLLXri]], debug-location !16
; CHECK-NEXT: DBG_VALUE_LIST !15, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 2, DW_OP_plus, DW_OP_LLVM_arg, 1, DW_OP_LLVM_arg, 3, DW_OP_plus, DW_OP_plus, DW_OP_stack_value), [[COPY1]], [[COPY1]], [[SLLXri]], [[SLLXri]], debug-location !16
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this testing the non-variadic case, too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the debug values for "p" and "q" are still non-variadic when entering SelectionDAG::salvageDebugInfo():

 DbgVal(Order=3)(SDNODE=t9:0):"p"
 DbgVal(Order=3)(SDNODE=t9:0):"q"!DIExpression(DW_OP_plus_uconst, 3, DW_OP_stack_value)

; CHECK-NEXT: [[ORri:%[0-9]+]]:intregs = ORri $g0, 42
; CHECK-NEXT: STrr [[COPY1]], killed [[SLLXri]], killed [[ORri]] :: (store (s32) into %ir.add.ptr)
; CHECK-NEXT: RETL 8