106c3fb27SDimitry Andric //===-- RISCVRegisterInfo.h - RISC-V Register Information Impl --*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 906c3fb27SDimitry Andric // This file contains the RISC-V implementation of the TargetRegisterInfo class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_RISCV_RISCVREGISTERINFO_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_RISCV_RISCVREGISTERINFO_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 17*0fca6ea1SDimitry Andric #include "llvm/TargetParser/RISCVTargetParser.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #define GET_REGINFO_HEADER 200b57cec5SDimitry Andric #include "RISCVGenRegisterInfo.inc" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace llvm { 230b57cec5SDimitry Andric 24*0fca6ea1SDimitry Andric namespace RISCVRI { 25*0fca6ea1SDimitry Andric enum { 26*0fca6ea1SDimitry Andric // The IsVRegClass value of this RegisterClass. 27*0fca6ea1SDimitry Andric IsVRegClassShift = 0, 28*0fca6ea1SDimitry Andric IsVRegClassShiftMask = 0b1 << IsVRegClassShift, 29*0fca6ea1SDimitry Andric // The VLMul value of this RegisterClass. This value is valid iff IsVRegClass 30*0fca6ea1SDimitry Andric // is true. 31*0fca6ea1SDimitry Andric VLMulShift = IsVRegClassShift + 1, 32*0fca6ea1SDimitry Andric VLMulShiftMask = 0b111 << VLMulShift, 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric // The NF value of this RegisterClass. This value is valid iff IsVRegClass is 35*0fca6ea1SDimitry Andric // true. 36*0fca6ea1SDimitry Andric NFShift = VLMulShift + 3, 37*0fca6ea1SDimitry Andric NFShiftMask = 0b111 << NFShift, 38*0fca6ea1SDimitry Andric }; 39*0fca6ea1SDimitry Andric 40*0fca6ea1SDimitry Andric /// \returns the IsVRegClass for the register class. 41*0fca6ea1SDimitry Andric static inline bool isVRegClass(uint64_t TSFlags) { 42*0fca6ea1SDimitry Andric return TSFlags & IsVRegClassShiftMask >> IsVRegClassShift; 43*0fca6ea1SDimitry Andric } 44*0fca6ea1SDimitry Andric 45*0fca6ea1SDimitry Andric /// \returns the LMUL for the register class. 46*0fca6ea1SDimitry Andric static inline RISCVII::VLMUL getLMul(uint64_t TSFlags) { 47*0fca6ea1SDimitry Andric return static_cast<RISCVII::VLMUL>((TSFlags & VLMulShiftMask) >> VLMulShift); 48*0fca6ea1SDimitry Andric } 49*0fca6ea1SDimitry Andric 50*0fca6ea1SDimitry Andric /// \returns the NF for the register class. 51*0fca6ea1SDimitry Andric static inline unsigned getNF(uint64_t TSFlags) { 52*0fca6ea1SDimitry Andric return static_cast<unsigned>((TSFlags & NFShiftMask) >> NFShift) + 1; 53*0fca6ea1SDimitry Andric } 54*0fca6ea1SDimitry Andric } // namespace RISCVRI 55*0fca6ea1SDimitry Andric 560b57cec5SDimitry Andric struct RISCVRegisterInfo : public RISCVGenRegisterInfo { 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric RISCVRegisterInfo(unsigned HwMode); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric const uint32_t *getCallPreservedMask(const MachineFunction &MF, 610b57cec5SDimitry Andric CallingConv::ID) const override; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric BitVector getReservedRegs(const MachineFunction &MF) const override; 66480093f4SDimitry Andric bool isAsmClobberable(const MachineFunction &MF, 675ffd83dbSDimitry Andric MCRegister PhysReg) const override; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric const uint32_t *getNoPreservedMask() const override; 700b57cec5SDimitry Andric 71bdd1243dSDimitry Andric // Update DestReg to have the value SrcReg plus an offset. This is 72bdd1243dSDimitry Andric // used during frame layout, and we may need to ensure that if we 73bdd1243dSDimitry Andric // split the offset internally that the DestReg is always aligned, 74bdd1243dSDimitry Andric // assuming that source reg was. 75bdd1243dSDimitry Andric void adjustReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator II, 76bdd1243dSDimitry Andric const DebugLoc &DL, Register DestReg, Register SrcReg, 77bdd1243dSDimitry Andric StackOffset Offset, MachineInstr::MIFlag Flag, 78bdd1243dSDimitry Andric MaybeAlign RequiredAlign) const; 79bdd1243dSDimitry Andric 80bdd1243dSDimitry Andric bool eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, 810b57cec5SDimitry Andric unsigned FIOperandNum, 820b57cec5SDimitry Andric RegScavenger *RS = nullptr) const override; 830b57cec5SDimitry Andric 84bdd1243dSDimitry Andric bool requiresVirtualBaseRegisters(const MachineFunction &MF) const override; 85bdd1243dSDimitry Andric 86bdd1243dSDimitry Andric bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override; 87bdd1243dSDimitry Andric 88bdd1243dSDimitry Andric bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg, 89bdd1243dSDimitry Andric int64_t Offset) const override; 90bdd1243dSDimitry Andric 91bdd1243dSDimitry Andric Register materializeFrameBaseRegister(MachineBasicBlock *MBB, int FrameIdx, 92bdd1243dSDimitry Andric int64_t Offset) const override; 93bdd1243dSDimitry Andric 94bdd1243dSDimitry Andric void resolveFrameIndex(MachineInstr &MI, Register BaseReg, 95bdd1243dSDimitry Andric int64_t Offset) const override; 96bdd1243dSDimitry Andric 97bdd1243dSDimitry Andric int64_t getFrameIndexInstrOffset(const MachineInstr *MI, 98bdd1243dSDimitry Andric int Idx) const override; 99bdd1243dSDimitry Andric 100bdd1243dSDimitry Andric void lowerVSPILL(MachineBasicBlock::iterator II) const; 101bdd1243dSDimitry Andric void lowerVRELOAD(MachineBasicBlock::iterator II) const; 102bdd1243dSDimitry Andric 1030b57cec5SDimitry Andric Register getFrameRegister(const MachineFunction &MF) const override; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric bool requiresRegisterScavenging(const MachineFunction &MF) const override { 1060b57cec5SDimitry Andric return true; 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric bool requiresFrameIndexScavenging(const MachineFunction &MF) const override { 1100b57cec5SDimitry Andric return true; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 113c14a5a88SDimitry Andric const TargetRegisterClass * 114c14a5a88SDimitry Andric getPointerRegClass(const MachineFunction &MF, 115c14a5a88SDimitry Andric unsigned Kind = 0) const override { 116c14a5a88SDimitry Andric return &RISCV::GPRRegClass; 117c14a5a88SDimitry Andric } 118fe6060f1SDimitry Andric 119fe6060f1SDimitry Andric const TargetRegisterClass * 120fe6060f1SDimitry Andric getLargestLegalSuperClass(const TargetRegisterClass *RC, 121fe6060f1SDimitry Andric const MachineFunction &) const override; 1224824e7fdSDimitry Andric 1234824e7fdSDimitry Andric void getOffsetOpcodes(const StackOffset &Offset, 1244824e7fdSDimitry Andric SmallVectorImpl<uint64_t> &Ops) const override; 12504eeddc0SDimitry Andric 12604eeddc0SDimitry Andric unsigned getRegisterCostTableIndex(const MachineFunction &MF) const override; 127bdd1243dSDimitry Andric 128bdd1243dSDimitry Andric bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order, 129bdd1243dSDimitry Andric SmallVectorImpl<MCPhysReg> &Hints, 130bdd1243dSDimitry Andric const MachineFunction &MF, const VirtRegMap *VRM, 131bdd1243dSDimitry Andric const LiveRegMatrix *Matrix) const override; 132*0fca6ea1SDimitry Andric 133*0fca6ea1SDimitry Andric const TargetRegisterClass * 134*0fca6ea1SDimitry Andric getLargestSuperClass(const TargetRegisterClass *RC) const override { 135*0fca6ea1SDimitry Andric if (RISCV::VRM8RegClass.hasSubClassEq(RC)) 136*0fca6ea1SDimitry Andric return &RISCV::VRM8RegClass; 137*0fca6ea1SDimitry Andric if (RISCV::VRM4RegClass.hasSubClassEq(RC)) 138*0fca6ea1SDimitry Andric return &RISCV::VRM4RegClass; 139*0fca6ea1SDimitry Andric if (RISCV::VRM2RegClass.hasSubClassEq(RC)) 140*0fca6ea1SDimitry Andric return &RISCV::VRM2RegClass; 141*0fca6ea1SDimitry Andric if (RISCV::VRRegClass.hasSubClassEq(RC)) 142*0fca6ea1SDimitry Andric return &RISCV::VRRegClass; 143*0fca6ea1SDimitry Andric return RC; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 146*0fca6ea1SDimitry Andric bool doesRegClassHavePseudoInitUndef( 147*0fca6ea1SDimitry Andric const TargetRegisterClass *RC) const override { 148*0fca6ea1SDimitry Andric return isVRRegClass(RC); 149*0fca6ea1SDimitry Andric } 150*0fca6ea1SDimitry Andric 151*0fca6ea1SDimitry Andric static bool isVRRegClass(const TargetRegisterClass *RC) { 152*0fca6ea1SDimitry Andric return RISCVRI::isVRegClass(RC->TSFlags) && 153*0fca6ea1SDimitry Andric RISCVRI::getNF(RC->TSFlags) == 1; 154*0fca6ea1SDimitry Andric } 155*0fca6ea1SDimitry Andric 156*0fca6ea1SDimitry Andric static bool isVRNRegClass(const TargetRegisterClass *RC) { 157*0fca6ea1SDimitry Andric return RISCVRI::isVRegClass(RC->TSFlags) && RISCVRI::getNF(RC->TSFlags) > 1; 158*0fca6ea1SDimitry Andric } 159*0fca6ea1SDimitry Andric 160*0fca6ea1SDimitry Andric static bool isRVVRegClass(const TargetRegisterClass *RC) { 161*0fca6ea1SDimitry Andric return RISCVRI::isVRegClass(RC->TSFlags); 162*0fca6ea1SDimitry Andric } 163*0fca6ea1SDimitry Andric }; 164*0fca6ea1SDimitry Andric } // namespace llvm 165*0fca6ea1SDimitry Andric 1660b57cec5SDimitry Andric #endif 167