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