[llvm] r313786 - Re-land "[DebugInfo] Insert DW_OP_deref when spilling indirect DBG_VALUEs"

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 20 11:19:08 PDT 2017


Author: rnk
Date: Wed Sep 20 11:19:08 2017
New Revision: 313786

URL: http://llvm.org/viewvc/llvm-project?rev=313786&view=rev
Log:
Re-land "[DebugInfo] Insert DW_OP_deref when spilling indirect DBG_VALUEs"

After r313775, it's easier to maintain a parallel BitVector of spilled
locations indexed by location number.

I wasn't able to build a good reduced test case for this iteration of
the bug, but I added a more direct assertion that spilled values must
use frame index locations. If this bug reappears, it won't only fire on
the NEON vector code that we detected it on, but on medium-sized
integer-only programs as well.

Added:
    llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll
    llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll
    llvm/trunk/test/DebugInfo/X86/spill-nospill.ll
Modified:
    llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp
    llvm/trunk/test/DebugInfo/X86/bbjoin.ll

Modified: llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp?rev=313786&r1=313785&r2=313786&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp Wed Sep 20 11:19:08 2017
@@ -108,8 +108,8 @@ class LDVImpl;
 /// held by the same virtual register. The equivalence class is the transitive
 /// closure of that relation.
 class UserValue {
-  const MDNode *Variable;   ///< The debug info variable we are part of.
-  const MDNode *Expression; ///< Any complex address expression.
+  const DILocalVariable *Variable; ///< The debug info variable we are part of.
+  const DIExpression *Expression; ///< Any complex address expression.
   bool IsIndirect;        ///< true if this is a register-indirect+offset value.
   DebugLoc dl;            ///< The debug location for the variable. This is
                           ///< used by dwarf writer to find lexical scope.
@@ -127,8 +127,9 @@ class UserValue {
   SmallSet<SlotIndex, 2> trimmedDefs;
 
   /// insertDebugValue - Insert a DBG_VALUE into MBB at Idx for LocNo.
-  void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo,
-                        LiveIntervals &LIS, const TargetInstrInfo &TII);
+  void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
+                        unsigned LocNo, bool Spilled, LiveIntervals &LIS,
+                        const TargetInstrInfo &TII);
 
   /// splitLocation - Replace OldLocNo ranges with NewRegs ranges where NewRegs
   /// is live. Returns true if any changes were made.
@@ -137,8 +138,8 @@ class UserValue {
 
 public:
   /// UserValue - Create a new UserValue.
-  UserValue(const MDNode *var, const MDNode *expr, bool i, DebugLoc L,
-            LocMap::Allocator &alloc)
+  UserValue(const DILocalVariable *var, const DIExpression *expr, bool i,
+            DebugLoc L, LocMap::Allocator &alloc)
       : Variable(var), Expression(expr), IsIndirect(i), dl(std::move(L)),
         leader(this), locInts(alloc) {}
 
@@ -154,8 +155,8 @@ public:
   UserValue *getNext() const { return next; }
 
   /// match - Does this UserValue match the parameters?
-  bool match(const MDNode *Var, const MDNode *Expr, const DILocation *IA,
-             bool indirect) const {
+  bool match(const DILocalVariable *Var, const DIExpression *Expr,
+             const DILocation *IA, bool indirect) const {
     return Var == Variable && Expr == Expression && dl->getInlinedAt() == IA &&
            indirect == IsIndirect;
   }
@@ -259,12 +260,14 @@ public:
                      LiveIntervals &LIS);
 
   /// rewriteLocations - Rewrite virtual register locations according to the
-  /// provided virtual register map.
-  void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI);
+  /// provided virtual register map. Record which locations were spilled.
+  void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
+                        BitVector &SpilledLocations);
 
   /// emitDebugValues - Recreate DBG_VALUE instruction from data structures.
-  void emitDebugValues(VirtRegMap *VRM,
-                       LiveIntervals &LIS, const TargetInstrInfo &TRI);
+  void emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
+                       const TargetInstrInfo &TRI,
+                       const BitVector &SpilledLocations);
 
   /// getDebugLoc - Return DebugLoc of this UserValue.
   DebugLoc getDebugLoc() { return dl;}
@@ -294,11 +297,11 @@ class LDVImpl {
   VRMap virtRegToEqClass;
 
   /// Map user variable to eq class leader.
-  using UVMap = DenseMap<const MDNode *, UserValue *>;
+  using UVMap = DenseMap<const DILocalVariable *, UserValue *>;
   UVMap userVarMap;
 
   /// getUserValue - Find or create a UserValue.
-  UserValue *getUserValue(const MDNode *Var, const MDNode *Expr,
+  UserValue *getUserValue(const DILocalVariable *Var, const DIExpression *Expr,
                           bool IsIndirect, const DebugLoc &DL);
 
   /// lookupVirtReg - Find the EC leader for VirtReg or null.
@@ -423,8 +426,9 @@ void UserValue::mapVirtRegs(LDVImpl *LDV
       LDV->mapVirtReg(locations[i].getReg(), this);
 }
 
-UserValue *LDVImpl::getUserValue(const MDNode *Var, const MDNode *Expr,
-                                 bool IsIndirect, const DebugLoc &DL) {
+UserValue *LDVImpl::getUserValue(const DILocalVariable *Var,
+                                 const DIExpression *Expr, bool IsIndirect,
+                                 const DebugLoc &DL) {
   UserValue *&Leader = userVarMap[Var];
   if (Leader) {
     UserValue *UV = Leader->getLeader();
@@ -463,11 +467,11 @@ bool LDVImpl::handleDebugValue(MachineIn
   }
 
   // Get or create the UserValue for (variable,offset).
-  bool IsIndirect = MI.isIndirectDebugValue();
+  bool IsIndirect = MI.getOperand(1).isImm();
   if (IsIndirect)
     assert(MI.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero offset");
-  const MDNode *Var = MI.getDebugVariable();
-  const MDNode *Expr = MI.getDebugExpression();
+  const DILocalVariable *Var = MI.getDebugVariable();
+  const DIExpression *Expr = MI.getDebugExpression();
   //here.
   UserValue *UV = getUserValue(Var, Expr, IsIndirect, MI.getDebugLoc());
   UV->addDef(Idx, MI.getOperand(0));
@@ -940,15 +944,20 @@ splitRegister(unsigned OldReg, ArrayRef<
     static_cast<LDVImpl*>(pImpl)->splitRegister(OldReg, NewRegs);
 }
 
-void UserValue::rewriteLocations(VirtRegMap &VRM,
-                                 const TargetRegisterInfo &TRI) {
+void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
+                                 BitVector &SpilledLocations) {
   // Build a set of new locations with new numbers so we can coalesce our
   // IntervalMap if two vreg intervals collapse to the same physical location.
   // Use MapVector instead of SetVector because MapVector::insert returns the
-  // position of the previously or newly inserted element.
+  // position of the previously or newly inserted element. The boolean value
+  // tracks if the location was produced by a spill.
+  // FIXME: This will be problematic if we ever support direct and indirect
+  // frame index locations, i.e. expressing both variables in memory and
+  // 'int x, *px = &x'. The "spilled" bit must become part of the location.
   MapVector<MachineOperand, bool> NewLocations;
   SmallVector<unsigned, 4> LocNoMap(locations.size());
   for (unsigned I = 0, E = locations.size(); I != E; ++I) {
+    bool Spilled = false;
     MachineOperand Loc = locations[I];
     // Only virtual registers are rewritten.
     if (Loc.isReg() && Loc.getReg() &&
@@ -963,6 +972,7 @@ void UserValue::rewriteLocations(VirtReg
       } else if (VRM.getStackSlot(VirtReg) != VirtRegMap::NO_STACK_SLOT) {
         // FIXME: Translate SubIdx to a stackslot offset.
         Loc = MachineOperand::CreateFI(VRM.getStackSlot(VirtReg));
+        Spilled = true;
       } else {
         Loc.setReg(0);
         Loc.setSubReg(0);
@@ -971,14 +981,22 @@ void UserValue::rewriteLocations(VirtReg
 
     // Insert this location if it doesn't already exist and record a mapping
     // from the old number to the new number.
-    auto InsertResult = NewLocations.insert({Loc, false});
-    LocNoMap[I] = std::distance(NewLocations.begin(), InsertResult.first);
+    auto InsertResult = NewLocations.insert({Loc, Spilled});
+    unsigned NewLocNo = std::distance(NewLocations.begin(), InsertResult.first);
+    LocNoMap[I] = NewLocNo;
   }
 
-  // Rewrite the locations.
+  // Rewrite the locations and record which ones were spill slots.
   locations.clear();
-  for (const auto &Pair : NewLocations)
+  SpilledLocations.clear();
+  SpilledLocations.resize(NewLocations.size());
+  for (auto &Pair : NewLocations) {
     locations.push_back(Pair.first);
+    if (Pair.second) {
+      unsigned NewLocNo = std::distance(&*NewLocations.begin(), &Pair);
+      SpilledLocations.set(NewLocNo);
+    }
+  }
 
   // Update the interval map, but only coalesce left, since intervals to the
   // right use the old location numbers. This should merge two contiguous
@@ -1016,7 +1034,7 @@ findInsertLocation(MachineBasicBlock *MB
 }
 
 void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
-                                 unsigned LocNo,
+                                 unsigned LocNo, bool Spilled,
                                  LiveIntervals &LIS,
                                  const TargetInstrInfo &TII) {
   MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS);
@@ -1026,25 +1044,38 @@ void UserValue::insertDebugValue(Machine
   assert(cast<DILocalVariable>(Variable)
              ->isValidLocationForIntrinsic(getDebugLoc()) &&
          "Expected inlined-at fields to agree");
-  if (Loc.isReg())
-    BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE),
-            IsIndirect, Loc.getReg(), Variable, Expression);
+
+  // If the location was spilled, the new DBG_VALUE will be indirect. If the
+  // original DBG_VALUE was indirect, we need to add DW_OP_deref to indicate
+  // that the original virtual register was a pointer.
+  bool NewIndirect = IsIndirect || Spilled;
+  const DIExpression *Expr = Expression;
+  if (Spilled && IsIndirect)
+    Expr = DIExpression::prepend(Expr, DIExpression::WithDeref);
+
+  assert((!Spilled || Loc.isFI()) &&
+         "a spilled location must be a frame index");
+
+  MachineInstrBuilder MIB =
+      BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE))
+          .add(Loc);
+  if (NewIndirect)
+    MIB.addImm(0U);
   else
-    BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE))
-        .add(Loc)
-        .addImm(0U)
-        .addMetadata(Variable)
-        .addMetadata(Expression);
+    MIB.addReg(0U, RegState::Debug);
+  MIB.addMetadata(Variable).addMetadata(Expr);
 }
 
 void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
-                                const TargetInstrInfo &TII) {
+                                const TargetInstrInfo &TII,
+                                const BitVector &SpilledLocations) {
   MachineFunction::iterator MFEnd = VRM->getMachineFunction().end();
 
   for (LocMap::const_iterator I = locInts.begin(); I.valid();) {
     SlotIndex Start = I.start();
     SlotIndex Stop = I.stop();
     unsigned LocNo = I.value();
+    bool Spilled = LocNo != UndefLocNo ? SpilledLocations.test(LocNo) : false;
 
     // If the interval start was trimmed to the lexical scope insert the
     // DBG_VALUE at the previous index (otherwise it appears after the
@@ -1057,7 +1088,7 @@ void UserValue::emitDebugValues(VirtRegM
     SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);
 
     DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);
-    insertDebugValue(&*MBB, Start, LocNo, LIS, TII);
+    insertDebugValue(&*MBB, Start, LocNo, Spilled, LIS, TII);
     // This interval may span multiple basic blocks.
     // Insert a DBG_VALUE into each one.
     while(Stop > MBBEnd) {
@@ -1067,7 +1098,7 @@ void UserValue::emitDebugValues(VirtRegM
         break;
       MBBEnd = LIS.getMBBEndIdx(&*MBB);
       DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);
-      insertDebugValue(&*MBB, Start, LocNo, LIS, TII);
+      insertDebugValue(&*MBB, Start, LocNo, Spilled, LIS, TII);
     }
     DEBUG(dbgs() << '\n');
     if (MBB == MFEnd)
@@ -1082,10 +1113,11 @@ void LDVImpl::emitDebugValues(VirtRegMap
   if (!MF)
     return;
   const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
+  BitVector SpilledLocations;
   for (unsigned i = 0, e = userValues.size(); i != e; ++i) {
     DEBUG(userValues[i]->print(dbgs(), TRI));
-    userValues[i]->rewriteLocations(*VRM, *TRI);
-    userValues[i]->emitDebugValues(VRM, *LIS, *TII);
+    userValues[i]->rewriteLocations(*VRM, *TRI, SpilledLocations);
+    userValues[i]->emitDebugValues(VRM, *LIS, *TII, SpilledLocations);
   }
   EmitDone = true;
 }

Modified: llvm/trunk/test/DebugInfo/X86/bbjoin.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/bbjoin.ll?rev=313786&r1=313785&r2=313786&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/bbjoin.ll (original)
+++ llvm/trunk/test/DebugInfo/X86/bbjoin.ll Wed Sep 20 11:19:08 2017
@@ -11,12 +11,12 @@
 ; }
 ; CHECK: ![[X:.*]] = !DILocalVariable(name: "x",
 ; CHECK: bb.0.entry:
-; CHECK:   DBG_VALUE 23, 0, ![[X]],
+; CHECK:   DBG_VALUE 23, debug-use _, ![[X]],
 ; CHECK:   DBG_VALUE %rsp, 0, ![[X]], !DIExpression(DW_OP_plus_uconst, 4, DW_OP_deref),
 ; CHECK: bb.1.if.then:
-; CHECK:   DBG_VALUE 43, 0, ![[X]],
+; CHECK:   DBG_VALUE 43, debug-use _, ![[X]],
 ; CHECK: bb.2.if.end:
-; CHECK-NOT:  DBG_VALUE 23, 0, ![[X]],
+; CHECK-NOT:  DBG_VALUE 23, debug-use _, ![[X]],
 ; CHECK:   RETQ %eax
 
 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

Added: llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll?rev=313786&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll (added)
+++ llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll Wed Sep 20 11:19:08 2017
@@ -0,0 +1,103 @@
+; RUN: llc < %s | FileCheck %s
+; RUN: llc -O0 < %s | FileCheck %s
+
+; Make sure we insert DW_OP_deref when spilling indirect DBG_VALUE instructions.
+
+; C++ source:
+; #define FORCE_SPILL() \
+;   __asm volatile("" : : : \
+;                    "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", \
+;                    "r9", "r10", "r11", "r12", "r13", "r14", "r15")
+; struct string {
+;   string();
+;   string(int i);
+;   ~string();
+;   int i = 0;
+; };
+; string get_string() {
+;   string result = 3;
+;   FORCE_SPILL();
+;   return result;
+; }
+
+; CHECK-LABEL: _Z10get_stringv:
+; CHECK: #DEBUG_VALUE: get_string:result <- [%RDI+0]
+; CHECK: movq   %rdi, [[OFFS:[0-9]+]](%rsp)          # 8-byte Spill
+; CHECK: #DEBUG_VALUE: get_string:result <- [DW_OP_plus_uconst [[OFFS]], DW_OP_deref] [%RSP+0]
+; CHECK: callq  _ZN6stringC1Ei
+; CHECK: #APP
+; CHECK: #NO_APP
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64--linux"
+
+%struct.string = type { i32 }
+
+; Function Attrs: uwtable
+define void @_Z10get_stringv(%struct.string* noalias sret %agg.result) #0 !dbg !7 {
+entry:
+  %nrvo = alloca i1, align 1
+  store i1 false, i1* %nrvo, align 1, !dbg !24
+  call void @llvm.dbg.declare(metadata %struct.string* %agg.result, metadata !23, metadata !DIExpression()), !dbg !25
+  call void @_ZN6stringC1Ei(%struct.string* %agg.result, i32 3), !dbg !26
+  call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"() #3, !dbg !27, !srcloc !28
+  store i1 true, i1* %nrvo, align 1, !dbg !29
+  %nrvo.val = load i1, i1* %nrvo, align 1, !dbg !30
+  br i1 %nrvo.val, label %nrvo.skipdtor, label %nrvo.unused, !dbg !30
+
+nrvo.unused:                                      ; preds = %entry
+  call void @_ZN6stringD1Ev(%struct.string* %agg.result), !dbg !30
+  br label %nrvo.skipdtor, !dbg !30
+
+nrvo.skipdtor:                                    ; preds = %nrvo.unused, %entry
+  ret void, !dbg !30
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+declare void @_ZN6stringC1Ei(%struct.string*, i32) unnamed_addr
+
+declare void @_ZN6stringD1Ev(%struct.string*) unnamed_addr
+
+attributes #0 = { uwtable }
+attributes #1 = { nounwind readnone speculatable }
+attributes #3 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 6.0.0 "}
+!7 = distinct !DISubprogram(name: "get_string", linkageName: "_Z10get_stringv", scope: !1, file: !1, line: 13, type: !8, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !22)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10}
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "string", file: !1, line: 7, size: 32, elements: !11, identifier: "_ZTS6string")
+!11 = !{!12, !14, !18, !21}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !10, file: !1, line: 11, baseType: !13, size: 32)
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !DISubprogram(name: "string", scope: !10, file: !1, line: 8, type: !15, isLocal: false, isDefinition: false, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true)
+!15 = !DISubroutineType(types: !16)
+!16 = !{null, !17}
+!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!18 = !DISubprogram(name: "string", scope: !10, file: !1, line: 9, type: !19, isLocal: false, isDefinition: false, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true)
+!19 = !DISubroutineType(types: !20)
+!20 = !{null, !17, !13}
+!21 = !DISubprogram(name: "~string", scope: !10, file: !1, line: 10, type: !15, isLocal: false, isDefinition: false, scopeLine: 10, flags: DIFlagPrototyped, isOptimized: true)
+!22 = !{!23}
+!23 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 14, type: !10)
+!24 = !DILocation(line: 14, column: 3, scope: !7)
+!25 = !DILocation(line: 14, column: 10, scope: !7)
+!26 = !DILocation(line: 14, column: 19, scope: !7)
+!27 = !DILocation(line: 15, column: 3, scope: !7)
+!28 = !{i32 -2147471175}
+!29 = !DILocation(line: 16, column: 3, scope: !7)
+!30 = !DILocation(line: 17, column: 1, scope: !7)

Added: llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll?rev=313786&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll (added)
+++ llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll Wed Sep 20 11:19:08 2017
@@ -0,0 +1,89 @@
+; RUN: llc < %s | FileCheck %s
+
+; Make sure we insert DW_OP_deref when spilling indirect DBG_VALUE instructions.
+; In this example, 'nt' is passed by address because it is not trivially
+; copyable. When we spill the physical argument register at the barrier, we need
+; to insert DW_OP_deref.
+
+; #define FORCE_SPILL() \
+;   __asm volatile("" : : : \
+;                    "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", \
+;                    "r9", "r10", "r11", "r12", "r13", "r14", "r15")
+; struct NonTrivial {
+;   NonTrivial();
+;   ~NonTrivial();
+;   int i;
+; };
+; int foo(NonTrivial nt) {
+;   FORCE_SPILL();
+;   return nt.i;
+; }
+
+; CHECK-LABEL: _Z3foo10NonTrivial:
+; CHECK: #DEBUG_VALUE: foo:nt <- [%RDI+0]
+; CHECK: movq    %rdi, -8(%rsp)          # 8-byte Spill
+; CHECK: #DEBUG_VALUE: foo:nt <- [DW_OP_constu 8, DW_OP_minus, DW_OP_deref] [%RSP+0]
+; CHECK: #APP
+; CHECK: #NO_APP
+; CHECK: movq    -8(%rsp), %rax          # 8-byte Reload
+; CHECK: movl    (%rax), %eax
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64--linux"
+
+%struct.NonTrivial = type { i32 }
+
+; Function Attrs: nounwind uwtable
+define i32 @_Z3foo10NonTrivial(%struct.NonTrivial* nocapture readonly %nt) local_unnamed_addr #0 !dbg !7 {
+entry:
+  tail call void @llvm.dbg.declare(metadata %struct.NonTrivial* %nt, metadata !20, metadata !DIExpression()), !dbg !21
+  tail call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"() #2, !dbg !22, !srcloc !23
+  %i = getelementptr inbounds %struct.NonTrivial, %struct.NonTrivial* %nt, i64 0, i32 0, !dbg !24
+  %0 = load i32, i32* %i, align 4, !dbg !24, !tbaa !25
+  ret i32 %0, !dbg !30
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind uwtable }
+attributes #1 = { nounwind readnone speculatable }
+attributes #2 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 6.0.0 "}
+!7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foo10NonTrivial", scope: !1, file: !1, line: 10, type: !8, isLocal: false, isDefinition: true, scopeLine: 10, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !19)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !11}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "NonTrivial", file: !1, line: 5, size: 32, elements: !12, identifier: "_ZTS10NonTrivial")
+!12 = !{!13, !14, !18}
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !11, file: !1, line: 8, baseType: !10, size: 32)
+!14 = !DISubprogram(name: "NonTrivial", scope: !11, file: !1, line: 6, type: !15, isLocal: false, isDefinition: false, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: true)
+!15 = !DISubroutineType(types: !16)
+!16 = !{null, !17}
+!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!18 = !DISubprogram(name: "~NonTrivial", scope: !11, file: !1, line: 7, type: !15, isLocal: false, isDefinition: false, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: true)
+!19 = !{!20}
+!20 = !DILocalVariable(name: "nt", arg: 1, scope: !7, file: !1, line: 10, type: !11)
+!21 = !DILocation(line: 10, column: 20, scope: !7)
+!22 = !DILocation(line: 11, column: 3, scope: !7)
+!23 = !{i32 -2147471481}
+!24 = !DILocation(line: 12, column: 13, scope: !7)
+!25 = !{!26, !27, i64 0}
+!26 = !{!"_ZTS10NonTrivial", !27, i64 0}
+!27 = !{!"int", !28, i64 0}
+!28 = !{!"omnipotent char", !29, i64 0}
+!29 = !{!"Simple C++ TBAA"}
+!30 = !DILocation(line: 12, column: 3, scope: !7)

Added: llvm/trunk/test/DebugInfo/X86/spill-nospill.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/spill-nospill.ll?rev=313786&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/spill-nospill.ll (added)
+++ llvm/trunk/test/DebugInfo/X86/spill-nospill.ll Wed Sep 20 11:19:08 2017
@@ -0,0 +1,113 @@
+; RUN: llc < %s | FileCheck %s
+; RUN: llc < %s -filetype=obj | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF
+
+; This test creates two UserValues in LiveDebugVariables with one location
+; each. x must be spilled, but y will be allocated to a CSR. x's location
+; should be indirect, but y's should be direct.
+
+; C source:
+; #define FORCE_SPILL() \
+;   __asm volatile("" : : : \
+;                    "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", \
+;                    "r9", "r10", "r11", "r12", "r13", "r14", "r15")
+; int g(int);
+; int f() {
+;   int x = g(0);
+;   FORCE_SPILL();
+;   int y = g(0);
+;   g(y);
+;   g(y);
+;   g(y);
+;   return x + y;
+; }
+
+; CHECK-LABEL: f: # @f
+; CHECK: callq   g
+; CHECK: movl    %eax, [[X_OFFS:[0-9]+]](%rsp)          # 4-byte Spill
+; CHECK: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[X_OFFS]]] [%RSP+0]
+; CHECK: #APP
+; CHECK: #NO_APP
+; CHECK: callq   g
+; CHECK: movl    %eax, %[[CSR:[^ ]*]]
+; CHECK: #DEBUG_VALUE: f:y <- %ESI
+; CHECK: movl    %[[CSR]], %ecx
+; CHECK: callq   g
+; CHECK: movl    %[[CSR]], %ecx
+; CHECK: callq   g
+; CHECK: movl    %[[CSR]], %ecx
+; CHECK: callq   g
+; CHECK: movl    [[X_OFFS]](%rsp), %eax          # 4-byte Reload
+; CHECK: #DEBUG_VALUE: f:x <- %EAX
+; CHECK: addl    %[[CSR]], %eax
+
+; DWARF:      DW_TAG_variable
+; DWARF-NEXT:   DW_AT_location        (
+; DWARF-NEXT:      {{.*}} - {{.*}}: DW_OP_breg7 RSP+36
+; DWARF-NEXT:      {{.*}} - {{.*}}: DW_OP_reg0 RAX)
+; DWARF-NEXT:   DW_AT_name    ("x")
+
+; DWARF:      DW_TAG_variable
+; DWARF-NEXT:   DW_AT_location        (
+; DWARF-NEXT:      {{.*}} - {{.*}}: DW_OP_reg4 RSI)
+; DWARF-NEXT:   DW_AT_name    ("y")
+
+; ModuleID = 'spill-nospill.c'
+source_filename = "spill-nospill.c"
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+; Function Attrs: nounwind uwtable
+define i32 @f() local_unnamed_addr #0 !dbg !8 {
+entry:
+  %call = tail call i32 @g(i32 0) #3, !dbg !15
+  tail call void @llvm.dbg.value(metadata i32 %call, metadata !13, metadata !DIExpression()), !dbg !16
+  tail call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"() #3, !dbg !17, !srcloc !18
+  %call1 = tail call i32 @g(i32 0) #3, !dbg !19
+  tail call void @llvm.dbg.value(metadata i32 %call1, metadata !14, metadata !DIExpression()), !dbg !20
+  %call2 = tail call i32 @g(i32 %call1) #3, !dbg !21
+  %call3 = tail call i32 @g(i32 %call1) #3, !dbg !22
+  %call4 = tail call i32 @g(i32 %call1) #3, !dbg !23
+  %add = add nsw i32 %call1, %call, !dbg !24
+  ret i32 %add, !dbg !25
+}
+
+declare i32 @g(i32) local_unnamed_addr #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #2
+
+attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind readnone speculatable }
+attributes #3 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "spill-nospill.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 2}
+!6 = !{i32 7, !"PIC Level", i32 2}
+!7 = !{!"clang version 6.0.0 "}
+!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 8, type: !9, isLocal: false, isDefinition: true, scopeLine: 8, isOptimized: true, unit: !0, variables: !12)
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !{!13, !14}
+!13 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 9, type: !11)
+!14 = !DILocalVariable(name: "y", scope: !8, file: !1, line: 11, type: !11)
+!15 = !DILocation(line: 9, column: 11, scope: !8)
+!16 = !DILocation(line: 9, column: 7, scope: !8)
+!17 = !DILocation(line: 10, column: 3, scope: !8)
+!18 = !{i32 -2147472112}
+!19 = !DILocation(line: 11, column: 11, scope: !8)
+!20 = !DILocation(line: 11, column: 7, scope: !8)
+!21 = !DILocation(line: 12, column: 3, scope: !8)
+!22 = !DILocation(line: 13, column: 3, scope: !8)
+!23 = !DILocation(line: 14, column: 3, scope: !8)
+!24 = !DILocation(line: 15, column: 12, scope: !8)
+!25 = !DILocation(line: 15, column: 3, scope: !8)




More information about the llvm-commits mailing list