Path: blob/main/contrib/llvm-project/llvm/lib/Target/VE/VERegisterInfo.cpp
96353 views
//===-- VERegisterInfo.cpp - VE Register Information ----------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the VE implementation of the TargetRegisterInfo class.9//10//===----------------------------------------------------------------------===//1112#include "VERegisterInfo.h"13#include "VE.h"14#include "VESubtarget.h"15#include "llvm/ADT/BitVector.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/CodeGen/MachineFrameInfo.h"18#include "llvm/CodeGen/MachineFunction.h"19#include "llvm/CodeGen/MachineInstrBuilder.h"20#include "llvm/CodeGen/MachineRegisterInfo.h"21#include "llvm/CodeGen/TargetInstrInfo.h"22#include "llvm/IR/Type.h"23#include "llvm/Support/CommandLine.h"24#include "llvm/Support/Debug.h"25#include "llvm/Support/ErrorHandling.h"2627using namespace llvm;2829#define DEBUG_TYPE "ve-register-info"3031#define GET_REGINFO_TARGET_DESC32#include "VEGenRegisterInfo.inc"3334// VE uses %s10 == %lp to keep return address35VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {}3637const MCPhysReg *38VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {39switch (MF->getFunction().getCallingConv()) {40case CallingConv::Fast:41// Being explicit (same as standard CC).42default:43return CSR_SaveList;44case CallingConv::PreserveAll:45return CSR_preserve_all_SaveList;46}47}4849const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF,50CallingConv::ID CC) const {51switch (CC) {52case CallingConv::Fast:53// Being explicit (same as standard CC).54default:55return CSR_RegMask;56case CallingConv::PreserveAll:57return CSR_preserve_all_RegMask;58}59}6061const uint32_t *VERegisterInfo::getNoPreservedMask() const {62return CSR_NoRegs_RegMask;63}6465BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const {66BitVector Reserved(getNumRegs());6768const Register ReservedRegs[] = {69VE::SX8, // Stack limit70VE::SX9, // Frame pointer71VE::SX10, // Link register (return address)72VE::SX11, // Stack pointer7374// FIXME: maybe not need to be reserved75VE::SX12, // Outer register76VE::SX13, // Id register for dynamic linker7778VE::SX14, // Thread pointer79VE::SX15, // Global offset table register80VE::SX16, // Procedure linkage table register81VE::SX17, // Linkage-area register82// sx18-sx33 are callee-saved registers83// sx34-sx63 are temporary registers84};8586for (auto R : ReservedRegs)87for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid();88++ItAlias)89Reserved.set(*ItAlias);9091// Reserve constant registers.92Reserved.set(VE::VM0);93Reserved.set(VE::VMP0);9495return Reserved;96}9798const TargetRegisterClass *99VERegisterInfo::getPointerRegClass(const MachineFunction &MF,100unsigned Kind) const {101return &VE::I64RegClass;102}103104static unsigned offsetToDisp(MachineInstr &MI) {105// Default offset in instruction's operands (reg+reg+imm).106unsigned OffDisp = 2;107108#define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii109110{111using namespace llvm::VE;112switch (MI.getOpcode()) {113case INLINEASM:114case RRCAS_multi_cases(TS1AML):115case RRCAS_multi_cases(TS1AMW):116case RRCAS_multi_cases(CASL):117case RRCAS_multi_cases(CASW):118// These instructions use AS format (reg+imm).119OffDisp = 1;120break;121}122}123#undef RRCAS_multi_cases124125return OffDisp;126}127128namespace {129class EliminateFrameIndex {130const TargetInstrInfo &TII;131const TargetRegisterInfo &TRI;132const DebugLoc &DL;133MachineBasicBlock &MBB;134MachineBasicBlock::iterator II;135Register clobber;136137// Some helper functions for the ease of instruction building.138MachineFunction &getFunc() const { return *MBB.getParent(); }139inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {140return TRI.getSubReg(Reg, Idx);141}142inline const MCInstrDesc &get(unsigned Opcode) const {143return TII.get(Opcode);144}145inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {146return BuildMI(MBB, II, DL, MCID, DestReg);147}148inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {149return build(get(InstOpc), DestReg);150}151inline MachineInstrBuilder build(const MCInstrDesc &MCID) {152return BuildMI(MBB, II, DL, MCID);153}154inline MachineInstrBuilder build(unsigned InstOpc) {155return build(get(InstOpc));156}157158// Calculate an address of frame index from a frame register and a given159// offset if the offset doesn't fit in the immediate field. Use a clobber160// register to hold calculated address.161void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,162int64_t Bytes = 0);163// Replace the frame index in \p MI with a frame register and a given offset164// if it fits in the immediate field. Otherwise, use pre-calculated address165// in a clobber regsiter.166void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,167int FIOperandNum);168169// Expand and eliminate Frame Index of pseudo STQrii and LDQrii.170void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,171int FIOperandNum);172void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,173int FIOperandNum);174// Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii.175void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset,176int FIOperandNum);177void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset,178int FIOperandNum);179// Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii.180void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,181int FIOperandNum);182void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,183int FIOperandNum);184185public:186EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,187const DebugLoc &DL, MachineBasicBlock &MBB,188MachineBasicBlock::iterator II)189: TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}190191// Expand and eliminate Frame Index from MI192void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,193int FIOperandNum);194};195} // namespace196197// Prepare the frame index if it doesn't fit in the immediate field. Use198// clobber register to hold calculated address.199void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,200int64_t &Offset, int64_t Bytes) {201if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {202// If the offset is small enough to fit in the immediate field, directly203// encode it. So, nothing to prepare here.204return;205}206207// If the offset doesn't fit, emit following codes. This clobbers SX13208// which we always know is available here.209// lea %clobber, Offset@lo210// and %clobber, %clobber, (32)0211// lea.sl %clobber, Offset@hi(FrameReg, %clobber)212build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));213build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));214build(VE::LEASLrri, clobber)215.addReg(clobber)216.addReg(FrameReg)217.addImm(Hi_32(Offset));218219// Use clobber register as a frame register and 0 offset220FrameReg = clobber;221Offset = 0;222}223224// Replace the frame index in \p MI with a proper byte and framereg offset.225void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,226int64_t Offset, int FIOperandNum) {227assert(isInt<32>(Offset));228229// The offset must be small enough to fit in the immediate field after230// call of prepareReplaceFI. Therefore, we directly encode it.231MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);232MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);233}234235void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,236int64_t Offset, int FIOperandNum) {237assert(MI.getOpcode() == VE::STQrii);238LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());239240prepareReplaceFI(MI, FrameReg, Offset, 8);241242Register SrcReg = MI.getOperand(3).getReg();243Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);244Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);245// VE stores HiReg to 8(addr) and LoReg to 0(addr)246MachineInstr *StMI =247build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);248replaceFI(*StMI, FrameReg, Offset, 0);249// Mutate to 'hi' store.250MI.setDesc(get(VE::STrii));251MI.getOperand(3).setReg(SrcHiReg);252Offset += 8;253replaceFI(MI, FrameReg, Offset, FIOperandNum);254}255256void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,257int64_t Offset, int FIOperandNum) {258assert(MI.getOpcode() == VE::LDQrii);259LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());260261prepareReplaceFI(MI, FrameReg, Offset, 8);262263Register DestReg = MI.getOperand(0).getReg();264Register DestHiReg = getSubReg(DestReg, VE::sub_even);265Register DestLoReg = getSubReg(DestReg, VE::sub_odd);266// VE loads HiReg from 8(addr) and LoReg from 0(addr)267MachineInstr *StMI =268build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);269replaceFI(*StMI, FrameReg, Offset, 1);270MI.setDesc(get(VE::LDrii));271MI.getOperand(0).setReg(DestHiReg);272Offset += 8;273replaceFI(MI, FrameReg, Offset, FIOperandNum);274}275276void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg,277int64_t Offset, int FIOperandNum) {278assert(MI.getOpcode() == VE::STVMrii);279LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump());280281// Original MI is:282// STVMrii frame-index, 0, offset, reg (, memory operand)283// Convert it to:284// SVMi tmp-reg, reg, 0285// STrii frame-reg, 0, offset, tmp-reg286// SVMi tmp-reg, reg, 1287// STrii frame-reg, 0, offset+8, tmp-reg288// SVMi tmp-reg, reg, 2289// STrii frame-reg, 0, offset+16, tmp-reg290// SVMi tmp-reg, reg, 3291// STrii frame-reg, 0, offset+24, tmp-reg292293prepareReplaceFI(MI, FrameReg, Offset, 24);294295Register SrcReg = MI.getOperand(3).getReg();296bool isKill = MI.getOperand(3).isKill();297// FIXME: it would be better to scavenge a register here instead of298// reserving SX16 all of the time.299Register TmpReg = VE::SX16;300for (int i = 0; i < 3; ++i) {301build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i);302MachineInstr *StMI =303build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(304TmpReg, getKillRegState(true));305replaceFI(*StMI, FrameReg, Offset, 0);306Offset += 8;307}308build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3);309MI.setDesc(get(VE::STrii));310MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);311replaceFI(MI, FrameReg, Offset, FIOperandNum);312}313314void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg,315int64_t Offset, int FIOperandNum) {316assert(MI.getOpcode() == VE::LDVMrii);317LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump());318319// Original MI is:320// LDVMri reg, frame-index, 0, offset (, memory operand)321// Convert it to:322// LDrii tmp-reg, frame-reg, 0, offset323// LVMir vm, 0, tmp-reg324// LDrii tmp-reg, frame-reg, 0, offset+8325// LVMir_m vm, 1, tmp-reg, vm326// LDrii tmp-reg, frame-reg, 0, offset+16327// LVMir_m vm, 2, tmp-reg, vm328// LDrii tmp-reg, frame-reg, 0, offset+24329// LVMir_m vm, 3, tmp-reg, vm330331prepareReplaceFI(MI, FrameReg, Offset, 24);332333Register DestReg = MI.getOperand(0).getReg();334// FIXME: it would be better to scavenge a register here instead of335// reserving SX16 all of the time.336unsigned TmpReg = VE::SX16;337for (int i = 0; i < 4; ++i) {338if (i != 3) {339MachineInstr *StMI =340build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);341replaceFI(*StMI, FrameReg, Offset, 1);342Offset += 8;343} else {344// Last LDrii replace the target instruction.345MI.setDesc(get(VE::LDrii));346MI.getOperand(0).ChangeToRegister(TmpReg, true);347}348// First LVM is LVMir. Others are LVMir_m. Last LVM places at the349// next of the target instruction.350if (i == 0)351build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true));352else if (i != 3)353build(VE::LVMir_m, DestReg)354.addImm(i)355.addReg(TmpReg, getKillRegState(true))356.addReg(DestReg);357else358BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg)359.addImm(3)360.addReg(TmpReg, getKillRegState(true))361.addReg(DestReg);362}363replaceFI(MI, FrameReg, Offset, FIOperandNum);364}365366void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg,367int64_t Offset, int FIOperandNum) {368assert(MI.getOpcode() == VE::STVM512rii);369LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump());370371prepareReplaceFI(MI, FrameReg, Offset, 56);372373Register SrcReg = MI.getOperand(3).getReg();374Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd);375Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even);376bool isKill = MI.getOperand(3).isKill();377// FIXME: it would be better to scavenge a register here instead of378// reserving SX16 all of the time.379Register TmpReg = VE::SX16;380// store low part of VMP381MachineInstr *LastMI = nullptr;382for (int i = 0; i < 4; ++i) {383LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i);384MachineInstr *StMI =385build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(386TmpReg, getKillRegState(true));387replaceFI(*StMI, FrameReg, Offset, 0);388Offset += 8;389}390if (isKill)391LastMI->addRegisterKilled(SrcLoReg, &TRI, true);392// store high part of VMP393for (int i = 0; i < 3; ++i) {394build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i);395MachineInstr *StMI =396build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(397TmpReg, getKillRegState(true));398replaceFI(*StMI, FrameReg, Offset, 0);399Offset += 8;400}401LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3);402if (isKill) {403LastMI->addRegisterKilled(SrcHiReg, &TRI, true);404// Add implicit super-register kills to the particular MI.405LastMI->addRegisterKilled(SrcReg, &TRI, true);406}407MI.setDesc(get(VE::STrii));408MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);409replaceFI(MI, FrameReg, Offset, FIOperandNum);410}411412void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg,413int64_t Offset, int FIOperandNum) {414assert(MI.getOpcode() == VE::LDVM512rii);415LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump());416417prepareReplaceFI(MI, FrameReg, Offset, 56);418419Register DestReg = MI.getOperand(0).getReg();420Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd);421Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even);422// FIXME: it would be better to scavenge a register here instead of423// reserving SX16 all of the time.424Register TmpReg = VE::SX16;425build(VE::IMPLICIT_DEF, DestReg);426for (int i = 0; i < 4; ++i) {427MachineInstr *LdMI =428build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);429replaceFI(*LdMI, FrameReg, Offset, 1);430build(VE::LVMir_m, DestLoReg)431.addImm(i)432.addReg(TmpReg, getKillRegState(true))433.addReg(DestLoReg);434Offset += 8;435}436for (int i = 0; i < 3; ++i) {437MachineInstr *LdMI =438build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);439replaceFI(*LdMI, FrameReg, Offset, 1);440build(VE::LVMir_m, DestHiReg)441.addImm(i)442.addReg(TmpReg, getKillRegState(true))443.addReg(DestHiReg);444Offset += 8;445}446MI.setDesc(get(VE::LDrii));447MI.getOperand(0).ChangeToRegister(TmpReg, true);448BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg)449.addImm(3)450.addReg(TmpReg, getKillRegState(true))451.addReg(DestHiReg);452replaceFI(MI, FrameReg, Offset, FIOperandNum);453}454455void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,456int64_t Offset, int FIOperandNum) {457switch (MI.getOpcode()) {458case VE::STQrii:459processSTQ(MI, FrameReg, Offset, FIOperandNum);460return;461case VE::LDQrii:462processLDQ(MI, FrameReg, Offset, FIOperandNum);463return;464case VE::STVMrii:465processSTVM(MI, FrameReg, Offset, FIOperandNum);466return;467case VE::LDVMrii:468processLDVM(MI, FrameReg, Offset, FIOperandNum);469return;470case VE::STVM512rii:471processSTVM512(MI, FrameReg, Offset, FIOperandNum);472return;473case VE::LDVM512rii:474processLDVM512(MI, FrameReg, Offset, FIOperandNum);475return;476}477prepareReplaceFI(MI, FrameReg, Offset);478replaceFI(MI, FrameReg, Offset, FIOperandNum);479}480481bool VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,482int SPAdj, unsigned FIOperandNum,483RegScavenger *RS) const {484assert(SPAdj == 0 && "Unexpected");485486MachineInstr &MI = *II;487int FrameIndex = MI.getOperand(FIOperandNum).getIndex();488489MachineFunction &MF = *MI.getParent()->getParent();490const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();491const VEFrameLowering &TFI = *getFrameLowering(MF);492const TargetInstrInfo &TII = *Subtarget.getInstrInfo();493const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();494DebugLoc DL = MI.getDebugLoc();495EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);496497// Retrieve FrameReg and byte offset for stack slot.498Register FrameReg;499int64_t Offset =500TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();501Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();502503EFI.processMI(MI, FrameReg, Offset, FIOperandNum);504return false;505}506507Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {508return VE::SX9;509}510511512