[llvm] r313400 - [DebugInfo] Insert DW_OP_deref when spilling indirect DBG_VALUEs

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 19 09:41:40 PDT 2017


I re-landed this in r313640 with a new test case that looks like this:

#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;
}

I forgot to zero out a BitVector before reusing it, so I would end up
claiming that both x and y were spilled in this example. Only x is spilled
and y is allocated to a callee-saved register.

The assertion came up in brotli because we ended up trying to claim that
the address of a variable was based on a non-pointer sized vector register,
which of course doesn't make sense.

On Mon, Sep 18, 2017 at 4:11 PM, Hans Wennborg <hans at chromium.org> wrote:

> I've reverted in r313589 since this caused asserts in the Chromium
> build (see http://crbug.com/766261).
>
> On Fri, Sep 15, 2017 at 2:54 PM, Reid Kleckner via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
> > Author: rnk
> > Date: Fri Sep 15 14:54:38 2017
> > New Revision: 313400
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=313400&view=rev
> > Log:
> > [DebugInfo] Insert DW_OP_deref when spilling indirect DBG_VALUEs
> >
> > Summary:
> > This comes up in optimized debug info for C++ programs that pass and
> > return objects indirectly by address. In these programs,
> > llvm.dbg.declare survives optimization, which causes us to emit indirect
> > DBG_VALUE instructions. The fast register allocator knows to insert
> > DW_OP_deref when spilling indirect DBG_VALUE instructions, but the
> > LiveDebugVariables did not until this change.
> >
> > This fixes part of PR34513. I need to look into why this doesn't work at
> > -O0 and I'll send follow up patches to handle that.
> >
> > Reviewers: aprantl, dblaikie, probinson
> >
> > Subscribers: qcolombet, hiraditya, llvm-commits
> >
> > Differential Revision: https://reviews.llvm.org/D37911
> >
> > Added:
> >     llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll
> >     llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.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=313400&r1=313399&r2=313400&view=diff
> > ============================================================
> ==================
> > --- llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp (original)
> > +++ llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp Fri Sep 15 14:54:38
> 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.
> > @@ -132,8 +132,9 @@ class UserValue {
> >    void coalesceLocation(unsigned LocNo);
> >
> >    /// 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.
> > @@ -142,8 +143,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) {}
> >
> > @@ -159,8 +160,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;
> >    }
> > @@ -262,12 +263,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;}
> > @@ -297,11 +300,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.
> > @@ -454,8 +457,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();
> > @@ -494,11 +498,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));
> > @@ -971,8 +975,10 @@ 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) {
> > +  SpilledLocations.resize(locations.size());
> > +
> >    // Iterate over locations in reverse makes it easier to handle
> coalescing.
> >    for (unsigned i = locations.size(); i ; --i) {
> >      unsigned LocNo = i-1;
> > @@ -991,6 +997,7 @@ UserValue::rewriteLocations(VirtRegMap &
> >      } else if (VRM.getStackSlot(VirtReg) != VirtRegMap::NO_STACK_SLOT) {
> >        // FIXME: Translate SubIdx to a stackslot offset.
> >        Loc = MachineOperand::CreateFI(VRM.getStackSlot(VirtReg));
> > +      SpilledLocations.set(LocNo);
> >      } else {
> >        Loc.setReg(0);
> >        Loc.setSubReg(0);
> > @@ -1024,7 +1031,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);
> > @@ -1034,25 +1041,35 @@ 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);
> > +
> > +  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 != ~0U ? 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
> > @@ -1065,7 +1082,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) {
> > @@ -1075,7 +1092,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)
> > @@ -1090,10 +1107,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=313400&r1=313399&r2=313400&view=diff
> > ============================================================
> ==================
> > --- llvm/trunk/test/DebugInfo/X86/bbjoin.ll (original)
> > +++ llvm/trunk/test/DebugInfo/X86/bbjoin.ll Fri Sep 15 14:54:38 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=313400&view=auto
> > ============================================================
> ==================
> > --- llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll (added)
> > +++ llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll Fri Sep 15
> 14:54:38 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=313400&view=auto
> > ============================================================
> ==================
> > --- llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll (added)
> > +++ llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll Fri Sep 15
> 14:54:38 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)
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170919/2c1f0ba3/attachment-0001.html>


More information about the llvm-commits mailing list