MipsSERegisterInfo.cpp [plain text]
#include "MipsSERegisterInfo.h"
#include "Mips.h"
#include "MipsAnalyzeImmediate.h"
#include "MipsMachineFunction.h"
#include "MipsSEInstrInfo.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.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"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
#define DEBUG_TYPE "mips-reg-info"
MipsSERegisterInfo::MipsSERegisterInfo() : MipsRegisterInfo() {}
bool MipsSERegisterInfo::
requiresRegisterScavenging(const MachineFunction &MF) const {
return true;
}
bool MipsSERegisterInfo::
requiresFrameIndexScavenging(const MachineFunction &MF) const {
return true;
}
const TargetRegisterClass *
MipsSERegisterInfo::intRegClass(unsigned Size) const {
if (Size == 4)
return &Mips::GPR32RegClass;
assert(Size == 8);
return &Mips::GPR64RegClass;
}
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 ;
case Mips::LD_W:
case Mips::ST_W:
return 10 + 2 ;
case Mips::LD_D:
case Mips::ST_D:
return 10 + 3 ;
default:
return 16;
}
}
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 8;
default:
return 1;
}
}
void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
unsigned OpNo, int FrameIndex,
uint64_t StackSize,
int64_t SPOffset) const {
MachineInstr &MI = *II;
MachineFunction &MF = *MI.getParent()->getParent();
MachineFrameInfo *MFI = MF.getFrameInfo();
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
bool isN64 =
static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64();
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
int MinCSFI = 0;
int MaxCSFI = -1;
if (CSI.size()) {
MinCSFI = CSI[0].getFrameIdx();
MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
}
bool EhDataRegFI = MipsFI->isEhDataRegFI(FrameIndex);
unsigned FrameReg;
if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) || EhDataRegFI)
FrameReg = isN64 ? Mips::SP_64 : Mips::SP;
else
FrameReg = getFrameRegister(MF);
bool IsKill = false;
int64_t Offset;
Offset = SPOffset + (int64_t)StackSize;
Offset += MI.getOperand(OpNo + 1).getImm();
DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n");
if (!MI.isDebugValue()) {
unsigned OffsetBitSize = getLoadStoreOffsetSizeInBits(MI.getOpcode());
unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode());
if (OffsetBitSize < 16 && isInt<16>(Offset) &&
(!isIntN(OffsetBitSize, Offset) ||
OffsetToAlignment(Offset, OffsetAlign) != 0)) {
MachineBasicBlock &MBB = *MI.getParent();
DebugLoc DL = II->getDebugLoc();
unsigned ADDiu = isN64 ? Mips::DADDiu : Mips::ADDiu;
const TargetRegisterClass *RC =
isN64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
unsigned Reg = RegInfo.createVirtualRegister(RC);
const MipsSEInstrInfo &TII =
*static_cast<const MipsSEInstrInfo *>(
MBB.getParent()->getSubtarget().getInstrInfo());
BuildMI(MBB, II, DL, TII.get(ADDiu), Reg).addReg(FrameReg).addImm(Offset);
FrameReg = Reg;
Offset = 0;
IsKill = true;
} else if (!isInt<16>(Offset)) {
MachineBasicBlock &MBB = *MI.getParent();
DebugLoc DL = II->getDebugLoc();
unsigned ADDu = isN64 ? Mips::DADDu : Mips::ADDu;
unsigned NewImm = 0;
const MipsSEInstrInfo &TII =
*static_cast<const MipsSEInstrInfo *>(
MBB.getParent()->getSubtarget().getInstrInfo());
unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL,
OffsetBitSize == 16 ? &NewImm : nullptr);
BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(FrameReg)
.addReg(Reg, RegState::Kill);
FrameReg = Reg;
Offset = SignExtend64<16>(NewImm);
IsKill = true;
}
}
MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill);
MI.getOperand(OpNo + 1).ChangeToImmediate(Offset);
}