1480093f4SDimitry Andric //===-- VERegisterInfo.cpp - VE Register Information ----------------------===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric // This file contains the VE implementation of the TargetRegisterInfo class. 10480093f4SDimitry Andric // 11480093f4SDimitry Andric //===----------------------------------------------------------------------===// 12480093f4SDimitry Andric 13480093f4SDimitry Andric #include "VERegisterInfo.h" 14480093f4SDimitry Andric #include "VE.h" 15480093f4SDimitry Andric #include "VESubtarget.h" 16480093f4SDimitry Andric #include "llvm/ADT/BitVector.h" 17480093f4SDimitry Andric #include "llvm/ADT/STLExtras.h" 18480093f4SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 19480093f4SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 20480093f4SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 21480093f4SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 22480093f4SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 23480093f4SDimitry Andric #include "llvm/IR/Type.h" 24480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 25*e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h" 26480093f4SDimitry Andric #include "llvm/Support/ErrorHandling.h" 27480093f4SDimitry Andric 28480093f4SDimitry Andric using namespace llvm; 29480093f4SDimitry Andric 30480093f4SDimitry Andric #define GET_REGINFO_TARGET_DESC 31480093f4SDimitry Andric #include "VEGenRegisterInfo.inc" 32480093f4SDimitry Andric 33480093f4SDimitry Andric // VE uses %s10 == %lp to keep return address 34480093f4SDimitry Andric VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {} 35480093f4SDimitry Andric 36480093f4SDimitry Andric const MCPhysReg * 37480093f4SDimitry Andric VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 385ffd83dbSDimitry Andric switch (MF->getFunction().getCallingConv()) { 39*e8d8bef9SDimitry Andric case CallingConv::Fast: 40*e8d8bef9SDimitry Andric // Being explicit (same as standard CC). 415ffd83dbSDimitry Andric default: 42480093f4SDimitry Andric return CSR_SaveList; 435ffd83dbSDimitry Andric case CallingConv::PreserveAll: 445ffd83dbSDimitry Andric return CSR_preserve_all_SaveList; 455ffd83dbSDimitry Andric } 46480093f4SDimitry Andric } 47480093f4SDimitry Andric 48480093f4SDimitry Andric const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF, 49480093f4SDimitry Andric CallingConv::ID CC) const { 505ffd83dbSDimitry Andric switch (CC) { 51*e8d8bef9SDimitry Andric case CallingConv::Fast: 52*e8d8bef9SDimitry Andric // Being explicit (same as standard CC). 535ffd83dbSDimitry Andric default: 54480093f4SDimitry Andric return CSR_RegMask; 555ffd83dbSDimitry Andric case CallingConv::PreserveAll: 565ffd83dbSDimitry Andric return CSR_preserve_all_RegMask; 575ffd83dbSDimitry Andric } 58480093f4SDimitry Andric } 59480093f4SDimitry Andric 60480093f4SDimitry Andric const uint32_t *VERegisterInfo::getNoPreservedMask() const { 61480093f4SDimitry Andric return CSR_NoRegs_RegMask; 62480093f4SDimitry Andric } 63480093f4SDimitry Andric 64480093f4SDimitry Andric BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const { 65480093f4SDimitry Andric BitVector Reserved(getNumRegs()); 66480093f4SDimitry Andric 675ffd83dbSDimitry Andric const Register ReservedRegs[] = { 685ffd83dbSDimitry Andric VE::SX8, // Stack limit 695ffd83dbSDimitry Andric VE::SX9, // Frame pointer 705ffd83dbSDimitry Andric VE::SX10, // Link register (return address) 715ffd83dbSDimitry Andric VE::SX11, // Stack pointer 72480093f4SDimitry Andric 735ffd83dbSDimitry Andric // FIXME: maybe not need to be reserved 745ffd83dbSDimitry Andric VE::SX12, // Outer register 755ffd83dbSDimitry Andric VE::SX13, // Id register for dynamic linker 76480093f4SDimitry Andric 775ffd83dbSDimitry Andric VE::SX14, // Thread pointer 785ffd83dbSDimitry Andric VE::SX15, // Global offset table register 795ffd83dbSDimitry Andric VE::SX16, // Procedure linkage table register 805ffd83dbSDimitry Andric VE::SX17, // Linkage-area register 81480093f4SDimitry Andric // sx18-sx33 are callee-saved registers 82480093f4SDimitry Andric // sx34-sx63 are temporary registers 835ffd83dbSDimitry Andric }; 845ffd83dbSDimitry Andric 855ffd83dbSDimitry Andric for (auto R : ReservedRegs) 865ffd83dbSDimitry Andric for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid(); 875ffd83dbSDimitry Andric ++ItAlias) 885ffd83dbSDimitry Andric Reserved.set(*ItAlias); 89480093f4SDimitry Andric 90*e8d8bef9SDimitry Andric // Reserve constant registers. 91*e8d8bef9SDimitry Andric Reserved.set(VE::VM0); 92*e8d8bef9SDimitry Andric Reserved.set(VE::VMP0); 93*e8d8bef9SDimitry Andric 94480093f4SDimitry Andric return Reserved; 95480093f4SDimitry Andric } 96480093f4SDimitry Andric 97*e8d8bef9SDimitry Andric bool VERegisterInfo::isConstantPhysReg(MCRegister PhysReg) const { 98*e8d8bef9SDimitry Andric switch (PhysReg) { 99*e8d8bef9SDimitry Andric case VE::VM0: 100*e8d8bef9SDimitry Andric case VE::VMP0: 101*e8d8bef9SDimitry Andric return true; 102*e8d8bef9SDimitry Andric default: 103*e8d8bef9SDimitry Andric return false; 104*e8d8bef9SDimitry Andric } 105*e8d8bef9SDimitry Andric } 106480093f4SDimitry Andric 107480093f4SDimitry Andric const TargetRegisterClass * 108480093f4SDimitry Andric VERegisterInfo::getPointerRegClass(const MachineFunction &MF, 109480093f4SDimitry Andric unsigned Kind) const { 110480093f4SDimitry Andric return &VE::I64RegClass; 111480093f4SDimitry Andric } 112480093f4SDimitry Andric 113*e8d8bef9SDimitry Andric static unsigned offsetToDisp(MachineInstr &MI) { 114*e8d8bef9SDimitry Andric // Default offset in instruction's operands (reg+reg+imm). 115*e8d8bef9SDimitry Andric unsigned OffDisp = 2; 116*e8d8bef9SDimitry Andric 117*e8d8bef9SDimitry Andric #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii 118*e8d8bef9SDimitry Andric 119*e8d8bef9SDimitry Andric { 120*e8d8bef9SDimitry Andric using namespace llvm::VE; 121*e8d8bef9SDimitry Andric switch (MI.getOpcode()) { 122*e8d8bef9SDimitry Andric case RRCAS_multi_cases(TS1AML): 123*e8d8bef9SDimitry Andric case RRCAS_multi_cases(TS1AMW): 124*e8d8bef9SDimitry Andric case RRCAS_multi_cases(CASL): 125*e8d8bef9SDimitry Andric case RRCAS_multi_cases(CASW): 126*e8d8bef9SDimitry Andric // These instructions use AS format (reg+imm). 127*e8d8bef9SDimitry Andric OffDisp = 1; 128*e8d8bef9SDimitry Andric break; 129*e8d8bef9SDimitry Andric } 130*e8d8bef9SDimitry Andric } 131*e8d8bef9SDimitry Andric #undef RRCAS_multi_cases 132*e8d8bef9SDimitry Andric 133*e8d8bef9SDimitry Andric return OffDisp; 134*e8d8bef9SDimitry Andric } 135*e8d8bef9SDimitry Andric 136480093f4SDimitry Andric static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II, 137480093f4SDimitry Andric MachineInstr &MI, const DebugLoc &dl, 1385ffd83dbSDimitry Andric unsigned FIOperandNum, int Offset, Register FrameReg) { 139480093f4SDimitry Andric // Replace frame index with a frame pointer reference directly. 140480093f4SDimitry Andric // VE has 32 bit offset field, so no need to expand a target instruction. 141480093f4SDimitry Andric // Directly encode it. 1425ffd83dbSDimitry Andric MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); 143*e8d8bef9SDimitry Andric MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset); 144480093f4SDimitry Andric } 145480093f4SDimitry Andric 146480093f4SDimitry Andric void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 147480093f4SDimitry Andric int SPAdj, unsigned FIOperandNum, 148480093f4SDimitry Andric RegScavenger *RS) const { 149480093f4SDimitry Andric assert(SPAdj == 0 && "Unexpected"); 150480093f4SDimitry Andric 151480093f4SDimitry Andric MachineInstr &MI = *II; 152480093f4SDimitry Andric DebugLoc dl = MI.getDebugLoc(); 153480093f4SDimitry Andric int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 154480093f4SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent(); 155480093f4SDimitry Andric const VEFrameLowering *TFI = getFrameLowering(MF); 156480093f4SDimitry Andric 1575ffd83dbSDimitry Andric Register FrameReg; 158480093f4SDimitry Andric int Offset; 159*e8d8bef9SDimitry Andric Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed(); 160480093f4SDimitry Andric 161*e8d8bef9SDimitry Andric Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm(); 162*e8d8bef9SDimitry Andric 163*e8d8bef9SDimitry Andric if (MI.getOpcode() == VE::STQrii) { 164*e8d8bef9SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 165*e8d8bef9SDimitry Andric Register SrcReg = MI.getOperand(3).getReg(); 166*e8d8bef9SDimitry Andric Register SrcHiReg = getSubReg(SrcReg, VE::sub_even); 167*e8d8bef9SDimitry Andric Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd); 168*e8d8bef9SDimitry Andric // VE stores HiReg to 8(addr) and LoReg to 0(addr) 169*e8d8bef9SDimitry Andric MachineInstr *StMI = BuildMI(*MI.getParent(), II, dl, TII.get(VE::STrii)) 170*e8d8bef9SDimitry Andric .addReg(FrameReg) 171*e8d8bef9SDimitry Andric .addImm(0) 172*e8d8bef9SDimitry Andric .addImm(0) 173*e8d8bef9SDimitry Andric .addReg(SrcLoReg); 174*e8d8bef9SDimitry Andric replaceFI(MF, II, *StMI, dl, 0, Offset, FrameReg); 175*e8d8bef9SDimitry Andric MI.setDesc(TII.get(VE::STrii)); 176*e8d8bef9SDimitry Andric MI.getOperand(3).setReg(SrcHiReg); 177*e8d8bef9SDimitry Andric Offset += 8; 178*e8d8bef9SDimitry Andric } else if (MI.getOpcode() == VE::LDQrii) { 179*e8d8bef9SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 180*e8d8bef9SDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 181*e8d8bef9SDimitry Andric Register DestHiReg = getSubReg(DestReg, VE::sub_even); 182*e8d8bef9SDimitry Andric Register DestLoReg = getSubReg(DestReg, VE::sub_odd); 183*e8d8bef9SDimitry Andric // VE loads HiReg from 8(addr) and LoReg from 0(addr) 184*e8d8bef9SDimitry Andric MachineInstr *StMI = 185*e8d8bef9SDimitry Andric BuildMI(*MI.getParent(), II, dl, TII.get(VE::LDrii), DestLoReg) 186*e8d8bef9SDimitry Andric .addReg(FrameReg) 187*e8d8bef9SDimitry Andric .addImm(0) 188*e8d8bef9SDimitry Andric .addImm(0); 189*e8d8bef9SDimitry Andric replaceFI(MF, II, *StMI, dl, 1, Offset, FrameReg); 190*e8d8bef9SDimitry Andric MI.setDesc(TII.get(VE::LDrii)); 191*e8d8bef9SDimitry Andric MI.getOperand(0).setReg(DestHiReg); 192*e8d8bef9SDimitry Andric Offset += 8; 193*e8d8bef9SDimitry Andric } 194480093f4SDimitry Andric 195480093f4SDimitry Andric replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg); 196480093f4SDimitry Andric } 197480093f4SDimitry Andric 198480093f4SDimitry Andric Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const { 199480093f4SDimitry Andric return VE::SX9; 200480093f4SDimitry Andric } 201