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 // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii. 184 void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset, 185 int FIOperandNum); 186 void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset, 187 int FIOperandNum); 188 // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii. 189 void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset, 190 int FIOperandNum); 191 void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset, 192 int FIOperandNum); 193 194 public: 195 EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, 196 const DebugLoc &DL, MachineBasicBlock &MBB, 197 MachineBasicBlock::iterator II) 198 : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {} 199 200 // Expand and eliminate Frame Index from MI 201 void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset, 202 int FIOperandNum); 203 }; 204 205 // Prepare the frame index if it doesn't fit in the immediate field. Use 206 // clobber register to hold calculated address. 207 void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg, 208 int64_t &Offset, int64_t Bytes) { 209 if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) { 210 // If the offset is small enough to fit in the immediate field, directly 211 // encode it. So, nothing to prepare here. 212 return; 213 } 214 215 // If the offset doesn't fit, emit following codes. This clobbers SX13 216 // which we always know is available here. 217 // lea %clobber, Offset@lo 218 // and %clobber, %clobber, (32)0 219 // lea.sl %clobber, Offset@hi(FrameReg, %clobber) 220 build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset)); 221 build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32)); 222 build(VE::LEASLrri, clobber) 223 .addReg(clobber) 224 .addReg(FrameReg) 225 .addImm(Hi_32(Offset)); 226 227 // Use clobber register as a frame register and 0 offset 228 FrameReg = clobber; 229 Offset = 0; 230 } 231 232 // Replace the frame index in \p MI with a proper byte and framereg offset. 233 void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg, 234 int64_t Offset, int FIOperandNum) { 235 assert(isInt<32>(Offset)); 236 237 // The offset must be small enough to fit in the immediate field after 238 // call of prepareReplaceFI. Therefore, we directly encode it. 239 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); 240 MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset); 241 } 242 243 void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg, 244 int64_t Offset, int FIOperandNum) { 245 assert(MI.getOpcode() == VE::STQrii); 246 LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump()); 247 248 prepareReplaceFI(MI, FrameReg, Offset, 8); 249 250 Register SrcReg = MI.getOperand(3).getReg(); 251 Register SrcHiReg = getSubReg(SrcReg, VE::sub_even); 252 Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd); 253 // VE stores HiReg to 8(addr) and LoReg to 0(addr) 254 MachineInstr *StMI = 255 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg); 256 replaceFI(*StMI, FrameReg, Offset, 0); 257 // Mutate to 'hi' store. 258 MI.setDesc(get(VE::STrii)); 259 MI.getOperand(3).setReg(SrcHiReg); 260 Offset += 8; 261 replaceFI(MI, FrameReg, Offset, FIOperandNum); 262 } 263 264 void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg, 265 int64_t Offset, int FIOperandNum) { 266 assert(MI.getOpcode() == VE::LDQrii); 267 LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump()); 268 269 prepareReplaceFI(MI, FrameReg, Offset, 8); 270 271 Register DestReg = MI.getOperand(0).getReg(); 272 Register DestHiReg = getSubReg(DestReg, VE::sub_even); 273 Register DestLoReg = getSubReg(DestReg, VE::sub_odd); 274 // VE loads HiReg from 8(addr) and LoReg from 0(addr) 275 MachineInstr *StMI = 276 build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0); 277 replaceFI(*StMI, FrameReg, Offset, 1); 278 MI.setDesc(get(VE::LDrii)); 279 MI.getOperand(0).setReg(DestHiReg); 280 Offset += 8; 281 replaceFI(MI, FrameReg, Offset, FIOperandNum); 282 } 283 284 void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg, 285 int64_t Offset, int FIOperandNum) { 286 assert(MI.getOpcode() == VE::STVMrii); 287 LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump()); 288 289 // Original MI is: 290 // STVMrii frame-index, 0, offset, reg (, memory operand) 291 // Convert it to: 292 // SVMi tmp-reg, reg, 0 293 // STrii frame-reg, 0, offset, tmp-reg 294 // SVMi tmp-reg, reg, 1 295 // STrii frame-reg, 0, offset+8, tmp-reg 296 // SVMi tmp-reg, reg, 2 297 // STrii frame-reg, 0, offset+16, tmp-reg 298 // SVMi tmp-reg, reg, 3 299 // STrii frame-reg, 0, offset+24, tmp-reg 300 301 prepareReplaceFI(MI, FrameReg, Offset, 24); 302 303 Register SrcReg = MI.getOperand(3).getReg(); 304 bool isKill = MI.getOperand(3).isKill(); 305 // FIXME: it would be better to scavenge a register here instead of 306 // reserving SX16 all of the time. 307 Register TmpReg = VE::SX16; 308 for (int i = 0; i < 3; ++i) { 309 build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i); 310 MachineInstr *StMI = 311 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( 312 TmpReg, getKillRegState(true)); 313 replaceFI(*StMI, FrameReg, Offset, 0); 314 Offset += 8; 315 } 316 build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3); 317 MI.setDesc(get(VE::STrii)); 318 MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true); 319 replaceFI(MI, FrameReg, Offset, FIOperandNum); 320 } 321 322 void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg, 323 int64_t Offset, int FIOperandNum) { 324 assert(MI.getOpcode() == VE::LDVMrii); 325 LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump()); 326 327 // Original MI is: 328 // LDVMri reg, frame-index, 0, offset (, memory operand) 329 // Convert it to: 330 // LDrii tmp-reg, frame-reg, 0, offset 331 // LVMir vm, 0, tmp-reg 332 // LDrii tmp-reg, frame-reg, 0, offset+8 333 // LVMir_m vm, 1, tmp-reg, vm 334 // LDrii tmp-reg, frame-reg, 0, offset+16 335 // LVMir_m vm, 2, tmp-reg, vm 336 // LDrii tmp-reg, frame-reg, 0, offset+24 337 // LVMir_m vm, 3, tmp-reg, vm 338 339 prepareReplaceFI(MI, FrameReg, Offset, 24); 340 341 Register DestReg = MI.getOperand(0).getReg(); 342 // FIXME: it would be better to scavenge a register here instead of 343 // reserving SX16 all of the time. 344 unsigned TmpReg = VE::SX16; 345 for (int i = 0; i < 4; ++i) { 346 if (i != 3) { 347 MachineInstr *StMI = 348 build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); 349 replaceFI(*StMI, FrameReg, Offset, 1); 350 Offset += 8; 351 } else { 352 // Last LDrii replace the target instruction. 353 MI.setDesc(get(VE::LDrii)); 354 MI.getOperand(0).ChangeToRegister(TmpReg, true); 355 } 356 // First LVM is LVMir. Others are LVMir_m. Last LVM places at the 357 // next of the target instruction. 358 if (i == 0) 359 build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true)); 360 else if (i != 3) 361 build(VE::LVMir_m, DestReg) 362 .addImm(i) 363 .addReg(TmpReg, getKillRegState(true)) 364 .addReg(DestReg); 365 else 366 BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg) 367 .addImm(3) 368 .addReg(TmpReg, getKillRegState(true)) 369 .addReg(DestReg); 370 } 371 replaceFI(MI, FrameReg, Offset, FIOperandNum); 372 } 373 374 void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg, 375 int64_t Offset, int FIOperandNum) { 376 assert(MI.getOpcode() == VE::STVM512rii); 377 LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump()); 378 379 prepareReplaceFI(MI, FrameReg, Offset, 56); 380 381 Register SrcReg = MI.getOperand(3).getReg(); 382 Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd); 383 Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even); 384 bool isKill = MI.getOperand(3).isKill(); 385 // FIXME: it would be better to scavenge a register here instead of 386 // reserving SX16 all of the time. 387 Register TmpReg = VE::SX16; 388 // store low part of VMP 389 MachineInstr *LastMI = nullptr; 390 for (int i = 0; i < 4; ++i) { 391 LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).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 if (isKill) 399 LastMI->addRegisterKilled(SrcLoReg, &TRI, true); 400 // store high part of VMP 401 for (int i = 0; i < 3; ++i) { 402 build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i); 403 MachineInstr *StMI = 404 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( 405 TmpReg, getKillRegState(true)); 406 replaceFI(*StMI, FrameReg, Offset, 0); 407 Offset += 8; 408 } 409 LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3); 410 if (isKill) { 411 LastMI->addRegisterKilled(SrcHiReg, &TRI, true); 412 // Add implicit super-register kills to the particular MI. 413 LastMI->addRegisterKilled(SrcReg, &TRI, true); 414 } 415 MI.setDesc(get(VE::STrii)); 416 MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true); 417 replaceFI(MI, FrameReg, Offset, FIOperandNum); 418 } 419 420 void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg, 421 int64_t Offset, int FIOperandNum) { 422 assert(MI.getOpcode() == VE::LDVM512rii); 423 LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump()); 424 425 prepareReplaceFI(MI, FrameReg, Offset, 56); 426 427 Register DestReg = MI.getOperand(0).getReg(); 428 Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd); 429 Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even); 430 // FIXME: it would be better to scavenge a register here instead of 431 // reserving SX16 all of the time. 432 Register TmpReg = VE::SX16; 433 build(VE::IMPLICIT_DEF, DestReg); 434 for (int i = 0; i < 4; ++i) { 435 MachineInstr *LdMI = 436 build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); 437 replaceFI(*LdMI, FrameReg, Offset, 1); 438 build(VE::LVMir_m, DestLoReg) 439 .addImm(i) 440 .addReg(TmpReg, getKillRegState(true)) 441 .addReg(DestLoReg); 442 Offset += 8; 443 } 444 for (int i = 0; i < 3; ++i) { 445 MachineInstr *LdMI = 446 build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); 447 replaceFI(*LdMI, FrameReg, Offset, 1); 448 build(VE::LVMir_m, DestHiReg) 449 .addImm(i) 450 .addReg(TmpReg, getKillRegState(true)) 451 .addReg(DestHiReg); 452 Offset += 8; 453 } 454 MI.setDesc(get(VE::LDrii)); 455 MI.getOperand(0).ChangeToRegister(TmpReg, true); 456 BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg) 457 .addImm(3) 458 .addReg(TmpReg, getKillRegState(true)) 459 .addReg(DestHiReg); 460 replaceFI(MI, FrameReg, Offset, FIOperandNum); 461 } 462 463 void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg, 464 int64_t Offset, int FIOperandNum) { 465 switch (MI.getOpcode()) { 466 case VE::STQrii: 467 processSTQ(MI, FrameReg, Offset, FIOperandNum); 468 return; 469 case VE::LDQrii: 470 processLDQ(MI, FrameReg, Offset, FIOperandNum); 471 return; 472 case VE::STVMrii: 473 processSTVM(MI, FrameReg, Offset, FIOperandNum); 474 return; 475 case VE::LDVMrii: 476 processLDVM(MI, FrameReg, Offset, FIOperandNum); 477 return; 478 case VE::STVM512rii: 479 processSTVM512(MI, FrameReg, Offset, FIOperandNum); 480 return; 481 case VE::LDVM512rii: 482 processLDVM512(MI, FrameReg, Offset, FIOperandNum); 483 return; 484 } 485 prepareReplaceFI(MI, FrameReg, Offset); 486 replaceFI(MI, FrameReg, Offset, FIOperandNum); 487 } 488 489 void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 490 int SPAdj, unsigned FIOperandNum, 491 RegScavenger *RS) const { 492 assert(SPAdj == 0 && "Unexpected"); 493 494 MachineInstr &MI = *II; 495 int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 496 497 MachineFunction &MF = *MI.getParent()->getParent(); 498 const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>(); 499 const VEFrameLowering &TFI = *getFrameLowering(MF); 500 const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 501 const VERegisterInfo &TRI = *Subtarget.getRegisterInfo(); 502 DebugLoc DL = MI.getDebugLoc(); 503 EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II); 504 505 // Retrieve FrameReg and byte offset for stack slot. 506 Register FrameReg; 507 int64_t Offset = 508 TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed(); 509 Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm(); 510 511 EFI.processMI(MI, FrameReg, Offset, FIOperandNum); 512 } 513 514 Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const { 515 return VE::SX9; 516 } 517