-
Notifications
You must be signed in to change notification settings - Fork 11.2k
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
[SelectionDAG] Salvage debug info for non-constant ADDs #68981
Conversation
The testcase shows we drop the debug info about variables "p", "q", and "r" during ISel. Co-authored-by: Mikael Holmen <mikael.holmen@ericsson.com>
Teach SelectionDAG::salvageDebugInfo() to salvage debug information for ADD nodes where the RHS is non-constant. Co-authored-by: Mikael Holmen <mikael.holmen@ericsson.com>
@llvm/pr-subscribers-llvm-selectiondag @llvm/pr-subscribers-debuginfo Author: David (dstenb) ChangesTeach SelectionDAG::salvageDebugInfo() to salvage debug information for Co-authored-by: Mikael Holmen <mikael.holmen@ericsson.com>
Full diff: https://github.com/llvm/llvm-project/pull/68981.diff 2 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index e831316efff52ba..200123a376d8e98 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -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"
@@ -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
@@ -10791,7 +10795,8 @@ 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.
@@ -10799,19 +10804,38 @@ void SelectionDAG::salvageDebugInfo(SDNode &N) {
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();
+
auto AdditionalDependencies = DV->getAdditionalDependencies();
SDDbgValue *Clone = getDbgValueList(DV->getVariable(), DIExpr,
NewLocOps, AdditionalDependencies,
DV->isIndirect(), DV->getDebugLoc(),
- DV->getOrder(), DV->isVariadic());
+ DV->getOrder(), IsVariadic);
ClonedDVs.push_back(Clone);
DV->setIsInvalidated();
DV->setIsEmitted();
diff --git a/llvm/test/DebugInfo/Sparc/pointer-add-unknown-offset-debug-info.mir b/llvm/test/DebugInfo/Sparc/pointer-add-unknown-offset-debug-info.mir
new file mode 100644
index 000000000000000..a9eabf895f0e6ad
--- /dev/null
+++ b/llvm/test/DebugInfo/Sparc/pointer-add-unknown-offset-debug-info.mir
@@ -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
+ ; 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
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Fix clang-format issue. |
; 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)
Thanks for the review! I'll land this shortly. |
This broke expensive-checks buildbots, e.g. https://lab.llvm.org/buildbot/#/builders/16/builds/56317, so I'll revert and investigate. |
…)" This reverts commit 3ab03ad. Reverted due to failing expensive-checks buildbots, e.g. https://lab.llvm.org/buildbot/#/builders/16/builds/56317. Will investigate that.
Reverted in 6b25890. |
…8981) Teach SelectionDAG::salvageDebugInfo() to salvage debug information for ADD nodes where the RHS is non-constant. In the first try, the test case used the MIR output that was produced by using -stop-before=sparc-isel. Running -start-before=sparc-isel on that output resulted in the following verifier error with EXPENSIVE_CHECKS: "Function has NoVRegs property but there are VReg operands". In this re-attempt the test case has been rewritten to a .ll test by extracting the IR from the original MIR file. The test still starts before sparc-isel. Co-authored-by: Mikael Holmen <mikael.holmen@ericsson.com>
The test case was generated using
I have extracted the IR code from the test file, and changed that a .ll test instead, still starting before sparc-isel. I saw that there are other tests starting before isel that looks like that, e.g. The patch was re-landed with that change in 22f1217. |
Changed = true; | ||
} | ||
(void)Changed; | ||
assert(Changed && "Salvage target doesn't use N"); | ||
|
||
bool IsVariadic = | ||
DV->isVariadic() || OrigLocOpsSize != NewLocOps.size(); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…2645) This is a follow-up to #68981, and fix for #72630, #72447. We may end up in SelectionDAG::salvageDebugInfo() with indirect debug values, and attempting to salvage ADD nodes with non-constant RHS would lead us to try to turn those indirect debug values variadic, which is not allowed. This triggered the following assert in the SDDbgValue constructor: Assertion `!(IsVariadic && IsIndirect)' failed. This also adds a lit test for salvaging when having an indirect debug value and constant RHS, as there seems like there was no such lit test. However, I am not sure if the use of the stack_value operation is correct in that case (which is existing behavior before #68981), but that at least documents the current behavior.
…vm#72645) This is a follow-up to llvm#68981, and fix for llvm#72630, llvm#72447. We may end up in SelectionDAG::salvageDebugInfo() with indirect debug values, and attempting to salvage ADD nodes with non-constant RHS would lead us to try to turn those indirect debug values variadic, which is not allowed. This triggered the following assert in the SDDbgValue constructor: Assertion `!(IsVariadic && IsIndirect)' failed. This also adds a lit test for salvaging when having an indirect debug value and constant RHS, as there seems like there was no such lit test. However, I am not sure if the use of the stack_value operation is correct in that case (which is existing behavior before llvm#68981), but that at least documents the current behavior.
…vm#72645) This is a follow-up to llvm#68981, and fix for llvm#72630, llvm#72447. We may end up in SelectionDAG::salvageDebugInfo() with indirect debug values, and attempting to salvage ADD nodes with non-constant RHS would lead us to try to turn those indirect debug values variadic, which is not allowed. This triggered the following assert in the SDDbgValue constructor: Assertion `!(IsVariadic && IsIndirect)' failed. This also adds a lit test for salvaging when having an indirect debug value and constant RHS, as there seems like there was no such lit test. However, I am not sure if the use of the stack_value operation is correct in that case (which is existing behavior before llvm#68981), but that at least documents the current behavior.
Teach SelectionDAG::salvageDebugInfo() to salvage debug information for
ADD nodes where the RHS is non-constant.
Co-authored-by: Mikael Holmen mikael.holmen@ericsson.com