xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVRegisterInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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