<div dir="ltr">I re-landed this in r313640 with a new test case that looks like this:<div><br></div><div><div>#define FORCE_SPILL()                                                          \</div><div>  __asm volatile(""                                                            \</div><div>                 :                                                             \</div><div>                 :                                                             \</div><div>                 : "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8",      \</div><div>                   "r9", "r10", "r11", "r12", "r13", "r14", "r15")</div><div>int g(int);</div><div>int f() {</div><div>  int x = g(0);</div><div>  FORCE_SPILL();</div><div>  int y = g(0);</div><div>  g(y);</div><div>  g(y);</div><div>  g(y);</div><div>  return x + y;</div><div>}</div></div><div><br></div><div>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.</div><div><br></div><div>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.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Sep 18, 2017 at 4:11 PM, Hans Wennborg <span dir="ltr"><<a href="mailto:hans@chromium.org" target="_blank">hans@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I've reverted in r313589 since this caused asserts in the Chromium<br>
build (see <a href="http://crbug.com/766261" rel="noreferrer" target="_blank">http://crbug.com/766261</a>).<br>
<div class="HOEnZb"><div class="h5"><br>
On Fri, Sep 15, 2017 at 2:54 PM, Reid Kleckner via llvm-commits<br>
<<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br>
> Author: rnk<br>
> Date: Fri Sep 15 14:54:38 2017<br>
> New Revision: 313400<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=313400&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=313400&view=rev</a><br>
> Log:<br>
> [DebugInfo] Insert DW_OP_deref when spilling indirect DBG_VALUEs<br>
><br>
> Summary:<br>
> This comes up in optimized debug info for C++ programs that pass and<br>
> return objects indirectly by address. In these programs,<br>
> llvm.dbg.declare survives optimization, which causes us to emit indirect<br>
> DBG_VALUE instructions. The fast register allocator knows to insert<br>
> DW_OP_deref when spilling indirect DBG_VALUE instructions, but the<br>
> LiveDebugVariables did not until this change.<br>
><br>
> This fixes part of PR34513. I need to look into why this doesn't work at<br>
> -O0 and I'll send follow up patches to handle that.<br>
><br>
> Reviewers: aprantl, dblaikie, probinson<br>
><br>
> Subscribers: qcolombet, hiraditya, llvm-commits<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D37911" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D37911</a><br>
><br>
> Added:<br>
>     llvm/trunk/test/DebugInfo/X86/<wbr>spill-indirect-nrvo.ll<br>
>     llvm/trunk/test/DebugInfo/X86/<wbr>spill-nontrivial-param.ll<br>
> Modified:<br>
>     llvm/trunk/lib/CodeGen/<wbr>LiveDebugVariables.cpp<br>
>     llvm/trunk/test/DebugInfo/X86/<wbr>bbjoin.ll<br>
><br>
> Modified: llvm/trunk/lib/CodeGen/<wbr>LiveDebugVariables.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp?rev=313400&r1=313399&r2=313400&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>CodeGen/LiveDebugVariables.<wbr>cpp?rev=313400&r1=313399&r2=<wbr>313400&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/lib/CodeGen/<wbr>LiveDebugVariables.cpp (original)<br>
> +++ llvm/trunk/lib/CodeGen/<wbr>LiveDebugVariables.cpp Fri Sep 15 14:54:38 2017<br>
> @@ -108,8 +108,8 @@ class LDVImpl;<br>
>  /// held by the same virtual register. The equivalence class is the transitive<br>
>  /// closure of that relation.<br>
>  class UserValue {<br>
> -  const MDNode *Variable;   ///< The debug info variable we are part of.<br>
> -  const MDNode *Expression; ///< Any complex address expression.<br>
> +  const DILocalVariable *Variable; ///< The debug info variable we are part of.<br>
> +  const DIExpression *Expression; ///< Any complex address expression.<br>
>    bool IsIndirect;        ///< true if this is a register-indirect+offset value.<br>
>    DebugLoc dl;            ///< The debug location for the variable. This is<br>
>                            ///< used by dwarf writer to find lexical scope.<br>
> @@ -132,8 +132,9 @@ class UserValue {<br>
>    void coalesceLocation(unsigned LocNo);<br>
><br>
>    /// insertDebugValue - Insert a DBG_VALUE into MBB at Idx for LocNo.<br>
> -  void insertDebugValue(<wbr>MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo,<br>
> -                        LiveIntervals &LIS, const TargetInstrInfo &TII);<br>
> +  void insertDebugValue(<wbr>MachineBasicBlock *MBB, SlotIndex Idx,<br>
> +                        unsigned LocNo, bool Spilled, LiveIntervals &LIS,<br>
> +                        const TargetInstrInfo &TII);<br>
><br>
>    /// splitLocation - Replace OldLocNo ranges with NewRegs ranges where NewRegs<br>
>    /// is live. Returns true if any changes were made.<br>
> @@ -142,8 +143,8 @@ class UserValue {<br>
><br>
>  public:<br>
>    /// UserValue - Create a new UserValue.<br>
> -  UserValue(const MDNode *var, const MDNode *expr, bool i, DebugLoc L,<br>
> -            LocMap::Allocator &alloc)<br>
> +  UserValue(const DILocalVariable *var, const DIExpression *expr, bool i,<br>
> +            DebugLoc L, LocMap::Allocator &alloc)<br>
>        : Variable(var), Expression(expr), IsIndirect(i), dl(std::move(L)),<br>
>          leader(this), locInts(alloc) {}<br>
><br>
> @@ -159,8 +160,8 @@ public:<br>
>    UserValue *getNext() const { return next; }<br>
><br>
>    /// match - Does this UserValue match the parameters?<br>
> -  bool match(const MDNode *Var, const MDNode *Expr, const DILocation *IA,<br>
> -             bool indirect) const {<br>
> +  bool match(const DILocalVariable *Var, const DIExpression *Expr,<br>
> +             const DILocation *IA, bool indirect) const {<br>
>      return Var == Variable && Expr == Expression && dl->getInlinedAt() == IA &&<br>
>             indirect == IsIndirect;<br>
>    }<br>
> @@ -262,12 +263,14 @@ public:<br>
>                       LiveIntervals &LIS);<br>
><br>
>    /// rewriteLocations - Rewrite virtual register locations according to the<br>
> -  /// provided virtual register map.<br>
> -  void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI);<br>
> +  /// provided virtual register map. Record which locations were spilled.<br>
> +  void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,<br>
> +                        BitVector &SpilledLocations);<br>
><br>
>    /// emitDebugValues - Recreate DBG_VALUE instruction from data structures.<br>
> -  void emitDebugValues(VirtRegMap *VRM,<br>
> -                       LiveIntervals &LIS, const TargetInstrInfo &TRI);<br>
> +  void emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,<br>
> +                       const TargetInstrInfo &TRI,<br>
> +                       const BitVector &SpilledLocations);<br>
><br>
>    /// getDebugLoc - Return DebugLoc of this UserValue.<br>
>    DebugLoc getDebugLoc() { return dl;}<br>
> @@ -297,11 +300,11 @@ class LDVImpl {<br>
>    VRMap virtRegToEqClass;<br>
><br>
>    /// Map user variable to eq class leader.<br>
> -  using UVMap = DenseMap<const MDNode *, UserValue *>;<br>
> +  using UVMap = DenseMap<const DILocalVariable *, UserValue *>;<br>
>    UVMap userVarMap;<br>
><br>
>    /// getUserValue - Find or create a UserValue.<br>
> -  UserValue *getUserValue(const MDNode *Var, const MDNode *Expr,<br>
> +  UserValue *getUserValue(const DILocalVariable *Var, const DIExpression *Expr,<br>
>                            bool IsIndirect, const DebugLoc &DL);<br>
><br>
>    /// lookupVirtReg - Find the EC leader for VirtReg or null.<br>
> @@ -454,8 +457,9 @@ void UserValue::mapVirtRegs(LDVImpl *LDV<br>
>        LDV->mapVirtReg(locations[i].<wbr>getReg(), this);<br>
>  }<br>
><br>
> -UserValue *LDVImpl::getUserValue(const MDNode *Var, const MDNode *Expr,<br>
> -                                 bool IsIndirect, const DebugLoc &DL) {<br>
> +UserValue *LDVImpl::getUserValue(const DILocalVariable *Var,<br>
> +                                 const DIExpression *Expr, bool IsIndirect,<br>
> +                                 const DebugLoc &DL) {<br>
>    UserValue *&Leader = userVarMap[Var];<br>
>    if (Leader) {<br>
>      UserValue *UV = Leader->getLeader();<br>
> @@ -494,11 +498,11 @@ bool LDVImpl::handleDebugValue(<wbr>MachineIn<br>
>    }<br>
><br>
>    // Get or create the UserValue for (variable,offset).<br>
> -  bool IsIndirect = MI.isIndirectDebugValue();<br>
> +  bool IsIndirect = MI.getOperand(1).isImm();<br>
>    if (IsIndirect)<br>
>      assert(MI.getOperand(1).<wbr>getImm() == 0 && "DBG_VALUE with nonzero offset");<br>
> -  const MDNode *Var = MI.getDebugVariable();<br>
> -  const MDNode *Expr = MI.getDebugExpression();<br>
> +  const DILocalVariable *Var = MI.getDebugVariable();<br>
> +  const DIExpression *Expr = MI.getDebugExpression();<br>
>    //here.<br>
>    UserValue *UV = getUserValue(Var, Expr, IsIndirect, MI.getDebugLoc());<br>
>    UV->addDef(Idx, MI.getOperand(0));<br>
> @@ -971,8 +975,10 @@ splitRegister(unsigned OldReg, ArrayRef<<br>
>      static_cast<LDVImpl*>(pImpl)-><wbr>splitRegister(OldReg, NewRegs);<br>
>  }<br>
><br>
> -void<br>
> -UserValue::rewriteLocations(<wbr>VirtRegMap &VRM, const TargetRegisterInfo &TRI) {<br>
> +void UserValue::rewriteLocations(<wbr>VirtRegMap &VRM, const TargetRegisterInfo &TRI,<br>
> +                                 BitVector &SpilledLocations) {<br>
> +  SpilledLocations.resize(<wbr>locations.size());<br>
> +<br>
>    // Iterate over locations in reverse makes it easier to handle coalescing.<br>
>    for (unsigned i = locations.size(); i ; --i) {<br>
>      unsigned LocNo = i-1;<br>
> @@ -991,6 +997,7 @@ UserValue::rewriteLocations(<wbr>VirtRegMap &<br>
>      } else if (VRM.getStackSlot(VirtReg) != VirtRegMap::NO_STACK_SLOT) {<br>
>        // FIXME: Translate SubIdx to a stackslot offset.<br>
>        Loc = MachineOperand::CreateFI(VRM.<wbr>getStackSlot(VirtReg));<br>
> +      SpilledLocations.set(LocNo);<br>
>      } else {<br>
>        Loc.setReg(0);<br>
>        Loc.setSubReg(0);<br>
> @@ -1024,7 +1031,7 @@ findInsertLocation(<wbr>MachineBasicBlock *MB<br>
>  }<br>
><br>
>  void UserValue::insertDebugValue(<wbr>MachineBasicBlock *MBB, SlotIndex Idx,<br>
> -                                 unsigned LocNo,<br>
> +                                 unsigned LocNo, bool Spilled,<br>
>                                   LiveIntervals &LIS,<br>
>                                   const TargetInstrInfo &TII) {<br>
>    MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS);<br>
> @@ -1034,25 +1041,35 @@ void UserValue::insertDebugValue(<wbr>Machine<br>
>    assert(cast<DILocalVariable>(<wbr>Variable)<br>
>               ->isValidLocationForIntrinsic(<wbr>getDebugLoc()) &&<br>
>           "Expected inlined-at fields to agree");<br>
> -  if (Loc.isReg())<br>
> -    BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_<wbr>VALUE),<br>
> -            IsIndirect, Loc.getReg(), Variable, Expression);<br>
> +<br>
> +  // If the location was spilled, the new DBG_VALUE will be indirect. If the<br>
> +  // original DBG_VALUE was indirect, we need to add DW_OP_deref to indicate<br>
> +  // that the original virtual register was a pointer.<br>
> +  bool NewIndirect = IsIndirect || Spilled;<br>
> +  const DIExpression *Expr = Expression;<br>
> +  if (Spilled && IsIndirect)<br>
> +    Expr = DIExpression::prepend(Expr, DIExpression::WithDeref);<br>
> +<br>
> +  MachineInstrBuilder MIB =<br>
> +      BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_<wbr>VALUE))<br>
> +          .add(Loc);<br>
> +  if (NewIndirect)<br>
> +    MIB.addImm(0U);<br>
>    else<br>
> -    BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_<wbr>VALUE))<br>
> -        .add(Loc)<br>
> -        .addImm(0U)<br>
> -        .addMetadata(Variable)<br>
> -        .addMetadata(Expression);<br>
> +    MIB.addReg(0U, RegState::Debug);<br>
> +  MIB.addMetadata(Variable).<wbr>addMetadata(Expr);<br>
>  }<br>
><br>
>  void UserValue::emitDebugValues(<wbr>VirtRegMap *VRM, LiveIntervals &LIS,<br>
> -                                const TargetInstrInfo &TII) {<br>
> +                                const TargetInstrInfo &TII,<br>
> +                                const BitVector &SpilledLocations) {<br>
>    MachineFunction::iterator MFEnd = VRM->getMachineFunction().end(<wbr>);<br>
><br>
>    for (LocMap::const_iterator I = locInts.begin(); I.valid();) {<br>
>      SlotIndex Start = I.start();<br>
>      SlotIndex Stop = I.stop();<br>
>      unsigned LocNo = I.value();<br>
> +    bool Spilled = LocNo != ~0U ? SpilledLocations.test(LocNo) : false;<br>
><br>
>      // If the interval start was trimmed to the lexical scope insert the<br>
>      // DBG_VALUE at the previous index (otherwise it appears after the<br>
> @@ -1065,7 +1082,7 @@ void UserValue::emitDebugValues(<wbr>VirtRegM<br>
>      SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);<br>
><br>
>      DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);<br>
> -    insertDebugValue(&*MBB, Start, LocNo, LIS, TII);<br>
> +    insertDebugValue(&*MBB, Start, LocNo, Spilled, LIS, TII);<br>
>      // This interval may span multiple basic blocks.<br>
>      // Insert a DBG_VALUE into each one.<br>
>      while(Stop > MBBEnd) {<br>
> @@ -1075,7 +1092,7 @@ void UserValue::emitDebugValues(<wbr>VirtRegM<br>
>          break;<br>
>        MBBEnd = LIS.getMBBEndIdx(&*MBB);<br>
>        DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);<br>
> -      insertDebugValue(&*MBB, Start, LocNo, LIS, TII);<br>
> +      insertDebugValue(&*MBB, Start, LocNo, Spilled, LIS, TII);<br>
>      }<br>
>      DEBUG(dbgs() << '\n');<br>
>      if (MBB == MFEnd)<br>
> @@ -1090,10 +1107,11 @@ void LDVImpl::emitDebugValues(<wbr>VirtRegMap<br>
>    if (!MF)<br>
>      return;<br>
>    const TargetInstrInfo *TII = MF->getSubtarget().<wbr>getInstrInfo();<br>
> +  BitVector SpilledLocations;<br>
>    for (unsigned i = 0, e = userValues.size(); i != e; ++i) {<br>
>      DEBUG(userValues[i]->print(<wbr>dbgs(), TRI));<br>
> -    userValues[i]-><wbr>rewriteLocations(*VRM, *TRI);<br>
> -    userValues[i]-><wbr>emitDebugValues(VRM, *LIS, *TII);<br>
> +    userValues[i]-><wbr>rewriteLocations(*VRM, *TRI, SpilledLocations);<br>
> +    userValues[i]-><wbr>emitDebugValues(VRM, *LIS, *TII, SpilledLocations);<br>
>    }<br>
>    EmitDone = true;<br>
>  }<br>
><br>
> Modified: llvm/trunk/test/DebugInfo/X86/<wbr>bbjoin.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/bbjoin.ll?rev=313400&r1=313399&r2=313400&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>DebugInfo/X86/bbjoin.ll?rev=<wbr>313400&r1=313399&r2=313400&<wbr>view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/DebugInfo/X86/<wbr>bbjoin.ll (original)<br>
> +++ llvm/trunk/test/DebugInfo/X86/<wbr>bbjoin.ll Fri Sep 15 14:54:38 2017<br>
> @@ -11,12 +11,12 @@<br>
>  ; }<br>
>  ; CHECK: ![[X:.*]] = !DILocalVariable(name: "x",<br>
>  ; CHECK: bb.0.entry:<br>
> -; CHECK:   DBG_VALUE 23, 0, ![[X]],<br>
> +; CHECK:   DBG_VALUE 23, debug-use _, ![[X]],<br>
>  ; CHECK:   DBG_VALUE %rsp, 0, ![[X]], !DIExpression(DW_OP_plus_<wbr>uconst, 4, DW_OP_deref),<br>
>  ; CHECK: bb.1.if.then:<br>
> -; CHECK:   DBG_VALUE 43, 0, ![[X]],<br>
> +; CHECK:   DBG_VALUE 43, debug-use _, ![[X]],<br>
>  ; CHECK: bb.2.if.end:<br>
> -; CHECK-NOT:  DBG_VALUE 23, 0, ![[X]],<br>
> +; CHECK-NOT:  DBG_VALUE 23, debug-use _, ![[X]],<br>
>  ; CHECK:   RETQ %eax<br>
><br>
>  target datalayout = "e-m:o-i64:64-f80:128-n8:16:<wbr>32:64-S128"<br>
><br>
> Added: llvm/trunk/test/DebugInfo/X86/<wbr>spill-indirect-nrvo.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll?rev=313400&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>DebugInfo/X86/spill-indirect-<wbr>nrvo.ll?rev=313400&view=auto</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/DebugInfo/X86/<wbr>spill-indirect-nrvo.ll (added)<br>
> +++ llvm/trunk/test/DebugInfo/X86/<wbr>spill-indirect-nrvo.ll Fri Sep 15 14:54:38 2017<br>
> @@ -0,0 +1,103 @@<br>
> +; RUN: llc < %s | FileCheck %s<br>
> +; RUN: llc -O0 < %s | FileCheck %s<br>
> +<br>
> +; Make sure we insert DW_OP_deref when spilling indirect DBG_VALUE instructions.<br>
> +<br>
> +; C++ source:<br>
> +; #define FORCE_SPILL() \<br>
> +;   __asm volatile("" : : : \<br>
> +;                    "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", \<br>
> +;                    "r9", "r10", "r11", "r12", "r13", "r14", "r15")<br>
> +; struct string {<br>
> +;   string();<br>
> +;   string(int i);<br>
> +;   ~string();<br>
> +;   int i = 0;<br>
> +; };<br>
> +; string get_string() {<br>
> +;   string result = 3;<br>
> +;   FORCE_SPILL();<br>
> +;   return result;<br>
> +; }<br>
> +<br>
> +; CHECK-LABEL: _Z10get_stringv:<br>
> +; CHECK: #DEBUG_VALUE: get_string:result <- [%RDI+0]<br>
> +; CHECK: movq   %rdi, [[OFFS:[0-9]+]](%rsp)          # 8-byte Spill<br>
> +; CHECK: #DEBUG_VALUE: get_string:result <- [DW_OP_plus_uconst [[OFFS]], DW_OP_deref] [%RSP+0]<br>
> +; CHECK: callq  _ZN6stringC1Ei<br>
> +; CHECK: #APP<br>
> +; CHECK: #NO_APP<br>
> +<br>
> +; ModuleID = 't.cpp'<br>
> +source_filename = "t.cpp"<br>
> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:<wbr>32:64-S128"<br>
> +target triple = "x86_64--linux"<br>
> +<br>
> +%struct.string = type { i32 }<br>
> +<br>
> +; Function Attrs: uwtable<br>
> +define void @_Z10get_stringv(%struct.<wbr>string* noalias sret %agg.result) #0 !dbg !7 {<br>
> +entry:<br>
> +  %nrvo = alloca i1, align 1<br>
> +  store i1 false, i1* %nrvo, align 1, !dbg !24<br>
> +  call void @llvm.dbg.declare(metadata %struct.string* %agg.result, metadata !23, metadata !DIExpression()), !dbg !25<br>
> +  call void @_ZN6stringC1Ei(%struct.<wbr>string* %agg.result, i32 3), !dbg !26<br>
> +  call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~<wbr>{rsi},~{rdi},~{rbp},~{r8},~{<wbr>r9},~{r10},~{r11},~{r12},~{<wbr>r13},~{r14},~{r15},~{dirflag},<wbr>~{fpsr},~{flags}"() #3, !dbg !27, !srcloc !28<br>
> +  store i1 true, i1* %nrvo, align 1, !dbg !29<br>
> +  %nrvo.val = load i1, i1* %nrvo, align 1, !dbg !30<br>
> +  br i1 %nrvo.val, label %nrvo.skipdtor, label %nrvo.unused, !dbg !30<br>
> +<br>
> +nrvo.unused:                                      ; preds = %entry<br>
> +  call void @_ZN6stringD1Ev(%struct.<wbr>string* %agg.result), !dbg !30<br>
> +  br label %nrvo.skipdtor, !dbg !30<br>
> +<br>
> +nrvo.skipdtor:                                    ; preds = %nrvo.unused, %entry<br>
> +  ret void, !dbg !30<br>
> +}<br>
> +<br>
> +; Function Attrs: nounwind readnone speculatable<br>
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1<br>
> +<br>
> +declare void @_ZN6stringC1Ei(%struct.<wbr>string*, i32) unnamed_addr<br>
> +<br>
> +declare void @_ZN6stringD1Ev(%struct.<wbr>string*) unnamed_addr<br>
> +<br>
> +attributes #0 = { uwtable }<br>
> +attributes #1 = { nounwind readnone speculatable }<br>
> +attributes #3 = { nounwind }<br>
> +<br>
> +!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
> +!llvm.module.flags = !{!3, !4, !5}<br>
> +!llvm.ident = !{!6}<br>
> +<br>
> +!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)<br>
> +!1 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\<wbr>5Cbuild")<br>
> +!2 = !{}<br>
> +!3 = !{i32 2, !"Dwarf Version", i32 4}<br>
> +!4 = !{i32 2, !"Debug Info Version", i32 3}<br>
> +!5 = !{i32 1, !"wchar_size", i32 4}<br>
> +!6 = !{!"clang version 6.0.0 "}<br>
> +!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)<br>
> +!8 = !DISubroutineType(types: !9)<br>
> +!9 = !{!10}<br>
> +!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "string", file: !1, line: 7, size: 32, elements: !11, identifier: "_ZTS6string")<br>
> +!11 = !{!12, !14, !18, !21}<br>
> +!12 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !10, file: !1, line: 11, baseType: !13, size: 32)<br>
> +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
> +!14 = !DISubprogram(name: "string", scope: !10, file: !1, line: 8, type: !15, isLocal: false, isDefinition: false, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true)<br>
> +!15 = !DISubroutineType(types: !16)<br>
> +!16 = !{null, !17}<br>
> +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)<br>
> +!18 = !DISubprogram(name: "string", scope: !10, file: !1, line: 9, type: !19, isLocal: false, isDefinition: false, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true)<br>
> +!19 = !DISubroutineType(types: !20)<br>
> +!20 = !{null, !17, !13}<br>
> +!21 = !DISubprogram(name: "~string", scope: !10, file: !1, line: 10, type: !15, isLocal: false, isDefinition: false, scopeLine: 10, flags: DIFlagPrototyped, isOptimized: true)<br>
> +!22 = !{!23}<br>
> +!23 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 14, type: !10)<br>
> +!24 = !DILocation(line: 14, column: 3, scope: !7)<br>
> +!25 = !DILocation(line: 14, column: 10, scope: !7)<br>
> +!26 = !DILocation(line: 14, column: 19, scope: !7)<br>
> +!27 = !DILocation(line: 15, column: 3, scope: !7)<br>
> +!28 = !{i32 -2147471175}<br>
> +!29 = !DILocation(line: 16, column: 3, scope: !7)<br>
> +!30 = !DILocation(line: 17, column: 1, scope: !7)<br>
><br>
> Added: llvm/trunk/test/DebugInfo/X86/<wbr>spill-nontrivial-param.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll?rev=313400&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>DebugInfo/X86/spill-<wbr>nontrivial-param.ll?rev=<wbr>313400&view=auto</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/DebugInfo/X86/<wbr>spill-nontrivial-param.ll (added)<br>
> +++ llvm/trunk/test/DebugInfo/X86/<wbr>spill-nontrivial-param.ll Fri Sep 15 14:54:38 2017<br>
> @@ -0,0 +1,89 @@<br>
> +; RUN: llc < %s | FileCheck %s<br>
> +<br>
> +; Make sure we insert DW_OP_deref when spilling indirect DBG_VALUE instructions.<br>
> +; In this example, 'nt' is passed by address because it is not trivially<br>
> +; copyable. When we spill the physical argument register at the barrier, we need<br>
> +; to insert DW_OP_deref.<br>
> +<br>
> +; #define FORCE_SPILL() \<br>
> +;   __asm volatile("" : : : \<br>
> +;                    "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", \<br>
> +;                    "r9", "r10", "r11", "r12", "r13", "r14", "r15")<br>
> +; struct NonTrivial {<br>
> +;   NonTrivial();<br>
> +;   ~NonTrivial();<br>
> +;   int i;<br>
> +; };<br>
> +; int foo(NonTrivial nt) {<br>
> +;   FORCE_SPILL();<br>
> +;   return nt.i;<br>
> +; }<br>
> +<br>
> +; CHECK-LABEL: _Z3foo10NonTrivial:<br>
> +; CHECK: #DEBUG_VALUE: foo:nt <- [%RDI+0]<br>
> +; CHECK: movq    %rdi, -8(%rsp)          # 8-byte Spill<br>
> +; CHECK: #DEBUG_VALUE: foo:nt <- [DW_OP_constu 8, DW_OP_minus, DW_OP_deref] [%RSP+0]<br>
> +; CHECK: #APP<br>
> +; CHECK: #NO_APP<br>
> +; CHECK: movq    -8(%rsp), %rax          # 8-byte Reload<br>
> +; CHECK: movl    (%rax), %eax<br>
> +<br>
> +; ModuleID = 't.cpp'<br>
> +source_filename = "t.cpp"<br>
> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:<wbr>32:64-S128"<br>
> +target triple = "x86_64--linux"<br>
> +<br>
> +%struct.NonTrivial = type { i32 }<br>
> +<br>
> +; Function Attrs: nounwind uwtable<br>
> +define i32 @_Z3foo10NonTrivial(%struct.<wbr>NonTrivial* nocapture readonly %nt) local_unnamed_addr #0 !dbg !7 {<br>
> +entry:<br>
> +  tail call void @llvm.dbg.declare(metadata %struct.NonTrivial* %nt, metadata !20, metadata !DIExpression()), !dbg !21<br>
> +  tail call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~<wbr>{rsi},~{rdi},~{rbp},~{r8},~{<wbr>r9},~{r10},~{r11},~{r12},~{<wbr>r13},~{r14},~{r15},~{dirflag},<wbr>~{fpsr},~{flags}"() #2, !dbg !22, !srcloc !23<br>
> +  %i = getelementptr inbounds %struct.NonTrivial, %struct.NonTrivial* %nt, i64 0, i32 0, !dbg !24<br>
> +  %0 = load i32, i32* %i, align 4, !dbg !24, !tbaa !25<br>
> +  ret i32 %0, !dbg !30<br>
> +}<br>
> +<br>
> +; Function Attrs: nounwind readnone speculatable<br>
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1<br>
> +<br>
> +attributes #0 = { nounwind uwtable }<br>
> +attributes #1 = { nounwind readnone speculatable }<br>
> +attributes #2 = { nounwind }<br>
> +<br>
> +!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
> +!llvm.module.flags = !{!3, !4, !5}<br>
> +!llvm.ident = !{!6}<br>
> +<br>
> +!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)<br>
> +!1 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\<wbr>5Cbuild")<br>
> +!2 = !{}<br>
> +!3 = !{i32 2, !"Dwarf Version", i32 4}<br>
> +!4 = !{i32 2, !"Debug Info Version", i32 3}<br>
> +!5 = !{i32 1, !"wchar_size", i32 4}<br>
> +!6 = !{!"clang version 6.0.0 "}<br>
> +!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)<br>
> +!8 = !DISubroutineType(types: !9)<br>
> +!9 = !{!10, !11}<br>
> +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
> +!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "NonTrivial", file: !1, line: 5, size: 32, elements: !12, identifier: "_ZTS10NonTrivial")<br>
> +!12 = !{!13, !14, !18}<br>
> +!13 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !11, file: !1, line: 8, baseType: !10, size: 32)<br>
> +!14 = !DISubprogram(name: "NonTrivial", scope: !11, file: !1, line: 6, type: !15, isLocal: false, isDefinition: false, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: true)<br>
> +!15 = !DISubroutineType(types: !16)<br>
> +!16 = !{null, !17}<br>
> +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)<br>
> +!18 = !DISubprogram(name: "~NonTrivial", scope: !11, file: !1, line: 7, type: !15, isLocal: false, isDefinition: false, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: true)<br>
> +!19 = !{!20}<br>
> +!20 = !DILocalVariable(name: "nt", arg: 1, scope: !7, file: !1, line: 10, type: !11)<br>
> +!21 = !DILocation(line: 10, column: 20, scope: !7)<br>
> +!22 = !DILocation(line: 11, column: 3, scope: !7)<br>
> +!23 = !{i32 -2147471481}<br>
> +!24 = !DILocation(line: 12, column: 13, scope: !7)<br>
> +!25 = !{!26, !27, i64 0}<br>
> +!26 = !{!"_ZTS10NonTrivial", !27, i64 0}<br>
> +!27 = !{!"int", !28, i64 0}<br>
> +!28 = !{!"omnipotent char", !29, i64 0}<br>
> +!29 = !{!"Simple C++ TBAA"}<br>
> +!30 = !DILocation(line: 12, column: 3, scope: !7)<br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br></div>