4037c4d370bb8e43b529b49c274d14f2d78a894c
[platform/upstream/llvm.git] / llvm / lib / Target / LoongArch / LoongArchRegisterInfo.cpp
1 //===- LoongArchRegisterInfo.cpp - LoongArch Register Information -*- C++ -*-=//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the LoongArch implementation of the TargetRegisterInfo
10 // class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "LoongArchRegisterInfo.h"
15 #include "LoongArch.h"
16 #include "LoongArchInstrInfo.h"
17 #include "LoongArchSubtarget.h"
18 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/RegisterScavenging.h"
23 #include "llvm/CodeGen/TargetFrameLowering.h"
24 #include "llvm/CodeGen/TargetInstrInfo.h"
25 #include "llvm/Support/ErrorHandling.h"
26
27 using namespace llvm;
28
29 #define GET_REGINFO_TARGET_DESC
30 #include "LoongArchGenRegisterInfo.inc"
31
32 LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode)
33     : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0,
34                                /*EHFlavor*/ 0,
35                                /*PC*/ 0, HwMode) {}
36
37 const MCPhysReg *
38 LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
39   auto &Subtarget = MF->getSubtarget<LoongArchSubtarget>();
40
41   if (MF->getFunction().getCallingConv() == CallingConv::GHC)
42     return CSR_NoRegs_SaveList;
43   switch (Subtarget.getTargetABI()) {
44   default:
45     llvm_unreachable("Unrecognized ABI");
46   case LoongArchABI::ABI_ILP32S:
47   case LoongArchABI::ABI_LP64S:
48     return CSR_ILP32S_LP64S_SaveList;
49   case LoongArchABI::ABI_ILP32F:
50   case LoongArchABI::ABI_LP64F:
51     return CSR_ILP32F_LP64F_SaveList;
52   case LoongArchABI::ABI_ILP32D:
53   case LoongArchABI::ABI_LP64D:
54     return CSR_ILP32D_LP64D_SaveList;
55   }
56 }
57
58 const uint32_t *
59 LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
60                                             CallingConv::ID CC) const {
61   auto &Subtarget = MF.getSubtarget<LoongArchSubtarget>();
62
63   if (CC == CallingConv::GHC)
64     return CSR_NoRegs_RegMask;
65   switch (Subtarget.getTargetABI()) {
66   default:
67     llvm_unreachable("Unrecognized ABI");
68   case LoongArchABI::ABI_ILP32S:
69   case LoongArchABI::ABI_LP64S:
70     return CSR_ILP32S_LP64S_RegMask;
71   case LoongArchABI::ABI_ILP32F:
72   case LoongArchABI::ABI_LP64F:
73     return CSR_ILP32F_LP64F_RegMask;
74   case LoongArchABI::ABI_ILP32D:
75   case LoongArchABI::ABI_LP64D:
76     return CSR_ILP32D_LP64D_RegMask;
77   }
78 }
79
80 const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const {
81   return CSR_NoRegs_RegMask;
82 }
83
84 BitVector
85 LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
86   const LoongArchFrameLowering *TFI = getFrameLowering(MF);
87   BitVector Reserved(getNumRegs());
88
89   // Use markSuperRegs to ensure any register aliases are also reserved
90   markSuperRegs(Reserved, LoongArch::R0);  // zero
91   markSuperRegs(Reserved, LoongArch::R2);  // tp
92   markSuperRegs(Reserved, LoongArch::R3);  // sp
93   markSuperRegs(Reserved, LoongArch::R21); // non-allocatable
94   if (TFI->hasFP(MF))
95     markSuperRegs(Reserved, LoongArch::R22); // fp
96   // Reserve the base register if we need to realign the stack and allocate
97   // variable-sized objects at runtime.
98   if (TFI->hasBP(MF))
99     markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp
100
101   // FIXME: To avoid generating COPY instructions between CFRs, only use $fcc0.
102   // This is required to work around the fact that COPY instruction between CFRs
103   // is not provided in LoongArch.
104   if (MF.getSubtarget<LoongArchSubtarget>().hasBasicF())
105     for (size_t Reg = LoongArch::FCC1; Reg <= LoongArch::FCC7; ++Reg)
106       markSuperRegs(Reserved, Reg);
107
108   assert(checkAllSuperRegsMarked(Reserved));
109   return Reserved;
110 }
111
112 Register
113 LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
114   const TargetFrameLowering *TFI = getFrameLowering(MF);
115   return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3;
116 }
117
118 bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
119                                                 int SPAdj,
120                                                 unsigned FIOperandNum,
121                                                 RegScavenger *RS) const {
122   // TODO: this implementation is a temporary placeholder which does just
123   // enough to allow other aspects of code generation to be tested.
124
125   assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
126
127   MachineInstr &MI = *II;
128   assert(MI.getOperand(FIOperandNum + 1).isImm() &&
129          "Unexpected FI-consuming insn");
130
131   MachineBasicBlock &MBB = *MI.getParent();
132   MachineFunction &MF = *MI.getParent()->getParent();
133   MachineRegisterInfo &MRI = MF.getRegInfo();
134   const LoongArchSubtarget &STI = MF.getSubtarget<LoongArchSubtarget>();
135   const LoongArchInstrInfo *TII = STI.getInstrInfo();
136   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
137   DebugLoc DL = MI.getDebugLoc();
138   bool IsLA64 = STI.is64Bit();
139   unsigned MIOpc = MI.getOpcode();
140
141   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
142   Register FrameReg;
143   StackOffset Offset =
144       TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) +
145       StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm());
146
147   bool FrameRegIsKill = false;
148
149   if (!isInt<12>(Offset.getFixed())) {
150     unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;
151     unsigned Add = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;
152
153     // The offset won't fit in an immediate, so use a scratch register instead.
154     // Modify Offset and FrameReg appropriately.
155     Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
156     TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed());
157     if (MIOpc == Addi) {
158       BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg())
159           .addReg(FrameReg)
160           .addReg(ScratchReg, RegState::Kill);
161       MI.eraseFromParent();
162       return true;
163     }
164     BuildMI(MBB, II, DL, TII->get(Add), ScratchReg)
165         .addReg(FrameReg)
166         .addReg(ScratchReg, RegState::Kill);
167     Offset = StackOffset::getFixed(0);
168     FrameReg = ScratchReg;
169     FrameRegIsKill = true;
170   }
171
172   // Spill CFRs.
173   if (MIOpc == LoongArch::PseudoST_CFR) {
174     Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
175     BuildMI(MBB, II, DL, TII->get(LoongArch::MOVCF2GR), ScratchReg)
176         .add(MI.getOperand(0));
177     BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
178         .addReg(ScratchReg, RegState::Kill)
179         .addReg(FrameReg)
180         .addImm(Offset.getFixed());
181     MI.eraseFromParent();
182     return true;
183   }
184
185   // Reload CFRs.
186   if (MIOpc == LoongArch::PseudoLD_CFR) {
187     Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
188     BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::LD_D : LoongArch::LD_W),
189             ScratchReg)
190         .addReg(FrameReg)
191         .addImm(Offset.getFixed());
192     BuildMI(MBB, II, DL, TII->get(LoongArch::MOVGR2CF))
193         .add(MI.getOperand(0))
194         .addReg(ScratchReg, RegState::Kill);
195     MI.eraseFromParent();
196     return true;
197   }
198
199   MI.getOperand(FIOperandNum)
200       .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
201   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());
202   return false;
203 }