#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"
using namespace llvm;
+#define DEBUG_TYPE "mips-reg-info"
+
MipsSERegisterInfo::MipsSERegisterInfo(const MipsSubtarget &ST)
: MipsRegisterInfo(ST) {}
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;
}
}
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;
-
- 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
+ // 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 < 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;
*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);