[llvm] 3cd93a4 - [DebugInfo] Make describeLoadedValue() reg aware

David Stenberg via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 9 01:44:58 PST 2019


Author: David Stenberg
Date: 2019-12-09T10:44:17+01:00
New Revision: 3cd93a4efcdeabeb20cb7bec9fbddcb540d337a1

URL: https://github.com/llvm/llvm-project/commit/3cd93a4efcdeabeb20cb7bec9fbddcb540d337a1
DIFF: https://github.com/llvm/llvm-project/commit/3cd93a4efcdeabeb20cb7bec9fbddcb540d337a1.diff

LOG: [DebugInfo] Make describeLoadedValue() reg aware

Currently the describeLoadedValue() hook is assumed to describe the
value of the instruction's first explicit define. The hook will not be
called for instructions with more than one explicit define.

This commit adds a register parameter to the describeLoadedValue() hook,
and invokes the hook for all registers in the worklist.

This will allow us to for example describe instructions which produce
more than two parameters' values; e.g. Hexagon's various combine
instructions.

This also fixes a case in our downstream target where we may pass
smaller parameters in the high part of a register. If such a parameter's
value is produced by a larger copy instruction, we can't describe the
call site value using the super-register, and we instead need to know
which sub-register that should be used.

This also allows us to handle cases like this:

  $ebx = [...]
  $rdi = MOVSX64rr32 $ebx
  $esi = MOV32rr $edi
  CALL64pcrel32 @call

The hook will first be invoked for the MOV32rr instruction, which will
say that @call's second parameter (passed in $esi) is described by $edi.
As $edi is not preserved it will be added to the worklist. When we get
to the MOVSX64rr32 instruction, we need to describe two values; the
sign-extended value of $ebx -> $rdi for the first parameter, and $ebx ->
$edi for the second parameter, which is now possible.

This commit modifies the dbgcall-site-lea-interpretation.mir test case.
In the test case, the values of some 32-bit parameters were produced
with LEA64r. Perhaps we can in general cases handle such by emitting
expressions that AND out the lower 32-bits, but I have not been able to
land in a case where a LEA64r is used for a 32-bit parameter instead of
LEA64_32 from C code.

I have not found a case where it would be useful to describe parameters
using implicit defines, so in this patch the hook is still only invoked
for explicit defines of forwarding registers.

Added: 
    llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-orr-moves.mir
    llvm/test/DebugInfo/MIR/X86/dbgcall-site-copy-super-sub.mir
    llvm/test/DebugInfo/MIR/X86/dbgcall-site-two-fwd-reg-defs.mir

Modified: 
    llvm/include/llvm/CodeGen/TargetInstrInfo.h
    llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
    llvm/lib/CodeGen/TargetInstrInfo.cpp
    llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
    llvm/lib/Target/AArch64/AArch64InstrInfo.h
    llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
    llvm/lib/Target/ARM/ARMBaseInstrInfo.h
    llvm/lib/Target/X86/X86InstrInfo.cpp
    llvm/lib/Target/X86/X86InstrInfo.h
    llvm/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 7d8386237ca8..dbc48f4546d3 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -72,6 +72,14 @@ struct DestSourcePair {
       : Destination(&Dest), Source(&Src) {}
 };
 
+/// Used to describe a register and immediate addition.
+struct RegImmPair {
+  Register Reg;
+  int64_t Imm;
+
+  RegImmPair(Register Reg, int64_t Imm) : Reg(Reg), Imm(Imm) {}
+};
+
 //---------------------------------------------------------------------------
 ///
 /// TargetInstrInfo - Interface to description of machine instruction set
@@ -950,11 +958,11 @@ class TargetInstrInfo : public MCInstrInfo {
   }
 
   /// If the specific machine instruction is an instruction that adds an
-  /// immediate value to its source operand and stores it in destination,
-  /// return destination and source registers as machine operands along with
-  /// \c Offset which has been added.
-  virtual Optional<DestSourcePair> isAddImmediate(const MachineInstr &MI,
-                                                  int64_t &Offset) const {
+  /// immediate value and a physical register, and stores the result in
+  /// the given physical register \c Reg, return a pair of the source
+  /// register and the offset which has been added.
+  virtual Optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
+                                              Register Reg) const {
     return None;
   }
 
@@ -1789,9 +1797,10 @@ class TargetInstrInfo : public MCInstrInfo {
   }
 
   /// Produce the expression describing the \p MI loading a value into
-  /// the parameter's forwarding register.
-  virtual Optional<ParamLoadedValue>
-  describeLoadedValue(const MachineInstr &MI) const;
+  /// the physical register \p Reg. This hook should only be used with
+  /// \p MIs belonging to VReg-less functions.
+  virtual Optional<ParamLoadedValue> describeLoadedValue(const MachineInstr &MI,
+                                                         Register Reg) const;
 
 private:
   unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 0aa4ae3958eb..89a0e350f8fe 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -595,7 +595,6 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
               Implicit.push_back(FwdReg);
             else
               Explicit.push_back(FwdReg);
-            break;
           }
         }
       }
@@ -640,39 +639,33 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
     for (auto Reg : concat<unsigned>(ExplicitFwdRegDefs, ImplicitFwdRegDefs))
       ForwardedRegWorklist.erase(Reg);
 
-    // The describeLoadedValue() hook currently does not have any information
-    // about which register it should describe in case of multiple defines, so
-    // for now we only handle instructions where a forwarded register is (at
-    // least partially) defined by the instruction's single explicit define.
-    if (I->getNumExplicitDefs() != 1 || ExplicitFwdRegDefs.empty())
-      continue;
-    unsigned ParamFwdReg = ExplicitFwdRegDefs[0];
-
-    if (auto ParamValue = TII->describeLoadedValue(*I)) {
-      if (ParamValue->first.isImm()) {
-        int64_t Val = ParamValue->first.getImm();
-        DbgValueLoc DbgLocVal(ParamValue->second, Val);
-        finishCallSiteParam(DbgLocVal, ParamFwdReg);
-      } else if (ParamValue->first.isReg()) {
-        Register RegLoc = ParamValue->first.getReg();
-       // TODO: For now, there is no use of describing the value loaded into the
-       //       register that is also the source registers (e.g. $r0 = add $r0, x).
-       if (ParamFwdReg == RegLoc)
-         continue;
-
-        unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
-        Register FP = TRI->getFrameRegister(*MF);
-        bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP);
-        if (TRI->isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP) {
-          DbgValueLoc DbgLocVal(ParamValue->second,
-                                MachineLocation(RegLoc,
-                                                /*IsIndirect=*/IsSPorFP));
+    for (auto ParamFwdReg : ExplicitFwdRegDefs) {
+      if (auto ParamValue = TII->describeLoadedValue(*I, ParamFwdReg)) {
+        if (ParamValue->first.isImm()) {
+          int64_t Val = ParamValue->first.getImm();
+          DbgValueLoc DbgLocVal(ParamValue->second, Val);
           finishCallSiteParam(DbgLocVal, ParamFwdReg);
-        // TODO: Add support for entry value plus an expression.
-        } else if (ShouldTryEmitEntryVals &&
-                   ParamValue->second->getNumElements() == 0) {
-          ForwardedRegWorklist.insert(RegLoc);
-          RegsForEntryValues[RegLoc] = ParamFwdReg;
+        } else if (ParamValue->first.isReg()) {
+          Register RegLoc = ParamValue->first.getReg();
+          // TODO: For now, there is no use of describing the value loaded into the
+          //       register that is also the source registers (e.g. $r0 = add $r0, x).
+          if (ParamFwdReg == RegLoc)
+            continue;
+
+          unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
+          Register 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, ParamFwdReg);
+          // TODO: Add support for entry value plus an expression.
+          } else if (ShouldTryEmitEntryVals &&
+                     ParamValue->second->getNumElements() == 0) {
+            ForwardedRegWorklist.insert(RegLoc);
+            RegsForEntryValues[RegLoc] = ParamFwdReg;
+          }
         }
       }
     }

diff  --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index d7a02eb61a2c..5c168f0a3b6f 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -1121,16 +1121,35 @@ bool TargetInstrInfo::hasLowDefLatency(const TargetSchedModel &SchedModel,
 }
 
 Optional<ParamLoadedValue>
-TargetInstrInfo::describeLoadedValue(const MachineInstr &MI) const {
+TargetInstrInfo::describeLoadedValue(const MachineInstr &MI,
+                                     Register Reg) const {
   const MachineFunction *MF = MI.getMF();
+  const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
   DIExpression *Expr = DIExpression::get(MF->getFunction().getContext(), {});
   int64_t Offset;
 
+  // To simplify the sub-register handling, verify that we only need to
+  // consider physical registers.
+  assert(MF->getProperties().hasProperty(
+      MachineFunctionProperties::Property::NoVRegs));
+
   if (auto DestSrc = isCopyInstr(MI)) {
-    return ParamLoadedValue(*DestSrc->Source, Expr);
-  } else if (auto DestSrc = isAddImmediate(MI, Offset)) {
+    Register DestReg = DestSrc->Destination->getReg();
+
+    if (Reg == DestReg)
+      return ParamLoadedValue(*DestSrc->Source, Expr);
+
+    // Cases where super- or sub-registers needs to be described should
+    // be handled by the target's hook implementation.
+    assert(!TRI->isSuperOrSubRegisterEq(Reg, DestReg) &&
+           "TargetInstrInfo::describeLoadedValue can't describe super- or "
+           "sub-regs for copy instructions");
+    return None;
+  } else if (auto RegImm = isAddImmediate(MI, Reg)) {
+    Register SrcReg = RegImm->Reg;
+    Offset = RegImm->Imm;
     Expr = DIExpression::prepend(Expr, DIExpression::ApplyOffset, Offset);
-    return ParamLoadedValue(*DestSrc->Source, Expr);
+    return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
   } else if (MI.hasOneMemOperand()) {
     // Only describe memory which provably does not escape the function. As
     // described in llvm.org/PR43343, escaped memory may be clobbered by the
@@ -1145,11 +1164,15 @@ TargetInstrInfo::describeLoadedValue(const MachineInstr &MI) const {
     if (!PSV || PSV->mayAlias(&MFI))
       return None;
 
-    const auto &TRI = MF->getSubtarget().getRegisterInfo();
     const MachineOperand *BaseOp;
     if (!TII->getMemOperandWithOffset(MI, BaseOp, Offset, TRI))
       return None;
 
+    assert(MI.getNumExplicitDefs() == 1 &&
+           "Can currently only handle mem instructions with a single define");
+
+    // TODO: In what way do we need to take Reg into consideration here?
+
     SmallVector<uint64_t, 8> Ops;
     DIExpression::appendOffset(Ops, Offset);
     Ops.push_back(dwarf::DW_OP_deref_size);

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 15d908d0797e..f952a2f62baa 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -30,6 +30,7 @@
 #include "llvm/CodeGen/StackMaps.h"
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/MC/MCAsmInfo.h"
@@ -6447,10 +6448,16 @@ AArch64InstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
   return None;
 }
 
-Optional<DestSourcePair>
-AArch64InstrInfo::isAddImmediate(const MachineInstr &MI,
-                                 int64_t &Offset) const {
+Optional<RegImmPair> AArch64InstrInfo::isAddImmediate(const MachineInstr &MI,
+                                                      Register Reg) const {
   int Sign = 1;
+  int64_t Offset = 0;
+
+  // TODO: Handle cases where Reg is a super- or sub-register of the
+  // destination register.
+  if (Reg != MI.getOperand(0).getReg())
+    return None;
+
   switch (MI.getOpcode()) {
   default:
     return None;
@@ -6474,14 +6481,60 @@ AArch64InstrInfo::isAddImmediate(const MachineInstr &MI,
     Offset = Offset << Shift;
   }
   }
-  return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
+  return RegImmPair{MI.getOperand(1).getReg(), Offset};
+}
+
+/// If the given ORR instruction is a copy, and \p DescribedReg overlaps with
+/// the destination register then, if possible, describe the value in terms of
+/// the source register.
+static Optional<ParamLoadedValue>
+describeORRLoadedValue(const MachineInstr &MI, Register DescribedReg,
+                       const TargetInstrInfo *TII,
+                       const TargetRegisterInfo *TRI) {
+  auto DestSrc = TII->isCopyInstr(MI);
+  if (!DestSrc)
+    return None;
+
+  Register DestReg = DestSrc->Destination->getReg();
+  Register SrcReg = DestSrc->Source->getReg();
+
+  auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
+
+  // If the described register is the destination, just return the source.
+  if (DestReg == DescribedReg)
+    return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
+
+  // ORRWrs zero-extends to 64-bits, so we need to consider such cases.
+  if (MI.getOpcode() == AArch64::ORRWrs &&
+      TRI->isSuperRegister(DestReg, DescribedReg))
+    return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
+
+  // We may need to describe the lower part of a ORRXrs move.
+  if (MI.getOpcode() == AArch64::ORRXrs &&
+      TRI->isSubRegister(DestReg, DescribedReg)) {
+    Register SrcSubReg = TRI->getSubReg(SrcReg, AArch64::sub_32);
+    return ParamLoadedValue(MachineOperand::CreateReg(SrcSubReg, false), Expr);
+  }
+
+  assert(!TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
+         "Unhandled ORR[XW]rs copy case");
+
+  return None;
 }
 
 Optional<ParamLoadedValue>
-AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI) const {
+AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI,
+                                      Register Reg) const {
+  const MachineFunction *MF = MI.getMF();
+  const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
   switch (MI.getOpcode()) {
   case AArch64::MOVZWi:
-  case AArch64::MOVZXi:
+  case AArch64::MOVZXi: {
+    // MOVZWi may be used for producing zero-extended 32-bit immediates in
+    // 64-bit parameters, so we need to consider super-registers.
+    if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
+      return None;
+
     if (!MI.getOperand(1).isImm())
       return None;
     int64_t Immediate = MI.getOperand(1).getImm();
@@ -6489,7 +6542,12 @@ AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI) const {
     return ParamLoadedValue(MachineOperand::CreateImm(Immediate << Shift),
                             nullptr);
   }
-  return TargetInstrInfo::describeLoadedValue(MI);
+  case AArch64::ORRWrs:
+  case AArch64::ORRXrs:
+    return describeORRLoadedValue(MI, Reg, this, TRI);
+  }
+
+  return TargetInstrInfo::describeLoadedValue(MI, Reg);
 }
 
 #define GET_INSTRINFO_HELPERS

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 136e17d8fff9..c3d27836f39a 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -265,11 +265,11 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
   /// on Windows.
   static bool isSEHInstruction(const MachineInstr &MI);
 
-  Optional<DestSourcePair> isAddImmediate(const MachineInstr &MI,
-                                          int64_t &Offset) const override;
+  Optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
+                                      Register Reg) const override;
 
-  Optional<ParamLoadedValue>
-  describeLoadedValue(const MachineInstr &MI) const override;
+  Optional<ParamLoadedValue> describeLoadedValue(const MachineInstr &MI,
+                                                 Register Reg) const override;
 
 #define GET_INSTRINFO_HELPER_DECLS
 #include "AArch64GenInstrInfo.inc"

diff  --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
index cecc16ffccba..3dcca3922596 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -5328,11 +5328,16 @@ ARMBaseInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
   return makeArrayRef(TargetFlags);
 }
 
-Optional<DestSourcePair>
-ARMBaseInstrInfo::isAddImmediate(const MachineInstr &MI,
-                                 int64_t &Offset) const {
+Optional<RegImmPair> ARMBaseInstrInfo::isAddImmediate(const MachineInstr &MI,
+                                                      Register Reg) const {
   int Sign = 1;
   unsigned Opcode = MI.getOpcode();
+  int64_t Offset = 0;
+
+  // TODO: Handle cases where Reg is a super- or sub-register of the
+  // destination register.
+  if (Reg != MI.getOperand(0).getReg())
+    return None;
 
   // We describe SUBri or ADDri instructions.
   if (Opcode == ARM::SUBri)
@@ -5348,7 +5353,7 @@ ARMBaseInstrInfo::isAddImmediate(const MachineInstr &MI,
     return None;
 
   Offset = MI.getOperand(2).getImm() * Sign;
-  return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
+  return RegImmPair{MI.getOperand(1).getReg(), Offset};
 }
 
 bool llvm::registerDefinedBetween(unsigned Reg,

diff  --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
index 8c231bc908a5..62695a0d7bbc 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -455,8 +455,8 @@ class ARMBaseInstrInfo : public ARMGenInstrInfo {
     return MI.getOperand(3).getReg();
   }
 
-  Optional<DestSourcePair> isAddImmediate(const MachineInstr &MI,
-                                          int64_t &Offset) const override;
+  Optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
+                                      Register Reg) const override;
 };
 
 /// Get the operands corresponding to the given \p Pred value. By default, the

diff  --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 41c6fc4aaf67..7f0058492c94 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -7551,15 +7551,57 @@ bool X86InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst) const {
   }
 }
 
+/// If \p DescribedReg overlaps with the MOVrr instruction's destination
+/// register then, if possible, describe the value in terms of the source
+/// register.
+static Optional<ParamLoadedValue>
+describeMOVrrLoadedValue(const MachineInstr &MI, Register DescribedReg,
+                         const TargetRegisterInfo *TRI) {
+  Register DestReg = MI.getOperand(0).getReg();
+  Register SrcReg = MI.getOperand(1).getReg();
+
+  auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
+
+  // If the described register is the destination, just return the source.
+  if (DestReg == DescribedReg)
+    return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
+
+  // If the described register is a sub-register of the destination register,
+  // then pick out the source register's corresponding sub-register.
+  if (unsigned SubRegIdx = TRI->getSubRegIndex(DestReg, DescribedReg)) {
+    unsigned SrcSubReg = TRI->getSubReg(SrcReg, SubRegIdx);
+    return ParamLoadedValue(MachineOperand::CreateReg(SrcSubReg, false), Expr);
+  }
+
+  // The remaining case to consider is when the described register is a
+  // super-register of the destination register. MOV8rr and MOV16rr does not
+  // write to any of the other bytes in the register, meaning that we'd have to
+  // describe the value using a combination of the source register and the
+  // non-overlapping bits in the described register, which is not currently
+  // possible.
+  if (MI.getOpcode() == X86::MOV8rr || MI.getOpcode() == X86::MOV16rr ||
+      !TRI->isSuperRegister(DestReg, DescribedReg))
+    return None;
+
+  assert(MI.getOpcode() == X86::MOV32rr && "Unexpected super-register case");
+  return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
+}
+
 Optional<ParamLoadedValue>
-X86InstrInfo::describeLoadedValue(const MachineInstr &MI) const {
+X86InstrInfo::describeLoadedValue(const MachineInstr &MI, Register Reg) const {
   const MachineOperand *Op = nullptr;
   DIExpression *Expr = nullptr;
 
+  const TargetRegisterInfo *TRI = &getRegisterInfo();
+
   switch (MI.getOpcode()) {
   case X86::LEA32r:
   case X86::LEA64r:
   case X86::LEA64_32r: {
+    // We may need to describe a 64-bit parameter with a 32-bit LEA.
+    if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
+      return None;
+
     // Operand 4 could be global address. For now we do not support
     // such situation.
     if (!MI.getOperand(4).isImm() || !MI.getOperand(2).isImm())
@@ -7567,7 +7609,6 @@ X86InstrInfo::describeLoadedValue(const MachineInstr &MI) const {
 
     const MachineOperand &Op1 = MI.getOperand(1);
     const MachineOperand &Op2 = MI.getOperand(3);
-    const TargetRegisterInfo *TRI = &getRegisterInfo();
     assert(Op2.isReg() && (Op2.getReg() == X86::NoRegister ||
                            Register::isPhysicalRegister(Op2.getReg())));
 
@@ -7634,15 +7675,53 @@ X86InstrInfo::describeLoadedValue(const MachineInstr &MI) const {
   case X86::MOV32ri:
   case X86::MOV64ri:
   case X86::MOV64ri32:
+    // MOV32ri may be used for producing zero-extended 32-bit immediates in
+    // 64-bit parameters, so we need to consider super-registers.
+    if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
+      return None;
     return ParamLoadedValue(MI.getOperand(1), Expr);
+  case X86::MOV8rr:
+  case X86::MOV16rr:
+  case X86::MOV32rr:
+  case X86::MOV64rr:
+    return describeMOVrrLoadedValue(MI, Reg, TRI);
   case X86::XOR32rr: {
+    // 64-bit parameters are zero-materialized using XOR32rr, so also consider
+    // super-registers.
+    if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
+      return None;
     if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg())
       return ParamLoadedValue(MachineOperand::CreateImm(0), Expr);
     return None;
   }
+  case X86::MOVSX64rr32: {
+    // We may need to describe the lower 32 bits of the MOVSX; for example, in
+    // cases like this:
+    //
+    //  $ebx = [...]
+    //  $rdi = MOVSX64rr32 $ebx
+    //  $esi = MOV32rr $edi
+    if (!TRI->isSubRegisterEq(MI.getOperand(0).getReg(), Reg))
+      return None;
+
+    Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
+
+    // If the described register is the destination register we need to
+    // sign-extend the source register from 32 bits. The other case we handle
+    // is when the described register is the 32-bit sub-register of the
+    // destination register, in case we just need to return the source
+    // register.
+    if (Reg == MI.getOperand(0).getReg())
+      Expr = DIExpression::appendExt(Expr, 32, 64, true);
+    else
+      assert(X86MCRegisterClasses[X86::GR32RegClassID].contains(Reg) &&
+             "Unhandled sub-register case for MOVSX64rr32");
+
+    return ParamLoadedValue(MI.getOperand(1), Expr);
+  }
   default:
     assert(!MI.isMoveImmediate() && "Unexpected MoveImm instruction");
-    return TargetInstrInfo::describeLoadedValue(MI);
+    return TargetInstrInfo::describeLoadedValue(MI, Reg);
   }
 }
 

diff  --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h
index 75e31d194f0e..1d2da5305357 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.h
+++ b/llvm/lib/Target/X86/X86InstrInfo.h
@@ -522,8 +522,8 @@ class X86InstrInfo final : public X86GenInstrInfo {
     return MI.getDesc().TSFlags & X86II::LOCK;
   }
 
-  Optional<ParamLoadedValue>
-  describeLoadedValue(const MachineInstr &MI) const override;
+  Optional<ParamLoadedValue> describeLoadedValue(const MachineInstr &MI,
+                                                 Register Reg) const override;
 
 protected:
   /// Commutes the operands in the given instruction by changing the operands

diff  --git a/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-orr-moves.mir b/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-orr-moves.mir
new file mode 100644
index 000000000000..916a14022ba5
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-orr-moves.mir
@@ -0,0 +1,273 @@
+# RUN: llc -debug-entry-values -start-after=livedebugvalues -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
+
+# Based on the following C reproducer:
+#
+# extern void call_int(int);
+# extern void call_int_int(int, int);
+# extern void call_long(long);
+# extern int global;
+#
+# int same_reg(int p) {
+#   call_int(p);
+#   return 0;
+# }
+#
+# int super_reg(unsigned p) {
+#   call_long(p);
+#   return 0;
+# }
+#
+# int sub_reg(int p, long q) {
+#   call_int_int(q, global);
+#   return p;
+# }
+
+--- |
+  target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+  target triple = "aarch64"
+
+  @global = external global i32, align 4
+
+  ; Function Attrs: noinline nounwind
+  define i32 @same_reg(i32 %p) #0 !dbg !19 {
+  entry:
+    call void @llvm.dbg.value(metadata i32 %p, metadata !23, metadata !DIExpression()), !dbg !24
+    tail call void @call_int(i32 %p), !dbg !25
+    ret i32 0, !dbg !26
+  }
+
+  declare !dbg !4 void @call_int(i32)
+
+  ; Function Attrs: noinline nounwind
+  define i32 @super_reg(i32 %p) #0 !dbg !27 {
+  entry:
+    call void @llvm.dbg.value(metadata i32 %p, metadata !32, metadata !DIExpression()), !dbg !33
+    %conv = zext i32 %p to i64, !dbg !34
+    tail call void @call_long(i64 %conv), !dbg !34
+    ret i32 0, !dbg !35
+  }
+
+  declare !dbg !8 void @call_long(i64)
+
+  ; Function Attrs: noinline nounwind
+  define i32 @sub_reg(i32 returned %p, i64 %q) #0 !dbg !36 {
+  entry:
+    call void @llvm.dbg.value(metadata i32 %p, metadata !40, metadata !DIExpression()), !dbg !42
+    call void @llvm.dbg.value(metadata i64 %q, metadata !41, metadata !DIExpression()), !dbg !42
+    %conv = trunc i64 %q to i32, !dbg !43
+    %0 = load i32, i32* @global, align 4, !dbg !43
+    tail call void @call_int_int(i32 %conv, i32 %0), !dbg !43
+    ret i32 %p, !dbg !44
+  }
+
+  declare !dbg !12 void @call_int_int(i32, i32)
+
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+  attributes #0 = { noinline nounwind  "frame-pointer"="all" }
+  attributes #1 = { nounwind readnone speculatable willreturn }
+
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!15, !16, !17}
+  !llvm.ident = !{!18}
+
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (ssh://gerritmirror.rnd.ki.sw.ericsson.se:29418/flextools/llvm-project.git f76e863b549ddccd5e917e2f3ff50646915654d2)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+  !1 = !DIFile(filename: "orrxrs.c", directory: "/repo/edasten/llvm-project/llvm")
+  !2 = !{}
+  !3 = !{!4, !8, !12}
+  !4 = !DISubprogram(name: "call_int", scope: !1, file: !1, line: 1, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !DISubroutineType(types: !6)
+  !6 = !{null, !7}
+  !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !8 = !DISubprogram(name: "call_long", scope: !1, file: !1, line: 3, type: !9, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !9 = !DISubroutineType(types: !10)
+  !10 = !{null, !11}
+  !11 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
+  !12 = !DISubprogram(name: "call_int_int", scope: !1, file: !1, line: 2, type: !13, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !13 = !DISubroutineType(types: !14)
+  !14 = !{null, !7, !7}
+  !15 = !{i32 2, !"Dwarf Version", i32 4}
+  !16 = !{i32 2, !"Debug Info Version", i32 3}
+  !17 = !{i32 1, !"wchar_size", i32 4}
+  !18 = !{!"clang version 10.0.0 (ssh://gerritmirror.rnd.ki.sw.ericsson.se:29418/flextools/llvm-project.git f76e863b549ddccd5e917e2f3ff50646915654d2)"}
+  !19 = distinct !DISubprogram(name: "same_reg", scope: !1, file: !1, line: 6, type: !20, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !22)
+  !20 = !DISubroutineType(types: !21)
+  !21 = !{!7, !7}
+  !22 = !{!23}
+  !23 = !DILocalVariable(name: "p", arg: 1, scope: !19, file: !1, line: 6, type: !7)
+  !24 = !DILocation(line: 0, scope: !19)
+  !25 = !DILocation(line: 7, scope: !19)
+  !26 = !DILocation(line: 8, scope: !19)
+  !27 = distinct !DISubprogram(name: "super_reg", scope: !1, file: !1, line: 11, type: !28, scopeLine: 11, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !31)
+  !28 = !DISubroutineType(types: !29)
+  !29 = !{!7, !30}
+  !30 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+  !31 = !{!32}
+  !32 = !DILocalVariable(name: "p", arg: 1, scope: !27, file: !1, line: 11, type: !30)
+  !33 = !DILocation(line: 0, scope: !27)
+  !34 = !DILocation(line: 12, scope: !27)
+  !35 = !DILocation(line: 13, scope: !27)
+  !36 = distinct !DISubprogram(name: "sub_reg", scope: !1, file: !1, line: 16, type: !37, scopeLine: 16, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !39)
+  !37 = !DISubroutineType(types: !38)
+  !38 = !{!7, !7, !11}
+  !39 = !{!40, !41}
+  !40 = !DILocalVariable(name: "p", arg: 1, scope: !36, file: !1, line: 16, type: !7)
+  !41 = !DILocalVariable(name: "q", arg: 2, scope: !36, file: !1, line: 16, type: !11)
+  !42 = !DILocation(line: 0, scope: !36)
+  !43 = !DILocation(line: 17, scope: !36)
+  !44 = !DILocation(line: 18, scope: !36)
+
+...
+---
+name:            same_reg
+alignment:       4
+tracksRegLiveness: true
+liveins:
+  - { reg: '$w0' }
+frameInfo:
+  stackSize:       16
+  maxAlignment:    8
+  adjustsStack:    true
+  hasCalls:        true
+  maxCallFrameSize: 0
+stack:
+  - { id: 0, type: spill-slot, offset: -8, size: 8, alignment: 8, callee-saved-register: '$lr' }
+  - { id: 1, type: spill-slot, offset: -16, size: 8, alignment: 8, callee-saved-register: '$fp' }
+callSites:
+  - { bb: 0, offset: 8, fwdArgRegs:
+      - { arg: 0, reg: '$w0' } }
+machineFunctionInfo: {}
+body:             |
+  bb.0.entry:
+    liveins: $w0, $lr
+
+    DBG_VALUE $w0, $noreg, !23, !DIExpression(), debug-location !24
+    DBG_VALUE $w0, $noreg, !23, !DIExpression(), debug-location !24
+    DBG_VALUE $w0, $noreg, !23, !DIExpression(), debug-location !24
+    early-clobber $sp = frame-setup STPXpre $fp, killed $lr, $sp, -2 :: (store 8 into %stack.1), (store 8 into %stack.0)
+    $fp = frame-setup ADDXri $sp, 0, 0
+    frame-setup CFI_INSTRUCTION def_cfa $w29, 16
+    frame-setup CFI_INSTRUCTION offset $w30, -8, debug-location !25
+    frame-setup CFI_INSTRUCTION offset $w29, -16, debug-location !25
+    BL @call_int, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, debug-location !25
+    DBG_VALUE $w0, $noreg, !23, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !24
+    $w0 = ORRWrs $wzr, $wzr, 0, debug-location !26
+    early-clobber $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2, debug-location !26 :: (load 8 from %stack.1), (load 8 from %stack.0)
+    RET undef $lr, implicit killed $w0, debug-location !26
+
+...
+
+# CHECK: DW_TAG_GNU_call_site
+# CHECK-NEXT: DW_AT_abstract_origin (0x0000002a "call_int")
+#
+# CHECK: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg0 W0)
+# CHECK-NEXT: DW_AT_GNU_call_site_value   (DW_OP_GNU_entry_value(DW_OP_reg0 W0))
+
+---
+name:            super_reg
+alignment:       4
+tracksRegLiveness: true
+liveins:
+  - { reg: '$w0' }
+frameInfo:
+  stackSize:       16
+  maxAlignment:    8
+  adjustsStack:    true
+  hasCalls:        true
+  maxCallFrameSize: 0
+stack:
+  - { id: 0, type: spill-slot, offset: -8, size: 8, alignment: 8, callee-saved-register: '$lr' }
+  - { id: 1, type: spill-slot, offset: -16, size: 8, alignment: 8, callee-saved-register: '$fp' }
+callSites:
+  - { bb: 0, offset: 9, fwdArgRegs:
+      - { arg: 0, reg: '$x0' } }
+machineFunctionInfo: {}
+body:             |
+  bb.0.entry:
+    liveins: $w0, $lr
+
+    DBG_VALUE $w0, $noreg, !32, !DIExpression(), debug-location !33
+    DBG_VALUE $w0, $noreg, !32, !DIExpression(), debug-location !33
+    early-clobber $sp = frame-setup STPXpre $fp, killed $lr, $sp, -2 :: (store 8 into %stack.1), (store 8 into %stack.0)
+    $fp = frame-setup ADDXri $sp, 0, 0
+    frame-setup CFI_INSTRUCTION def_cfa $w29, 16
+    frame-setup CFI_INSTRUCTION offset $w30, -8, debug-location !34
+    frame-setup CFI_INSTRUCTION offset $w29, -16, debug-location !34
+    renamable $w0 = ORRWrs $wzr, killed renamable $w0, 0, implicit-def $x0, debug-location !34
+    DBG_VALUE $w0, $noreg, !32, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !33
+    BL @call_long, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $x0, implicit-def $sp, debug-location !34
+    $w0 = ORRWrs $wzr, $wzr, 0, debug-location !35
+    early-clobber $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2, debug-location !35 :: (load 8 from %stack.1), (load 8 from %stack.0)
+    RET undef $lr, implicit killed $w0, debug-location !35
+
+...
+
+# CHECK: DW_TAG_GNU_call_site
+# CHECK-NEXT: DW_AT_abstract_origin (0x0000003e "call_long")
+#
+# CHECK: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg0 W0)
+# CHECK-NEXT: DW_AT_GNU_call_site_value   (DW_OP_GNU_entry_value(DW_OP_reg0 W0))
+
+---
+name:            sub_reg
+alignment:       4
+tracksRegLiveness: true
+liveins:
+  - { reg: '$w0' }
+  - { reg: '$x1' }
+frameInfo:
+  stackSize:       32
+  maxAlignment:    16
+  adjustsStack:    true
+  hasCalls:        true
+  maxCallFrameSize: 0
+stack:
+  - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16, callee-saved-register: '$x19' }
+  - { id: 1, type: spill-slot, offset: -24, size: 8, alignment: 8, callee-saved-register: '$lr' }
+  - { id: 2, type: spill-slot, offset: -32, size: 8, alignment: 8, callee-saved-register: '$fp' }
+callSites:
+  - { bb: 0, offset: 17, fwdArgRegs:
+      - { arg: 0, reg: '$w0' }
+      - { arg: 1, reg: '$w1' } }
+machineFunctionInfo: {}
+body:             |
+  bb.0.entry:
+    liveins: $w0, $x1, $lr, $x19
+
+    DBG_VALUE $w0, $noreg, !40, !DIExpression(), debug-location !42
+    DBG_VALUE $x1, $noreg, !41, !DIExpression(), debug-location !42
+    early-clobber $sp = frame-setup STPXpre $fp, killed $lr, $sp, -4 :: (store 8 into %stack.2), (store 8 into %stack.1)
+    frame-setup STRXui killed $x19, $sp, 2 :: (store 8 into %stack.0)
+    $fp = frame-setup ADDXri $sp, 0, 0
+    frame-setup CFI_INSTRUCTION def_cfa $w29, 32
+    frame-setup CFI_INSTRUCTION offset $w19, -16
+    frame-setup CFI_INSTRUCTION offset $w30, -24
+    frame-setup CFI_INSTRUCTION offset $w29, -32
+    renamable $x9 = ADRP target-flags(aarch64-page) @global, debug-location !43
+    $x8 = ORRXrs $xzr, killed $x1, 0
+    DBG_VALUE $x8, $noreg, !41, !DIExpression(), debug-location !42
+    renamable $w1 = LDRWui killed renamable $x9, target-flags(aarch64-pageoff, aarch64-nc) @global, debug-location !43 :: (dereferenceable load 4 from @global)
+    $w19 = ORRWrs $wzr, killed $w0, 0
+    DBG_VALUE $w19, $noreg, !40, !DIExpression(), debug-location !42
+    DBG_VALUE $w19, $noreg, !40, !DIExpression(), debug-location !42
+    $w0 = ORRWrs $wzr, killed $w8, 0, implicit $x8, debug-location !43
+    BL @call_int_int, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit-def $sp, debug-location !43
+    DBG_VALUE $x1, $noreg, !41, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !42
+    $w0 = ORRWrs $wzr, killed $w19, 0, debug-location !44
+    DBG_VALUE $w0, $noreg, !40, !DIExpression(), debug-location !42
+    $x19 = frame-destroy LDRXui $sp, 2, debug-location !44 :: (load 8 from %stack.0)
+    early-clobber $sp, $fp, $lr = frame-destroy LDPXpost $sp, 4, debug-location !44 :: (load 8 from %stack.2), (load 8 from %stack.1)
+    RET undef $lr, implicit killed $w0, debug-location !44
+
+...
+
+# CHECK: DW_TAG_GNU_call_site
+# CHECK-NEXT: DW_AT_abstract_origin (0x00000052 "call_int_int")
+#
+# CHECK: DW_TAG_GNU_call_site_parameter
+# FIXME: The DW_AT_location attribute should actually refer to W0! See PR44118.
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg8 W8)
+# CHECK-NEXT: DW_AT_GNU_call_site_value   (DW_OP_GNU_entry_value(DW_OP_reg1 W1))

diff  --git a/llvm/test/DebugInfo/MIR/X86/dbgcall-site-copy-super-sub.mir b/llvm/test/DebugInfo/MIR/X86/dbgcall-site-copy-super-sub.mir
new file mode 100644
index 000000000000..a2d51a203512
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/X86/dbgcall-site-copy-super-sub.mir
@@ -0,0 +1,118 @@
+# RUN: llc -debug-entry-values -start-after=livedebugvalues -filetype=obj %s -o -| llvm-dwarfdump -| FileCheck %s
+
+# Based on the following reproducer:
+#
+# #include <stdint.h>
+#
+# extern uint32_t value32(void);
+# extern uint64_t value64(void);
+# extern void call32(uint32_t);
+# extern void call64(uint64_t);
+#
+# uint32_t test_sub_reg() {
+#   uint32_t local = value32();
+#   call64(local);
+#   return local;
+# }
+
+--- |
+  ; ModuleID = 'ext.c'
+  source_filename = "ext.c"
+  target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-unknown-linux-gnu"
+
+  ; Function Attrs: minsize nounwind optsize uwtable
+  define i32 @test_sub_reg() #0 !dbg !22 {
+  entry:
+    %call = tail call i32 @value32(), !dbg !29
+    call void @llvm.dbg.value(metadata i32 %call, metadata !28, metadata !DIExpression()), !dbg !30
+    %conv = zext i32 %call to i64, !dbg !31
+    tail call void @call64(i64 %conv), !dbg !31
+    ret i32 %call, !dbg !32
+  }
+
+  declare !dbg !4 i32 @value32()
+
+  declare !dbg !8 void @call64(i64)
+
+  declare !dbg !12 i64 @value64()
+
+  declare !dbg !15 void @call32(i32)
+
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+  attributes #0 = { minsize nounwind optsize uwtable }
+  attributes #1 = { nounwind readnone speculatable willreturn }
+
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!18, !19, !20}
+  !llvm.ident = !{!21}
+
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+  !1 = !DIFile(filename: "ext.c", directory: "/")
+  !2 = !{}
+  !3 = !{!4, !8, !12, !15}
+  !4 = !DISubprogram(name: "value32", scope: !1, file: !1, line: 3, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !DISubroutineType(types: !6)
+  !6 = !{!7}
+  !7 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+  !8 = !DISubprogram(name: "call64", scope: !1, file: !1, line: 6, type: !9, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !9 = !DISubroutineType(types: !10)
+  !10 = !{null, !11}
+  !11 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned)
+  !12 = !DISubprogram(name: "value64", scope: !1, file: !1, line: 4, type: !13, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !13 = !DISubroutineType(types: !14)
+  !14 = !{!11}
+  !15 = !DISubprogram(name: "call32", scope: !1, file: !1, line: 5, type: !16, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !16 = !DISubroutineType(types: !17)
+  !17 = !{null, !7}
+  !18 = !{i32 2, !"Dwarf Version", i32 4}
+  !19 = !{i32 2, !"Debug Info Version", i32 3}
+  !20 = !{i32 1, !"wchar_size", i32 4}
+  !21 = !{!"clang version 10.0.0"}
+  !22 = distinct !DISubprogram(name: "test_sub_reg", scope: !1, file: !1, line: 8, type: !23, scopeLine: 8, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !27)
+  !23 = !DISubroutineType(types: !24)
+  !24 = !{!25}
+  !25 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint32_t", file: !26, line: 52, baseType: !7)
+  !26 = !DIFile(filename: "/usr/include/stdint.h", directory: "")
+  !27 = !{!28}
+  !28 = !DILocalVariable(name: "local", scope: !22, file: !1, line: 9, type: !25)
+  !29 = !DILocation(line: 9, scope: !22)
+  !30 = !DILocation(line: 0, scope: !22)
+  !31 = !DILocation(line: 10, scope: !22)
+  !32 = !DILocation(line: 11, scope: !22)
+
+...
+---
+name:            test_sub_reg
+tracksRegLiveness: true
+callSites:
+  - { bb: 0, offset: 3 }
+  - { bb: 0, offset: 7, fwdArgRegs:
+      - { arg: 0, reg: '$rdi' } }
+body:             |
+  bb.0.entry:
+    liveins: $rbx
+
+    frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp, debug-location !29
+    CFI_INSTRUCTION def_cfa_offset 16
+    CFI_INSTRUCTION offset $rbx, -16
+    CALL64pcrel32 @value32, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !29
+    $ebx = MOV32rr $eax, debug-location !29
+    DBG_VALUE $ebx, $noreg, !28, !DIExpression(), debug-location !30
+    renamable $edi = MOV32rr $ebx, implicit-def $rdi, debug-location !31
+    CALL64pcrel32 @call64, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, debug-location !31
+    $eax = MOV32rr killed $ebx, debug-location !32
+    $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !32
+    CFI_INSTRUCTION def_cfa_offset 8, debug-location !32
+    RETQ killed $eax, debug-location !32
+
+...
+
+# Verify that a call site value is emitted for the 64-bit parameter that is
+# loaded using the zero-extending MOV32rr.
+
+# 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_breg3 RBX+0)

diff  --git a/llvm/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir b/llvm/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir
index 008dece20016..1bb70f6d4530 100644
--- a/llvm/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir
+++ b/llvm/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir
@@ -121,11 +121,11 @@ body:             |
     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 $edi = LEA64_32r $r14, 2, $r15, 4, $noreg
+    renamable $esi = LEA64_32r $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
+    renamable $r9d = LEA64_32r  $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

diff  --git a/llvm/test/DebugInfo/MIR/X86/dbgcall-site-two-fwd-reg-defs.mir b/llvm/test/DebugInfo/MIR/X86/dbgcall-site-two-fwd-reg-defs.mir
new file mode 100644
index 000000000000..db0934c595c3
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/X86/dbgcall-site-two-fwd-reg-defs.mir
@@ -0,0 +1,141 @@
+# RUN: llc -O1 -debug-entry-values -start-after=livedebugvalues -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s
+
+# Based on the following C reproducer:
+#
+# extern void call(long, int);
+# extern int a, b, c, d;
+#
+# int e() { return a; }
+#
+# int main() {
+#   d = c;
+#   b = e();
+#   call(c, c);
+#   return 0;
+# }
+
+--- |
+  target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64"
+
+  @a = external global i32, align 4
+  @c = external global i32, align 4
+  @d = external global i32, align 4
+  @b = external global i32, align 4
+
+  ; Function Attrs: noinline norecurse nounwind readonly
+  define i32 @e() #0 !dbg !13 {
+  entry:
+    %0 = load i32, i32* @a, align 4, !dbg !16
+    ret i32 %0, !dbg !16
+  }
+
+  ; Function Attrs: noinline nounwind
+  define i32 @main() #1 !dbg !17 {
+  entry:
+    %0 = load i32, i32* @c, align 4, !dbg !19
+    store i32 %0, i32* @d, align 4, !dbg !19
+    %call = tail call i32 @e(), !dbg !20
+    store i32 %call, i32* @b, align 4, !dbg !20
+    %conv = sext i32 %0 to i64, !dbg !21
+    tail call void @call(i64 %conv, i32 %0), !dbg !21
+    ret i32 0, !dbg !22
+  }
+
+  declare !dbg !4 void @call(i64, i32)
+
+  attributes #0 = { noinline norecurse nounwind readonly "frame-pointer"="all" }
+  attributes #1 = { noinline nounwind "frame-pointer"="all" }
+
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!9, !10, !11}
+  !llvm.ident = !{!12}
+
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+  !1 = !DIFile(filename: "x86_two_defs.c", directory: "/")
+  !2 = !{}
+  !3 = !{!4}
+  !4 = !DISubprogram(name: "call", scope: !1, file: !1, line: 1, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !DISubroutineType(types: !6)
+  !6 = !{null, !7, !8}
+  !7 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
+  !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !9 = !{i32 2, !"Dwarf Version", i32 5}
+  !10 = !{i32 2, !"Debug Info Version", i32 3}
+  !11 = !{i32 1, !"wchar_size", i32 4}
+  !12 = !{!"clang version 10.0.0"}
+  !13 = distinct !DISubprogram(name: "e", scope: !1, file: !1, line: 5, type: !14, scopeLine: 5, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
+  !14 = !DISubroutineType(types: !15)
+  !15 = !{!8}
+  !16 = !DILocation(line: 6, scope: !13)
+  !17 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 9, type: !14, scopeLine: 9, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
+  !19 = !DILocation(line: 10, scope: !17)
+  !20 = !DILocation(line: 11, scope: !17)
+  !21 = !DILocation(line: 12, scope: !17)
+  !22 = !DILocation(line: 13, scope: !17)
+
+...
+---
+name:            e
+tracksRegLiveness: true
+body:             |
+  bb.0.entry:
+    frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION def_cfa_offset 16
+    CFI_INSTRUCTION offset $rbp, -16
+    $rbp = frame-setup MOV64rr $rsp
+    CFI_INSTRUCTION def_cfa_register $rbp
+    renamable $eax = MOV32rm $rip, 1, $noreg, @a, $noreg, debug-location !16 :: (dereferenceable load 4 from @a)
+    $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !16
+    CFI_INSTRUCTION def_cfa $rsp, 8, debug-location !16
+    RETQ $eax, debug-location !16
+
+...
+---
+name:            main
+tracksRegLiveness: true
+callSites:
+  - { bb: 0, offset: 10 }
+  - { bb: 0, offset: 14, fwdArgRegs:
+      - { arg: 0, reg: '$rdi' }
+      - { arg: 1, reg: '$esi' } }
+body:             |
+  bb.0.entry:
+    liveins: $rbx
+
+    frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION def_cfa_offset 16
+    CFI_INSTRUCTION offset $rbp, -16
+    $rbp = frame-setup MOV64rr $rsp
+    CFI_INSTRUCTION def_cfa_register $rbp
+    frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp, debug-location !19
+    frame-setup PUSH64r undef $rax, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION offset $rbx, -24
+    renamable $ebx = MOV32rm $rip, 1, $noreg, @c, $noreg, debug-location !19 :: (dereferenceable load 4 from @c)
+    MOV32mr $rip, 1, $noreg, @d, $noreg, renamable $ebx, debug-location !19 :: (store 4 into @d)
+    CALL64pcrel32 @e, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !20
+    MOV32mr $rip, 1, $noreg, @b, $noreg, killed renamable $eax, debug-location !20 :: (store 4 into @b)
+    renamable $rdi = MOVSX64rr32 killed renamable $ebx, debug-location !21
+    $esi = MOV32rr $edi, debug-location !21
+    CALL64pcrel32 @call, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit killed $esi, implicit-def $rsp, implicit-def $ssp, debug-location !21
+    $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, debug-location !22
+    $rsp = frame-destroy ADD64ri8 $rsp, 8, implicit-def dead $eflags, debug-location !22
+    $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !22
+    $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !22
+    CFI_INSTRUCTION def_cfa $rsp, 8, debug-location !22
+    RETQ $eax, debug-location !22
+
+...
+
+# Verify that call site entries are emitted for both parameters in the call to
+# %call. Both parameters should be described by the preserved $ebx register,
+# and the value for the first parameter (passed in $rdi) should be
+# sign-extended to 64 bits.
+
+# CHECK: DW_TAG_call_site_parameter
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg4 RSI)
+# CHECK-NEXT: DW_AT_call_value    (DW_OP_breg3 RBX+0)
+
+# CHECK: DW_TAG_call_site_parameter
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg5 RDI)
+# CHECK-NEXT: DW_AT_call_value    (DW_OP_breg3 RBX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_convert ({{.*}}) "DW_ATE_signed_32", DW_OP_convert ({{.*}}) "DW_ATE_signed_64")


        


More information about the llvm-commits mailing list