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