brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.8 KiB · 99e1f61 Raw
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