diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 59 | ||||
-rw-r--r-- | llvm/lib/CodeGen/TargetInstrInfo.cpp | 33 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 72 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.h | 8 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMBaseInstrInfo.h | 4 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.cpp | 85 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.h | 4 |
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 |