summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp59
-rw-r--r--llvm/lib/CodeGen/TargetInstrInfo.cpp33
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrInfo.cpp72
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrInfo.h8
-rw-r--r--llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp13
-rw-r--r--llvm/lib/Target/ARM/ARMBaseInstrInfo.h4
-rw-r--r--llvm/lib/Target/X86/X86InstrInfo.cpp85
-rw-r--r--llvm/lib/Target/X86/X86InstrInfo.h4
8 files changed, 218 insertions, 60 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 0aa4ae3958e..89a0e350f8f 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 d7a02eb61a2..5c168f0a3b6 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 15d908d0797..f952a2f62ba 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 136e17d8fff..c3d27836f39 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -265,11 +265,11 @@ public:
/// 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 cecc16ffccb..3dcca392259 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 8c231bc908a..62695a0d7bb 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -455,8 +455,8 @@ public:
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 41c6fc4aaf6..7f0058492c9 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 75e31d194f0..1d2da530535 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.h
+++ b/llvm/lib/Target/X86/X86InstrInfo.h
@@ -522,8 +522,8 @@ public:
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
OpenPOWER on IntegriCloud