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