forked from OSchip/llvm-project
Revert "[DebugInfo] Make describeLoadedValue() reg aware"
This reverts commit 3cd93a4efc
.
I'll recommit with a well-formatted arcanist commit message.
This commit is contained in:
parent
3cd93a4efc
commit
f3696533f2
|
@ -72,14 +72,6 @@ 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
|
||||
|
@ -958,11 +950,11 @@ public:
|
|||
}
|
||||
|
||||
/// If the specific machine instruction is an instruction that adds an
|
||||
/// 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 {
|
||||
/// 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 {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -1797,10 +1789,9 @@ public:
|
|||
}
|
||||
|
||||
/// Produce the expression describing the \p MI loading a value into
|
||||
/// 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;
|
||||
/// the parameter's forwarding register.
|
||||
virtual Optional<ParamLoadedValue>
|
||||
describeLoadedValue(const MachineInstr &MI) const;
|
||||
|
||||
private:
|
||||
unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;
|
||||
|
|
|
@ -595,6 +595,7 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
|
|||
Implicit.push_back(FwdReg);
|
||||
else
|
||||
Explicit.push_back(FwdReg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -639,33 +640,39 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
|
|||
for (auto Reg : concat<unsigned>(ExplicitFwdRegDefs, ImplicitFwdRegDefs))
|
||||
ForwardedRegWorklist.erase(Reg);
|
||||
|
||||
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);
|
||||
} 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;
|
||||
// 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];
|
||||
|
||||
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;
|
||||
}
|
||||
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));
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1121,35 +1121,16 @@ bool TargetInstrInfo::hasLowDefLatency(const TargetSchedModel &SchedModel,
|
|||
}
|
||||
|
||||
Optional<ParamLoadedValue>
|
||||
TargetInstrInfo::describeLoadedValue(const MachineInstr &MI,
|
||||
Register Reg) const {
|
||||
TargetInstrInfo::describeLoadedValue(const MachineInstr &MI) 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)) {
|
||||
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;
|
||||
return ParamLoadedValue(*DestSrc->Source, Expr);
|
||||
} else if (auto DestSrc = isAddImmediate(MI, Offset)) {
|
||||
Expr = DIExpression::prepend(Expr, DIExpression::ApplyOffset, Offset);
|
||||
return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
|
||||
return ParamLoadedValue(*DestSrc->Source, 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
|
||||
|
@ -1164,15 +1145,11 @@ TargetInstrInfo::describeLoadedValue(const MachineInstr &MI,
|
|||
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);
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#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"
|
||||
|
@ -6448,16 +6447,10 @@ AArch64InstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
|
|||
return None;
|
||||
}
|
||||
|
||||
Optional<RegImmPair> AArch64InstrInfo::isAddImmediate(const MachineInstr &MI,
|
||||
Register Reg) const {
|
||||
Optional<DestSourcePair>
|
||||
AArch64InstrInfo::isAddImmediate(const MachineInstr &MI,
|
||||
int64_t &Offset) 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;
|
||||
|
@ -6481,60 +6474,14 @@ Optional<RegImmPair> AArch64InstrInfo::isAddImmediate(const MachineInstr &MI,
|
|||
Offset = Offset << Shift;
|
||||
}
|
||||
}
|
||||
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;
|
||||
return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
|
||||
}
|
||||
|
||||
Optional<ParamLoadedValue>
|
||||
AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI,
|
||||
Register Reg) const {
|
||||
const MachineFunction *MF = MI.getMF();
|
||||
const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
|
||||
AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI) const {
|
||||
switch (MI.getOpcode()) {
|
||||
case AArch64::MOVZWi:
|
||||
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;
|
||||
|
||||
case AArch64::MOVZXi:
|
||||
if (!MI.getOperand(1).isImm())
|
||||
return None;
|
||||
int64_t Immediate = MI.getOperand(1).getImm();
|
||||
|
@ -6542,12 +6489,7 @@ AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI,
|
|||
return ParamLoadedValue(MachineOperand::CreateImm(Immediate << Shift),
|
||||
nullptr);
|
||||
}
|
||||
case AArch64::ORRWrs:
|
||||
case AArch64::ORRXrs:
|
||||
return describeORRLoadedValue(MI, Reg, this, TRI);
|
||||
}
|
||||
|
||||
return TargetInstrInfo::describeLoadedValue(MI, Reg);
|
||||
return TargetInstrInfo::describeLoadedValue(MI);
|
||||
}
|
||||
|
||||
#define GET_INSTRINFO_HELPERS
|
||||
|
|
|
@ -265,11 +265,11 @@ public:
|
|||
/// on Windows.
|
||||
static bool isSEHInstruction(const MachineInstr &MI);
|
||||
|
||||
Optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
|
||||
Register Reg) const override;
|
||||
Optional<DestSourcePair> isAddImmediate(const MachineInstr &MI,
|
||||
int64_t &Offset) const override;
|
||||
|
||||
Optional<ParamLoadedValue> describeLoadedValue(const MachineInstr &MI,
|
||||
Register Reg) const override;
|
||||
Optional<ParamLoadedValue>
|
||||
describeLoadedValue(const MachineInstr &MI) const override;
|
||||
|
||||
#define GET_INSTRINFO_HELPER_DECLS
|
||||
#include "AArch64GenInstrInfo.inc"
|
||||
|
|
|
@ -5328,16 +5328,11 @@ ARMBaseInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
|
|||
return makeArrayRef(TargetFlags);
|
||||
}
|
||||
|
||||
Optional<RegImmPair> ARMBaseInstrInfo::isAddImmediate(const MachineInstr &MI,
|
||||
Register Reg) const {
|
||||
Optional<DestSourcePair>
|
||||
ARMBaseInstrInfo::isAddImmediate(const MachineInstr &MI,
|
||||
int64_t &Offset) 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)
|
||||
|
@ -5353,7 +5348,7 @@ Optional<RegImmPair> ARMBaseInstrInfo::isAddImmediate(const MachineInstr &MI,
|
|||
return None;
|
||||
|
||||
Offset = MI.getOperand(2).getImm() * Sign;
|
||||
return RegImmPair{MI.getOperand(1).getReg(), Offset};
|
||||
return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
|
||||
}
|
||||
|
||||
bool llvm::registerDefinedBetween(unsigned Reg,
|
||||
|
|
|
@ -455,8 +455,8 @@ public:
|
|||
return MI.getOperand(3).getReg();
|
||||
}
|
||||
|
||||
Optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
|
||||
Register Reg) const override;
|
||||
Optional<DestSourcePair> isAddImmediate(const MachineInstr &MI,
|
||||
int64_t &Offset) const override;
|
||||
};
|
||||
|
||||
/// Get the operands corresponding to the given \p Pred value. By default, the
|
||||
|
|
|
@ -7551,57 +7551,15 @@ 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, Register Reg) const {
|
||||
X86InstrInfo::describeLoadedValue(const MachineInstr &MI) 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())
|
||||
|
@ -7609,6 +7567,7 @@ X86InstrInfo::describeLoadedValue(const MachineInstr &MI, Register Reg) 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())));
|
||||
|
||||
|
@ -7675,53 +7634,15 @@ X86InstrInfo::describeLoadedValue(const MachineInstr &MI, Register Reg) 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, Reg);
|
||||
return TargetInstrInfo::describeLoadedValue(MI);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -522,8 +522,8 @@ public:
|
|||
return MI.getDesc().TSFlags & X86II::LOCK;
|
||||
}
|
||||
|
||||
Optional<ParamLoadedValue> describeLoadedValue(const MachineInstr &MI,
|
||||
Register Reg) const override;
|
||||
Optional<ParamLoadedValue>
|
||||
describeLoadedValue(const MachineInstr &MI) const override;
|
||||
|
||||
protected:
|
||||
/// Commutes the operands in the given instruction by changing the operands
|
||||
|
|
|
@ -1,273 +0,0 @@
|
|||
# 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))
|
|
@ -1,118 +0,0 @@
|
|||
# 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)
|
|
@ -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 $edi = LEA64_32r $r14, 2, $r15, 4, $noreg
|
||||
renamable $esi = LEA64_32r $r14, 1, $noreg, 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 $r9d = LEA64_32r $noreg, 1, $r15, 10, $noreg, implicit-def $r9d
|
||||
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
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
# 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")
|
Loading…
Reference in New Issue