[llvm-branch-commits] [llvm] a7e3339 - [AArch64][SVE] Emit DWARF location expression for SVE stack objects.

Sander de Smalen via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Jan 6 02:00:07 PST 2021


Author: Sander de Smalen
Date: 2021-01-06T09:40:53Z
New Revision: a7e3339f3b0eb71e43d44e6f59cc8db6a7b110bf

URL: https://github.com/llvm/llvm-project/commit/a7e3339f3b0eb71e43d44e6f59cc8db6a7b110bf
DIFF: https://github.com/llvm/llvm-project/commit/a7e3339f3b0eb71e43d44e6f59cc8db6a7b110bf.diff

LOG: [AArch64][SVE] Emit DWARF location expression for SVE stack objects.

Extend PEI to emit a DWARF expression for StackOffsets that have
a fixed and scalable component. This means the expression that needs
to be added is either:
  <base> + offset
or:
  <base> + offset + scalable_offset * scalereg

where for SVE, the scale reg is the Vector Granule Dwarf register, which
encodes the number of 64bit 'granules' in an SVE vector and which
the debugger can evaluate at runtime.

Reviewed By: jmorse

Differential Revision: https://reviews.llvm.org/D90020

Added: 
    llvm/test/CodeGen/AArch64/debug-info-sve-dbg-value.mir

Modified: 
    llvm/include/llvm/CodeGen/TargetRegisterInfo.h
    llvm/lib/CodeGen/PrologEpilogInserter.cpp
    llvm/lib/CodeGen/TargetRegisterInfo.cpp
    llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
    llvm/lib/Target/AArch64/AArch64RegisterInfo.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index de2c1b069784..6f32729a1e83 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -34,6 +34,7 @@
 namespace llvm {
 
 class BitVector;
+class DIExpression;
 class LiveRegMatrix;
 class MachineFunction;
 class MachineInstr;
@@ -923,6 +924,15 @@ class TargetRegisterInfo : public MCRegisterInfo {
     llvm_unreachable("isFrameOffsetLegal does not exist on this target");
   }
 
+  /// Gets the DWARF expression opcodes for \p Offset.
+  virtual void getOffsetOpcodes(const StackOffset &Offset,
+                                SmallVectorImpl<uint64_t> &Ops) const;
+
+  /// Prepends a DWARF expression for \p Offset to DIExpression \p Expr.
+  DIExpression *
+  prependOffsetExpression(const DIExpression *Expr, unsigned PrependFlags,
+                          const StackOffset &Offset) const;
+
   /// Spill the register so it can be used by the register scavenger.
   /// Return true if the register was spilled, false otherwise.
   /// If this function does not spill the register, the scavenger

diff  --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 7c38b193a980..65b2165bf2a0 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -1211,8 +1211,6 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &MF,
 
         StackOffset Offset =
             TFI->getFrameIndexReference(MF, FrameIdx, Reg);
-        assert(!Offset.getScalable() &&
-               "Frame offsets with a scalable component are not supported");
         MI.getOperand(0).ChangeToRegister(Reg, false /*isDef*/);
         MI.getOperand(0).setIsDebug();
 
@@ -1238,7 +1236,8 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &MF,
           // Make the DBG_VALUE direct.
           MI.getDebugOffset().ChangeToRegister(0, false);
         }
-        DIExpr = DIExpression::prepend(DIExpr, PrependFlags, Offset.getFixed());
+
+        DIExpr = TRI.prependOffsetExpression(DIExpr, PrependFlags, Offset);
         MI.getDebugExpressionOp().setMetadata(DIExpr);
         continue;
       }

diff  --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index e89353c9ad27..4a190c9f50af 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -26,6 +26,7 @@
 #include "llvm/CodeGen/VirtRegMap.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/Attributes.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/Function.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/Support/CommandLine.h"
@@ -532,6 +533,31 @@ TargetRegisterInfo::lookThruCopyLike(Register SrcReg,
   }
 }
 
+void TargetRegisterInfo::getOffsetOpcodes(
+    const StackOffset &Offset, SmallVectorImpl<uint64_t> &Ops) const {
+  assert(!Offset.getScalable() && "Scalable offsets are not handled");
+  DIExpression::appendOffset(Ops, Offset.getFixed());
+}
+
+DIExpression *
+TargetRegisterInfo::prependOffsetExpression(const DIExpression *Expr,
+                                            unsigned PrependFlags,
+                                            const StackOffset &Offset) const {
+  assert((PrependFlags &
+          ~(DIExpression::DerefBefore | DIExpression::DerefAfter |
+            DIExpression::StackValue | DIExpression::EntryValue)) == 0 &&
+         "Unsupported prepend flag");
+  SmallVector<uint64_t, 16> OffsetExpr;
+  if (PrependFlags & DIExpression::DerefBefore)
+    OffsetExpr.push_back(dwarf::DW_OP_deref);
+  getOffsetOpcodes(Offset, OffsetExpr);
+  if (PrependFlags & DIExpression::DerefAfter)
+    OffsetExpr.push_back(dwarf::DW_OP_deref);
+  return DIExpression::prependOpcodes(Expr, OffsetExpr,
+                                      PrependFlags & DIExpression::StackValue,
+                                      PrependFlags & DIExpression::EntryValue);
+}
+
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 LLVM_DUMP_METHOD
 void TargetRegisterInfo::dumpReg(Register Reg, unsigned SubRegIndex,

diff  --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index 954b0960fc02..231e8b3089f6 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -24,6 +24,7 @@
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
 #include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Function.h"
 #include "llvm/Support/raw_ostream.h"
@@ -592,6 +593,33 @@ createScratchRegisterForInstruction(MachineInstr &MI,
   }
 }
 
+void AArch64RegisterInfo::getOffsetOpcodes(
+    const StackOffset &Offset, SmallVectorImpl<uint64_t> &Ops) const {
+  // The smallest scalable element supported by scaled SVE addressing
+  // modes are predicates, which are 2 scalable bytes in size. So the scalable
+  // byte offset must always be a multiple of 2.
+  assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
+
+  // Add fixed-sized offset using existing DIExpression interface.
+  DIExpression::appendOffset(Ops, Offset.getFixed());
+
+  unsigned VG = getDwarfRegNum(AArch64::VG, true);
+  int64_t VGSized = Offset.getScalable() / 2;
+  if (VGSized > 0) {
+    Ops.push_back(dwarf::DW_OP_constu);
+    Ops.push_back(VGSized);
+    Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
+    Ops.push_back(dwarf::DW_OP_mul);
+    Ops.push_back(dwarf::DW_OP_plus);
+  } else if (VGSized < 0) {
+    Ops.push_back(dwarf::DW_OP_constu);
+    Ops.push_back(-VGSized);
+    Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
+    Ops.push_back(dwarf::DW_OP_mul);
+    Ops.push_back(dwarf::DW_OP_minus);
+  }
+}
+
 void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
                                               int SPAdj, unsigned FIOperandNum,
                                               RegScavenger *RS) const {
@@ -610,7 +638,7 @@ void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   Register FrameReg;
 
   // Special handling of dbg_value, stackmap patchpoint statepoint instructions.
-  if (MI.isDebugValue() || MI.getOpcode() == TargetOpcode::STACKMAP ||
+  if (MI.getOpcode() == TargetOpcode::STACKMAP ||
       MI.getOpcode() == TargetOpcode::PATCHPOINT ||
       MI.getOpcode() == TargetOpcode::STATEPOINT) {
     StackOffset Offset =

diff  --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
index d7580d7b6833..1c74d39d404f 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
@@ -135,6 +135,9 @@ class AArch64RegisterInfo final : public AArch64GenRegisterInfo {
                       unsigned SubReg, const TargetRegisterClass *DstRC,
                       unsigned DstSubReg, const TargetRegisterClass *NewRC,
                       LiveIntervals &LIS) const override;
+
+  void getOffsetOpcodes(const StackOffset &Offset,
+                        SmallVectorImpl<uint64_t> &Ops) const override;
 };
 
 } // end namespace llvm

diff  --git a/llvm/test/CodeGen/AArch64/debug-info-sve-dbg-value.mir b/llvm/test/CodeGen/AArch64/debug-info-sve-dbg-value.mir
new file mode 100644
index 000000000000..ffce40c9c4f4
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/debug-info-sve-dbg-value.mir
@@ -0,0 +1,126 @@
+# RUN: llc -o %t -filetype=obj -start-before=prologepilog %s
+# RUN: llvm-dwarfdump --name="value0" %t | FileCheck %s --check-prefix=CHECK0
+# RUN: llvm-dwarfdump --name="value1" %t | FileCheck %s --check-prefix=CHECK1
+# RUN: llvm-dwarfdump --name="value2" %t | FileCheck %s --check-prefix=CHECK2
+# RUN: llvm-dwarfdump --name="value3" %t | FileCheck %s --check-prefix=CHECK3
+# RUN: llvm-dwarfdump --name="value4" %t | FileCheck %s --check-prefix=CHECK4
+# RUN: llvm-dwarfdump --name="value5" %t | FileCheck %s --check-prefix=CHECK5
+
+# CHECK0: : DW_OP_breg31 WSP+8, DW_OP_lit16, DW_OP_plus)
+# CHECK0: DW_AT_type {{.*}}ty32
+#
+# CHECK1: : DW_OP_breg31 WSP+16)
+# CHECK1: DW_AT_type {{.*}}ty32
+#
+# CHECK2: : DW_OP_breg31 WSP+16, DW_OP_lit16, DW_OP_bregx VG+0, DW_OP_mul, DW_OP_plus)
+# CHECK2: DW_AT_type {{.*}}svint32_t
+#
+# CHECK3: : DW_OP_breg31 WSP+16, DW_OP_lit8, DW_OP_bregx VG+0, DW_OP_mul, DW_OP_plus)
+# CHECK3: DW_AT_type {{.*}}svint32_t
+#
+# CHECK4: : DW_OP_breg31 WSP+16, DW_OP_lit7, DW_OP_bregx VG+0, DW_OP_mul, DW_OP_plus)
+# CHECK4: DW_AT_type {{.*}}svbool_t
+#
+# CHECK5: : DW_OP_breg31 WSP+16, DW_OP_lit6, DW_OP_bregx VG+0, DW_OP_mul, DW_OP_plus)
+# CHECK5: DW_AT_type {{.*}}svbool_t
+
+--- |
+  ; ModuleID = 'bla.mir'
+  source_filename = "bla.mir"
+  target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+
+  define void @foo() #0 !dbg !5 {
+  entry:
+    unreachable, !dbg !8
+  }
+
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+  attributes #0 = { "target-features"="+sve" }
+
+  !llvm.dbg.cu = !{!0}
+  !llvm.debugify = !{!3, !3}
+  !llvm.module.flags = !{!4}
+
+  !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+  !1 = !DIFile(filename: "bla.mir", directory: "/")
+  !2 = !{}
+  !3 = !{i32 1}
+  !4 = !{i32 2, !"Debug Info Version", i32 3}
+  !5 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !9)
+  !6 = !DISubroutineType(types: !2)
+  !7 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_signed)
+  !8 = !DILocation(line: 1, column: 1, scope: !5)
+  !9 = !{!10, !11, !12, !13, !14, !15}
+  !10 = !DILocalVariable(name: "value0", scope: !5, file: !1, line: 1, type: !7)
+  !11 = !DILocalVariable(name: "value1", scope: !5, file: !1, line: 1, type: !7)
+  !12 = !DILocalVariable(name: "value2", scope: !5, file: !1, line: 1, type: !16)
+  !13 = !DILocalVariable(name: "value3", scope: !5, file: !1, line: 1, type: !16)
+  !14 = !DILocalVariable(name: "value4", scope: !5, file: !1, line: 1, type: !21)
+  !15 = !DILocalVariable(name: "value5", scope: !5, file: !1, line: 1, type: !21)
+  !16 = !DIDerivedType(tag: DW_TAG_typedef, name: "svint32_t", file: !1, line: 1, baseType: !17)
+  !17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__SVInt32_t", file: !1, baseType: !18)
+  !18 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, flags: DIFlagVector, elements: !19)
+  !19 = !{!20}
+  !20 = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 2, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
+  !21 = !DIDerivedType(tag: DW_TAG_typedef, name: "svbool_t", file: !1, line: 90, baseType: !22)
+  !22 = !DIDerivedType(tag: DW_TAG_typedef, name: "__SVBool_t", file: !1, baseType: !23)
+  !23 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, flags: DIFlagVector, elements: !25)
+  !24 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
+  !25 = !{!26}
+  !26 = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 1, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
+
+
+...
+---
+name:            foo
+alignment:       4
+tracksRegLiveness: true
+liveins:
+  - { reg: '$z0' }
+  - { reg: '$z1' }
+  - { reg: '$p0' }
+  - { reg: '$p1' }
+  - { reg: '$x0' }
+  - { reg: '$x1' }
+frameInfo:
+  maxAlignment:    16
+  adjustsStack:    true
+  hasCalls:        true
+  maxCallFrameSize: 0
+  localFrameSize:  4
+stack:
+  - { id: 0, size: 8,  alignment: 8 }
+  - { id: 1, size: 8,  alignment: 8 }
+  - { id: 2, size: 16, alignment: 16, stack-id: sve-vec }
+  - { id: 3, size: 16, alignment: 16, stack-id: sve-vec }
+  - { id: 4, size: 2,  alignment: 2,  stack-id: sve-vec }
+  - { id: 5, size: 2,  alignment: 2,  stack-id: sve-vec }
+machineFunctionInfo: {}
+body:             |
+  bb.0.entry:
+    liveins: $p0, $p1, $w0, $x1, $z0, $z1
+
+    ; Avoid stack slot scavenging.
+    $lr = IMPLICIT_DEF
+
+    STRXui killed renamable $x0, %stack.0, 0, debug-location !8
+    DBG_VALUE %stack.0, $noreg, !10, !DIExpression(DW_OP_constu, 16, DW_OP_plus, DW_OP_deref), debug-location !8
+    STRXui killed renamable $x1, %stack.1, 0, debug-location !8
+    DBG_VALUE %stack.1, $noreg, !11, !DIExpression(DW_OP_constu, 16, DW_OP_plus, DW_OP_deref), debug-location !8
+
+    renamable $p2 = PTRUE_S 31, debug-location !DILocation(line: 4, column: 1, scope: !5)
+    ST1W_IMM renamable $z0, renamable $p2, %stack.2, 0, debug-location !DILocation(line: 5, column: 1, scope: !5)
+    DBG_VALUE %stack.2, $noreg, !12, !DIExpression(DW_OP_deref), debug-location !DILocation(line: 5, column: 1, scope: !5)
+    ST1W_IMM renamable $z1, killed renamable $p2, %stack.3, 0, debug-location !DILocation(line: 6, column: 1, scope: !5)
+    DBG_VALUE %stack.3, $noreg, !13, !DIExpression(DW_OP_deref), debug-location !DILocation(line: 6, column: 1, scope: !5)
+
+    STR_PXI killed renamable $p0, %stack.4, 0, debug-location !DILocation(line: 2, column: 1, scope: !5)
+    DBG_VALUE %stack.4, $noreg, !14, !DIExpression(DW_OP_deref), debug-location !DILocation(line: 2, column: 1, scope: !5)
+    STR_PXI killed renamable $p1, %stack.5, 0, debug-location !DILocation(line: 3, column: 1, scope: !5)
+    DBG_VALUE %stack.5, $noreg, !15, !DIExpression(DW_OP_deref), debug-location !DILocation(line: 3, column: 1, scope: !5)
+
+    RET_ReallyLR implicit $z0, implicit $z1, debug-location !DILocation(line: 7, column: 1, scope: !5)
+
+...


        


More information about the llvm-branch-commits mailing list