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/CodeGen/MachineFrameInfo.h" 18 #include "llvm/CodeGen/MachineFunction.h" 19 #include "llvm/CodeGen/MachineInstrBuilder.h" 20 #include "llvm/CodeGen/TargetInstrInfo.h" 21 #include "llvm/IR/Type.h" 22 #include "llvm/Support/Debug.h" 23 24 using namespace llvm; 25 26 #define DEBUG_TYPE "ve-register-info" 27 28 #define GET_REGINFO_TARGET_DESC 29 #include "VEGenRegisterInfo.inc" 30 31 // VE uses %s10 == %lp to keep return address 32 VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {} 33 34 const MCPhysReg * 35 VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 36 switch (MF->getFunction().getCallingConv()) { 37 case CallingConv::Fast: 38 // Being explicit (same as standard CC). 39 default: 40 return CSR_SaveList; 41 case CallingConv::PreserveAll: 42 return CSR_preserve_all_SaveList; 43 } 44 } 45 46 const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF, 47 CallingConv::ID CC) const { 48 switch (CC) { 49 case CallingConv::Fast: 50 // Being explicit (same as standard CC). 51 default: 52 return CSR_RegMask; 53 case CallingConv::PreserveAll: 54 return CSR_preserve_all_RegMask; 55 } 56 } 57 58 const uint32_t *VERegisterInfo::getNoPreservedMask() const { 59 return CSR_NoRegs_RegMask; 60 } 61 62 BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const { 63 BitVector Reserved(getNumRegs()); 64 65 const Register ReservedRegs[] = { 66 VE::SX8, // Stack limit 67 VE::SX9, // Frame pointer 68 VE::SX10, // Link register (return address) 69 VE::SX11, // Stack pointer 70 71 // FIXME: maybe not need to be reserved 72 VE::SX12, // Outer register 73 VE::SX13, // Id register for dynamic linker 74 75 VE::SX14, // Thread pointer 76 VE::SX15, // Global offset table register 77 VE::SX16, // Procedure linkage table register 78 VE::SX17, // Linkage-area register 79 // sx18-sx33 are callee-saved registers 80 // sx34-sx63 are temporary registers 81 }; 82 83 for (auto R : ReservedRegs) 84 for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid(); 85 ++ItAlias) 86 Reserved.set(*ItAlias); 87 88 // Reserve constant registers. 89 Reserved.set(VE::VM0); 90 Reserved.set(VE::VMP0); 91 92 return Reserved; 93 } 94 95 const TargetRegisterClass * 96 VERegisterInfo::getPointerRegClass(const MachineFunction &MF, 97 unsigned Kind) const { 98 return &VE::I64RegClass; 99 } 100 101 static unsigned offsetToDisp(MachineInstr &MI) { 102 // Default offset in instruction's operands (reg+reg+imm). 103 unsigned OffDisp = 2; 104 105 #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii 106 107 { 108 using namespace llvm::VE; 109 switch (MI.getOpcode()) { 110 case INLINEASM: 111 case RRCAS_multi_cases(TS1AML): 112 case RRCAS_multi_cases(TS1AMW): 113 case RRCAS_multi_cases(CASL): 114 case RRCAS_multi_cases(CASW): 115 // These instructions use AS format (reg+imm). 116 OffDisp = 1; 117 break; 118 } 119 } 120 #undef RRCAS_multi_cases 121 122 return OffDisp; 123 } 124 125 namespace { 126 class EliminateFrameIndex { 127 const TargetInstrInfo &TII; 128 const TargetRegisterInfo &TRI; 129 const DebugLoc &DL; 130 MachineBasicBlock &MBB; 131 MachineBasicBlock::iterator II; 132 Register clobber; 133 134 // Some helper functions for the ease of instruction building. 135 MachineFunction &getFunc() const { return *MBB.getParent(); } 136 inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const { 137 return TRI.getSubReg(Reg, Idx); 138 } 139 inline const MCInstrDesc &get(unsigned Opcode) const { 140 return TII.get(Opcode); 141 } 142 inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) { 143 return BuildMI(MBB, II, DL, MCID, DestReg); 144 } 145 inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) { 146 return build(get(InstOpc), DestReg); 147 } 148 inline MachineInstrBuilder build(const MCInstrDesc &MCID) { 149 return BuildMI(MBB, II, DL, MCID); 150 } 151 inline MachineInstrBuilder build(unsigned InstOpc) { 152 return build(get(InstOpc)); 153 } 154 155 // Calculate an address of frame index from a frame register and a given 156 // offset if the offset doesn't fit in the immediate field. Use a clobber 157 // register to hold calculated address. 158 void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset, 159 int64_t Bytes = 0); 160 // Replace the frame index in \p MI with a frame register and a given offset 161 // if it fits in the immediate field. Otherwise, use pre-calculated address 162 // in a clobber regsiter. 163 void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset, 164 int FIOperandNum); 165 166 // Expand and eliminate Frame Index of pseudo STQrii and LDQrii. 167 void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset, 168 int FIOperandNum); 169 void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset, 170 int FIOperandNum); 171 // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii. 172 void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset, 173 int FIOperandNum); 174 void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset, 175 int FIOperandNum); 176 // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii. 177 void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset, 178 int FIOperandNum); 179 void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset, 180 int FIOperandNum); 181 182 public: 183 EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, 184 const DebugLoc &DL, MachineBasicBlock &MBB, 185 MachineBasicBlock::iterator II) 186 : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {} 187 188 // Expand and eliminate Frame Index from MI 189 void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset, 190 int FIOperandNum); 191 }; 192 } // namespace 193 194 // Prepare the frame index if it doesn't fit in the immediate field. Use 195 // clobber register to hold calculated address. 196 void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg, 197 int64_t &Offset, int64_t Bytes) { 198 if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) { 199 // If the offset is small enough to fit in the immediate field, directly 200 // encode it. So, nothing to prepare here. 201 return; 202 } 203 204 // If the offset doesn't fit, emit following codes. This clobbers SX13 205 // which we always know is available here. 206 // lea %clobber, Offset@lo 207 // and %clobber, %clobber, (32)0 208 // lea.sl %clobber, Offset@hi(FrameReg, %clobber) 209 build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset)); 210 build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32)); 211 build(VE::LEASLrri, clobber) 212 .addReg(clobber) 213 .addReg(FrameReg) 214 .addImm(Hi_32(Offset)); 215 216 // Use clobber register as a frame register and 0 offset 217 FrameReg = clobber; 218 Offset = 0; 219 } 220 221 // Replace the frame index in \p MI with a proper byte and framereg offset. 222 void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg, 223 int64_t Offset, int FIOperandNum) { 224 assert(isInt<32>(Offset)); 225 226 // The offset must be small enough to fit in the immediate field after 227 // call of prepareReplaceFI. Therefore, we directly encode it. 228 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); 229 MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset); 230 } 231 232 void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg, 233 int64_t Offset, int FIOperandNum) { 234 assert(MI.getOpcode() == VE::STQrii); 235 LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump()); 236 237 prepareReplaceFI(MI, FrameReg, Offset, 8); 238 239 Register SrcReg = MI.getOperand(3).getReg(); 240 Register SrcHiReg = getSubReg(SrcReg, VE::sub_even); 241 Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd); 242 // VE stores HiReg to 8(addr) and LoReg to 0(addr) 243 MachineInstr *StMI = 244 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg); 245 replaceFI(*StMI, FrameReg, Offset, 0); 246 // Mutate to 'hi' store. 247 MI.setDesc(get(VE::STrii)); 248 MI.getOperand(3).setReg(SrcHiReg); 249 Offset += 8; 250 replaceFI(MI, FrameReg, Offset, FIOperandNum); 251 } 252 253 void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg, 254 int64_t Offset, int FIOperandNum) { 255 assert(MI.getOpcode() == VE::LDQrii); 256 LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump()); 257 258 prepareReplaceFI(MI, FrameReg, Offset, 8); 259 260 Register DestReg = MI.getOperand(0).getReg(); 261 Register DestHiReg = getSubReg(DestReg, VE::sub_even); 262 Register DestLoReg = getSubReg(DestReg, VE::sub_odd); 263 // VE loads HiReg from 8(addr) and LoReg from 0(addr) 264 MachineInstr *StMI = 265 build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0); 266 replaceFI(*StMI, FrameReg, Offset, 1); 267 MI.setDesc(get(VE::LDrii)); 268 MI.getOperand(0).setReg(DestHiReg); 269 Offset += 8; 270 replaceFI(MI, FrameReg, Offset, FIOperandNum); 271 } 272 273 void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg, 274 int64_t Offset, int FIOperandNum) { 275 assert(MI.getOpcode() == VE::STVMrii); 276 LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump()); 277 278 // Original MI is: 279 // STVMrii frame-index, 0, offset, reg (, memory operand) 280 // Convert it to: 281 // SVMi tmp-reg, reg, 0 282 // STrii frame-reg, 0, offset, tmp-reg 283 // SVMi tmp-reg, reg, 1 284 // STrii frame-reg, 0, offset+8, tmp-reg 285 // SVMi tmp-reg, reg, 2 286 // STrii frame-reg, 0, offset+16, tmp-reg 287 // SVMi tmp-reg, reg, 3 288 // STrii frame-reg, 0, offset+24, tmp-reg 289 290 prepareReplaceFI(MI, FrameReg, Offset, 24); 291 292 Register SrcReg = MI.getOperand(3).getReg(); 293 bool isKill = MI.getOperand(3).isKill(); 294 // FIXME: it would be better to scavenge a register here instead of 295 // reserving SX16 all of the time. 296 Register TmpReg = VE::SX16; 297 for (int i = 0; i < 3; ++i) { 298 build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i); 299 MachineInstr *StMI = 300 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( 301 TmpReg, getKillRegState(true)); 302 replaceFI(*StMI, FrameReg, Offset, 0); 303 Offset += 8; 304 } 305 build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3); 306 MI.setDesc(get(VE::STrii)); 307 MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true); 308 replaceFI(MI, FrameReg, Offset, FIOperandNum); 309 } 310 311 void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg, 312 int64_t Offset, int FIOperandNum) { 313 assert(MI.getOpcode() == VE::LDVMrii); 314 LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump()); 315 316 // Original MI is: 317 // LDVMri reg, frame-index, 0, offset (, memory operand) 318 // Convert it to: 319 // LDrii tmp-reg, frame-reg, 0, offset 320 // LVMir vm, 0, tmp-reg 321 // LDrii tmp-reg, frame-reg, 0, offset+8 322 // LVMir_m vm, 1, tmp-reg, vm 323 // LDrii tmp-reg, frame-reg, 0, offset+16 324 // LVMir_m vm, 2, tmp-reg, vm 325 // LDrii tmp-reg, frame-reg, 0, offset+24 326 // LVMir_m vm, 3, tmp-reg, vm 327 328 prepareReplaceFI(MI, FrameReg, Offset, 24); 329 330 Register DestReg = MI.getOperand(0).getReg(); 331 // FIXME: it would be better to scavenge a register here instead of 332 // reserving SX16 all of the time. 333 unsigned TmpReg = VE::SX16; 334 for (int i = 0; i < 4; ++i) { 335 if (i != 3) { 336 MachineInstr *StMI = 337 build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); 338 replaceFI(*StMI, FrameReg, Offset, 1); 339 Offset += 8; 340 } else { 341 // Last LDrii replace the target instruction. 342 MI.setDesc(get(VE::LDrii)); 343 MI.getOperand(0).ChangeToRegister(TmpReg, true); 344 } 345 // First LVM is LVMir. Others are LVMir_m. Last LVM places at the 346 // next of the target instruction. 347 if (i == 0) 348 build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true)); 349 else if (i != 3) 350 build(VE::LVMir_m, DestReg) 351 .addImm(i) 352 .addReg(TmpReg, getKillRegState(true)) 353 .addReg(DestReg); 354 else 355 BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg) 356 .addImm(3) 357 .addReg(TmpReg, getKillRegState(true)) 358 .addReg(DestReg); 359 } 360 replaceFI(MI, FrameReg, Offset, FIOperandNum); 361 } 362 363 void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg, 364 int64_t Offset, int FIOperandNum) { 365 assert(MI.getOpcode() == VE::STVM512rii); 366 LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump()); 367 368 prepareReplaceFI(MI, FrameReg, Offset, 56); 369 370 Register SrcReg = MI.getOperand(3).getReg(); 371 Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd); 372 Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even); 373 bool isKill = MI.getOperand(3).isKill(); 374 // FIXME: it would be better to scavenge a register here instead of 375 // reserving SX16 all of the time. 376 Register TmpReg = VE::SX16; 377 // store low part of VMP 378 MachineInstr *LastMI = nullptr; 379 for (int i = 0; i < 4; ++i) { 380 LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i); 381 MachineInstr *StMI = 382 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( 383 TmpReg, getKillRegState(true)); 384 replaceFI(*StMI, FrameReg, Offset, 0); 385 Offset += 8; 386 } 387 if (isKill) 388 LastMI->addRegisterKilled(SrcLoReg, &TRI, true); 389 // store high part of VMP 390 for (int i = 0; i < 3; ++i) { 391 build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i); 392 MachineInstr *StMI = 393 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( 394 TmpReg, getKillRegState(true)); 395 replaceFI(*StMI, FrameReg, Offset, 0); 396 Offset += 8; 397 } 398 LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3); 399 if (isKill) { 400 LastMI->addRegisterKilled(SrcHiReg, &TRI, true); 401 // Add implicit super-register kills to the particular MI. 402 LastMI->addRegisterKilled(SrcReg, &TRI, true); 403 } 404 MI.setDesc(get(VE::STrii)); 405 MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true); 406 replaceFI(MI, FrameReg, Offset, FIOperandNum); 407 } 408 409 void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg, 410 int64_t Offset, int FIOperandNum) { 411 assert(MI.getOpcode() == VE::LDVM512rii); 412 LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump()); 413 414 prepareReplaceFI(MI, FrameReg, Offset, 56); 415 416 Register DestReg = MI.getOperand(0).getReg(); 417 Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd); 418 Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even); 419 // FIXME: it would be better to scavenge a register here instead of 420 // reserving SX16 all of the time. 421 Register TmpReg = VE::SX16; 422 build(VE::IMPLICIT_DEF, DestReg); 423 for (int i = 0; i < 4; ++i) { 424 MachineInstr *LdMI = 425 build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); 426 replaceFI(*LdMI, FrameReg, Offset, 1); 427 build(VE::LVMir_m, DestLoReg) 428 .addImm(i) 429 .addReg(TmpReg, getKillRegState(true)) 430 .addReg(DestLoReg); 431 Offset += 8; 432 } 433 for (int i = 0; i < 3; ++i) { 434 MachineInstr *LdMI = 435 build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); 436 replaceFI(*LdMI, FrameReg, Offset, 1); 437 build(VE::LVMir_m, DestHiReg) 438 .addImm(i) 439 .addReg(TmpReg, getKillRegState(true)) 440 .addReg(DestHiReg); 441 Offset += 8; 442 } 443 MI.setDesc(get(VE::LDrii)); 444 MI.getOperand(0).ChangeToRegister(TmpReg, true); 445 BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg) 446 .addImm(3) 447 .addReg(TmpReg, getKillRegState(true)) 448 .addReg(DestHiReg); 449 replaceFI(MI, FrameReg, Offset, FIOperandNum); 450 } 451 452 void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg, 453 int64_t Offset, int FIOperandNum) { 454 switch (MI.getOpcode()) { 455 case VE::STQrii: 456 processSTQ(MI, FrameReg, Offset, FIOperandNum); 457 return; 458 case VE::LDQrii: 459 processLDQ(MI, FrameReg, Offset, FIOperandNum); 460 return; 461 case VE::STVMrii: 462 processSTVM(MI, FrameReg, Offset, FIOperandNum); 463 return; 464 case VE::LDVMrii: 465 processLDVM(MI, FrameReg, Offset, FIOperandNum); 466 return; 467 case VE::STVM512rii: 468 processSTVM512(MI, FrameReg, Offset, FIOperandNum); 469 return; 470 case VE::LDVM512rii: 471 processLDVM512(MI, FrameReg, Offset, FIOperandNum); 472 return; 473 } 474 prepareReplaceFI(MI, FrameReg, Offset); 475 replaceFI(MI, FrameReg, Offset, FIOperandNum); 476 } 477 478 bool VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 479 int SPAdj, unsigned FIOperandNum, 480 RegScavenger *RS) const { 481 assert(SPAdj == 0 && "Unexpected"); 482 483 MachineInstr &MI = *II; 484 int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 485 486 MachineFunction &MF = *MI.getParent()->getParent(); 487 const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>(); 488 const VEFrameLowering &TFI = *getFrameLowering(MF); 489 const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 490 const VERegisterInfo &TRI = *Subtarget.getRegisterInfo(); 491 DebugLoc DL = MI.getDebugLoc(); 492 EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II); 493 494 // Retrieve FrameReg and byte offset for stack slot. 495 Register FrameReg; 496 int64_t Offset = 497 TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed(); 498 Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm(); 499 500 EFI.processMI(MI, FrameReg, Offset, FIOperandNum); 501 return false; 502 } 503 504 Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const { 505 return VE::SX9; 506 } 507