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 static bool isALUArithLoOpcode(unsigned Opcode) {
70   switch (Opcode) {
71   case Lanai::ADD_I_LO:
72   case Lanai::SUB_I_LO:
73   case Lanai::ADD_F_I_LO:
74   case Lanai::SUB_F_I_LO:
75   case Lanai::ADDC_I_LO:
76   case Lanai::SUBB_I_LO:
77   case Lanai::ADDC_F_I_LO:
78   case Lanai::SUBB_F_I_LO:
79     return true;
80   default:
81     return false;
82   }
83 }
84 
85 static unsigned getOppositeALULoOpcode(unsigned Opcode) {
86   switch (Opcode) {
87   case Lanai::ADD_I_LO:
88     return Lanai::SUB_I_LO;
89   case Lanai::SUB_I_LO:
90     return Lanai::ADD_I_LO;
91   case Lanai::ADD_F_I_LO:
92     return Lanai::SUB_F_I_LO;
93   case Lanai::SUB_F_I_LO:
94     return Lanai::ADD_F_I_LO;
95   case Lanai::ADDC_I_LO:
96     return Lanai::SUBB_I_LO;
97   case Lanai::SUBB_I_LO:
98     return Lanai::ADDC_I_LO;
99   case Lanai::ADDC_F_I_LO:
100     return Lanai::SUBB_F_I_LO;
101   case Lanai::SUBB_F_I_LO:
102     return Lanai::ADDC_F_I_LO;
103   default:
104     llvm_unreachable("Invalid ALU lo opcode");
105   }
106 }
107 
108 static unsigned getRRMOpcodeVariant(unsigned Opcode) {
109   switch (Opcode) {
110   case Lanai::LDBs_RI:
111     return Lanai::LDBs_RR;
112   case Lanai::LDBz_RI:
113     return Lanai::LDBz_RR;
114   case Lanai::LDHs_RI:
115     return Lanai::LDHs_RR;
116   case Lanai::LDHz_RI:
117     return Lanai::LDHz_RR;
118   case Lanai::LDW_RI:
119     return Lanai::LDW_RR;
120   case Lanai::STB_RI:
121     return Lanai::STB_RR;
122   case Lanai::STH_RI:
123     return Lanai::STH_RR;
124   case Lanai::SW_RI:
125     return Lanai::SW_RR;
126   default:
127     llvm_unreachable("Opcode has no RRM variant");
128   }
129 }
130 
131 bool LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
132                                             int SPAdj, unsigned FIOperandNum,
133                                             RegScavenger *RS) const {
134   assert(SPAdj == 0 && "Unexpected");
135 
136   MachineInstr &MI = *II;
137   MachineFunction &MF = *MI.getParent()->getParent();
138   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
139   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
140   bool HasFP = TFI->hasFP(MF);
141   DebugLoc DL = MI.getDebugLoc();
142 
143   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
144 
145   int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) +
146                MI.getOperand(FIOperandNum + 1).getImm();
147 
148   // Addressable stack objects are addressed using neg. offsets from fp
149   // or pos. offsets from sp/basepointer
150   if (!HasFP || (hasStackRealignment(MF) && FrameIndex >= 0))
151     Offset += MF.getFrameInfo().getStackSize();
152 
153   Register FrameReg = getFrameRegister(MF);
154   if (FrameIndex >= 0) {
155     if (hasBasePointer(MF))
156       FrameReg = getBaseRegister();
157     else if (hasStackRealignment(MF))
158       FrameReg = Lanai::SP;
159   }
160 
161   // Replace frame index with a frame pointer reference.
162   // If the offset is small enough to fit in the immediate field, directly
163   // encode it.
164   // Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence.
165   if ((isSPLSOpcode(MI.getOpcode()) && !isInt<10>(Offset)) ||
166       !isInt<16>(Offset)) {
167     assert(RS && "Register scavenging must be on");
168     Register Reg = RS->FindUnusedReg(&Lanai::GPRRegClass);
169     if (!Reg)
170       Reg = RS->scavengeRegisterBackwards(Lanai::GPRRegClass, II, false, SPAdj);
171     assert(Reg && "Register scavenger failed");
172 
173     bool HasNegOffset = false;
174     // ALU ops have unsigned immediate values. If the Offset is negative, we
175     // negate it here and reverse the opcode later.
176     if (Offset < 0) {
177       HasNegOffset = true;
178       Offset = -Offset;
179     }
180 
181     if (!isInt<16>(Offset)) {
182       // Reg = hi(offset) | lo(offset)
183       BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::MOVHI), Reg)
184           .addImm(static_cast<uint32_t>(Offset) >> 16);
185       BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::OR_I_LO), Reg)
186           .addReg(Reg)
187           .addImm(Offset & 0xffffU);
188     } else {
189       // Reg = mov(offset)
190       BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::ADD_I_LO), Reg)
191           .addImm(0)
192           .addImm(Offset);
193     }
194     // Reg = FrameReg OP Reg
195     if (MI.getOpcode() == Lanai::ADD_I_LO) {
196       BuildMI(*MI.getParent(), II, DL,
197               HasNegOffset ? TII->get(Lanai::SUB_R) : TII->get(Lanai::ADD_R),
198               MI.getOperand(0).getReg())
199           .addReg(FrameReg)
200           .addReg(Reg)
201           .addImm(LPCC::ICC_T);
202       MI.eraseFromParent();
203       return true;
204     }
205     if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) {
206       MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode())));
207       if (HasNegOffset) {
208         // Change the ALU op (operand 3) from LPAC::ADD (the default) to
209         // LPAC::SUB with the already negated offset.
210         assert((MI.getOperand(3).getImm() == LPAC::ADD) &&
211                "Unexpected ALU op in RRM instruction");
212         MI.getOperand(3).setImm(LPAC::SUB);
213       }
214     } else
215       llvm_unreachable("Unexpected opcode in frame index operation");
216 
217     MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
218     MI.getOperand(FIOperandNum + 1)
219         .ChangeToRegister(Reg, /*isDef=*/false, /*isImp=*/false,
220                           /*isKill=*/true);
221     return false;
222   }
223 
224   // ALU arithmetic ops take unsigned immediates. If the offset is negative,
225   // we replace the instruction with one that inverts the opcode and negates
226   // the immediate.
227   if ((Offset < 0) && isALUArithLoOpcode(MI.getOpcode())) {
228     unsigned NewOpcode = getOppositeALULoOpcode(MI.getOpcode());
229     // We know this is an ALU op, so we know the operands are as follows:
230     // 0: destination register
231     // 1: source register (frame register)
232     // 2: immediate
233     BuildMI(*MI.getParent(), II, DL, TII->get(NewOpcode),
234             MI.getOperand(0).getReg())
235         .addReg(FrameReg)
236         .addImm(-Offset);
237     MI.eraseFromParent();
238     return true;
239   }
240 
241   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
242   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
243   return false;
244 }
245 
246 bool LanaiRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
247   const MachineFrameInfo &MFI = MF.getFrameInfo();
248   // When we need stack realignment and there are dynamic allocas, we can't
249   // reference off of the stack pointer, so we reserve a base pointer.
250   if (hasStackRealignment(MF) && MFI.hasVarSizedObjects())
251     return true;
252 
253   return false;
254 }
255 
256 unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; }
257 
258 Register
259 LanaiRegisterInfo::getFrameRegister(const MachineFunction & /*MF*/) const {
260   return Lanai::FP;
261 }
262 
263 Register LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; }
264 
265 const uint32_t *
266 LanaiRegisterInfo::getCallPreservedMask(const MachineFunction & /*MF*/,
267                                         CallingConv::ID /*CC*/) const {
268   return CSR_RegMask;
269 }
270