diff options
Diffstat (limited to 'lib/Target/Lanai/LanaiRegisterInfo.cpp')
| -rw-r--r-- | lib/Target/Lanai/LanaiRegisterInfo.cpp | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/lib/Target/Lanai/LanaiRegisterInfo.cpp b/lib/Target/Lanai/LanaiRegisterInfo.cpp new file mode 100644 index 000000000000..a4c612258e7b --- /dev/null +++ b/lib/Target/Lanai/LanaiRegisterInfo.cpp @@ -0,0 +1,287 @@ +//===-- LanaiRegisterInfo.cpp - Lanai Register Information ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Lanai implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "LanaiRegisterInfo.h" +#include "Lanai.h" +#include "LanaiSubtarget.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/RegisterScavenging.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetInstrInfo.h" + +#define GET_REGINFO_TARGET_DESC +#include "LanaiGenRegisterInfo.inc" + +using namespace llvm; + +LanaiRegisterInfo::LanaiRegisterInfo() : LanaiGenRegisterInfo(Lanai::RCA) {} + +const uint16_t * +LanaiRegisterInfo::getCalleeSavedRegs(const MachineFunction * /*MF*/) const { + return CSR_SaveList; +} + +BitVector LanaiRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + + Reserved.set(Lanai::R0); + Reserved.set(Lanai::R1); + Reserved.set(Lanai::PC); + Reserved.set(Lanai::R2); + Reserved.set(Lanai::SP); + Reserved.set(Lanai::R4); + Reserved.set(Lanai::FP); + Reserved.set(Lanai::R5); + Reserved.set(Lanai::RR1); + Reserved.set(Lanai::R10); + Reserved.set(Lanai::RR2); + Reserved.set(Lanai::R11); + Reserved.set(Lanai::RCA); + Reserved.set(Lanai::R15); + if (hasBasePointer(MF)) + Reserved.set(getBaseRegister()); + return Reserved; +} + +bool LanaiRegisterInfo::requiresRegisterScavenging( + const MachineFunction & /*MF*/) const { + return true; +} + +bool LanaiRegisterInfo::trackLivenessAfterRegAlloc( + const MachineFunction & /*MF*/) const { + return true; +} + +static bool isALUArithLoOpcode(unsigned Opcode) { + switch (Opcode) { + case Lanai::ADD_I_LO: + case Lanai::SUB_I_LO: + case Lanai::ADD_F_I_LO: + case Lanai::SUB_F_I_LO: + case Lanai::ADDC_I_LO: + case Lanai::SUBB_I_LO: + case Lanai::ADDC_F_I_LO: + case Lanai::SUBB_F_I_LO: + return true; + default: + return false; + } +} + +static unsigned getOppositeALULoOpcode(unsigned Opcode) { + switch (Opcode) { + case Lanai::ADD_I_LO: + return Lanai::SUB_I_LO; + case Lanai::SUB_I_LO: + return Lanai::ADD_I_LO; + case Lanai::ADD_F_I_LO: + return Lanai::SUB_F_I_LO; + case Lanai::SUB_F_I_LO: + return Lanai::ADD_F_I_LO; + case Lanai::ADDC_I_LO: + return Lanai::SUBB_I_LO; + case Lanai::SUBB_I_LO: + return Lanai::ADDC_I_LO; + case Lanai::ADDC_F_I_LO: + return Lanai::SUBB_F_I_LO; + case Lanai::SUBB_F_I_LO: + return Lanai::ADDC_F_I_LO; + default: + llvm_unreachable("Invalid ALU lo opcode"); + } +} + +static unsigned getRRMOpcodeVariant(unsigned Opcode) { + switch (Opcode) { + case Lanai::LDBs_RI: + return Lanai::LDBs_RR; + case Lanai::LDBz_RI: + return Lanai::LDBz_RR; + case Lanai::LDHs_RI: + return Lanai::LDHs_RR; + case Lanai::LDHz_RI: + return Lanai::LDHz_RR; + case Lanai::LDW_RI: + return Lanai::LDW_RR; + case Lanai::STB_RI: + return Lanai::STB_RR; + case Lanai::STH_RI: + return Lanai::STH_RR; + case Lanai::SW_RI: + return Lanai::SW_RR; + default: + llvm_unreachable("Opcode has no RRM variant"); + } +} + +void LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { + assert(SPAdj == 0 && "Unexpected"); + + MachineInstr &MI = *II; + MachineFunction &MF = *MI.getParent()->getParent(); + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + bool HasFP = TFI->hasFP(MF); + DebugLoc DL = MI.getDebugLoc(); + + int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); + + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + + MI.getOperand(FIOperandNum + 1).getImm(); + + // Addressable stack objects are addressed using neg. offsets from fp + // or pos. offsets from sp/basepointer + if (!HasFP || (needsStackRealignment(MF) && FrameIndex >= 0)) + Offset += MF.getFrameInfo()->getStackSize(); + + unsigned FrameReg = getFrameRegister(MF); + if (FrameIndex >= 0) { + if (hasBasePointer(MF)) + FrameReg = getBaseRegister(); + else if (needsStackRealignment(MF)) + FrameReg = Lanai::SP; + } + + // Replace frame index with a frame pointer reference. + // If the offset is small enough to fit in the immediate field, directly + // encode it. + // Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence. + if ((isSPLSOpcode(MI.getOpcode()) && !isInt<10>(Offset)) || + !isInt<16>(Offset)) { + assert(RS && "Register scavenging must be on"); + unsigned Reg = RS->FindUnusedReg(&Lanai::GPRRegClass); + if (!Reg) + Reg = RS->scavengeRegister(&Lanai::GPRRegClass, II, SPAdj); + assert(Reg && "Register scavenger failed"); + + bool HasNegOffset = false; + // ALU ops have unsigned immediate values. If the Offset is negative, we + // negate it here and reverse the opcode later. + if (Offset < 0) { + HasNegOffset = true; + Offset = -Offset; + } + + if (!isInt<16>(Offset)) { + // Reg = hi(offset) | lo(offset) + BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::MOVHI), Reg) + .addImm(static_cast<uint32_t>(Offset) >> 16); + BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::OR_I_LO), Reg) + .addReg(Reg) + .addImm(Offset & 0xffffU); + } else { + // Reg = mov(offset) + BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::ADD_I_LO), Reg) + .addImm(0) + .addImm(Offset); + } + // Reg = FrameReg OP Reg + if (MI.getOpcode() == Lanai::ADD_I_LO) { + BuildMI(*MI.getParent(), II, DL, + HasNegOffset ? TII->get(Lanai::SUB_R) : TII->get(Lanai::ADD_R), + MI.getOperand(0).getReg()) + .addReg(FrameReg) + .addReg(Reg) + .addImm(LPCC::ICC_T); + MI.eraseFromParent(); + return; + } + if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) { + MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode()))); + if (HasNegOffset) { + // Change the ALU op (operand 3) from LPAC::ADD (the default) to + // LPAC::SUB with the already negated offset. + assert((MI.getOperand(3).getImm() == LPAC::ADD) && + "Unexpected ALU op in RRM instruction"); + MI.getOperand(3).setImm(LPAC::SUB); + } + } else + llvm_unreachable("Unexpected opcode in frame index operation"); + + MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false); + MI.getOperand(FIOperandNum + 1) + .ChangeToRegister(Reg, /*isDef=*/false, /*isImp=*/false, + /*isKill=*/true); + return; + } + + // ALU arithmetic ops take unsigned immediates. If the offset is negative, + // we replace the instruction with one that inverts the opcode and negates + // the immediate. + if ((Offset < 0) && isALUArithLoOpcode(MI.getOpcode())) { + unsigned NewOpcode = getOppositeALULoOpcode(MI.getOpcode()); + // We know this is an ALU op, so we know the operands are as follows: + // 0: destination register + // 1: source register (frame register) + // 2: immediate + BuildMI(*MI.getParent(), II, DL, TII->get(NewOpcode), + MI.getOperand(0).getReg()) + .addReg(FrameReg) + .addImm(-Offset); + MI.eraseFromParent(); + } else { + MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); + } +} + +bool LanaiRegisterInfo::hasBasePointer(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + // When we need stack realignment and there are dynamic allocas, we can't + // reference off of the stack pointer, so we reserve a base pointer. + if (needsStackRealignment(MF) && MFI->hasVarSizedObjects()) + return true; + + return false; +} + +unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; } + +unsigned +LanaiRegisterInfo::getFrameRegister(const MachineFunction & /*MF*/) const { + return Lanai::FP; +} + +unsigned LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; } + +bool LanaiRegisterInfo::canRealignStack(const MachineFunction &MF) const { + if (!TargetRegisterInfo::canRealignStack(MF)) + return false; + return true; +} + +unsigned LanaiRegisterInfo::getEHExceptionRegister() const { + llvm_unreachable("no exception support"); + return 0; +} + +unsigned LanaiRegisterInfo::getEHHandlerRegister() const { + llvm_unreachable("no exception support"); + return 0; +} + +const uint32_t * +LanaiRegisterInfo::getCallPreservedMask(const MachineFunction & /*MF*/, + CallingConv::ID /*CC*/) const { + return CSR_RegMask; +} |
