]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / Lanai / LanaiRegisterInfo.cpp
1 //===-- LanaiRegisterInfo.cpp - Lanai 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 Lanai implementation of the TargetRegisterInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "LanaiRegisterInfo.h"
14 #include "LanaiAluCode.h"
15 #include "LanaiCondCode.h"
16 #include "LanaiFrameLowering.h"
17 #include "LanaiInstrInfo.h"
18 #include "llvm/ADT/BitVector.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/RegisterScavenging.h"
24 #include "llvm/CodeGen/TargetFrameLowering.h"
25 #include "llvm/CodeGen/TargetInstrInfo.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/IR/Type.h"
28 #include "llvm/Support/ErrorHandling.h"
29
30 #define GET_REGINFO_TARGET_DESC
31 #include "LanaiGenRegisterInfo.inc"
32
33 using namespace llvm;
34
35 LanaiRegisterInfo::LanaiRegisterInfo() : LanaiGenRegisterInfo(Lanai::RCA) {}
36
37 const uint16_t *
38 LanaiRegisterInfo::getCalleeSavedRegs(const MachineFunction * /*MF*/) const {
39   return CSR_SaveList;
40 }
41
42 BitVector LanaiRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
43   BitVector Reserved(getNumRegs());
44
45   Reserved.set(Lanai::R0);
46   Reserved.set(Lanai::R1);
47   Reserved.set(Lanai::PC);
48   Reserved.set(Lanai::R2);
49   Reserved.set(Lanai::SP);
50   Reserved.set(Lanai::R4);
51   Reserved.set(Lanai::FP);
52   Reserved.set(Lanai::R5);
53   Reserved.set(Lanai::RR1);
54   Reserved.set(Lanai::R10);
55   Reserved.set(Lanai::RR2);
56   Reserved.set(Lanai::R11);
57   Reserved.set(Lanai::RCA);
58   Reserved.set(Lanai::R15);
59   if (hasBasePointer(MF))
60     Reserved.set(getBaseRegister());
61   return Reserved;
62 }
63
64 bool LanaiRegisterInfo::requiresRegisterScavenging(
65     const MachineFunction & /*MF*/) const {
66   return true;
67 }
68
69 bool LanaiRegisterInfo::trackLivenessAfterRegAlloc(
70     const MachineFunction & /*MF*/) const {
71   return true;
72 }
73
74 static bool isALUArithLoOpcode(unsigned Opcode) {
75   switch (Opcode) {
76   case Lanai::ADD_I_LO:
77   case Lanai::SUB_I_LO:
78   case Lanai::ADD_F_I_LO:
79   case Lanai::SUB_F_I_LO:
80   case Lanai::ADDC_I_LO:
81   case Lanai::SUBB_I_LO:
82   case Lanai::ADDC_F_I_LO:
83   case Lanai::SUBB_F_I_LO:
84     return true;
85   default:
86     return false;
87   }
88 }
89
90 static unsigned getOppositeALULoOpcode(unsigned Opcode) {
91   switch (Opcode) {
92   case Lanai::ADD_I_LO:
93     return Lanai::SUB_I_LO;
94   case Lanai::SUB_I_LO:
95     return Lanai::ADD_I_LO;
96   case Lanai::ADD_F_I_LO:
97     return Lanai::SUB_F_I_LO;
98   case Lanai::SUB_F_I_LO:
99     return Lanai::ADD_F_I_LO;
100   case Lanai::ADDC_I_LO:
101     return Lanai::SUBB_I_LO;
102   case Lanai::SUBB_I_LO:
103     return Lanai::ADDC_I_LO;
104   case Lanai::ADDC_F_I_LO:
105     return Lanai::SUBB_F_I_LO;
106   case Lanai::SUBB_F_I_LO:
107     return Lanai::ADDC_F_I_LO;
108   default:
109     llvm_unreachable("Invalid ALU lo opcode");
110   }
111 }
112
113 static unsigned getRRMOpcodeVariant(unsigned Opcode) {
114   switch (Opcode) {
115   case Lanai::LDBs_RI:
116     return Lanai::LDBs_RR;
117   case Lanai::LDBz_RI:
118     return Lanai::LDBz_RR;
119   case Lanai::LDHs_RI:
120     return Lanai::LDHs_RR;
121   case Lanai::LDHz_RI:
122     return Lanai::LDHz_RR;
123   case Lanai::LDW_RI:
124     return Lanai::LDW_RR;
125   case Lanai::STB_RI:
126     return Lanai::STB_RR;
127   case Lanai::STH_RI:
128     return Lanai::STH_RR;
129   case Lanai::SW_RI:
130     return Lanai::SW_RR;
131   default:
132     llvm_unreachable("Opcode has no RRM variant");
133   }
134 }
135
136 void LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
137                                             int SPAdj, unsigned FIOperandNum,
138                                             RegScavenger *RS) const {
139   assert(SPAdj == 0 && "Unexpected");
140
141   MachineInstr &MI = *II;
142   MachineFunction &MF = *MI.getParent()->getParent();
143   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
144   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
145   bool HasFP = TFI->hasFP(MF);
146   DebugLoc DL = MI.getDebugLoc();
147
148   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
149
150   int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) +
151                MI.getOperand(FIOperandNum + 1).getImm();
152
153   // Addressable stack objects are addressed using neg. offsets from fp
154   // or pos. offsets from sp/basepointer
155   if (!HasFP || (needsStackRealignment(MF) && FrameIndex >= 0))
156     Offset += MF.getFrameInfo().getStackSize();
157
158   unsigned FrameReg = getFrameRegister(MF);
159   if (FrameIndex >= 0) {
160     if (hasBasePointer(MF))
161       FrameReg = getBaseRegister();
162     else if (needsStackRealignment(MF))
163       FrameReg = Lanai::SP;
164   }
165
166   // Replace frame index with a frame pointer reference.
167   // If the offset is small enough to fit in the immediate field, directly
168   // encode it.
169   // Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence.
170   if ((isSPLSOpcode(MI.getOpcode()) && !isInt<10>(Offset)) ||
171       !isInt<16>(Offset)) {
172     assert(RS && "Register scavenging must be on");
173     unsigned Reg = RS->FindUnusedReg(&Lanai::GPRRegClass);
174     if (!Reg)
175       Reg = RS->scavengeRegister(&Lanai::GPRRegClass, II, SPAdj);
176     assert(Reg && "Register scavenger failed");
177
178     bool HasNegOffset = false;
179     // ALU ops have unsigned immediate values. If the Offset is negative, we
180     // negate it here and reverse the opcode later.
181     if (Offset < 0) {
182       HasNegOffset = true;
183       Offset = -Offset;
184     }
185
186     if (!isInt<16>(Offset)) {
187       // Reg = hi(offset) | lo(offset)
188       BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::MOVHI), Reg)
189           .addImm(static_cast<uint32_t>(Offset) >> 16);
190       BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::OR_I_LO), Reg)
191           .addReg(Reg)
192           .addImm(Offset & 0xffffU);
193     } else {
194       // Reg = mov(offset)
195       BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::ADD_I_LO), Reg)
196           .addImm(0)
197           .addImm(Offset);
198     }
199     // Reg = FrameReg OP Reg
200     if (MI.getOpcode() == Lanai::ADD_I_LO) {
201       BuildMI(*MI.getParent(), II, DL,
202               HasNegOffset ? TII->get(Lanai::SUB_R) : TII->get(Lanai::ADD_R),
203               MI.getOperand(0).getReg())
204           .addReg(FrameReg)
205           .addReg(Reg)
206           .addImm(LPCC::ICC_T);
207       MI.eraseFromParent();
208       return;
209     }
210     if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) {
211       MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode())));
212       if (HasNegOffset) {
213         // Change the ALU op (operand 3) from LPAC::ADD (the default) to
214         // LPAC::SUB with the already negated offset.
215         assert((MI.getOperand(3).getImm() == LPAC::ADD) &&
216                "Unexpected ALU op in RRM instruction");
217         MI.getOperand(3).setImm(LPAC::SUB);
218       }
219     } else
220       llvm_unreachable("Unexpected opcode in frame index operation");
221
222     MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
223     MI.getOperand(FIOperandNum + 1)
224         .ChangeToRegister(Reg, /*isDef=*/false, /*isImp=*/false,
225                           /*isKill=*/true);
226     return;
227   }
228
229   // ALU arithmetic ops take unsigned immediates. If the offset is negative,
230   // we replace the instruction with one that inverts the opcode and negates
231   // the immediate.
232   if ((Offset < 0) && isALUArithLoOpcode(MI.getOpcode())) {
233     unsigned NewOpcode = getOppositeALULoOpcode(MI.getOpcode());
234     // We know this is an ALU op, so we know the operands are as follows:
235     // 0: destination register
236     // 1: source register (frame register)
237     // 2: immediate
238     BuildMI(*MI.getParent(), II, DL, TII->get(NewOpcode),
239             MI.getOperand(0).getReg())
240         .addReg(FrameReg)
241         .addImm(-Offset);
242     MI.eraseFromParent();
243   } else {
244     MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
245     MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
246   }
247 }
248
249 bool LanaiRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
250   const MachineFrameInfo &MFI = MF.getFrameInfo();
251   // When we need stack realignment and there are dynamic allocas, we can't
252   // reference off of the stack pointer, so we reserve a base pointer.
253   if (needsStackRealignment(MF) && MFI.hasVarSizedObjects())
254     return true;
255
256   return false;
257 }
258
259 unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; }
260
261 Register
262 LanaiRegisterInfo::getFrameRegister(const MachineFunction & /*MF*/) const {
263   return Lanai::FP;
264 }
265
266 Register LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; }
267
268 const uint32_t *
269 LanaiRegisterInfo::getCallPreservedMask(const MachineFunction & /*MF*/,
270                                         CallingConv::ID /*CC*/) const {
271   return CSR_RegMask;
272 }