//===-- 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; }