1 //===-- VERegisterInfo.cpp - VE Register Information ----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the VE implementation of the TargetRegisterInfo class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "VERegisterInfo.h" 14 #include "VE.h" 15 #include "VESubtarget.h" 16 #include "llvm/ADT/BitVector.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/CodeGen/MachineFrameInfo.h" 19 #include "llvm/CodeGen/MachineFunction.h" 20 #include "llvm/CodeGen/MachineInstrBuilder.h" 21 #include "llvm/CodeGen/MachineRegisterInfo.h" 22 #include "llvm/CodeGen/TargetInstrInfo.h" 23 #include "llvm/IR/Type.h" 24 #include "llvm/Support/CommandLine.h" 25 #include "llvm/Support/Debug.h" 26 #include "llvm/Support/ErrorHandling.h" 27 28 using namespace llvm; 29 30 #define DEBUG_TYPE "ve-register-info" 31 32 #define GET_REGINFO_TARGET_DESC 33 #include "VEGenRegisterInfo.inc" 34 35 // VE uses %s10 == %lp to keep return address 36 VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {} 37 38 const MCPhysReg * 39 VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 40 switch (MF->getFunction().getCallingConv()) { 41 case CallingConv::Fast: 42 // Being explicit (same as standard CC). 43 default: 44 return CSR_SaveList; 45 case CallingConv::PreserveAll: 46 return CSR_preserve_all_SaveList; 47 } 48 } 49 50 const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF, 51 CallingConv::ID CC) const { 52 switch (CC) { 53 case CallingConv::Fast: 54 // Being explicit (same as standard CC). 55 default: 56 return CSR_RegMask; 57 case CallingConv::PreserveAll: 58 return CSR_preserve_all_RegMask; 59 } 60 } 61 62 const uint32_t *VERegisterInfo::getNoPreservedMask() const { 63 return CSR_NoRegs_RegMask; 64 } 65 66 BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const { 67 BitVector Reserved(getNumRegs()); 68 69 const Register ReservedRegs[] = { 70 VE::SX8, // Stack limit 71 VE::SX9, // Frame pointer 72 VE::SX10, // Link register (return address) 73 VE::SX11, // Stack pointer 74 75 // FIXME: maybe not need to be reserved 76 VE::SX12, // Outer register 77 VE::SX13, // Id register for dynamic linker 78 79 VE::SX14, // Thread pointer 80 VE::SX15, // Global offset table register 81 VE::SX16, // Procedure linkage table register 82 VE::SX17, // Linkage-area register 83 // sx18-sx33 are callee-saved registers 84 // sx34-sx63 are temporary registers 85 }; 86 87 for (auto R : ReservedRegs) 88 for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid(); 89 ++ItAlias) 90 Reserved.set(*ItAlias); 91 92 // Reserve constant registers. 93 Reserved.set(VE::VM0); 94 Reserved.set(VE::VMP0); 95 96 return Reserved; 97 } 98 99 bool VERegisterInfo::isConstantPhysReg(MCRegister PhysReg) const { 100 switch (PhysReg) { 101 case VE::VM0: 102 case VE::VMP0: 103 return true; 104 default: 105 return false; 106 } 107 } 108 109 const TargetRegisterClass * 110 VERegisterInfo::getPointerRegClass(const MachineFunction &MF, 111 unsigned Kind) const { 112 return &VE::I64RegClass; 113 } 114 115 static unsigned offsetToDisp(MachineInstr &MI) { 116 // Default offset in instruction's operands (reg+reg+imm). 117 unsigned OffDisp = 2; 118 119 #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii 120 121 { 122 using namespace llvm::VE; 123 switch (MI.getOpcode()) { 124 case RRCAS_multi_cases(TS1AML): 125 case RRCAS_multi_cases(TS1AMW): 126 case RRCAS_multi_cases(CASL): 127 case RRCAS_multi_cases(CASW): 128 // These instructions use AS format (reg+imm). 129 OffDisp = 1; 130 break; 131 } 132 } 133 #undef RRCAS_multi_cases 134 135 return OffDisp; 136 } 137 138 class EliminateFrameIndex { 139 const TargetInstrInfo &TII; 140 const TargetRegisterInfo &TRI; 141 const DebugLoc &DL; 142 MachineBasicBlock &MBB; 143 MachineBasicBlock::iterator II; 144 Register clobber; 145 146 // Some helper functions for the ease of instruction building. 147 MachineFunction &getFunc() const { return *MBB.getParent(); } 148 inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const { 149 return TRI.getSubReg(Reg, Idx); 150 } 151 inline const MCInstrDesc &get(unsigned Opcode) const { 152 return TII.get(Opcode); 153 } 154 inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) { 155 return BuildMI(MBB, II, DL, MCID, DestReg); 156 } 157 inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) { 158 return build(get(InstOpc), DestReg); 159 } 160 inline MachineInstrBuilder build(const MCInstrDesc &MCID) { 161 return BuildMI(MBB, II, DL, MCID); 162 } 163 inline MachineInstrBuilder build(unsigned InstOpc) { 164 return build(get(InstOpc)); 165 } 166 167 // Calculate an address of frame index from a frame register and a given 168 // offset if the offset doesn't fit in the immediate field. Use a clobber 169 // register to hold calculated address. 170 void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset, 171 int64_t Bytes = 0); 172 // Replace the frame index in \p MI with a frame register and a given offset 173 // if it fits in the immediate field. Otherwise, use pre-calculated address 174 // in a clobber regsiter. 175 void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset, 176 int FIOperandNum); 177 178 // Expand and eliminate Frame Index of pseudo STQrii and LDQrii. 179 void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset, 180 int FIOperandNum); 181 void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset, 182 int FIOperandNum); 183 184 public: 185 EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, 186 const DebugLoc &DL, MachineBasicBlock &MBB, 187 MachineBasicBlock::iterator II) 188 : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {} 189 190 // Expand and eliminate Frame Index from MI 191 void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset, 192 int FIOperandNum); 193 }; 194 195 // Prepare the frame index if it doesn't fit in the immediate field. Use 196 // clobber register to hold calculated address. 197 void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg, 198 int64_t &Offset, int64_t Bytes) { 199 if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) { 200 // If the offset is small enough to fit in the immediate field, directly 201 // encode it. So, nothing to prepare here. 202 return; 203 } 204 205 // If the offset doesn't fit, emit following codes. This clobbers SX13 206 // which we always know is available here. 207 // lea %clobber, Offset@lo 208 // and %clobber, %clobber, (32)0 209 // lea.sl %clobber, Offset@hi(FrameReg, %clobber) 210 build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset)); 211 build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32)); 212 build(VE::LEASLrri, clobber) 213 .addReg(clobber) 214 .addReg(FrameReg) 215 .addImm(Hi_32(Offset)); 216 217 // Use clobber register as a frame register and 0 offset 218 FrameReg = clobber; 219 Offset = 0; 220 } 221 222 // Replace the frame index in \p MI with a proper byte and framereg offset. 223 void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg, 224 int64_t Offset, int FIOperandNum) { 225 assert(isInt<32>(Offset)); 226 227 // The offset must be small enough to fit in the immediate field after 228 // call of prepareReplaceFI. Therefore, we directly encode it. 229 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); 230 MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset); 231 } 232 233 void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg, 234 int64_t Offset, int FIOperandNum) { 235 assert(MI.getOpcode() == VE::STQrii); 236 LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump()); 237 238 prepareReplaceFI(MI, FrameReg, Offset, 8); 239 240 Register SrcReg = MI.getOperand(3).getReg(); 241 Register SrcHiReg = getSubReg(SrcReg, VE::sub_even); 242 Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd); 243 // VE stores HiReg to 8(addr) and LoReg to 0(addr) 244 MachineInstr *StMI = 245 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg); 246 replaceFI(*StMI, FrameReg, Offset, 0); 247 // Mutate to 'hi' store. 248 MI.setDesc(get(VE::STrii)); 249 MI.getOperand(3).setReg(SrcHiReg); 250 Offset += 8; 251 replaceFI(MI, FrameReg, Offset, FIOperandNum); 252 } 253 254 void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg, 255 int64_t Offset, int FIOperandNum) { 256 assert(MI.getOpcode() == VE::LDQrii); 257 LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump()); 258 259 prepareReplaceFI(MI, FrameReg, Offset, 8); 260 261 Register DestReg = MI.getOperand(0).getReg(); 262 Register DestHiReg = getSubReg(DestReg, VE::sub_even); 263 Register DestLoReg = getSubReg(DestReg, VE::sub_odd); 264 // VE loads HiReg from 8(addr) and LoReg from 0(addr) 265 MachineInstr *StMI = 266 build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0); 267 replaceFI(*StMI, FrameReg, Offset, 1); 268 MI.setDesc(get(VE::LDrii)); 269 MI.getOperand(0).setReg(DestHiReg); 270 Offset += 8; 271 replaceFI(MI, FrameReg, Offset, FIOperandNum); 272 } 273 274 void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg, 275 int64_t Offset, int FIOperandNum) { 276 switch (MI.getOpcode()) { 277 case VE::STQrii: 278 processSTQ(MI, FrameReg, Offset, FIOperandNum); 279 return; 280 case VE::LDQrii: 281 processLDQ(MI, FrameReg, Offset, FIOperandNum); 282 return; 283 } 284 prepareReplaceFI(MI, FrameReg, Offset); 285 replaceFI(MI, FrameReg, Offset, FIOperandNum); 286 } 287 288 void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 289 int SPAdj, unsigned FIOperandNum, 290 RegScavenger *RS) const { 291 assert(SPAdj == 0 && "Unexpected"); 292 293 MachineInstr &MI = *II; 294 int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 295 296 MachineFunction &MF = *MI.getParent()->getParent(); 297 const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>(); 298 const VEFrameLowering &TFI = *getFrameLowering(MF); 299 const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 300 const VERegisterInfo &TRI = *Subtarget.getRegisterInfo(); 301 DebugLoc DL = MI.getDebugLoc(); 302 EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II); 303 304 // Retrieve FrameReg and byte offset for stack slot. 305 Register FrameReg; 306 int64_t Offset = 307 TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed(); 308 Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm(); 309 310 EFI.processMI(MI, FrameReg, Offset, FIOperandNum); 311 } 312 313 Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const { 314 return VE::SX9; 315 } 316