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.
isVRegClass(uint64_t TSFlags)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.
getLMul(uint64_t TSFlags)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.
getNF(uint64_t TSFlags)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
requiresRegisterScavengingRISCVRegisterInfo1050b57cec5SDimitry Andric bool requiresRegisterScavenging(const MachineFunction &MF) const override {
1060b57cec5SDimitry Andric return true;
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
requiresFrameIndexScavengingRISCVRegisterInfo1090b57cec5SDimitry 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 *
getLargestSuperClassRISCVRegisterInfo134*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
doesRegClassHavePseudoInitUndefRISCVRegisterInfo146*0fca6ea1SDimitry Andric bool doesRegClassHavePseudoInitUndef(
147*0fca6ea1SDimitry Andric const TargetRegisterClass *RC) const override {
148*0fca6ea1SDimitry Andric return isVRRegClass(RC);
149*0fca6ea1SDimitry Andric }
150*0fca6ea1SDimitry Andric
isVRRegClassRISCVRegisterInfo151*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
isVRNRegClassRISCVRegisterInfo156*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
isRVVRegClassRISCVRegisterInfo160*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