[llvm] r365444 - Reland "[LiveDebugValues] Emit the debug entry values"

Djordje Todorovic via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 9 01:36:34 PDT 2019


Author: djtodoro
Date: Tue Jul  9 01:36:34 2019
New Revision: 365444

URL: http://llvm.org/viewvc/llvm-project?rev=365444&view=rev
Log:
Reland "[LiveDebugValues] Emit the debug entry values"

Emit replacements for clobbered parameters location if the parameter
has unmodified value throughout the funciton. This is basic scenario
where we can use the debug entry values.

([12/13] Introduce the debug entry values.)

Co-authored-by: Ananth Sowda <asowda at cisco.com>
Co-authored-by: Nikola Prica <nikola.prica at rt-rk.com>
Co-authored-by: Ivan Baev <ibaev at cisco.com>

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

Added:
    llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir
    llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir
    llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir
Modified:
    llvm/trunk/include/llvm/CodeGen/MachineInstr.h
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
    llvm/trunk/lib/CodeGen/LiveDebugValues.cpp
    llvm/trunk/lib/CodeGen/MachineVerifier.cpp

Modified: llvm/trunk/include/llvm/CodeGen/MachineInstr.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineInstr.h?rev=365444&r1=365443&r2=365444&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineInstr.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineInstr.h Tue Jul  9 01:36:34 2019
@@ -24,6 +24,7 @@
 #include "llvm/CodeGen/MachineMemOperand.h"
 #include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/MC/MCInstrDesc.h"
@@ -1018,6 +1019,12 @@ public:
       && getOperand(1).isImm();
   }
 
+  /// A DBG_VALUE is an entry value iff its debug expression contains the
+  /// DW_OP_entry_value DWARF operation.
+  bool isDebugEntryValue() const {
+    return isDebugValue() && getDebugExpression()->isEntryValue();
+  }
+
   /// Return true if the instruction is a debug value which describes a part of
   /// a variable as unavailable.
   bool isUndefDebugValue() const {

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=365444&r1=365443&r2=365444&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Tue Jul  9 01:36:34 2019
@@ -1128,6 +1128,12 @@ void DwarfCompileUnit::addComplexAddress
     DwarfExpr.setMemoryLocationKind();
 
   DIExpressionCursor Cursor(DIExpr);
+
+  if (DIExpr->isEntryValue()) {
+    DwarfExpr.setEntryValueFlag();
+    DwarfExpr.addEntryValueExpression(Cursor);
+  }
+
   const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
   if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
     return;

Modified: llvm/trunk/lib/CodeGen/LiveDebugValues.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveDebugValues.cpp?rev=365444&r1=365443&r2=365444&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LiveDebugValues.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveDebugValues.cpp Tue Jul  9 01:36:34 2019
@@ -39,6 +39,7 @@
 #include "llvm/CodeGen/TargetFrameLowering.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/Config/llvm-config.h"
@@ -185,7 +186,8 @@ private:
       InvalidKind = 0,
       RegisterKind,
       SpillLocKind,
-      ImmediateKind
+      ImmediateKind,
+      EntryValueKind
     } Kind = InvalidKind;
 
     /// The value location. Stored separately to avoid repeatedly
@@ -199,14 +201,15 @@ private:
       const ConstantInt *CImm;
     } Loc;
 
-    VarLoc(const MachineInstr &MI, LexicalScopes &LS)
-        : Var(MI), MI(MI), UVS(MI.getDebugLoc(), LS) {
+    VarLoc(const MachineInstr &MI, LexicalScopes &LS,
+          VarLocKind K = InvalidKind)
+        : Var(MI), MI(MI), UVS(MI.getDebugLoc(), LS){
       static_assert((sizeof(Loc) == sizeof(uint64_t)),
                     "hash does not cover all members of Loc");
       assert(MI.isDebugValue() && "not a DBG_VALUE");
       assert(MI.getNumOperands() == 4 && "malformed DBG_VALUE");
       if (int RegNo = isDbgValueDescribedByReg(MI)) {
-        Kind = RegisterKind;
+        Kind = MI.isDebugEntryValue() ? EntryValueKind : RegisterKind;
         Loc.RegNo = RegNo;
       } else if (MI.getOperand(0).isImm()) {
         Kind = ImmediateKind;
@@ -218,6 +221,8 @@ private:
         Kind = ImmediateKind;
         Loc.CImm = MI.getOperand(0).getCImm();
       }
+      assert((Kind != ImmediateKind || !MI.isDebugEntryValue()) &&
+             "entry values must be register locations");
     }
 
     /// The constructor for spill locations.
@@ -256,12 +261,12 @@ private:
 
     /// This operator guarantees that VarLocs are sorted by Variable first.
     bool operator<(const VarLoc &Other) const {
-      if (Var == Other.Var)
-        return Loc.Hash < Other.Loc.Hash;
-      return Var < Other.Var;
+      return std::tie(Var, Kind, Loc.Hash) <
+             std::tie(Other.Var, Other.Kind, Other.Loc.Hash);
     }
   };
 
+  using DebugParamMap = SmallDenseMap<const DILocalVariable *, MachineInstr *>;
   using VarLocMap = UniqueVector<VarLoc>;
   using VarLocSet = SparseBitVector<>;
   using VarLocInMBB = SmallDenseMap<const MachineBasicBlock *, VarLocSet>;
@@ -347,17 +352,23 @@ private:
                           VarLocMap &VarLocIDs);
   void transferSpillOrRestoreInst(MachineInstr &MI, OpenRangesSet &OpenRanges,
                                   VarLocMap &VarLocIDs, TransferMap &Transfers);
+  void emitEntryValues(MachineInstr &MI, OpenRangesSet &OpenRanges,
+                       VarLocMap &VarLocIDs, TransferMap &Transfers,
+                       DebugParamMap &DebugEntryVals,
+                       SparseBitVector<> &KillSet);
   void transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges,
                             VarLocMap &VarLocIDs, TransferMap &Transfers);
   void transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges,
-                           const VarLocMap &VarLocIDs);
+                           VarLocMap &VarLocIDs, TransferMap &Transfers,
+                           DebugParamMap &DebugEntryVals);
   bool transferTerminatorInst(MachineInstr &MI, OpenRangesSet &OpenRanges,
                               VarLocInMBB &OutLocs, const VarLocMap &VarLocIDs);
 
   bool process(MachineInstr &MI, OpenRangesSet &OpenRanges,
                VarLocInMBB &OutLocs, VarLocMap &VarLocIDs,
-               TransferMap &Transfers, bool transferChanges,
-               OverlapMap &OverlapFragments, VarToFragments &SeenFragments);
+               TransferMap &Transfers, DebugParamMap &DebugEntryVals,
+               bool transferChanges, OverlapMap &OverlapFragments,
+               VarToFragments &SeenFragments);
 
   void accumulateFragmentMap(MachineInstr &MI, VarToFragments &SeenFragments,
                              OverlapMap &OLapMap);
@@ -568,6 +579,44 @@ void LiveDebugValues::transferDebugValue
   }
 }
 
+void LiveDebugValues::emitEntryValues(MachineInstr &MI,
+                                      OpenRangesSet &OpenRanges,
+                                      VarLocMap &VarLocIDs,
+                                      TransferMap &Transfers,
+                                      DebugParamMap &DebugEntryVals,
+                                      SparseBitVector<> &KillSet) {
+  MachineFunction *MF = MI.getParent()->getParent();
+  for (unsigned ID : KillSet) {
+    if (!VarLocIDs[ID].Var.getVar()->isParameter())
+      continue;
+
+    const MachineInstr *CurrDebugInstr = &VarLocIDs[ID].MI;
+
+    // If parameter's DBG_VALUE is not in the map that means we can't
+    // generate parameter's entry value.
+    if (!DebugEntryVals.count(CurrDebugInstr->getDebugVariable()))
+      continue;
+
+    auto ParamDebugInstr = DebugEntryVals[CurrDebugInstr->getDebugVariable()];
+    DIExpression *NewExpr = DIExpression::prepend(
+        ParamDebugInstr->getDebugExpression(), DIExpression::EntryValue);
+    MachineInstr *EntryValDbgMI =
+        BuildMI(*MF, ParamDebugInstr->getDebugLoc(), ParamDebugInstr->getDesc(),
+                ParamDebugInstr->isIndirectDebugValue(),
+                ParamDebugInstr->getOperand(0).getReg(),
+                ParamDebugInstr->getDebugVariable(), NewExpr);
+
+    if (ParamDebugInstr->isIndirectDebugValue())
+      EntryValDbgMI->getOperand(1).setImm(
+          ParamDebugInstr->getOperand(1).getImm());
+
+    Transfers.push_back({&MI, EntryValDbgMI});
+    VarLoc VL(*EntryValDbgMI, LS);
+    unsigned EntryValLocID = VarLocIDs.insert(VL);
+    OpenRanges.insert(EntryValLocID, VL.Var);
+  }
+}
+
 /// Create new TransferDebugPair and insert it in \p Transfers. The VarLoc
 /// with \p OldVarID should be deleted form \p OpenRanges and replaced with
 /// new VarLoc. If \p NewReg is different than default zero value then the
@@ -658,9 +707,9 @@ void LiveDebugValues::insertTransferDebu
 }
 
 /// A definition of a register may mark the end of a range.
-void LiveDebugValues::transferRegisterDef(MachineInstr &MI,
-                                          OpenRangesSet &OpenRanges,
-                                          const VarLocMap &VarLocIDs) {
+void LiveDebugValues::transferRegisterDef(
+    MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs,
+    TransferMap &Transfers, DebugParamMap &DebugEntryVals) {
   MachineFunction *MF = MI.getMF();
   const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
   unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
@@ -690,6 +739,13 @@ void LiveDebugValues::transferRegisterDe
     }
   }
   OpenRanges.erase(KillSet, VarLocIDs);
+
+  if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>()) {
+    auto &TM = TPC->getTM<TargetMachine>();
+    if (TM.Options.EnableDebugEntryValues)
+      emitEntryValues(MI, OpenRanges, VarLocIDs, Transfers, DebugEntryVals,
+                      KillSet);
+  }
 }
 
 /// Decide if @MI is a spill instruction and return true if it is. We use 2
@@ -941,12 +997,14 @@ void LiveDebugValues::accumulateFragment
 /// This routine creates OpenRanges and OutLocs.
 bool LiveDebugValues::process(MachineInstr &MI, OpenRangesSet &OpenRanges,
                               VarLocInMBB &OutLocs, VarLocMap &VarLocIDs,
-                              TransferMap &Transfers, bool transferChanges,
+                              TransferMap &Transfers, DebugParamMap &DebugEntryVals,
+                              bool transferChanges,
                               OverlapMap &OverlapFragments,
                               VarToFragments &SeenFragments) {
   bool Changed = false;
   transferDebugValue(MI, OpenRanges, VarLocIDs);
-  transferRegisterDef(MI, OpenRanges, VarLocIDs);
+  transferRegisterDef(MI, OpenRanges, VarLocIDs, Transfers,
+                      DebugEntryVals);
   if (transferChanges) {
     transferRegisterCopy(MI, OpenRanges, VarLocIDs, Transfers);
     transferSpillOrRestoreInst(MI, OpenRanges, VarLocIDs, Transfers);
@@ -1100,6 +1158,43 @@ bool LiveDebugValues::ExtendRanges(Machi
 
   enum : bool { dontTransferChanges = false, transferChanges = true };
 
+  // Besides parameter's modification, check whether a DBG_VALUE is inlined
+  // in order to deduce whether the variable that it tracks comes from
+  // a different function. If that is the case we can't track its entry value.
+  auto IsUnmodifiedFuncParam = [&](const MachineInstr &MI) {
+    auto *DIVar = MI.getDebugVariable();
+    return DIVar->isParameter() && DIVar->isNotModified() &&
+           !MI.getDebugLoc()->getInlinedAt();
+  };
+
+  const TargetLowering *TLI = MF.getSubtarget().getTargetLowering();
+  unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
+  unsigned FP = TRI->getFrameRegister(MF);
+  auto IsRegOtherThanSPAndFP = [&](const MachineOperand &Op) -> bool {
+    return Op.isReg() && Op.getReg() != SP && Op.getReg() != FP;
+  };
+
+  // Working set of currently collected debug variables mapped to DBG_VALUEs
+  // representing candidates for production of debug entry values.
+  DebugParamMap DebugEntryVals;
+
+  MachineBasicBlock &First_MBB = *(MF.begin());
+  // Only in the case of entry MBB collect DBG_VALUEs representing
+  // function parameters in order to generate debug entry values for them.
+  // Currently, we generate debug entry values only for parameters that are
+  // unmodified throughout the function and located in a register.
+  // TODO: Add support for parameters that are described as fragments.
+  // TODO: Add support for modified arguments that can be expressed
+  // by using its entry value.
+  // TODO: Add support for local variables that are expressed in terms of
+  // parameters entry values.
+  for (auto &MI : First_MBB)
+    if (MI.isDebugValue() && IsUnmodifiedFuncParam(MI) &&
+        !MI.isIndirectDebugValue() && IsRegOtherThanSPAndFP(MI.getOperand(0)) &&
+        !DebugEntryVals.count(MI.getDebugVariable()) &&
+        !MI.getDebugExpression()->isFragment())
+      DebugEntryVals[MI.getDebugVariable()] = &MI;
+
   // Initialize every mbb with OutLocs.
   // We are not looking at any spill instructions during the initial pass
   // over the BBs. The LiveDebugVariables pass has already created DBG_VALUE
@@ -1107,9 +1202,16 @@ bool LiveDebugValues::ExtendRanges(Machi
   // within the BB in which the spill occurs.
   for (auto &MBB : MF) {
     for (auto &MI : MBB) {
-      process(MI, OpenRanges, OutLocs, VarLocIDs, Transfers,
+      process(MI, OpenRanges, OutLocs, VarLocIDs, Transfers, DebugEntryVals,
               dontTransferChanges, OverlapFragments, SeenFragments);
     }
+    // Add any entry DBG_VALUE instructions necessitated by parameter
+    // clobbering.
+    for (auto &TR : Transfers) {
+      MBB.insertAfter(MachineBasicBlock::iterator(*TR.TransferInst),
+                     TR.DebugInst);
+    }
+    Transfers.clear();
   }
 
   auto hasNonArtificialLocation = [](const MachineInstr &MI) -> bool {
@@ -1158,7 +1260,8 @@ bool LiveDebugValues::ExtendRanges(Machi
         for (auto &MI : *MBB)
           OLChanged |=
               process(MI, OpenRanges, OutLocs, VarLocIDs, Transfers,
-                      transferChanges, OverlapFragments, SeenFragments);
+                      DebugEntryVals, transferChanges, OverlapFragments,
+                      SeenFragments);
 
         // Add any DBG_VALUE instructions necessitated by spills.
         for (auto &TR : Transfers)

Modified: llvm/trunk/lib/CodeGen/MachineVerifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineVerifier.cpp?rev=365444&r1=365443&r2=365444&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineVerifier.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineVerifier.cpp Tue Jul  9 01:36:34 2019
@@ -840,7 +840,7 @@ void MachineVerifier::visitMachineBundle
   if (MI->isTerminator() && !TII->isPredicated(*MI)) {
     if (!FirstTerminator)
       FirstTerminator = MI;
-  } else if (FirstTerminator) {
+  } else if (FirstTerminator && !MI->isDebugEntryValue()) {
     report("Non-terminator instruction after the first terminator", MI);
     errs() << "First terminator was:\t" << *FirstTerminator;
   }

Added: llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir?rev=365444&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir (added)
+++ llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir Tue Jul  9 01:36:34 2019
@@ -0,0 +1,67 @@
+# RUN: llc -mtriple=x86_64-pc-linux %s -dwarf-version=5 -start-after=livedebugvalues -filetype=obj -o %t
+# RUN: llvm-dwarfdump -v %t | FileCheck %s
+#
+# CHECK: DW_AT_location {{.*}} (DW_OP_entry_value
+#
+--- |
+  ; ModuleID = 'test.ll'
+  source_filename = "test.c"
+  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-unknown-linux-gnu"
+  
+  ; Function Attrs: noinline nounwind uwtable
+  define dso_local void @fn1(i8* %x) local_unnamed_addr !dbg !12 {
+  entry:
+    call void @llvm.dbg.value(metadata i8* %x, metadata !16, metadata !DIExpression()), !dbg !18
+    %0 = ptrtoint i8* %x to i64, !dbg !18
+    %y = trunc i64 %0 to i32, !dbg !18
+    call void @llvm.dbg.value(metadata i32 %y, metadata !17, metadata !DIExpression()), !dbg !18
+    tail call void @fn2(i32 7), !dbg !18
+    ret void, !dbg !18
+  }
+  
+  declare !dbg !4 dso_local void @fn2(i32) local_unnamed_addr
+  
+  ; Function Attrs: nounwind readnone speculatable
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!8, !9, !10}
+  !llvm.ident = !{!11}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+  !1 = !DIFile(filename: "test.c", directory: "/dir")
+  !2 = !{}
+  !3 = !{!4}
+  !4 = !DISubprogram(name: "fn2", scope: !1, file: !1, line: 1, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !DISubroutineType(types: !6)
+  !6 = !{null, !7}
+  !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !8 = !{i32 2, !"Dwarf Version", i32 5}
+  !9 = !{i32 2, !"Debug Info Version", i32 3}
+  !10 = !{i32 1, !"wchar_size", i32 4}
+  !11 = !{!"clang version 9.0.0"}
+  !12 = distinct !DISubprogram(name: "fn1", scope: !1, file: !1, line: 5, type: !13, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !15)
+  !13 = !DISubroutineType(types: !14)
+  !14 = !{null, !7, !7}
+  !15 = !{!16, !17}
+  !16 = !DILocalVariable(name: "x", arg: 1, scope: !12, file: !1, line: 5, type: !7, flags: DIFlagArgumentNotModified)
+  !17 = !DILocalVariable(name: "y", scope: !12, file: !1, line: 5, type: !7)
+  !18 = !DILocation(line: 0, scope: !12)
+
+...
+---
+name:            fn1
+alignment:       4
+tracksRegLiveness: true
+body:             |
+  bb.0.entry:
+  liveins: $rdi
+    DBG_VALUE $rdi, $noreg, !16, !DIExpression(), debug-location !18
+    DBG_VALUE $edi, $noreg, !16, !DIExpression(), debug-location !18
+    DBG_VALUE $edi, $noreg, !17, !DIExpression(), debug-location !18
+    $edi = KILL renamable $edi, implicit killed $rdi, debug-location !18
+    DBG_VALUE $rdi, $noreg, !16, !DIExpression(DW_OP_entry_value, 1), debug-location !18
+    TAILJMPd64 @fn2, csr_64, implicit $rsp, implicit $ssp, implicit $rsp, implicit $ssp, implicit killed $edi, debug-location !18
+
+...

Added: llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir?rev=365444&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir (added)
+++ llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir Tue Jul  9 01:36:34 2019
@@ -0,0 +1,79 @@
+# RUN: llc -debug-entry-values -run-pass=livedebugvalues -march=x86-64 -o - %s | FileCheck %s
+#
+#extern void fn2(int);
+#
+#__attribute__((noinline))
+#void
+#fn1 (int x, int y) {
+#  int u = x + y;
+#  if (x > 1)
+#    u += 1;
+#  else
+#    u += 2;
+#  int a = 7;
+#  fn2 (a);
+#  u --;
+#}
+# CHECK: DBG_VALUE $edi, $noreg, !14, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
+# CHECK: DBG_VALUE $esi, $noreg, !15, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
+
+--- |
+  ; ModuleID = 'test.c'
+  source_filename = "test.c"
+  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+  
+  ; Function Attrs: noinline nounwind uwtable
+  define dso_local void @fn1(i32 %x, i32 %y) local_unnamed_addr !dbg !9 {
+  entry:
+    call void @llvm.dbg.value(metadata i32 %x, metadata !14, metadata !DIExpression()), !dbg !18
+    call void @llvm.dbg.value(metadata i32 %y, metadata !15, metadata !DIExpression()), !dbg !18
+    call void @llvm.dbg.value(metadata i32 7, metadata !17, metadata !DIExpression()), !dbg !18
+    tail call void @fn2(i32 7), !dbg !18
+    ret void, !dbg !18
+  }
+  
+  declare !dbg !4 dso_local void @fn2(i32) local_unnamed_addr
+  
+  ; Function Attrs: nounwind readnone speculatable
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+  
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!5, !6, !7}
+  !llvm.ident = !{!8}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+  !1 = !DIFile(filename: "test.c", directory: "/dir")
+  !2 = !{}
+  !3 = !{!4}
+  !4 = !DISubprogram(name: "fn2", scope: !1, file: !1, line: 11, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !{i32 2, !"Dwarf Version", i32 4}
+  !6 = !{i32 2, !"Debug Info Version", i32 3}
+  !7 = !{i32 1, !"wchar_size", i32 4}
+  !8 = !{!"clang version 9.0.0"}
+  !9 = distinct !DISubprogram(name: "fn1", scope: !1, file: !1, line: 15, type: !10, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13)
+  !10 = !DISubroutineType(types: !11)
+  !11 = !{null, !12, !12}
+  !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !13 = !{!14, !15, !16, !17}
+  !14 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !1, line: 15, type: !12, flags: DIFlagArgumentNotModified)
+  !15 = !DILocalVariable(name: "y", arg: 2, scope: !9, file: !1, line: 15, type: !12, flags: DIFlagArgumentNotModified)
+  !16 = !DILocalVariable(name: "u", scope: !9, file: !1, line: 16, type: !12, flags: DIFlagArgumentNotModified)
+  !17 = !DILocalVariable(name: "a", scope: !9, file: !1, line: 21, type: !12, flags: DIFlagArgumentNotModified)
+  !18 = !DILocation(line: 15, column: 10, scope: !9)
+
+...
+---
+name:            fn1
+alignment:       4
+tracksRegLiveness: true
+liveins:         []
+body:             |
+  bb.0.entry:
+    DBG_VALUE $edi, $noreg, !14, !DIExpression(), debug-location !18
+    DBG_VALUE $esi, $noreg, !15, !DIExpression(), debug-location !18
+    DBG_VALUE 7, $noreg, !17, !DIExpression(), debug-location !18
+    $edi = MOV32ri 7, debug-location !18
+    TAILJMPd64 @fn2, csr_64, implicit $rsp, implicit $ssp, implicit $rsp, implicit $ssp, implicit killed $edi, debug-location !18
+
+...

Added: llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir?rev=365444&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir (added)
+++ llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir Tue Jul  9 01:36:34 2019
@@ -0,0 +1,83 @@
+# RUN: llc -debug-entry-values -run-pass=livedebugvalues -march=x86-64 -o - %s| FileCheck %s
+#
+#int global;
+#int foo(int p, int q, int r) {
+#  global = p + 1;
+#  asm __volatile("" : : : "edi", "esi", "edx");
+#  return 123;
+#}
+#
+# Verify that DW_OP_entry_values are generated for parameters with multiple
+# DBG_VALUEs at entry block.
+# CHECK: DBG_VALUE $edi, $noreg, !{{.*}}, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
+# CHECK: DBG_VALUE $edx, $noreg, !{{.*}}, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
+# CHECK: DBG_VALUE $esi, $noreg, !{{.*}}, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
+
+--- |
+  ; ModuleID = 'multiple-param-dbg-value-entry.ll'
+  source_filename = "multiple-param-dbg-value-entry.c"
+  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+  
+  @global = common dso_local local_unnamed_addr global i32 0, align 4, !dbg !0
+  
+  define dso_local i32 @foo(i32 %p, i32 %q, i32 %r) local_unnamed_addr !dbg !11 {
+  entry:
+    call void @llvm.dbg.value(metadata i32 %p, metadata !15, metadata !DIExpression()), !dbg !18
+    call void @llvm.dbg.value(metadata i32 %q, metadata !16, metadata !DIExpression()), !dbg !18
+    call void @llvm.dbg.value(metadata i32 %r, metadata !17, metadata !DIExpression()), !dbg !18
+    %add = add nsw i32 %p, 1, !dbg !18
+    store i32 %add, i32* @global, align 4, !dbg !18
+    tail call void asm sideeffect "", "~{edi},~{esi},~{edx},~{dirflag},~{fpsr},~{flags}"(), !dbg !18, !srcloc !19
+    ret i32 123, !dbg !18
+  }
+  
+  ; Function Attrs: nounwind readnone speculatable
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+  
+  !llvm.dbg.cu = !{!2}
+  !llvm.module.flags = !{!7, !8, !9}
+  !llvm.ident = !{!10}
+  
+  !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+  !1 = distinct !DIGlobalVariable(name: "global", scope: !2, file: !3, line: 8, type: !6, isLocal: false, isDefinition: true)
+  !2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 9.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+  !3 = !DIFile(filename: "multiple-param-dbg-value-entry.c", directory: "/")
+  !4 = !{}
+  !5 = !{!0}
+  !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !7 = !{i32 2, !"Dwarf Version", i32 4}
+  !8 = !{i32 2, !"Debug Info Version", i32 3}
+  !9 = !{i32 1, !"wchar_size", i32 4}
+  !10 = !{!"clang version 9.0.0 "}
+  !11 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 9, type: !12, scopeLine: 9, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !14)
+  !12 = !DISubroutineType(types: !13)
+  !13 = !{!6, !6, !6, !6}
+  !14 = !{!15, !16, !17}
+  !15 = !DILocalVariable(name: "p", arg: 1, scope: !11, file: !3, line: 9, type: !6, flags: DIFlagArgumentNotModified)
+  !16 = !DILocalVariable(name: "q", arg: 2, scope: !11, file: !3, line: 9, type: !6, flags: DIFlagArgumentNotModified)
+  !17 = !DILocalVariable(name: "r", arg: 3, scope: !11, file: !3, line: 9, type: !6, flags: DIFlagArgumentNotModified)
+  !18 = !DILocation(line: 9, column: 13, scope: !11)
+  !19 = !{i32 213}
+
+...
+---
+name:            foo
+alignment:       4
+tracksRegLiveness: true
+liveins:         
+  - { reg: '$edi' }
+body:             |
+  bb.0.entry:
+    liveins: $edi
+  
+    DBG_VALUE $edi, $noreg, !15, !DIExpression(), debug-location !18
+    DBG_VALUE $edi, $noreg, !15, !DIExpression(), debug-location !18
+    DBG_VALUE $esi, $noreg, !16, !DIExpression(), debug-location !18
+    DBG_VALUE $edx, $noreg, !17, !DIExpression(), debug-location !18
+    renamable $edi = nsw INC32r killed renamable $edi, implicit-def dead $eflags, debug-location !18
+    MOV32mr $rip, 1, $noreg, @global, $noreg, killed renamable $edi, debug-location !18 :: (store 4 into @global)
+    INLINEASM &"", 1, 12, implicit-def dead early-clobber $edi, 12, implicit-def dead early-clobber $esi, 12, implicit-def dead early-clobber $edx, 12, implicit-def dead early-clobber $df, 12, implicit-def dead early-clobber $fpsw, 12, implicit-def dead early-clobber $eflags, !19, debug-location !18
+    $eax = MOV32ri 123, debug-location !18
+    RETQ killed $eax, debug-location !18
+
+...




More information about the llvm-commits mailing list