summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86InstrInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/X86InstrInfo.cpp')
-rw-r--r--llvm/lib/Target/X86/X86InstrInfo.cpp85
1 files changed, 82 insertions, 3 deletions
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);
}
}
OpenPOWER on IntegriCloud