summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/ARM/ARMBaseInstrInfo.h3
-rw-r--r--llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp27
-rw-r--r--llvm/lib/Target/ARM/Thumb2InstrInfo.cpp25
3 files changed, 42 insertions, 13 deletions
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
index c28983fcc15..6e9385e8f42 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -601,7 +601,8 @@ bool rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
bool rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
unsigned FrameReg, int &Offset,
- const ARMBaseInstrInfo &TII);
+ const ARMBaseInstrInfo &TII,
+ const TargetRegisterInfo *TRI);
/// Return true if Reg is defd between From and To
bool registerDefinedBetween(unsigned Reg, MachineBasicBlock::iterator From,
diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index 2fcbd7ecf6b..133d3eaf0ed 100644
--- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -669,7 +669,7 @@ void ARMBaseRegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg,
Done = rewriteARMFrameIndex(MI, i, BaseReg, Off, TII);
else {
assert(AFI->isThumb2Function());
- Done = rewriteT2FrameIndex(MI, i, BaseReg, Off, TII);
+ Done = rewriteT2FrameIndex(MI, i, BaseReg, Off, TII, this);
}
assert(Done && "Unable to resolve frame index!");
(void)Done;
@@ -781,7 +781,7 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
Done = rewriteARMFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII);
else {
assert(AFI->isThumb2Function());
- Done = rewriteT2FrameIndex(MI, FIOperandNum, FrameReg, Offset, TII);
+ Done = rewriteT2FrameIndex(MI, FIOperandNum, FrameReg, Offset, TII, this);
}
if (Done)
return;
@@ -789,21 +789,32 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
// If we get here, the immediate doesn't fit into the instruction. We folded
// as much as possible above, handle the rest, providing a register that is
// SP+LargeImm.
- assert((Offset ||
- (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrMode4 ||
- (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrMode6) &&
- "This code isn't needed if offset already handled!");
+ assert(
+ (Offset ||
+ (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrMode4 ||
+ (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrMode6 ||
+ (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrModeT2_i7 ||
+ (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrModeT2_i7s2 ||
+ (MI.getDesc().TSFlags & ARMII::AddrModeMask) ==
+ ARMII::AddrModeT2_i7s4) &&
+ "This code isn't needed if offset already handled!");
unsigned ScratchReg = 0;
int PIdx = MI.findFirstPredOperandIdx();
ARMCC::CondCodes Pred = (PIdx == -1)
? ARMCC::AL : (ARMCC::CondCodes)MI.getOperand(PIdx).getImm();
Register PredReg = (PIdx == -1) ? Register() : MI.getOperand(PIdx+1).getReg();
- if (Offset == 0)
+
+ const MCInstrDesc &MCID = MI.getDesc();
+ const TargetRegisterClass *RegClass =
+ TII.getRegClass(MCID, FIOperandNum, this, *MI.getParent()->getParent());
+
+ if (Offset == 0 &&
+ (Register::isVirtualRegister(FrameReg) || RegClass->contains(FrameReg)))
// Must be addrmode4/6.
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, false);
else {
- ScratchReg = MF.getRegInfo().createVirtualRegister(&ARM::GPRRegClass);
+ ScratchReg = MF.getRegInfo().createVirtualRegister(RegClass);
if (!AFI->isThumbFunction())
emitARMRegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg,
Offset, Pred, PredReg, TII);
diff --git a/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp b/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
index eae72810897..fa7fe9932cc 100644
--- a/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
+++ b/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
@@ -470,12 +470,17 @@ immediateOffsetOpcode(unsigned opcode)
bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
unsigned FrameReg, int &Offset,
- const ARMBaseInstrInfo &TII) {
+ const ARMBaseInstrInfo &TII,
+ const TargetRegisterInfo *TRI) {
unsigned Opcode = MI.getOpcode();
const MCInstrDesc &Desc = MI.getDesc();
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
bool isSub = false;
+ MachineFunction &MF = *MI.getParent()->getParent();
+ const TargetRegisterClass *RegClass =
+ TII.getRegClass(Desc, FrameRegIdx, TRI, MF);
+
// Memory operands in inline assembly always use AddrModeT2_i12.
if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
@@ -645,10 +650,21 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
// Attempt to fold address computation
- // Common case: small offset, fits into instruction.
+ // Common case: small offset, fits into instruction. We need to make sure
+ // the register class is correct too, for instructions like the MVE
+ // VLDRH.32, which only accepts low tGPR registers.
int ImmedOffset = Offset / Scale;
unsigned Mask = (1 << NumBits) - 1;
- if ((unsigned)Offset <= Mask * Scale) {
+ if ((unsigned)Offset <= Mask * Scale &&
+ (Register::isVirtualRegister(FrameReg) ||
+ RegClass->contains(FrameReg))) {
+ if (Register::isVirtualRegister(FrameReg)) {
+ // Make sure the register class for the virtual register is correct
+ MachineRegisterInfo *MRI = &MF.getRegInfo();
+ if (!MRI->constrainRegClass(FrameReg, RegClass))
+ llvm_unreachable("Unable to constrain virtual register class.");
+ }
+
// Replace the FrameIndex with fp/sp
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
if (isSub) {
@@ -681,7 +697,8 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
}
Offset = (isSub) ? -Offset : Offset;
- return Offset == 0;
+ return Offset == 0 && (Register::isVirtualRegister(FrameReg) ||
+ RegClass->contains(FrameReg));
}
ARMCC::CondCodes llvm::getITInstrPredicate(const MachineInstr &MI,
OpenPOWER on IntegriCloud