Skip to content
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

Merged
merged 3 commits into from
Oct 25, 2023

Conversation

dstenb
Copy link
Collaborator

@dstenb dstenb commented Oct 13, 2023

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

  • [DebugInfo] Precommit testcase for pointer addition with unknown offset
  • [SelectionDAG] Salvage debug info for non-constant ADDs

dstenb and others added 2 commits October 13, 2023 13:45
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>
@llvmbot llvmbot added debuginfo llvm:SelectionDAG SelectionDAGISel as well labels Oct 13, 2023
@dstenb dstenb requested review from jmorse and SLTozer October 13, 2023 11:59
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 13, 2023

@llvm/pr-subscribers-llvm-selectiondag

@llvm/pr-subscribers-debuginfo

Author: David (dstenb)

Changes

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>

  • [DebugInfo] Precommit testcase for pointer addition with unknown offset
  • [SelectionDAG] Salvage debug info for non-constant ADDs

Full diff: https://github.com/llvm/llvm-project/pull/68981.diff

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (+31-7)
  • (added) llvm/test/DebugInfo/Sparc/pointer-add-unknown-offset-debug-info.mir (+60)
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

@github-actions
Copy link

github-actions bot commented Oct 13, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@dstenb
Copy link
Collaborator Author

dstenb commented Oct 19, 2023

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
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)

@dstenb
Copy link
Collaborator Author

dstenb commented Oct 25, 2023

Thanks for the review! I'll land this shortly.

@dstenb dstenb merged commit 3ab03ad into llvm:main Oct 25, 2023
3 checks passed
@dstenb
Copy link
Collaborator Author

dstenb commented Oct 25, 2023

This broke expensive-checks buildbots, e.g. https://lab.llvm.org/buildbot/#/builders/16/builds/56317, so I'll revert and investigate.

dstenb added a commit that referenced this pull request Oct 25, 2023
…)"

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.
@dstenb
Copy link
Collaborator Author

dstenb commented Oct 25, 2023

Reverted in 6b25890.

dstenb added a commit that referenced this pull request Oct 25, 2023
…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>
@dstenb
Copy link
Collaborator Author

dstenb commented Oct 25, 2023

The test case was generated using -stop-before=sparc-isel, which produced MIR output with no body for the function. Running -start-before=sparc-isel on that output (as was done in the test case) resulted in the following verifier error which broke the expensive-checks bots:

*** Bad machine code: Function has NoVRegs property but there are VReg operands ***
- function:    pointer_add_unknown_offset
LLVM ERROR: Found 1 machine code errors.

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. llvm/test/CodeGen/AArch64/callbr-asm-outputs-indirect-isel.ll. I verified that this works with update_mir_test_checks.py (the only difference is that the CHECKs are inserted in the IR code instead).

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();
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.

dstenb added a commit that referenced this pull request Nov 18, 2023
…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.
sr-tream pushed a commit to sr-tream/llvm-project that referenced this pull request Nov 20, 2023
…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.
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
debuginfo llvm:SelectionDAG SelectionDAGISel as well
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants