[llvm] r367446 - Reland "[DwarfDebug] Dump call site debug info"

Eric Christopher via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 31 14:27:09 PDT 2019


Had another build error in assert builds (unused variable). I fixed it thusly:

commit 36fb93982f0e518a5399874aae09abc043f63bed
Author: Eric Christopher <echristo at gmail.com>
Date:   Wed Jul 31 21:02:03 2019 +0000

    Fix unused variable warning for non-assert builds.

    llvm-svn: 367482

-eric

On Wed, Jul 31, 2019 at 9:50 AM Djordje Todorovic via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
>
> Author: djtodoro
> Date: Wed Jul 31 09:51:28 2019
> New Revision: 367446
>
> URL: http://llvm.org/viewvc/llvm-project?rev=367446&view=rev
> Log:
> Reland "[DwarfDebug] Dump call site debug info"
>
> The build failure found after the rL365467 has been
> resolved.
>
> Differential Revision: https://reviews.llvm.org/D60716
>
> Added:
>     llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir
>     llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir
>     llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir
>     llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll
> Modified:
>     llvm/trunk/docs/LangRef.rst
>     llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h
>     llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
>     llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp
>     llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp
>     llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
>     llvm/trunk/lib/IR/DebugInfoMetadata.cpp
>     llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
>     llvm/trunk/lib/Target/X86/X86InstrInfo.h
>     llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll
>     llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp
>
> Modified: llvm/trunk/docs/LangRef.rst
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/docs/LangRef.rst (original)
> +++ llvm/trunk/docs/LangRef.rst Wed Jul 31 09:51:28 2019
> @@ -4769,6 +4769,10 @@ The current supported opcode vocabulary
>    ``DW_OP_entry_value`` may also appear after the ``AsmPrinter`` pass when
>    a call site parameter value (``DW_AT_call_site_parameter_value``)
>    is represented as entry value of the parameter.
> +- ``DW_OP_breg`` (or ``DW_OP_bregx``) represents a content on the provided
> +  signed offset of the specified register. The opcode is only generated by the
> +  ``AsmPrinter`` pass to describe call site parameter value which requires an
> +  expression over two registers.
>
>  DWARF specifies three kinds of simple location descriptions: Register, memory,
>  and implicit location descriptions.  Note that a location description is
>
> Modified: llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h Wed Jul 31 09:51:28 2019
> @@ -60,6 +60,8 @@ class TargetSubtargetInfo;
>
>  template <class T> class SmallVectorImpl;
>
> +using ParamLoadedValue = std::pair<const MachineOperand*, DIExpression*>;
> +
>  //---------------------------------------------------------------------------
>  ///
>  /// TargetInstrInfo - Interface to description of machine instruction set
> @@ -1691,6 +1693,11 @@ public:
>      return false;
>    }
>
> +  /// Produce the expression describing the \p MI loading a value into
> +  /// the parameter's forwarding register.
> +  virtual Optional<ParamLoadedValue>
> +  describeLoadedValue(const MachineInstr &MI) const;
> +
>  private:
>    unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;
>    unsigned CatchRetOpcode;
>
> Modified: llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.h?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.h Wed Jul 31 09:51:28 2019
> @@ -535,6 +535,11 @@ public:
>      return false;
>    }
>
> +  /// This is a wrapper around getCallPreservedMask().
> +  /// Return true if the register is preserved after the call.
> +  virtual bool isCalleeSavedPhysReg(unsigned PhysReg,
> +                                    const MachineFunction &MF) const;
> +
>    /// Prior to adding the live-out mask to a stackmap or patchpoint
>    /// instruction, provide the target the opportunity to adjust it (mainly to
>    /// remove pseudo-registers that should be ignored).
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Wed Jul 31 09:51:28 2019
> @@ -892,32 +892,106 @@ void DwarfCompileUnit::constructAbstract
>      ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
>  }
>
> -DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
> -                                                 const DISubprogram &CalleeSP,
> -                                                 bool IsTail,
> -                                                 const MCExpr *PCOffset) {
> +dwarf::Tag DwarfCompileUnit::getDwarf5OrGNUCallSiteTag(dwarf::Tag Tag) const {
> +  bool ApplyGNUExtensions = DD->getDwarfVersion() == 4 && DD->tuneForGDB();
> +  if (!ApplyGNUExtensions)
> +    return Tag;
> +  switch (Tag) {
> +  case dwarf::DW_TAG_call_site:
> +    return dwarf::DW_TAG_GNU_call_site;
> +  case dwarf::DW_TAG_call_site_parameter:
> +    return dwarf::DW_TAG_GNU_call_site_parameter;
> +  default:
> +    llvm_unreachable("unhandled call site tag");
> +  }
> +}
> +
> +dwarf::Attribute
> +DwarfCompileUnit::getDwarf5OrGNUCallSiteAttr(dwarf::Attribute Attr) const {
> +  bool ApplyGNUExtensions = DD->getDwarfVersion() == 4 && DD->tuneForGDB();
> +  if (!ApplyGNUExtensions)
> +    return Attr;
> +  switch (Attr) {
> +  case dwarf::DW_AT_call_all_calls:
> +    return dwarf::DW_AT_GNU_all_call_sites;
> +  case dwarf::DW_AT_call_target:
> +    return dwarf::DW_AT_GNU_call_site_target;
> +  case dwarf::DW_AT_call_origin:
> +    return dwarf::DW_AT_abstract_origin;
> +  case dwarf::DW_AT_call_pc:
> +    return dwarf::DW_AT_low_pc;
> +  case dwarf::DW_AT_call_value:
> +    return dwarf::DW_AT_GNU_call_site_value;
> +  case dwarf::DW_AT_call_tail_call:
> +    return dwarf::DW_AT_GNU_tail_call;
> +  default:
> +    llvm_unreachable("unhandled call site attribute");
> +  }
> +}
> +
> +DIE &DwarfCompileUnit::constructCallSiteEntryDIE(
> +    DIE &ScopeDIE, const DISubprogram *CalleeSP, bool IsTail,
> +    const MCSymbol *PCAddr, const MCExpr *PCOffset, unsigned CallReg) {
>    // Insert a call site entry DIE within ScopeDIE.
> -  DIE &CallSiteDIE =
> -      createAndAddDIE(dwarf::DW_TAG_call_site, ScopeDIE, nullptr);
> +  DIE &CallSiteDIE = createAndAddDIE(
> +      getDwarf5OrGNUCallSiteTag(dwarf::DW_TAG_call_site), ScopeDIE, nullptr);
>
> -  // For the purposes of showing tail call frames in backtraces, a key piece of
> -  // information is DW_AT_call_origin, a pointer to the callee DIE.
> -  DIE *CalleeDIE = getOrCreateSubprogramDIE(&CalleeSP);
> -  assert(CalleeDIE && "Could not create DIE for call site entry origin");
> -  addDIEEntry(CallSiteDIE, dwarf::DW_AT_call_origin, *CalleeDIE);
> +  if (CallReg) {
> +    // Indirect call.
> +    addAddress(CallSiteDIE,
> +               getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_target),
> +               MachineLocation(CallReg));
> +  } else {
> +    DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP);
> +    assert(CalleeDIE && "Could not create DIE for call site entry origin");
> +    addDIEEntry(CallSiteDIE,
> +                getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_origin),
> +                *CalleeDIE);
> +  }
>
> -  if (IsTail) {
> +  if (IsTail)
>      // Attach DW_AT_call_tail_call to tail calls for standards compliance.
> -    addFlag(CallSiteDIE, dwarf::DW_AT_call_tail_call);
> -  } else {
> -    // Attach the return PC to allow the debugger to disambiguate call paths
> -    // from one function to another.
> +    addFlag(CallSiteDIE,
> +            getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_tail_call));
> +
> +  // Attach the return PC to allow the debugger to disambiguate call paths
> +  // from one function to another.
> +  if (DD->getDwarfVersion() == 4 && DD->tuneForGDB()) {
> +    assert(PCAddr && "Missing PC information for a call");
> +    addLabelAddress(CallSiteDIE, dwarf::DW_AT_low_pc, PCAddr);
> +  } else if (!IsTail || DD->tuneForGDB()) {
>      assert(PCOffset && "Missing return PC information for a call");
>      addAddressExpr(CallSiteDIE, dwarf::DW_AT_call_return_pc, PCOffset);
>    }
> +
>    return CallSiteDIE;
>  }
>
> +void DwarfCompileUnit::constructCallSiteParmEntryDIEs(
> +    DIE &CallSiteDIE, SmallVector<DbgCallSiteParam, 4> &Params) {
> +  for (const auto &Param : Params) {
> +    unsigned Register = Param.getRegister();
> +    auto CallSiteDieParam =
> +        DIE::get(DIEValueAllocator,
> +                 getDwarf5OrGNUCallSiteTag(dwarf::DW_TAG_call_site_parameter));
> +    insertDIE(CallSiteDieParam);
> +    addAddress(*CallSiteDieParam, dwarf::DW_AT_location,
> +               MachineLocation(Register));
> +
> +    DIELoc *Loc = new (DIEValueAllocator) DIELoc;
> +    DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
> +    DwarfExpr.setCallSiteParamValueFlag();
> +
> +    DwarfDebug::emitDebugLocValue(*Asm, nullptr, Param.getValue(), DwarfExpr);
> +
> +    addBlock(*CallSiteDieParam,
> +             getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_value),
> +             DwarfExpr.finalize());
> +
> +    CallSiteDIE.addChild(CallSiteDieParam);
> +  }
> +}
> +
>  DIE *DwarfCompileUnit::constructImportedEntityDIE(
>      const DIImportedEntity *Module) {
>    DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag());
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Wed Jul 31 09:51:28 2019
> @@ -227,12 +227,33 @@ public:
>
>    void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
>
> +  /// This takes the official DWARF 5 tag and returns the appropriate
> +  /// GNU tag if needed.
> +  dwarf::Tag getDwarf5OrGNUCallSiteTag(dwarf::Tag Tag) const;
> +  /// This takes the official DWARF 5 attribute and returns the appropriate
> +  /// GNU attribute if needed.
> +  dwarf::Attribute getDwarf5OrGNUCallSiteAttr(dwarf::Attribute Attr) const;
> +
>    /// Construct a call site entry DIE describing a call within \p Scope to a
> -  /// callee described by \p CalleeSP. \p IsTail specifies whether the call is
> -  /// a tail call. \p PCOffset must be non-zero for non-tail calls or be the
> +  /// callee described by \p CalleeSP.
> +  /// \p IsTail specifies whether the call is a tail call.
> +  /// \p PCAddr (used for GDB + DWARF 4 tuning) points to the PC value after
> +  /// the call instruction.
> +  /// \p PCOffset (used for cases other than GDB + DWARF 4 tuning) must be
> +  /// non-zero for non-tail calls (in the case of non-gdb tuning, since for
> +  /// GDB + DWARF 5 tuning we still generate PC info for tail calls) or be the
>    /// function-local offset to PC value after the call instruction.
> -  DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram &CalleeSP,
> -                                 bool IsTail, const MCExpr *PCOffset);
> +  /// \p CallReg is a register location for an indirect call. For direct calls
> +  /// the \p CallReg is set to 0.
> +  DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram *CalleeSP,
> +                                 bool IsTail, const MCSymbol *PCAddr,
> +                                 const MCExpr *PCOffset, unsigned CallReg);
> +  /// Construct call site parameter DIEs for the \p CallSiteDIE. The \p Params
> +  /// were collected by the \ref collectCallSiteParameters.
> +  /// Note: The order of parameters does not matter, since debuggers recognize
> +  ///       call site parameters by the DW_AT_location attribute.
> +  void constructCallSiteParmEntryDIEs(DIE &CallSiteDIE,
> +                                      SmallVector<DbgCallSiteParam, 4> &Params);
>
>    /// Construct import_module DIE.
>    DIE *constructImportedEntityDIE(const DIImportedEntity *Module);
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Wed Jul 31 09:51:28 2019
> @@ -26,6 +26,7 @@
>  #include "llvm/ADT/STLExtras.h"
>  #include "llvm/ADT/SmallVector.h"
>  #include "llvm/ADT/StringRef.h"
> +#include "llvm/ADT/Statistic.h"
>  #include "llvm/ADT/Triple.h"
>  #include "llvm/ADT/Twine.h"
>  #include "llvm/BinaryFormat/Dwarf.h"
> @@ -39,6 +40,7 @@
>  #include "llvm/CodeGen/MachineModuleInfo.h"
>  #include "llvm/CodeGen/MachineOperand.h"
>  #include "llvm/CodeGen/TargetInstrInfo.h"
> +#include "llvm/CodeGen/TargetLowering.h"
>  #include "llvm/CodeGen/TargetRegisterInfo.h"
>  #include "llvm/CodeGen/TargetSubtargetInfo.h"
>  #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
> @@ -83,6 +85,8 @@ using namespace llvm;
>
>  #define DEBUG_TYPE "dwarfdebug"
>
> +STATISTIC(NumCSParams, "Number of dbg call site params created");
> +
>  static cl::opt<bool>
>  DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
>                           cl::desc("Disable debug info printing"));
> @@ -551,6 +555,146 @@ void DwarfDebug::constructAbstractSubpro
>    }
>  }
>
> +/// Try to interpret values loaded into registers that forward parameters
> +/// for \p CallMI. Store parameters with interpreted value into \p Params.
> +static void collectCallSiteParameters(const MachineInstr *CallMI,
> +                                      ParamSet &Params) {
> +  auto *MF = CallMI->getMF();
> +  auto CalleesMap = MF->getCallSitesInfo();
> +  auto CallFwdRegsInfo = CalleesMap.find(CallMI);
> +
> +  // There is no information for the call instruction.
> +  if (CallFwdRegsInfo == CalleesMap.end())
> +    return;
> +
> +  auto *MBB = CallMI->getParent();
> +  const auto &TRI = MF->getSubtarget().getRegisterInfo();
> +  const auto &TII = MF->getSubtarget().getInstrInfo();
> +  const auto &TLI = MF->getSubtarget().getTargetLowering();
> +
> +  // Skip the call instruction.
> +  auto I = std::next(CallMI->getReverseIterator());
> +
> +  DenseSet<unsigned> ForwardedRegWorklist;
> +  // Add all the forwarding registers into the ForwardedRegWorklist.
> +  for (auto ArgReg : CallFwdRegsInfo->second) {
> +    bool InsertedReg = ForwardedRegWorklist.insert(ArgReg.Reg).second;
> +    assert(InsertedReg && "Single register used to forward two arguments?");
> +  }
> +
> +  // We erase, from the ForwardedRegWorklist, those forwarding registers for
> +  // which we successfully describe a loaded value (by using
> +  // the describeLoadedValue()). For those remaining arguments in the working
> +  // list, for which we do not describe a loaded value by
> +  // the describeLoadedValue(), we try to generate an entry value expression
> +  // for their call site value desctipion, if the call is within the entry MBB.
> +  // The RegsForEntryValues maps a forwarding register into the register holding
> +  // the entry value.
> +  // TODO: Handle situations when call site parameter value can be described
> +  // as the entry value within basic blocks other then the first one.
> +  bool ShouldTryEmitEntryVals = MBB->getIterator() == MF->begin();
> +  DenseMap<unsigned, unsigned> RegsForEntryValues;
> +
> +  // If the MI is an instruction defining a parameter's forwarding register,
> +  // add it into the Defs. If the MI clobbers more then one register, we use
> +  // the Defs in order to remove all the registers from
> +  // the ForwardedRegWorklist, since we do not support such situations now.
> +  auto getForwardingRegsDefinedByMI = [&](const MachineInstr &MI,
> +                                         SmallVectorImpl<unsigned> &Defs) {
> +    if (MI.isDebugInstr())
> +      return;
> +
> +    for (const MachineOperand &MO : MI.operands()) {
> +      if (MO.isReg() && MO.isDef() && TRI->isPhysicalRegister(MO.getReg())) {
> +        for (auto FwdReg : ForwardedRegWorklist) {
> +          if (TRI->regsOverlap(FwdReg, MO.getReg())) {
> +            Defs.push_back(FwdReg);
> +            break;
> +          }
> +        }
> +      }
> +    }
> +  };
> +
> +  auto finishCallSiteParam = [&](DbgValueLoc DbgLocVal, unsigned Reg) {
> +    unsigned FwdReg = Reg;
> +    if (ShouldTryEmitEntryVals) {
> +      auto EntryValReg = RegsForEntryValues.find(Reg);
> +      if (EntryValReg != RegsForEntryValues.end())
> +        FwdReg = EntryValReg->second;
> +    }
> +
> +    DbgCallSiteParam CSParm(FwdReg, DbgLocVal);
> +    Params.push_back(CSParm);
> +    ++NumCSParams;
> +  };
> +
> +  // Search for a loading value in forwaring registers.
> +  for (; I != MBB->rend(); ++I) {
> +    // If the next instruction is a call we can not interpret parameter's
> +    // forwarding registers or we finished the interpretation of all parameters.
> +    if (I->isCall())
> +      return;
> +
> +    if (ForwardedRegWorklist.empty())
> +      return;
> +
> +    SmallVector<unsigned, 4> Defs;
> +    getForwardingRegsDefinedByMI(*I, Defs);
> +    if (Defs.empty())
> +      continue;
> +
> +    // If the MI clobbers more then one forwarding register we must remove
> +    // all of them from the working list.
> +    for (auto Reg : Defs)
> +      ForwardedRegWorklist.erase(Reg);
> +    if (I->getNumDefs() != 1)
> +      continue;
> +    unsigned Reg = Defs[0];
> +
> +    if (auto ParamValue = TII->describeLoadedValue(*I)) {
> +      if (ParamValue->first->isImm()) {
> +        unsigned Val = ParamValue->first->getImm();
> +        DbgValueLoc DbgLocVal(ParamValue->second, Val);
> +        finishCallSiteParam(DbgLocVal, Reg);
> +      } else if (ParamValue->first->isReg()) {
> +        unsigned RegLoc = ParamValue->first->getReg();
> +        unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
> +        unsigned FP = TRI->getFrameRegister(*MF);
> +        bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP);
> +        if (TRI->isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP) {
> +          DbgValueLoc DbgLocVal(ParamValue->second,
> +                                MachineLocation(RegLoc,
> +                                                /*IsIndirect=*/IsSPorFP));
> +          finishCallSiteParam(DbgLocVal, Reg);
> +        } else if (ShouldTryEmitEntryVals) {
> +          ForwardedRegWorklist.insert(RegLoc);
> +          RegsForEntryValues[RegLoc] = Reg;
> +        }
> +      }
> +    }
> +  }
> +
> +  // Emit the call site parameter's value as an entry value.
> +  if (ShouldTryEmitEntryVals) {
> +    // Create an entry value expression where the expression following
> +    // the 'DW_OP_entry_value' will be the size of 1 (a register operation).
> +    DIExpression *EntryExpr = DIExpression::get(MF->getFunction().getContext(),
> +                                                {dwarf::DW_OP_entry_value, 1});
> +    for (auto RegEntry : ForwardedRegWorklist) {
> +      unsigned FwdReg = RegEntry;
> +      auto EntryValReg = RegsForEntryValues.find(RegEntry);
> +        if (EntryValReg != RegsForEntryValues.end())
> +          FwdReg = EntryValReg->second;
> +
> +      DbgValueLoc DbgLocVal(EntryExpr, MachineLocation(RegEntry));
> +      DbgCallSiteParam CSParm(FwdReg, DbgLocVal);
> +      Params.push_back(CSParm);
> +      ++NumCSParams;
> +    }
> +  }
> +}
> +
>  void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
>                                              DwarfCompileUnit &CU, DIE &ScopeDIE,
>                                              const MachineFunction &MF) {
> @@ -563,10 +707,12 @@ void DwarfDebug::constructCallSiteEntryD
>    // for both tail and non-tail calls. Don't use DW_AT_call_all_source_calls
>    // because one of its requirements is not met: call site entries for
>    // optimized-out calls are elided.
> -  CU.addFlag(ScopeDIE, dwarf::DW_AT_call_all_calls);
> +  CU.addFlag(ScopeDIE,
> +             CU.getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_all_calls));
>
>    const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
>    assert(TII && "TargetInstrInfo not found: cannot label tail calls");
> +  bool ApplyGNUExtensions = getDwarfVersion() == 4 && tuneForGDB();
>
>    // Emit call site entries for each call or tail call in the function.
>    for (const MachineBasicBlock &MBB : MF) {
> @@ -581,30 +727,66 @@ void DwarfDebug::constructCallSiteEntryD
>          return;
>
>        // If this is a direct call, find the callee's subprogram.
> +      // In the case of an indirect call find the register that holds
> +      // the callee.
>        const MachineOperand &CalleeOp = MI.getOperand(0);
> -      if (!CalleeOp.isGlobal())
> -        continue;
> -      const Function *CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
> -      if (!CalleeDecl || !CalleeDecl->getSubprogram())
> +      if (!CalleeOp.isGlobal() && !CalleeOp.isReg())
>          continue;
>
> +      unsigned CallReg = 0;
> +      const DISubprogram *CalleeSP = nullptr;
> +      const Function *CalleeDecl = nullptr;
> +      if (CalleeOp.isReg()) {
> +        CallReg = CalleeOp.getReg();
> +        if (!CallReg)
> +          continue;
> +      } else {
> +        CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
> +        if (!CalleeDecl || !CalleeDecl->getSubprogram())
> +          continue;
> +        CalleeSP = CalleeDecl->getSubprogram();
> +      }
> +
>        // TODO: Omit call site entries for runtime calls (objc_msgSend, etc).
> -      // TODO: Add support for indirect calls.
>
>        bool IsTail = TII->isTailCall(MI);
>
> -      // For tail calls, no return PC information is needed. For regular calls,
> -      // the return PC is needed to disambiguate paths in the call graph which
> -      // could lead to some target function.
> +      // For tail calls, for non-gdb tuning, no return PC information is needed.
> +      // For regular calls (and tail calls in GDB tuning), the return PC
> +      // is needed to disambiguate paths in the call graph which could lead to
> +      // some target function.
>        const MCExpr *PCOffset =
> -          IsTail ? nullptr : getFunctionLocalOffsetAfterInsn(&MI);
> +          (IsTail && !tuneForGDB()) ? nullptr
> +                                    : getFunctionLocalOffsetAfterInsn(&MI);
> +
> +      // Address of a call-like instruction for a normal call or a jump-like
> +      // instruction for a tail call. This is needed for GDB + DWARF 4 tuning.
> +      const MCSymbol *PCAddr =
> +          ApplyGNUExtensions ? const_cast<MCSymbol*>(getLabelAfterInsn(&MI))
> +                             : nullptr;
> +
> +      assert((IsTail || PCOffset || PCAddr) &&
> +             "Call without return PC information");
>
> -      assert((IsTail || PCOffset) && "Call without return PC information");
>        LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> "
> -                        << CalleeDecl->getName() << (IsTail ? " [tail]" : "")
> -                        << "\n");
> -      CU.constructCallSiteEntryDIE(ScopeDIE, *CalleeDecl->getSubprogram(),
> -                                   IsTail, PCOffset);
> +                        << (CalleeDecl ? CalleeDecl->getName()
> +                                       : StringRef(MF.getSubtarget()
> +                                                       .getRegisterInfo()
> +                                                       ->getName(CallReg)))
> +                        << (IsTail ? " [IsTail]" : "") << "\n");
> +
> +      DIE &CallSiteDIE =
> +            CU.constructCallSiteEntryDIE(ScopeDIE, CalleeSP, IsTail, PCAddr,
> +                                         PCOffset, CallReg);
> +
> +      // For now only GDB supports call site parameter debug info.
> +      if (Asm->TM.Options.EnableDebugEntryValues &&
> +          tuneForGDB()) {
> +        ParamSet Params;
> +        // Try to interpret values of call site parameters.
> +        collectCallSiteParameters(&MI, Params);
> +        CU.constructCallSiteParmEntryDIEs(CallSiteDIE, Params);
> +      }
>      }
>    }
>  }
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Wed Jul 31 09:51:28 2019
> @@ -254,6 +254,25 @@ public:
>    }
>  };
>
> +/// Used for tracking debug info about call site parameters.
> +class DbgCallSiteParam {
> +private:
> +  unsigned Register; ///< Parameter register at the callee entry point.
> +  DbgValueLoc Value; ///< Corresponding location for the parameter value at
> +                     ///< the call site.
> +public:
> +  DbgCallSiteParam(unsigned Reg, DbgValueLoc Val)
> +      : Register(Reg), Value(Val) {
> +    assert(Reg && "Parameter register cannot be undef");
> +  }
> +
> +  unsigned getRegister() const { return Register; }
> +  DbgValueLoc getValue() const { return Value; }
> +};
> +
> +/// Collection used for storing debug call site parameters.
> +using ParamSet = SmallVector<DbgCallSiteParam, 4>;
> +
>  /// Helper used to pair up a symbol and its DWARF compile unit.
>  struct SymbolCU {
>    SymbolCU(DwarfCompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {}
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp Wed Jul 31 09:51:28 2019
> @@ -241,15 +241,19 @@ bool DwarfExpression::addMachineRegExpre
>      return false;
>    }
>
> -  // Handle simple register locations.
> -  if (!isMemoryLocation() && !HasComplexExpression) {
> +  // Handle simple register locations. If we are supposed to emit
> +  // a call site parameter expression and if that expression is just a register
> +  // location, emit it with addBReg and offset 0, because we should emit a DWARF
> +  // expression representing a value, rather than a location.
> +  if (!isMemoryLocation() && !HasComplexExpression && (!isParameterValue() ||
> +                                                       isEntryValue())) {
>      for (auto &Reg : DwarfRegs) {
>        if (Reg.DwarfRegNo >= 0)
>          addReg(Reg.DwarfRegNo, Reg.Comment);
>        addOpPiece(Reg.Size);
>      }
>
> -    if (isEntryValue() && DwarfVersion >= 4)
> +    if (isEntryValue() && !isParameterValue() && DwarfVersion >= 4)
>        emitOp(dwarf::DW_OP_stack_value);
>
>      DwarfRegs.clear();
> @@ -340,7 +344,17 @@ void DwarfExpression::addExpression(DIEx
>
>    while (ExprCursor) {
>      auto Op = ExprCursor.take();
> -    switch (Op->getOp()) {
> +    uint64_t OpNum = Op->getOp();
> +
> +    if (OpNum >= dwarf::DW_OP_reg0 && OpNum <= dwarf::DW_OP_reg31) {
> +      emitOp(OpNum);
> +      continue;
> +    } else if (OpNum >= dwarf::DW_OP_breg0 && OpNum <= dwarf::DW_OP_breg31) {
> +      addBReg(OpNum - dwarf::DW_OP_breg0, Op->getArg(0));
> +      continue;
> +    }
> +
> +    switch (OpNum) {
>      case dwarf::DW_OP_LLVM_fragment: {
>        unsigned SizeInBits = Op->getArg(1);
>        unsigned FragmentOffset = Op->getArg(0);
> @@ -389,7 +403,7 @@ void DwarfExpression::addExpression(DIEx
>      case dwarf::DW_OP_lit0:
>      case dwarf::DW_OP_not:
>      case dwarf::DW_OP_dup:
> -      emitOp(Op->getOp());
> +      emitOp(OpNum);
>        break;
>      case dwarf::DW_OP_deref:
>        assert(!isRegisterLocation());
> @@ -458,12 +472,21 @@ void DwarfExpression::addExpression(DIEx
>      case dwarf::DW_OP_LLVM_tag_offset:
>        TagOffset = Op->getArg(0);
>        break;
> +    case dwarf::DW_OP_regx:
> +      emitOp(dwarf::DW_OP_regx);
> +      emitUnsigned(Op->getArg(0));
> +      break;
> +    case dwarf::DW_OP_bregx:
> +      emitOp(dwarf::DW_OP_bregx);
> +      emitUnsigned(Op->getArg(0));
> +      emitSigned(Op->getArg(1));
> +      break;
>      default:
>        llvm_unreachable("unhandled opcode found in expression");
>      }
>    }
>
> -  if (isImplicitLocation())
> +  if (isImplicitLocation() && !isParameterValue())
>      // Turn this into an implicit location description.
>      addStackValue();
>  }
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h Wed Jul 31 09:51:28 2019
> @@ -120,7 +120,7 @@ protected:
>    enum { Unknown = 0, Register, Memory, Implicit };
>
>    /// The flags of location description being produced.
> -  enum { EntryValue = 1 };
> +  enum { EntryValue = 1, CallSiteParamValue };
>
>    unsigned LocationKind : 3;
>    unsigned LocationFlags : 2;
> @@ -147,6 +147,10 @@ public:
>      return LocationFlags & EntryValue;
>    }
>
> +  bool isParameterValue() {
> +    return LocationFlags & CallSiteParamValue;
> +  }
> +
>    Optional<uint8_t> TagOffset;
>
>  protected:
> @@ -264,6 +268,11 @@ public:
>      LocationFlags |= EntryValue;
>    }
>
> +  /// Lock this down to become a call site parameter location.
> +  void setCallSiteParamValueFlag() {
> +    LocationFlags |= CallSiteParamValue;
> +  }
> +
>    /// Emit a machine register location. As an optimization this may also consume
>    /// the prefix of a DwarfExpression if a more efficient representation for
>    /// combining the register location and the first operation exists.
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Wed Jul 31 09:51:28 2019
> @@ -205,6 +205,10 @@ void DwarfUnit::insertDIE(const DINode *
>    MDNodeToDieMap.insert(std::make_pair(Desc, D));
>  }
>
> +void DwarfUnit::insertDIE(DIE *D) {
> +  MDNodeToDieMap.insert(std::make_pair(nullptr, D));
> +}
> +
>  void DwarfUnit::addFlag(DIE &Die, dwarf::Attribute Attribute) {
>    if (DD->getDwarfVersion() >= 4)
>      Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_flag_present,
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h Wed Jul 31 09:51:28 2019
> @@ -127,6 +127,8 @@ public:
>    /// the mappings are kept in DwarfDebug.
>    void insertDIE(const DINode *Desc, DIE *D);
>
> +  void insertDIE(DIE *D);
> +
>    /// Add a flag that is true to the DIE.
>    void addFlag(DIE &Die, dwarf::Attribute Attribute);
>
>
> Modified: llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp (original)
> +++ llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp Wed Jul 31 09:51:28 2019
> @@ -23,6 +23,7 @@
>  #include "llvm/CodeGen/TargetRegisterInfo.h"
>  #include "llvm/CodeGen/TargetSchedule.h"
>  #include "llvm/IR/DataLayout.h"
> +#include "llvm/IR/DebugInfoMetadata.h"
>  #include "llvm/MC/MCAsmInfo.h"
>  #include "llvm/MC/MCInstrItineraries.h"
>  #include "llvm/Support/CommandLine.h"
> @@ -1120,6 +1121,36 @@ bool TargetInstrInfo::hasLowDefLatency(c
>    return (DefCycle != -1 && DefCycle <= 1);
>  }
>
> +Optional<ParamLoadedValue>
> +TargetInstrInfo::describeLoadedValue(const MachineInstr &MI) const {
> +  const MachineFunction *MF = MI.getMF();
> +  const MachineOperand *Op = nullptr;
> +  DIExpression *Expr = DIExpression::get(MF->getFunction().getContext(), {});;
> +  const MachineOperand *SrcRegOp, *DestRegOp;
> +
> +  if (isCopyInstr(MI, SrcRegOp, DestRegOp)) {
> +    Op = SrcRegOp;
> +    return ParamLoadedValue(Op, Expr);
> +  } else if (MI.isMoveImmediate()) {
> +    Op = &MI.getOperand(1);
> +    return ParamLoadedValue(Op, Expr);
> +  } else if (MI.hasOneMemOperand()) {
> +    int64_t Offset;
> +    const auto &TRI = MF->getSubtarget().getRegisterInfo();
> +    const auto &TII = MF->getSubtarget().getInstrInfo();
> +    const MachineOperand *BaseOp;
> +
> +    if (!TII->getMemOperandWithOffset(MI, BaseOp, Offset, TRI))
> +      return None;
> +
> +    Expr = DIExpression::prepend(Expr, DIExpression::DerefAfter, Offset);
> +    Op = BaseOp;
> +    return ParamLoadedValue(Op, Expr);
> +  }
> +
> +  return None;
> +}
> +
>  /// Both DefMI and UseMI must be valid.  By default, call directly to the
>  /// itinerary. This may be overriden by the target.
>  int TargetInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
>
> Modified: llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp (original)
> +++ llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp Wed Jul 31 09:51:28 2019
> @@ -433,6 +433,19 @@ TargetRegisterInfo::getRegAllocationHint
>    return false;
>  }
>
> +bool TargetRegisterInfo::isCalleeSavedPhysReg(
> +    unsigned PhysReg, const MachineFunction &MF) const {
> +  if (PhysReg == 0)
> +    return false;
> +  const uint32_t *callerPreservedRegs =
> +      getCallPreservedMask(MF, MF.getFunction().getCallingConv());
> +  if (callerPreservedRegs) {
> +    assert(isPhysicalRegister(PhysReg) && "Expected physical register");
> +    return (callerPreservedRegs[PhysReg / 32] >> PhysReg % 32) & 1;
> +  }
> +  return false;
> +}
> +
>  bool TargetRegisterInfo::canRealignStack(const MachineFunction &MF) const {
>    return !MF.getFunction().hasFnAttribute("no-realign-stack");
>  }
>
> Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp (original)
> +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp Wed Jul 31 09:51:28 2019
> @@ -733,6 +733,7 @@ bool DWARFAttribute::mayHaveLocationDesc
>    case DW_AT_call_data_value:
>    // Extensions.
>    case DW_AT_GNU_call_site_value:
> +  case DW_AT_GNU_call_site_target:
>      return true;
>    default:
>      return false;
>
> Modified: llvm/trunk/lib/IR/DebugInfoMetadata.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/DebugInfoMetadata.cpp (original)
> +++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp Wed Jul 31 09:51:28 2019
> @@ -828,15 +828,23 @@ DIExpression *DIExpression::getImpl(LLVM
>  }
>
>  unsigned DIExpression::ExprOperand::getSize() const {
> -  switch (getOp()) {
> +  uint64_t Op = getOp();
> +
> +  if (Op >= dwarf::DW_OP_breg0 && Op <= dwarf::DW_OP_breg31)
> +    return 2;
> +
> +  switch (Op) {
>    case dwarf::DW_OP_LLVM_convert:
>    case dwarf::DW_OP_LLVM_fragment:
> +  case dwarf::DW_OP_bregx:
>      return 3;
>    case dwarf::DW_OP_constu:
> +  case dwarf::DW_OP_consts:
>    case dwarf::DW_OP_deref_size:
>    case dwarf::DW_OP_plus_uconst:
>    case dwarf::DW_OP_LLVM_tag_offset:
>    case dwarf::DW_OP_entry_value:
> +  case dwarf::DW_OP_regx:
>      return 2;
>    default:
>      return 1;
> @@ -849,8 +857,13 @@ bool DIExpression::isValid() const {
>      if (I->get() + I->getSize() > E->get())
>        return false;
>
> +    uint64_t Op = I->getOp();
> +    if ((Op >= dwarf::DW_OP_reg0 && Op <= dwarf::DW_OP_reg31) ||
> +        (Op >= dwarf::DW_OP_breg0 && Op <= dwarf::DW_OP_breg31))
> +      return true;
> +
>      // Check that the operand is valid.
> -    switch (I->getOp()) {
> +    switch (Op) {
>      default:
>        return false;
>      case dwarf::DW_OP_LLVM_fragment:
> @@ -905,6 +918,8 @@ bool DIExpression::isValid() const {
>      case dwarf::DW_OP_lit0:
>      case dwarf::DW_OP_not:
>      case dwarf::DW_OP_dup:
> +    case dwarf::DW_OP_regx:
> +    case dwarf::DW_OP_bregx:
>        break;
>      }
>    }
>
> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Wed Jul 31 09:51:28 2019
> @@ -30,7 +30,7 @@
>  #include "llvm/CodeGen/StackMaps.h"
>  #include "llvm/IR/DerivedTypes.h"
>  #include "llvm/IR/Function.h"
> -#include "llvm/IR/LLVMContext.h"
> +#include "llvm/IR/DebugInfoMetadata.h"
>  #include "llvm/MC/MCAsmInfo.h"
>  #include "llvm/MC/MCExpr.h"
>  #include "llvm/MC/MCInst.h"
> @@ -7367,6 +7367,92 @@ bool X86InstrInfo::isAssociativeAndCommu
>    }
>  }
>
> +Optional<ParamLoadedValue>
> +X86InstrInfo::describeLoadedValue(const MachineInstr &MI) const {
> +  const MachineOperand *Op = nullptr;
> +  DIExpression *Expr = nullptr;
> +
> +  switch (MI.getOpcode()) {
> +  case X86::LEA32r:
> +  case X86::LEA64r:
> +  case X86::LEA64_32r: {
> +    // Operand 4 could be global address. For now we do not support
> +    // such situation.
> +    if (!MI.getOperand(4).isImm() || !MI.getOperand(2).isImm())
> +      return None;
> +
> +    const MachineOperand &Op1 = MI.getOperand(1);
> +    const MachineOperand &Op2 = MI.getOperand(3);
> +    const TargetRegisterInfo *TRI = &getRegisterInfo();
> +    assert(Op2.isReg() &&
> +           (Op2.getReg() == X86::NoRegister ||
> +            TargetRegisterInfo::isPhysicalRegister(Op2.getReg())));
> +
> +    // Omit situations like:
> +    // %rsi = lea %rsi, 4, ...
> +    if ((Op1.isReg() && Op1.getReg() == MI.getOperand(0).getReg()) ||
> +        Op2.getReg() == MI.getOperand(0).getReg())
> +      return None;
> +    else if ((Op1.isReg() && Op1.getReg() != X86::NoRegister &&
> +              TRI->regsOverlap(Op1.getReg(), MI.getOperand(0).getReg())) ||
> +             (Op2.getReg() != X86::NoRegister &&
> +              TRI->regsOverlap(Op2.getReg(), MI.getOperand(0).getReg())))
> +      return None;
> +
> +    int64_t Coef = MI.getOperand(2).getImm();
> +    int64_t Offset = MI.getOperand(4).getImm();
> +    SmallVector<uint64_t, 8> Ops;
> +
> +    if ((Op1.isReg() && Op1.getReg() != X86::NoRegister)) {
> +      Op = &Op1;
> +    } else if (Op1.isFI())
> +      Op = &Op1;
> +
> +    if (Op && Op->isReg() && Op->getReg() == Op2.getReg() && Coef > 0) {
> +      Ops.push_back(dwarf::DW_OP_constu);
> +      Ops.push_back(Coef + 1);
> +      Ops.push_back(dwarf::DW_OP_mul);
> +    } else {
> +      if (Op && Op2.getReg() != X86::NoRegister) {
> +        int dwarfReg = TRI->getDwarfRegNum(Op2.getReg(), false);
> +        if (dwarfReg < 0)
> +          return None;
> +        else if (dwarfReg < 32) {
> +          Ops.push_back(dwarf::DW_OP_breg0 + dwarfReg);
> +          Ops.push_back(0);
> +        } else {
> +          Ops.push_back(dwarf::DW_OP_bregx);
> +          Ops.push_back(dwarfReg);
> +          Ops.push_back(0);
> +        }
> +      } else if (!Op) {
> +        assert(Op2.getReg() != X86::NoRegister);
> +        Op = &Op2;
> +      }
> +
> +      if (Coef > 1) {
> +        assert(Op2.getReg() != X86::NoRegister);
> +        Ops.push_back(dwarf::DW_OP_constu);
> +        Ops.push_back(Coef);
> +        Ops.push_back(dwarf::DW_OP_mul);
> +      }
> +
> +      if (((Op1.isReg() && Op1.getReg() != X86::NoRegister) || Op1.isFI()) &&
> +          Op2.getReg() != X86::NoRegister) {
> +        Ops.push_back(dwarf::DW_OP_plus);
> +      }
> +    }
> +
> +    DIExpression::appendOffset(Ops, Offset);
> +    Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), Ops);
> +
> +    return ParamLoadedValue(Op, Expr);;
> +  }
> +  default:
> +    return TargetInstrInfo::describeLoadedValue(MI);
> +  }
> +}
> +
>  /// This is an architecture-specific helper function of reassociateOps.
>  /// Set special operand attributes for new instructions after reassociation.
>  void X86InstrInfo::setSpecialOperandAttr(MachineInstr &OldMI1,
>
> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Wed Jul 31 09:51:28 2019
> @@ -527,6 +527,9 @@ public:
>  #define GET_INSTRINFO_HELPER_DECLS
>  #include "X86GenInstrInfo.inc"
>
> +  Optional<ParamLoadedValue>
> +  describeLoadedValue(const MachineInstr &MI) const override;
> +
>  protected:
>    /// Commutes the operands in the given instruction by changing the operands
>    /// order and/or changing the instruction's opcode and/or the immediate value
>
> Added: llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir?rev=367446&view=auto
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir (added)
> +++ llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir Wed Jul 31 09:51:28 2019
> @@ -0,0 +1,202 @@
> +# RUN: llc -debug-entry-values -start-after=machineverifier -filetype=obj %s -o -| llvm-dwarfdump -| FileCheck %s
> +#
> +# CHECK:        DW_TAG_GNU_call_site
> +# CHECK-NEXT:     DW_AT_abstract_origin {{.*}} "foo"
> +# CHECK-NEXT:     DW_AT_low_pc
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg2 RCX)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0)
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg1 RDX)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_fbreg +8)
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg5 RDI)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_GNU_entry_value(DW_OP_reg4 RSI))
> +# CHECK-EMPTY:
> +# CHECK:        DW_TAG_GNU_call_site
> +# CHECK-NEXT:     DW_AT_abstract_origin {{.*}}"foo"
> +# CHECK-NEXT:     DW_AT_low_pc
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg2 RCX)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_fbreg +8, DW_OP_deref)
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg4 RSI)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_lit4)
> +# CHECK-EMPTY:
> +# CHECK-NOT:      DW_TAG_GNU_call_site_parameter
> +#
> +# Check that call site interpretation analysis can interpret instructions such
> +# as move immediate, register to register moves, stack loading and LEA
> +# instructions. Last negative check should verify that we are not producing
> +# interpretation for RDX register since its loaded value is call clobberable.
> +# Also check that we are generating proper call site debug entities.
> +--- |
> +  ; ModuleID = 'dbgcall-site-interpretation.c'
> +  source_filename = "dbgcall-site-interpretation.c"
> +  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> +  target triple = "x86_64-unknown-linux-gnu"
> +
> +  ; Function Attrs: nounwind uwtable
> +  define dso_local i32 @baa(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) local_unnamed_addr !dbg !9 {
> +  entry:
> +    %arg3.addr = alloca i32, align 4
> +    %local2 = alloca i32, align 4
> +    call void @llvm.dbg.value(metadata i32 %arg1, metadata !14, metadata !DIExpression()), !dbg !21
> +    call void @llvm.dbg.value(metadata i32 %arg2, metadata !15, metadata !DIExpression()), !dbg !21
> +    call void @llvm.dbg.value(metadata i32 %arg3, metadata !16, metadata !DIExpression()), !dbg !21
> +    store i32 %arg3, i32* %arg3.addr, align 4
> +    call void @llvm.dbg.value(metadata i32 %arg4, metadata !17, metadata !DIExpression()), !dbg !21
> +    %0 = bitcast i32* %local2 to i8*, !dbg !21
> +    call void @llvm.dbg.value(metadata i32* %arg3.addr, metadata !16, metadata !DIExpression(DW_OP_deref)), !dbg !21
> +    %call = call i32 @foo(i32 %arg1, i32 %arg2, i32* nonnull %arg3.addr, i32 %arg4), !dbg !21
> +    call void @llvm.dbg.value(metadata i32 %call, metadata !18, metadata !DIExpression()), !dbg !21
> +    %cmp = icmp sgt i32 %arg1, %arg2, !dbg !21
> +    %1 = load i32, i32* %arg3.addr, align 4, !dbg !21
> +    call void @llvm.dbg.value(metadata i32 %1, metadata !16, metadata !DIExpression()), !dbg !21
> +    %add = add nsw i32 %1, %arg1, !dbg !21
> +    %add1 = add nsw i32 %arg4, %arg2, !dbg !21
> +    %local1.0 = select i1 %cmp, i32 %add, i32 %add1, !dbg !21
> +    call void @llvm.dbg.value(metadata i32 %local1.0, metadata !18, metadata !DIExpression()), !dbg !21
> +    %rem = srem i32 %1, %arg1, !dbg !21
> +    %tobool = icmp eq i32 %rem, 0, !dbg !21
> +    %mul = mul nsw i32 %1, %arg1, !dbg !21
> +    %add3 = add nsw i32 %1, %arg4, !dbg !21
> +    %storemerge = select i1 %tobool, i32 %mul, i32 %add3, !dbg !21
> +    call void @llvm.dbg.value(metadata i32 %storemerge, metadata !19, metadata !DIExpression()), !dbg !21
> +    store i32 %storemerge, i32* %local2, align 4, !dbg !21
> +    %cmp6 = icmp slt i32 %storemerge, %arg4, !dbg !21
> +    %local3.0.v = select i1 %cmp6, i32 %local1.0, i32 %arg1, !dbg !21
> +    %local3.0 = mul nsw i32 %local3.0.v, %storemerge, !dbg !21
> +    call void @llvm.dbg.value(metadata i32 %local3.0, metadata !20, metadata !DIExpression()), !dbg !21
> +    call void @llvm.dbg.value(metadata i32* %local2, metadata !19, metadata !DIExpression(DW_OP_deref)), !dbg !21
> +    %call12 = call i32 @foo(i32 %local1.0, i32 4, i32* nonnull %local2, i32 %local3.0), !dbg !21
> +    call void @llvm.dbg.value(metadata i32 %call12, metadata !14, metadata !DIExpression()), !dbg !21
> +    %add13 = add nsw i32 %call12, 4, !dbg !21
> +    ret i32 %add13, !dbg !21
> +  }
> +
> +  declare !dbg !4 dso_local i32 @foo(i32, i32, i32*, 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: "dbgcall-site-interpretation.c", directory: "/dir")
> +  !2 = !{}
> +  !3 = !{!4}
> +  !4 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 9, 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: "baa", scope: !1, file: !1, line: 10, type: !10, scopeLine: 10, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13)
> +  !10 = !DISubroutineType(types: !11)
> +  !11 = !{!12, !12, !12, !12, !12}
> +  !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> +  !13 = !{!14, !15, !16, !17, !18, !19, !20}
> +  !14 = !DILocalVariable(name: "arg1", arg: 1, scope: !9, file: !1, line: 10, type: !12)
> +  !15 = !DILocalVariable(name: "arg2", arg: 2, scope: !9, file: !1, line: 10, type: !12, flags: DIFlagArgumentNotModified)
> +  !16 = !DILocalVariable(name: "arg3", arg: 3, scope: !9, file: !1, line: 10, type: !12)
> +  !17 = !DILocalVariable(name: "arg4", arg: 4, scope: !9, file: !1, line: 10, type: !12, flags: DIFlagArgumentNotModified)
> +  !18 = !DILocalVariable(name: "local1", scope: !9, file: !1, line: 11, type: !12)
> +  !19 = !DILocalVariable(name: "local2", scope: !9, file: !1, line: 11, type: !12)
> +  !20 = !DILocalVariable(name: "local3", scope: !9, file: !1, line: 11, type: !12)
> +  !21 = !DILocation(line: 10, column: 13, scope: !9)
> +
> +...
> +---
> +name:            baa
> +liveins:
> +  - { reg: '$edi', virtual-reg: '' }
> +  - { reg: '$esi', virtual-reg: '' }
> +  - { reg: '$edx', virtual-reg: '' }
> +  - { reg: '$ecx', virtual-reg: '' }
> +callSites:
> +  - { bb: 0, offset: 23, fwdArgRegs:
> +      - { arg: 0, reg: '$edi' }
> +      - { arg: 1, reg: '$esi' }
> +      - { arg: 2, reg: '$rdx' }
> +      - { arg: 3, reg: '$ecx' } }
> +  - { bb: 0, offset: 49, fwdArgRegs:
> +      - { arg: 0, reg: '$edi' }
> +      - { arg: 1, reg: '$esi' }
> +      - { arg: 2, reg: '$rdx' }
> +      - { arg: 3, reg: '$ecx' } }
> +body:             |
> +  bb.0.entry:
> +    liveins: $ecx, $edi, $edx, $esi, $r15, $r14, $rbx
> +
> +    DBG_VALUE $edi, $noreg, !14, !DIExpression(), debug-location !21
> +    DBG_VALUE $esi, $noreg, !15, !DIExpression(), debug-location !21
> +    DBG_VALUE $edx, $noreg, !16, !DIExpression(), debug-location !21
> +    DBG_VALUE $ecx, $noreg, !17, !DIExpression(), debug-location !21
> +    frame-setup PUSH64r killed $r15, implicit-def $rsp, implicit $rsp
> +    CFI_INSTRUCTION def_cfa_offset 16
> +    frame-setup PUSH64r killed $r14, implicit-def $rsp, implicit $rsp
> +    CFI_INSTRUCTION def_cfa_offset 24
> +    frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp
> +    CFI_INSTRUCTION def_cfa_offset 32
> +    $rsp = frame-setup SUB64ri8 $rsp, 16, implicit-def dead $eflags
> +    CFI_INSTRUCTION def_cfa_offset 48
> +    CFI_INSTRUCTION offset $rbx, -32
> +    CFI_INSTRUCTION offset $r14, -24
> +    CFI_INSTRUCTION offset $r15, -16
> +    $r14d = MOV32rr $ecx, implicit-def $r14
> +    DBG_VALUE $edx, $noreg, !16, !DIExpression(), debug-location !21
> +    $r15d = MOV32rr $esi, implicit-def $r15
> +    $ebx = MOV32rr $edi, implicit-def $rbx
> +    $edi = MOV32rr $esi
> +    MOV32mr $rsp, 1, $noreg, 8, $noreg, killed renamable $edx :: (store 4 into %ir.arg3.addr)
> +    renamable $rdx = LEA64r $rsp, 1, $noreg, 8, $noreg
> +    renamable $ecx = MOV32rr $r14d,
> +    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit $rdx, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, implicit-def $rax, debug-location !21
> +    DBG_VALUE $noreg, $noreg, !18, !DIExpression(), debug-location !21
> +    $rdx = MOV64rr renamable $rax
> +    $ecx = KILL renamable $ecx, implicit-def $rcx
> +    renamable $eax = LEA64_32r renamable $rcx, 1, renamable $rbx, 0, $noreg, debug-location !21
> +    renamable $edi = LEA64_32r renamable $r14, 1, renamable $r15, 0, $noreg, debug-location !21
> +    CMP32rr renamable $ebx, renamable $r15d, implicit-def $eflags, implicit killed $r15, debug-location !21
> +    renamable $edi = CMOV32rr killed renamable $edi, killed renamable $eax, 15, implicit killed $eflags, debug-location !21
> +    DBG_VALUE $edi, $noreg, !18, !DIExpression(), debug-location !21
> +    $eax = MOV32rr $ecx, debug-location !21
> +    CDQ implicit-def $eax, implicit-def $edx, implicit $eax, debug-location !21
> +    IDIV32r renamable $ebx, implicit-def dead $eax, implicit-def $edx, implicit-def dead $eflags, implicit $eax, implicit $edx, debug-location !21
> +    $eax = MOV32rr $ecx, debug-location !21
> +    renamable $eax = nsw IMUL32rr killed renamable $eax, renamable $ebx, implicit-def dead $eflags, debug-location !21
> +    renamable $ecx = nsw ADD32rr renamable $ecx, renamable $r14d, implicit-def dead $eflags, implicit killed $rcx, implicit-def $rcx, debug-location !21
> +    TEST32rr killed renamable $edx, renamable $edx, implicit-def $eflags, debug-location !21
> +    renamable $ecx = CMOV32rr renamable $ecx, killed renamable $eax, 4, implicit killed $eflags, implicit killed $rcx, implicit-def $rcx, debug-location !21
> +    DBG_VALUE $ecx, $noreg, !19, !DIExpression(), debug-location !21
> +    MOV32mr $rsp, 1, $noreg, 12, $noreg, renamable $ecx, debug-location !21 :: (store 4 into %ir.local2)
> +    CMP32rr renamable $ecx, renamable $r14d, implicit-def $eflags, implicit killed $r14, debug-location !21
> +    renamable $ebx = CMOV32rr renamable $ebx, renamable $edi, 12, implicit killed $eflags, implicit killed $rbx, implicit-def $rbx, debug-location !21
> +    renamable $ecx = nsw IMUL32rr renamable $ecx, renamable $ebx, implicit-def dead $eflags, implicit killed $rbx, implicit killed $rcx, implicit-def $rcx, debug-location !21
> +    DBG_VALUE $rsp, $noreg, !19, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref), debug-location !21
> +    DBG_VALUE $ecx, $noreg, !20, !DIExpression(), debug-location !21
> +    $esi = MOV32ri 4, debug-location !21
> +    renamable $ecx = MOV32rm $rsp, 1, $noreg, 8, $noreg, implicit-def $rcx, debug-location !21 :: (dereferenceable load 4 from %ir.arg3.addr)
> +    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit $rdx, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, implicit-def $rax, debug-location !21
> +    DBG_VALUE $eax, $noreg, !14, !DIExpression(), debug-location !21
> +    renamable $eax = nsw ADD32ri8 killed renamable $eax, 4, implicit-def dead $eflags, debug-location !21
> +    $rsp = frame-destroy ADD64ri8 $rsp, 16, implicit-def dead $eflags, debug-location !21
> +    CFI_INSTRUCTION def_cfa_offset 32, debug-location !21
> +    $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
> +    CFI_INSTRUCTION def_cfa_offset 24, debug-location !21
> +    $r14 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
> +    DBG_VALUE $ecx, $noreg, !17, !DIExpression(DW_OP_entry_value, 1), debug-location !21
> +    CFI_INSTRUCTION def_cfa_offset 16, debug-location !21
> +    $r15 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
> +    DBG_VALUE $esi, $noreg, !15, !DIExpression(DW_OP_entry_value, 1), debug-location !21
> +    CFI_INSTRUCTION def_cfa_offset 8, debug-location !21
> +    RETQ $eax, debug-location !21
> +
> +...
>
> Added: llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir?rev=367446&view=auto
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir (added)
> +++ llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir Wed Jul 31 09:51:28 2019
> @@ -0,0 +1,140 @@
> +# RUN: llc -debug-entry-values -start-after=machineverifier -filetype=obj %s -o -| llvm-dwarfdump -| FileCheck %s
> +# CHECK:        DW_TAG_GNU_call_site
> +# CHECK-NEXT:     DW_AT_abstract_origin {{.*}} "foo")
> +# CHECK-NEXT:     DW_AT_low_pc {{.*}}
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg9 R9)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg15 R15+10)
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg8 R8)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg15 R15+0, DW_OP_lit2, DW_OP_mul, DW_OP_plus_uconst 0x8)
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg1 RDX)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0, DW_OP_lit5, DW_OP_mul, DW_OP_plus_uconst 0x8)
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg4 RSI)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0)
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg5 RDI)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0, DW_OP_breg15 R15+0, DW_OP_lit2, DW_OP_mul, DW_OP_plus, DW_OP_plus_uconst 0x4)
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg2 RCX)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0, DW_OP_breg15 R15+0, DW_OP_plus)
> +# CHECK:        DW_TAG_GNU_call_site
> +# CHECK-NEXT:     DW_AT_abstract_origin {{.*}} "foo2")
> +# CHECK-NEXT:     DW_AT_low_pc {{.*}}
> +# CHECK-EMPTY:
> +# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:       DW_AT_location      (DW_OP_reg5 RDI)
> +# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0, DW_OP_lit2, DW_OP_mul)
> +--- |
> +  ; ModuleID = 'dbgcall-site-lea-interpretation.ll'
> +  source_filename = "dbgcall-site-lea-interpretation.c"
> +  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> +  target triple = "x86_64-unknown-linux-gnu"
> +
> +  define dso_local i32 @baa(i32 %arg1, i32 %arg2, i32 %arg3) local_unnamed_addr !dbg !10 {
> +  entry:
> +    %arg1.addr = alloca i32, align 4
> +    %arg3.addr = alloca i32, align 4
> +    %local1 = alloca i32, align 4
> +    store i32 %arg1, i32* %arg1.addr, align 4
> +    store i32 %arg3, i32* %arg3.addr, align 4
> +    %0 = bitcast i32* %local1 to i8*, !dbg !14
> +    %mul = mul nsw i32 %arg3, %arg1, !dbg !14
> +    store i32 %mul, i32* %local1, align 4, !dbg !14
> +    %add = add nsw i32 %arg2, %arg1, !dbg !14
> +    %sub = sub nsw i32 %add, %arg3, !dbg !14
> +    %call = call i32 @foo(i32 %mul, i32 %sub, i32* nonnull %local1, i32* nonnull %arg1.addr, i32* nonnull %arg3.addr, i32 %add), !dbg !14
> +    %1 = load i32, i32* %local1, align 4, !dbg !14
> +    %add2 = add nsw i32 %1, %call, !dbg !14
> +    store i32 %add2, i32* %local1, align 4, !dbg !14
> +    %call3 = call i32 @foo2(i32* nonnull %local1), !dbg !14
> +    %2 = load i32, i32* %local1, align 4, !dbg !14
> +    ret i32 %2, !dbg !14
> +  }
> +
> +  declare !dbg !4 dso_local i32 @foo(i32, i32, i32*, i32*, i32*, i32) local_unnamed_addr
> +
> +  declare !dbg !5 dso_local i32 @foo2(i32*) local_unnamed_addr
> +
> +  !llvm.dbg.cu = !{!0}
> +  !llvm.module.flags = !{!6, !7, !8}
> +  !llvm.ident = !{!9}
> +
> +  !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: "dbgcall-site-lea-interpretation.c", directory: "/dir")
> +  !2 = !{}
> +  !3 = !{!4, !5}
> +  !4 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 8, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
> +  !5 = !DISubprogram(name: "foo2", scope: !1, file: !1, line: 9, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
> +  !6 = !{i32 2, !"Dwarf Version", i32 4}
> +  !7 = !{i32 2, !"Debug Info Version", i32 3}
> +  !8 = !{i32 1, !"wchar_size", i32 4}
> +  !9 = !{!"clang version 9.0.0"}
> +  !10 = distinct !DISubprogram(name: "baa", scope: !1, file: !1, line: 11, type: !11, scopeLine: 11, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
> +  !11 = !DISubroutineType(types: !12)
> +  !12 = !{!13, !13, !13, !13}
> +  !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> +  !14 = !DILocation(line: 11, column: 13, scope: !10)
> +
> +...
> +---
> +name:            baa
> +liveins:
> +  - { reg: '$edi', virtual-reg: '' }
> +  - { reg: '$esi', virtual-reg: '' }
> +  - { reg: '$edx', virtual-reg: '' }
> +callSites:
> +  - { bb: 0, offset: 21, fwdArgRegs:
> +      - { arg: 0, reg: '$edi' }
> +      - { arg: 1, reg: '$esi' }
> +      - { arg: 2, reg: '$rdx' }
> +      - { arg: 3, reg: '$rcx' }
> +      - { arg: 4, reg: '$r8' }
> +      - { arg: 5, reg: '$r9d' } }
> +  - { bb: 0, offset: 24, fwdArgRegs:
> +      - { arg: 0, reg: '$rdi' } }
> +body:             |
> +  bb.0.entry:
> +    liveins: $edi, $edx, $esi, $rbx
> +
> +    frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp
> +    CFI_INSTRUCTION def_cfa_offset 16
> +    $rsp = frame-setup SUB64ri8 $rsp, 16, implicit-def dead $eflags
> +    CFI_INSTRUCTION def_cfa_offset 32
> +    CFI_INSTRUCTION offset $rbx, -16
> +    $r9d = MOV32rr $esi
> +    $r14 = MOV64rr $rsi
> +    $r15 = MOV64rr $rdi
> +    MOV32mr $rsp, 1, $noreg, 12, $noreg, renamable $edi :: (store 4 into %ir.arg1.addr)
> +    MOV32mr $rsp, 1, $noreg, 8, $noreg, renamable $edx :: (store 4 into %ir.arg3.addr)
> +    renamable $r9d = nsw ADD32rr killed renamable $r9d, renamable $edi, implicit-def dead $eflags, debug-location !14
> +    $esi = MOV32rr $r9d, debug-location !14
> +    renamable $esi = nsw SUB32rr killed renamable $esi, renamable $edx, implicit-def dead $eflags, debug-location !14
> +    renamable $edx = nsw IMUL32rr killed renamable $edx, killed renamable $edi, implicit-def dead $eflags, debug-location !14
> +    MOV32mr $rsp, 1, $noreg, 4, $noreg, renamable $edx, debug-location !14 :: (store 4 into %ir.local1)
> +    renamable $rcx = LEA64r $r14, 1, $r15, 0, $noreg
> +    renamable $rdi = LEA64r $r14, 2, $r15, 4, $noreg
> +    renamable $rsi = LEA64r $r14, 1, $noreg, 0, $noreg
> +    renamable $rdx = LEA64r $r14, 4, $r14, 8, $noreg
> +    renamable $r8 = LEA64r $noreg, 2, $r15, 8, $noreg
> +    renamable $r9 = LEA64r  $noreg, 1, $r15, 10, $noreg, implicit-def $r9d
> +    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit $rdx, implicit $rcx, implicit $r8, implicit $r9d, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !14
> +    ADD32mr $rsp, 1, $noreg, 4, $noreg, killed renamable $eax, implicit-def dead $eflags, debug-location !14 :: (store 4 into %ir.local1), (dereferenceable load 4 from %ir.local1)
> +    $rdi = LEA64r $r14, 1, killed $r14, 0, $noreg
> +    CALL64pcrel32 @foo2, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def dead $eax, debug-location !14
> +    renamable $eax = MOV32rm $rsp, 1, $noreg, 4, $noreg, debug-location !14 :: (dereferenceable load 4 from %ir.local1)
> +    $rsp = frame-destroy ADD64ri8 $rsp, 16, implicit-def dead $eflags, debug-location !14
> +    CFI_INSTRUCTION def_cfa_offset 16, debug-location !14
> +    $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !14
> +    CFI_INSTRUCTION def_cfa_offset 8, debug-location !14
> +    RETQ $eax, debug-location !14
> +
> +...
>
> Added: llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir?rev=367446&view=auto
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir (added)
> +++ llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir Wed Jul 31 09:51:28 2019
> @@ -0,0 +1,159 @@
> +# RUN: llc -debug-entry-values -filetype=obj -mtriple=x86_64-unknown-unknown -start-after=machineverifier -o - %s| llvm-dwarfdump - | FileCheck %s
> +#
> +# extern void foo(int *a, int b, int c, int d, int e, int f);
> +# extern int getVal();
> +#
> +# void baa(int arg1, int arg2, int arg3) {
> +#   int local1 = getVal();
> +#   foo(&local1, arg2, 10, 15, arg3 + 3, arg1 + arg2);
> +# }
> +#
> +# CHECK: DW_TAG_GNU_call_site
> +# CHECK:   DW_AT_abstract_origin {{.*}} "getVal"
> +#
> +# CHECK:       DW_TAG_GNU_call_site
> +# CHECK:         DW_AT_abstract_origin {{.*}} "foo"
> +# CHECK:         DW_AT_low_pc {{.*}}
> +# CHECK-EMPTY:
> +# CHECK:         DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:      DW_AT_location      (DW_OP_reg2 RCX)
> +# CHECK-NEXT:      DW_AT_GNU_call_site_value   (DW_OP_lit15)
> +# CHECK:         DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:      DW_AT_location      (DW_OP_reg1 RDX)
> +# CHECK-NEXT:      DW_AT_GNU_call_site_value   (DW_OP_lit10)
> +# CHECK:         DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:      DW_AT_location      (DW_OP_reg4 RSI)
> +# CHECK-NEXT:      DW_AT_GNU_call_site_value   (DW_OP_breg3 RBX+0)
> +# CHECK:         DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:      DW_AT_location      (DW_OP_reg5 RDI)
> +# CHECK-NEXT:      DW_AT_GNU_call_site_value   (DW_OP_fbreg +12)
> +# CHECK:         DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:      DW_AT_location      (DW_OP_reg9 R9)
> +# CHECK-NEXT:      DW_AT_GNU_call_site_value   (DW_OP_breg15 R15+0, DW_OP_breg3 RBX+0, DW_OP_plus)
> +# CHECK:         DW_TAG_GNU_call_site_parameter
> +# CHECK-NEXT:      DW_AT_location      (DW_OP_reg8 R8)
> +# CHECK-NEXT:      DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+3)
> +--- |
> +  ; ModuleID = 'test.c'
> +  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: nounwind uwtable
> +  define dso_local void @baa(i32 %arg1, i32 %arg2, i32 %arg3) local_unnamed_addr !dbg !10 {
> +  entry:
> +    %local1 = alloca i32, align 4
> +    call void @llvm.dbg.value(metadata i32 %arg1, metadata !15, metadata !DIExpression()), !dbg !19
> +    call void @llvm.dbg.value(metadata i32 %arg2, metadata !16, metadata !DIExpression()), !dbg !20
> +    call void @llvm.dbg.value(metadata i32 %arg3, metadata !17, metadata !DIExpression()), !dbg !21
> +    %0 = bitcast i32* %local1 to i8*, !dbg !22
> +    %call = tail call i32 (...) @getVal(), !dbg !23
> +    call void @llvm.dbg.value(metadata i32 %call, metadata !18, metadata !DIExpression()), !dbg !24
> +    store i32 %call, i32* %local1, align 4, !dbg !24
> +    %add = add nsw i32 %arg3, 3, !dbg !24
> +    %add1 = add nsw i32 %arg2, %arg1, !dbg !24
> +    call void @llvm.dbg.value(metadata i32* %local1, metadata !18, metadata !DIExpression(DW_OP_deref)), !dbg !24
> +    call void @foo(i32* nonnull %local1, i32 %arg2, i32 10, i32 15, i32 %add, i32 %add1), !dbg !24
> +    ret void, !dbg !24
> +  }
> +
> +  declare !dbg !4 dso_local i32 @getVal(...) local_unnamed_addr
> +
> +  declare !dbg !5 dso_local void @foo(i32*, i32, i32, i32, i32, i32) local_unnamed_addr
> +
> +  ; Function Attrs: nounwind readnone speculatable
> +  declare void @llvm.dbg.value(metadata, metadata, metadata)
> +
> +  !llvm.dbg.cu = !{!0}
> +  !llvm.module.flags = !{!6, !7, !8}
> +  !llvm.ident = !{!9}
> +
> +  !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, !5}
> +  !4 = !DISubprogram(name: "getVal", scope: !1, file: !1, line: 2, spFlags: DISPFlagOptimized, retainedNodes: !2)
> +  !5 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
> +  !6 = !{i32 2, !"Dwarf Version", i32 4}
> +  !7 = !{i32 2, !"Debug Info Version", i32 3}
> +  !8 = !{i32 1, !"wchar_size", i32 4}
> +  !9 = !{!"clang version 9.0.0"}
> +  !10 = distinct !DISubprogram(name: "baa", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
> +  !11 = !DISubroutineType(types: !12)
> +  !12 = !{null, !13, !13, !13}
> +  !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> +  !14 = !{!15, !16, !17, !18}
> +  !15 = !DILocalVariable(name: "arg1", arg: 1, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
> +  !16 = !DILocalVariable(name: "arg2", arg: 2, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
> +  !17 = !DILocalVariable(name: "arg3", arg: 3, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
> +  !18 = !DILocalVariable(name: "local1", scope: !10, file: !1, line: 5, type: !13)
> +  !19 = !DILocation(line: 4, column: 14, scope: !10)
> +  !20 = !DILocation(line: 4, column: 24, scope: !10)
> +  !21 = !DILocation(line: 4, column: 34, scope: !10)
> +  !22 = !DILocation(line: 5, column: 3, scope: !10)
> +  !23 = !DILocation(line: 5, column: 16, scope: !10)
> +  !24 = !DILocation(line: 5, column: 7, scope: !10)
> +
> +...
> +---
> +name:            baa
> +liveins:
> +  - { reg: '$edi', virtual-reg: '' }
> +  - { reg: '$esi', virtual-reg: '' }
> +  - { reg: '$edx', virtual-reg: '' }
> +callSites:
> +  - { bb: 0, offset: 21, fwdArgRegs: [] }
> +  - { bb: 0, offset: 31, fwdArgRegs:
> +      - { arg: 0, reg: '$rdi' }
> +      - { arg: 1, reg: '$esi' }
> +      - { arg: 2, reg: '$edx' }
> +      - { arg: 3, reg: '$ecx' }
> +      - { arg: 4, reg: '$r8d' }
> +      - { arg: 5, reg: '$r9d' } }
> +body:             |
> +  bb.0.entry:
> +    liveins: $edi, $edx, $esi, $r15, $r14, $rbx
> +
> +    DBG_VALUE $edi, $noreg, !15, !DIExpression(), debug-location !19
> +    DBG_VALUE $esi, $noreg, !16, !DIExpression(), debug-location !20
> +    DBG_VALUE $edx, $noreg, !17, !DIExpression(), debug-location !21
> +    frame-setup PUSH64r killed $r15, implicit-def $rsp, implicit $rsp
> +    CFI_INSTRUCTION def_cfa_offset 16
> +    frame-setup PUSH64r killed $r14, implicit-def $rsp, implicit $rsp
> +    CFI_INSTRUCTION def_cfa_offset 24
> +    frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp
> +    CFI_INSTRUCTION def_cfa_offset 32
> +    $rsp = frame-setup SUB64ri8 $rsp, 16, implicit-def dead $eflags
> +    CFI_INSTRUCTION def_cfa_offset 48
> +    CFI_INSTRUCTION offset $rbx, -32
> +    CFI_INSTRUCTION offset $r14, -24
> +    CFI_INSTRUCTION offset $r15, -16
> +    $r14d = MOV32rr $edx, implicit-def $r14
> +    $ebx = MOV32rr $esi, implicit-def $rbx
> +    $r15d = MOV32rr $edi, implicit-def $r15
> +    DBG_VALUE $r14d, $noreg, !17, !DIExpression(), debug-location !21
> +    DBG_VALUE $ebx, $noreg, !16, !DIExpression(), debug-location !20
> +    DBG_VALUE $r15d, $noreg, !15, !DIExpression(), debug-location !19
> +    dead $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, implicit-def $al, debug-location !23
> +    CALL64pcrel32 @getVal, csr_64, implicit $rsp, implicit $ssp, implicit $al, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !23
> +    DBG_VALUE $eax, $noreg, !18, !DIExpression(), debug-location !24
> +    MOV32mr $rsp, 1, $noreg, 12, $noreg, killed renamable $eax, debug-location !24 :: (store 4 into %ir.local1)
> +    renamable $r8d = LEA64_32r killed renamable $r14, 1, $noreg, 3, $noreg, debug-location !24
> +    renamable $r9d = LEA64_32r killed renamable $r15, 1, renamable $rbx, 0, $noreg, debug-location !24
> +    DBG_VALUE $rsp, $noreg, !18, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref), debug-location !24
> +    renamable $rdi = LEA64r $rsp, 1, $noreg, 12, $noreg
> +    $esi = MOV32rr $ebx, implicit killed $rbx, debug-location !24
> +    $edx = MOV32ri 10, debug-location !24
> +    $ecx = MOV32ri 15, debug-location !24
> +    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit $edx, implicit killed $ecx, implicit $r8d, implicit $r9d, implicit-def $rsp, implicit-def $ssp, debug-location !24
> +    $rsp = frame-destroy ADD64ri8 $rsp, 16, implicit-def dead $eflags, debug-location !24
> +    CFI_INSTRUCTION def_cfa_offset 32, debug-location !24
> +    $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !24
> +    CFI_INSTRUCTION def_cfa_offset 24, debug-location !24
> +    $r14 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !24
> +    CFI_INSTRUCTION def_cfa_offset 16, debug-location !24
> +    $r15 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !24
> +    CFI_INSTRUCTION def_cfa_offset 8, debug-location !24
> +    RETQ debug-location !24
> +
> +...
>
> Modified: llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll (original)
> +++ llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll Wed Jul 31 09:51:28 2019
> @@ -14,14 +14,14 @@
>
>  ; REQUIRES: object-emission
>  ; RUN: %llc_dwarf -mtriple=x86_64-- < %s -o - | FileCheck %s -check-prefix=ASM
> -; RUN: %llc_dwarf -mtriple=x86_64-- < %s -filetype=obj -o %t.o
> +; RUN: %llc_dwarf -debugger-tune=lldb -mtriple=x86_64-- < %s -filetype=obj -o %t.o
>  ; RUN: llvm-dwarfdump %t.o -o - | FileCheck %s -check-prefix=OBJ -implicit-check-not=DW_TAG_call_site
>  ; RUN: llvm-dwarfdump -verify %t.o 2>&1 | FileCheck %s -check-prefix=VERIFY
>  ; RUN: llvm-dwarfdump -statistics %t.o | FileCheck %s -check-prefix=STATS
>  ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis -o /dev/null
>
>  ; VERIFY: No errors.
> -; STATS: "call site entries":5
> +; STATS: "call site DIEs":6
>
>  @sink = global i32 0, align 4, !dbg !0
>
> @@ -85,6 +85,9 @@ entry:
>  ; OBJ:   DW_TAG_call_site
>  ; OBJ:     DW_AT_call_origin ([[foo_sp]])
>  ; OBJ:     DW_AT_call_return_pc
> +; OBJ:   DW_TAG_call_site
> +; OBJ:     DW_AT_call_target
> +; OBJ:     DW_AT_call_return_pc
>  define i32 @main() !dbg !29 {
>  entry:
>    call void @_Z3foov(), !dbg !32
>
> Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll?rev=367446&view=auto
> ==============================================================================
> --- llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll (added)
> +++ llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll Wed Jul 31 09:51:28 2019
> @@ -0,0 +1,76 @@
> +; RUN: llc -debug-entry-values %s -o - -filetype=obj \
> +; RUN:   | llvm-dwarfdump -statistics - | FileCheck %s
> +;
> +; The LLVM IR file was generated on this source code by using
> +; option '-femit-param-entry-values'.
> +;
> +; extern void foo(int *a, int b, int c, int d, int e, int f);
> +; extern int getVal();
> +;
> +; void baa(int arg1, int arg2, int arg3) {
> +;   int local1 = getVal();
> +;   foo(&local1, arg2, 10, 15, arg3 + 3, arg1 + arg2);
> +; }
> +;
> +; CHECK: "call site DIEs":2
> +; CHECK-SAME: "call site parameter DIEs":6
> +;
> +; ModuleID = 'test.c'
> +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: nounwind uwtable
> +define dso_local void @baa(i32 %arg1, i32 %arg2, i32 %arg3) local_unnamed_addr #0 !dbg !10 {
> +entry:
> +  %local1 = alloca i32, align 4
> +  call void @llvm.dbg.value(metadata i32 %arg1, metadata !15, metadata !DIExpression()), !dbg !19
> +  call void @llvm.dbg.value(metadata i32 %arg2, metadata !16, metadata !DIExpression()), !dbg !20
> +  call void @llvm.dbg.value(metadata i32 %arg3, metadata !17, metadata !DIExpression()), !dbg !21
> +  %0 = bitcast i32* %local1 to i8*, !dbg !22
> +  %call = tail call i32 (...) @getVal(), !dbg !23
> +  call void @llvm.dbg.value(metadata i32 %call, metadata !18, metadata !DIExpression()), !dbg !24
> +  store i32 %call, i32* %local1, align 4, !dbg !24
> +  %add = add nsw i32 %arg3, 3, !dbg !24
> +  %add1 = add nsw i32 %arg2, %arg1, !dbg !24
> +  call void @llvm.dbg.value(metadata i32* %local1, metadata !18, metadata !DIExpression(DW_OP_deref)), !dbg !24
> +  call void @foo(i32* nonnull %local1, i32 %arg2, i32 10, i32 15, i32 %add, i32 %add1), !dbg !24
> +  ret void, !dbg !24
> +}
> +
> +declare !dbg !4 dso_local i32 @getVal(...) local_unnamed_addr
> +
> +declare !dbg !5 dso_local void @foo(i32*, i32, i32, i32, i32, i32) local_unnamed_addr
> +
> +; Function Attrs: nounwind readnone speculatable
> +declare void @llvm.dbg.value(metadata, metadata, metadata)
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!6, !7, !8}
> +!llvm.ident = !{!9}
> +
> +!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, !5}
> +!4 = !DISubprogram(name: "getVal", scope: !1, file: !1, line: 2, spFlags: DISPFlagOptimized, retainedNodes: !2)
> +!5 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
> +!6 = !{i32 2, !"Dwarf Version", i32 4}
> +!7 = !{i32 2, !"Debug Info Version", i32 3}
> +!8 = !{i32 1, !"wchar_size", i32 4}
> +!9 = !{!"clang version 9.0.0"}
> +!10 = distinct !DISubprogram(name: "baa", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
> +!11 = !DISubroutineType(types: !12)
> +!12 = !{null, !13, !13, !13}
> +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> +!14 = !{!15, !16, !17, !18}
> +!15 = !DILocalVariable(name: "arg1", arg: 1, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
> +!16 = !DILocalVariable(name: "arg2", arg: 2, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
> +!17 = !DILocalVariable(name: "arg3", arg: 3, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
> +!18 = !DILocalVariable(name: "local1", scope: !10, file: !1, line: 5, type: !13)
> +!19 = !DILocation(line: 4, column: 14, scope: !10)
> +!20 = !DILocation(line: 4, column: 24, scope: !10)
> +!21 = !DILocation(line: 4, column: 34, scope: !10)
> +!22 = !DILocation(line: 5, column: 3, scope: !10)
> +!23 = !DILocation(line: 5, column: 16, scope: !10)
> +!24 = !DILocation(line: 5, column: 7, scope: !10)
>
> Modified: llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp?rev=367446&r1=367445&r2=367446&view=diff
> ==============================================================================
> --- llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp (original)
> +++ llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp Wed Jul 31 09:51:28 2019
> @@ -56,9 +56,12 @@ struct GlobalStats {
>    /// Total number of PC range bytes in each variable's enclosing scope,
>    /// starting from the first definition of the variable.
>    unsigned ScopeBytesFromFirstDefinition = 0;
> -  /// Total number of call site entries (DW_TAG_call_site) or
> -  /// (DW_AT_call_file & DW_AT_call_line).
> +  /// Total number of call site entries (DW_AT_call_file & DW_AT_call_line).
>    unsigned CallSiteEntries = 0;
> +  /// Total number of call site DIEs (DW_TAG_call_site).
> +  unsigned CallSiteDIEs = 0;
> +  /// Total number of call site parameter DIEs (DW_TAG_call_site_parameter).
> +  unsigned CallSiteParamDIEs = 0;
>    /// Total byte size of concrete functions. This byte size includes
>    /// inline functions contained in the concrete functions.
>    uint64_t FunctionSize = 0;
> @@ -94,8 +97,15 @@ static void collectStatsForDie(DWARFDie
>    uint64_t BytesCovered = 0;
>    uint64_t OffsetToFirstDefinition = 0;
>
> -  if (Die.getTag() == dwarf::DW_TAG_call_site) {
> -    GlobalStats.CallSiteEntries++;
> +  if (Die.getTag() == dwarf::DW_TAG_call_site ||
> +      Die.getTag() == dwarf::DW_TAG_GNU_call_site) {
> +    GlobalStats.CallSiteDIEs++;
> +    return;
> +  }
> +
> +  if (Die.getTag() == dwarf::DW_TAG_call_site_parameter ||
> +      Die.getTag() == dwarf::DW_TAG_GNU_call_site_parameter) {
> +    GlobalStats.CallSiteParamDIEs++;
>      return;
>    }
>
> @@ -387,6 +397,8 @@ bool collectStatsForObjectFile(ObjectFil
>    printDatum(OS, "source variables", VarParamTotal);
>    printDatum(OS, "variables with location", VarParamWithLoc);
>    printDatum(OS, "call site entries", GlobalStats.CallSiteEntries);
> +  printDatum(OS, "call site DIEs", GlobalStats.CallSiteDIEs);
> +  printDatum(OS, "call site parameter DIEs", GlobalStats.CallSiteParamDIEs);
>    printDatum(OS, "scope bytes total",
>               GlobalStats.ScopeBytesFromFirstDefinition);
>    printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list