506 lines · cpp
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-exception6//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 24using namespace llvm;25 26#define DEBUG_TYPE "ve-register-info"27 28#define GET_REGINFO_TARGET_DESC29#include "VEGenRegisterInfo.inc"30 31// VE uses %s10 == %lp to keep return address32VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {}33 34const MCPhysReg *35VERegisterInfo::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 46const 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 58const uint32_t *VERegisterInfo::getNoPreservedMask() const {59 return CSR_NoRegs_RegMask;60}61 62BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const {63 BitVector Reserved(getNumRegs());64 65 const Register ReservedRegs[] = {66 VE::SX8, // Stack limit67 VE::SX9, // Frame pointer68 VE::SX10, // Link register (return address)69 VE::SX11, // Stack pointer70 71 // FIXME: maybe not need to be reserved72 VE::SX12, // Outer register73 VE::SX13, // Id register for dynamic linker74 75 VE::SX14, // Thread pointer76 VE::SX15, // Global offset table register77 VE::SX16, // Procedure linkage table register78 VE::SX17, // Linkage-area register79 // sx18-sx33 are callee-saved registers80 // sx34-sx63 are temporary registers81 };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 95const TargetRegisterClass *96VERegisterInfo::getPointerRegClass(unsigned Kind) const {97 return &VE::I64RegClass;98}99 100static unsigned offsetToDisp(MachineInstr &MI) {101 // Default offset in instruction's operands (reg+reg+imm).102 unsigned OffDisp = 2;103 104#define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii105 106 {107 using namespace llvm::VE;108 switch (MI.getOpcode()) {109 case INLINEASM:110 case RRCAS_multi_cases(TS1AML):111 case RRCAS_multi_cases(TS1AMW):112 case RRCAS_multi_cases(CASL):113 case RRCAS_multi_cases(CASW):114 // These instructions use AS format (reg+imm).115 OffDisp = 1;116 break;117 }118 }119#undef RRCAS_multi_cases120 121 return OffDisp;122}123 124namespace {125class EliminateFrameIndex {126 const TargetInstrInfo &TII;127 const TargetRegisterInfo &TRI;128 const DebugLoc &DL;129 MachineBasicBlock &MBB;130 MachineBasicBlock::iterator II;131 Register clobber;132 133 // Some helper functions for the ease of instruction building.134 MachineFunction &getFunc() const { return *MBB.getParent(); }135 inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {136 return TRI.getSubReg(Reg, Idx);137 }138 inline const MCInstrDesc &get(unsigned Opcode) const {139 return TII.get(Opcode);140 }141 inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {142 return BuildMI(MBB, II, DL, MCID, DestReg);143 }144 inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {145 return build(get(InstOpc), DestReg);146 }147 inline MachineInstrBuilder build(const MCInstrDesc &MCID) {148 return BuildMI(MBB, II, DL, MCID);149 }150 inline MachineInstrBuilder build(unsigned InstOpc) {151 return build(get(InstOpc));152 }153 154 // Calculate an address of frame index from a frame register and a given155 // offset if the offset doesn't fit in the immediate field. Use a clobber156 // register to hold calculated address.157 void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,158 int64_t Bytes = 0);159 // Replace the frame index in \p MI with a frame register and a given offset160 // if it fits in the immediate field. Otherwise, use pre-calculated address161 // in a clobber regsiter.162 void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,163 int FIOperandNum);164 165 // Expand and eliminate Frame Index of pseudo STQrii and LDQrii.166 void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,167 int FIOperandNum);168 void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,169 int FIOperandNum);170 // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii.171 void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset,172 int FIOperandNum);173 void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset,174 int FIOperandNum);175 // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii.176 void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,177 int FIOperandNum);178 void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,179 int FIOperandNum);180 181public:182 EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,183 const DebugLoc &DL, MachineBasicBlock &MBB,184 MachineBasicBlock::iterator II)185 : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}186 187 // Expand and eliminate Frame Index from MI188 void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,189 int FIOperandNum);190};191} // namespace192 193// Prepare the frame index if it doesn't fit in the immediate field. Use194// clobber register to hold calculated address.195void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,196 int64_t &Offset, int64_t Bytes) {197 if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {198 // If the offset is small enough to fit in the immediate field, directly199 // encode it. So, nothing to prepare here.200 return;201 }202 203 // If the offset doesn't fit, emit following codes. This clobbers SX13204 // which we always know is available here.205 // lea %clobber, Offset@lo206 // and %clobber, %clobber, (32)0207 // lea.sl %clobber, Offset@hi(FrameReg, %clobber)208 build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));209 build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));210 build(VE::LEASLrri, clobber)211 .addReg(clobber)212 .addReg(FrameReg)213 .addImm(Hi_32(Offset));214 215 // Use clobber register as a frame register and 0 offset216 FrameReg = clobber;217 Offset = 0;218}219 220// Replace the frame index in \p MI with a proper byte and framereg offset.221void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,222 int64_t Offset, int FIOperandNum) {223 assert(isInt<32>(Offset));224 225 // The offset must be small enough to fit in the immediate field after226 // call of prepareReplaceFI. Therefore, we directly encode it.227 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);228 MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);229}230 231void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,232 int64_t Offset, int FIOperandNum) {233 assert(MI.getOpcode() == VE::STQrii);234 LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());235 236 prepareReplaceFI(MI, FrameReg, Offset, 8);237 238 Register SrcReg = MI.getOperand(3).getReg();239 Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);240 Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);241 // VE stores HiReg to 8(addr) and LoReg to 0(addr)242 MachineInstr *StMI =243 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);244 replaceFI(*StMI, FrameReg, Offset, 0);245 // Mutate to 'hi' store.246 MI.setDesc(get(VE::STrii));247 MI.getOperand(3).setReg(SrcHiReg);248 Offset += 8;249 replaceFI(MI, FrameReg, Offset, FIOperandNum);250}251 252void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,253 int64_t Offset, int FIOperandNum) {254 assert(MI.getOpcode() == VE::LDQrii);255 LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());256 257 prepareReplaceFI(MI, FrameReg, Offset, 8);258 259 Register DestReg = MI.getOperand(0).getReg();260 Register DestHiReg = getSubReg(DestReg, VE::sub_even);261 Register DestLoReg = getSubReg(DestReg, VE::sub_odd);262 // VE loads HiReg from 8(addr) and LoReg from 0(addr)263 MachineInstr *StMI =264 build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);265 replaceFI(*StMI, FrameReg, Offset, 1);266 MI.setDesc(get(VE::LDrii));267 MI.getOperand(0).setReg(DestHiReg);268 Offset += 8;269 replaceFI(MI, FrameReg, Offset, FIOperandNum);270}271 272void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg,273 int64_t Offset, int FIOperandNum) {274 assert(MI.getOpcode() == VE::STVMrii);275 LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump());276 277 // Original MI is:278 // STVMrii frame-index, 0, offset, reg (, memory operand)279 // Convert it to:280 // SVMi tmp-reg, reg, 0281 // STrii frame-reg, 0, offset, tmp-reg282 // SVMi tmp-reg, reg, 1283 // STrii frame-reg, 0, offset+8, tmp-reg284 // SVMi tmp-reg, reg, 2285 // STrii frame-reg, 0, offset+16, tmp-reg286 // SVMi tmp-reg, reg, 3287 // STrii frame-reg, 0, offset+24, tmp-reg288 289 prepareReplaceFI(MI, FrameReg, Offset, 24);290 291 Register SrcReg = MI.getOperand(3).getReg();292 bool isKill = MI.getOperand(3).isKill();293 // FIXME: it would be better to scavenge a register here instead of294 // reserving SX16 all of the time.295 Register TmpReg = VE::SX16;296 for (int i = 0; i < 3; ++i) {297 build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i);298 MachineInstr *StMI =299 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(300 TmpReg, getKillRegState(true));301 replaceFI(*StMI, FrameReg, Offset, 0);302 Offset += 8;303 }304 build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3);305 MI.setDesc(get(VE::STrii));306 MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);307 replaceFI(MI, FrameReg, Offset, FIOperandNum);308}309 310void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg,311 int64_t Offset, int FIOperandNum) {312 assert(MI.getOpcode() == VE::LDVMrii);313 LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump());314 315 // Original MI is:316 // LDVMri reg, frame-index, 0, offset (, memory operand)317 // Convert it to:318 // LDrii tmp-reg, frame-reg, 0, offset319 // LVMir vm, 0, tmp-reg320 // LDrii tmp-reg, frame-reg, 0, offset+8321 // LVMir_m vm, 1, tmp-reg, vm322 // LDrii tmp-reg, frame-reg, 0, offset+16323 // LVMir_m vm, 2, tmp-reg, vm324 // LDrii tmp-reg, frame-reg, 0, offset+24325 // LVMir_m vm, 3, tmp-reg, vm326 327 prepareReplaceFI(MI, FrameReg, Offset, 24);328 329 Register DestReg = MI.getOperand(0).getReg();330 // FIXME: it would be better to scavenge a register here instead of331 // reserving SX16 all of the time.332 unsigned TmpReg = VE::SX16;333 for (int i = 0; i < 4; ++i) {334 if (i != 3) {335 MachineInstr *StMI =336 build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);337 replaceFI(*StMI, FrameReg, Offset, 1);338 Offset += 8;339 } else {340 // Last LDrii replace the target instruction.341 MI.setDesc(get(VE::LDrii));342 MI.getOperand(0).ChangeToRegister(TmpReg, true);343 }344 // First LVM is LVMir. Others are LVMir_m. Last LVM places at the345 // next of the target instruction.346 if (i == 0)347 build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true));348 else if (i != 3)349 build(VE::LVMir_m, DestReg)350 .addImm(i)351 .addReg(TmpReg, getKillRegState(true))352 .addReg(DestReg);353 else354 BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg)355 .addImm(3)356 .addReg(TmpReg, getKillRegState(true))357 .addReg(DestReg);358 }359 replaceFI(MI, FrameReg, Offset, FIOperandNum);360}361 362void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg,363 int64_t Offset, int FIOperandNum) {364 assert(MI.getOpcode() == VE::STVM512rii);365 LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump());366 367 prepareReplaceFI(MI, FrameReg, Offset, 56);368 369 Register SrcReg = MI.getOperand(3).getReg();370 Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd);371 Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even);372 bool isKill = MI.getOperand(3).isKill();373 // FIXME: it would be better to scavenge a register here instead of374 // reserving SX16 all of the time.375 Register TmpReg = VE::SX16;376 // store low part of VMP377 MachineInstr *LastMI = nullptr;378 for (int i = 0; i < 4; ++i) {379 LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i);380 MachineInstr *StMI =381 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(382 TmpReg, getKillRegState(true));383 replaceFI(*StMI, FrameReg, Offset, 0);384 Offset += 8;385 }386 if (isKill)387 LastMI->addRegisterKilled(SrcLoReg, &TRI, true);388 // store high part of VMP389 for (int i = 0; i < 3; ++i) {390 build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i);391 MachineInstr *StMI =392 build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(393 TmpReg, getKillRegState(true));394 replaceFI(*StMI, FrameReg, Offset, 0);395 Offset += 8;396 }397 LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3);398 if (isKill) {399 LastMI->addRegisterKilled(SrcHiReg, &TRI, true);400 // Add implicit super-register kills to the particular MI.401 LastMI->addRegisterKilled(SrcReg, &TRI, true);402 }403 MI.setDesc(get(VE::STrii));404 MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);405 replaceFI(MI, FrameReg, Offset, FIOperandNum);406}407 408void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg,409 int64_t Offset, int FIOperandNum) {410 assert(MI.getOpcode() == VE::LDVM512rii);411 LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump());412 413 prepareReplaceFI(MI, FrameReg, Offset, 56);414 415 Register DestReg = MI.getOperand(0).getReg();416 Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd);417 Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even);418 // FIXME: it would be better to scavenge a register here instead of419 // reserving SX16 all of the time.420 Register TmpReg = VE::SX16;421 build(VE::IMPLICIT_DEF, DestReg);422 for (int i = 0; i < 4; ++i) {423 MachineInstr *LdMI =424 build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);425 replaceFI(*LdMI, FrameReg, Offset, 1);426 build(VE::LVMir_m, DestLoReg)427 .addImm(i)428 .addReg(TmpReg, getKillRegState(true))429 .addReg(DestLoReg);430 Offset += 8;431 }432 for (int i = 0; i < 3; ++i) {433 MachineInstr *LdMI =434 build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);435 replaceFI(*LdMI, FrameReg, Offset, 1);436 build(VE::LVMir_m, DestHiReg)437 .addImm(i)438 .addReg(TmpReg, getKillRegState(true))439 .addReg(DestHiReg);440 Offset += 8;441 }442 MI.setDesc(get(VE::LDrii));443 MI.getOperand(0).ChangeToRegister(TmpReg, true);444 BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg)445 .addImm(3)446 .addReg(TmpReg, getKillRegState(true))447 .addReg(DestHiReg);448 replaceFI(MI, FrameReg, Offset, FIOperandNum);449}450 451void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,452 int64_t Offset, int FIOperandNum) {453 switch (MI.getOpcode()) {454 case VE::STQrii:455 processSTQ(MI, FrameReg, Offset, FIOperandNum);456 return;457 case VE::LDQrii:458 processLDQ(MI, FrameReg, Offset, FIOperandNum);459 return;460 case VE::STVMrii:461 processSTVM(MI, FrameReg, Offset, FIOperandNum);462 return;463 case VE::LDVMrii:464 processLDVM(MI, FrameReg, Offset, FIOperandNum);465 return;466 case VE::STVM512rii:467 processSTVM512(MI, FrameReg, Offset, FIOperandNum);468 return;469 case VE::LDVM512rii:470 processLDVM512(MI, FrameReg, Offset, FIOperandNum);471 return;472 }473 prepareReplaceFI(MI, FrameReg, Offset);474 replaceFI(MI, FrameReg, Offset, FIOperandNum);475}476 477bool VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,478 int SPAdj, unsigned FIOperandNum,479 RegScavenger *RS) const {480 assert(SPAdj == 0 && "Unexpected");481 482 MachineInstr &MI = *II;483 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();484 485 MachineFunction &MF = *MI.getParent()->getParent();486 const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();487 const VEFrameLowering &TFI = *getFrameLowering(MF);488 const TargetInstrInfo &TII = *Subtarget.getInstrInfo();489 const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();490 DebugLoc DL = MI.getDebugLoc();491 EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);492 493 // Retrieve FrameReg and byte offset for stack slot.494 Register FrameReg;495 int64_t Offset =496 TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();497 Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();498 499 EFI.processMI(MI, FrameReg, Offset, FIOperandNum);500 return false;501}502 503Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {504 return VE::SX9;505}506