blob: d175ad26c742c87b5902ab36d4bfce04ea92389e [file] [log] [blame]
//===-- VERegisterInfo.cpp - VE Register Information ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the VE implementation of the TargetRegisterInfo class.
//
//===----------------------------------------------------------------------===//
#include "VERegisterInfo.h"
#include "VE.h"
#include "VESubtarget.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/CodeGen/TargetInstrInfo.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
#define GET_REGINFO_TARGET_DESC
#include "VEGenRegisterInfo.inc"
// VE uses %s10 == %lp to keep return address
VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {}
const MCPhysReg *
VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
switch (MF->getFunction().getCallingConv()) {
case CallingConv::Fast:
// Being explicit (same as standard CC).
default:
return CSR_SaveList;
case CallingConv::PreserveAll:
return CSR_preserve_all_SaveList;
}
}
const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID CC) const {
switch (CC) {
case CallingConv::Fast:
// Being explicit (same as standard CC).
default:
return CSR_RegMask;
case CallingConv::PreserveAll:
return CSR_preserve_all_RegMask;
}
}
const uint32_t *VERegisterInfo::getNoPreservedMask() const {
return CSR_NoRegs_RegMask;
}
BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
const Register ReservedRegs[] = {
VE::SX8, // Stack limit
VE::SX9, // Frame pointer
VE::SX10, // Link register (return address)
VE::SX11, // Stack pointer
// FIXME: maybe not need to be reserved
VE::SX12, // Outer register
VE::SX13, // Id register for dynamic linker
VE::SX14, // Thread pointer
VE::SX15, // Global offset table register
VE::SX16, // Procedure linkage table register
VE::SX17, // Linkage-area register
// sx18-sx33 are callee-saved registers
// sx34-sx63 are temporary registers
};
for (auto R : ReservedRegs)
for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid();
++ItAlias)
Reserved.set(*ItAlias);
// Reserve constant registers.
Reserved.set(VE::VM0);
Reserved.set(VE::VMP0);
return Reserved;
}
bool VERegisterInfo::isConstantPhysReg(MCRegister PhysReg) const {
switch (PhysReg) {
case VE::VM0:
case VE::VMP0:
return true;
default:
return false;
}
}
const TargetRegisterClass *
VERegisterInfo::getPointerRegClass(const MachineFunction &MF,
unsigned Kind) const {
return &VE::I64RegClass;
}
static unsigned offsetToDisp(MachineInstr &MI) {
// Default offset in instruction's operands (reg+reg+imm).
unsigned OffDisp = 2;
#define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii
{
using namespace llvm::VE;
switch (MI.getOpcode()) {
case RRCAS_multi_cases(TS1AML):
case RRCAS_multi_cases(TS1AMW):
case RRCAS_multi_cases(CASL):
case RRCAS_multi_cases(CASW):
// These instructions use AS format (reg+imm).
OffDisp = 1;
break;
}
}
#undef RRCAS_multi_cases
return OffDisp;
}
static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II,
MachineInstr &MI, const DebugLoc &dl,
unsigned FIOperandNum, int Offset, Register FrameReg) {
// Replace frame index with a frame pointer reference directly.
// VE has 32 bit offset field, so no need to expand a target instruction.
// Directly encode it.
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
}
void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
MachineInstr &MI = *II;
DebugLoc dl = MI.getDebugLoc();
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
MachineFunction &MF = *MI.getParent()->getParent();
const VEFrameLowering *TFI = getFrameLowering(MF);
Register FrameReg;
int Offset;
Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();
if (MI.getOpcode() == VE::STQrii) {
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
Register SrcReg = MI.getOperand(3).getReg();
Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
// VE stores HiReg to 8(addr) and LoReg to 0(addr)
MachineInstr *StMI = BuildMI(*MI.getParent(), II, dl, TII.get(VE::STrii))
.addReg(FrameReg)
.addImm(0)
.addImm(0)
.addReg(SrcLoReg);
replaceFI(MF, II, *StMI, dl, 0, Offset, FrameReg);
MI.setDesc(TII.get(VE::STrii));
MI.getOperand(3).setReg(SrcHiReg);
Offset += 8;
} else if (MI.getOpcode() == VE::LDQrii) {
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
Register DestReg = MI.getOperand(0).getReg();
Register DestHiReg = getSubReg(DestReg, VE::sub_even);
Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
// VE loads HiReg from 8(addr) and LoReg from 0(addr)
MachineInstr *StMI =
BuildMI(*MI.getParent(), II, dl, TII.get(VE::LDrii), DestLoReg)
.addReg(FrameReg)
.addImm(0)
.addImm(0);
replaceFI(MF, II, *StMI, dl, 1, Offset, FrameReg);
MI.setDesc(TII.get(VE::LDrii));
MI.getOperand(0).setReg(DestHiReg);
Offset += 8;
}
replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg);
}
Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
return VE::SX9;
}