diff options
Diffstat (limited to 'lib/Target/Mips/MipsSERegisterInfo.cpp')
| -rw-r--r-- | lib/Target/Mips/MipsSERegisterInfo.cpp | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/lib/Target/Mips/MipsSERegisterInfo.cpp b/lib/Target/Mips/MipsSERegisterInfo.cpp index 2d440840aaff..0af1a6b9e5c3 100644 --- a/lib/Target/Mips/MipsSERegisterInfo.cpp +++ b/lib/Target/Mips/MipsSERegisterInfo.cpp @@ -24,9 +24,8 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/DebugInfo.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" @@ -40,6 +39,8 @@ using namespace llvm; +#define DEBUG_TYPE "mips-reg-info" + MipsSERegisterInfo::MipsSERegisterInfo(const MipsSubtarget &ST) : MipsRegisterInfo(ST) {} @@ -62,21 +63,42 @@ MipsSERegisterInfo::intRegClass(unsigned Size) const { return &Mips::GPR64RegClass; } -/// Determine whether a given opcode is an MSA load/store (supporting 10-bit -/// offsets) or a non-MSA load/store (supporting 16-bit offsets). -static inline bool isMSALoadOrStore(const unsigned Opcode) { +/// Get the size of the offset supported by the given load/store. +/// The result includes the effects of any scale factors applied to the +/// instruction immediate. +static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode) { switch (Opcode) { case Mips::LD_B: + case Mips::ST_B: + return 10; case Mips::LD_H: + case Mips::ST_H: + return 10 + 1 /* scale factor */; case Mips::LD_W: + case Mips::ST_W: + return 10 + 2 /* scale factor */; case Mips::LD_D: - case Mips::ST_B: + case Mips::ST_D: + return 10 + 3 /* scale factor */; + default: + return 16; + } +} + +/// Get the scale factor applied to the immediate in the given load/store. +static inline unsigned getLoadStoreOffsetAlign(const unsigned Opcode) { + switch (Opcode) { + case Mips::LD_H: case Mips::ST_H: + return 2; + case Mips::LD_W: case Mips::ST_W: + return 4; + case Mips::LD_D: case Mips::ST_D: - return true; + return 8; default: - return false; + return 1; } } @@ -131,13 +153,16 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, if (!MI.isDebugValue()) { // Make sure Offset fits within the field available. - // For MSA instructions, this is a 10-bit signed immediate, otherwise it is - // a 16-bit signed immediate. - unsigned OffsetBitSize = isMSALoadOrStore(MI.getOpcode()) ? 10 : 16; + // For MSA instructions, this is a 10-bit signed immediate (scaled by + // element size), otherwise it is a 16-bit signed immediate. + unsigned OffsetBitSize = getLoadStoreOffsetSizeInBits(MI.getOpcode()); + unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode()); - if (OffsetBitSize == 10 && !isInt<10>(Offset) && isInt<16>(Offset)) { - // If we have an offset that needs to fit into a signed 10-bit immediate - // and doesn't, but does fit into 16-bits then use an ADDiu + if (OffsetBitSize < 16 && isInt<16>(Offset) && + (!isIntN(OffsetBitSize, Offset) || + OffsetToAlignment(Offset, OffsetAlign) != 0)) { + // If we have an offset that needs to fit into a signed n-bit immediate + // (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); unsigned ADDiu = Subtarget.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; @@ -164,7 +189,7 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, *static_cast<const MipsSEInstrInfo *>( MBB.getParent()->getTarget().getInstrInfo()); unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL, - OffsetBitSize == 16 ? &NewImm : NULL); + OffsetBitSize == 16 ? &NewImm : nullptr); BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(FrameReg) .addReg(Reg, RegState::Kill); |
