1 //===-- LanaiRegisterInfo.cpp - Lanai Register Information ------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains the Lanai implementation of the TargetRegisterInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "LanaiRegisterInfo.h"
15 #include "LanaiSubtarget.h"
16 #include "llvm/ADT/BitVector.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/RegisterScavenging.h"
22 #include "llvm/CodeGen/TargetFrameLowering.h"
23 #include "llvm/CodeGen/TargetInstrInfo.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/Type.h"
26 #include "llvm/Support/ErrorHandling.h"
28 #define GET_REGINFO_TARGET_DESC
29 #include "LanaiGenRegisterInfo.inc"
33 LanaiRegisterInfo::LanaiRegisterInfo() : LanaiGenRegisterInfo(Lanai::RCA
) {}
36 LanaiRegisterInfo::getCalleeSavedRegs(const MachineFunction
* /*MF*/) const {
40 BitVector
LanaiRegisterInfo::getReservedRegs(const MachineFunction
&MF
) const {
41 BitVector
Reserved(getNumRegs());
43 Reserved
.set(Lanai::R0
);
44 Reserved
.set(Lanai::R1
);
45 Reserved
.set(Lanai::PC
);
46 Reserved
.set(Lanai::R2
);
47 Reserved
.set(Lanai::SP
);
48 Reserved
.set(Lanai::R4
);
49 Reserved
.set(Lanai::FP
);
50 Reserved
.set(Lanai::R5
);
51 Reserved
.set(Lanai::RR1
);
52 Reserved
.set(Lanai::R10
);
53 Reserved
.set(Lanai::RR2
);
54 Reserved
.set(Lanai::R11
);
55 Reserved
.set(Lanai::RCA
);
56 Reserved
.set(Lanai::R15
);
57 if (hasBasePointer(MF
))
58 Reserved
.set(getBaseRegister());
62 bool LanaiRegisterInfo::requiresRegisterScavenging(
63 const MachineFunction
& /*MF*/) const {
67 bool LanaiRegisterInfo::trackLivenessAfterRegAlloc(
68 const MachineFunction
& /*MF*/) const {
72 static bool isALUArithLoOpcode(unsigned Opcode
) {
76 case Lanai::ADD_F_I_LO
:
77 case Lanai::SUB_F_I_LO
:
78 case Lanai::ADDC_I_LO
:
79 case Lanai::SUBB_I_LO
:
80 case Lanai::ADDC_F_I_LO
:
81 case Lanai::SUBB_F_I_LO
:
88 static unsigned getOppositeALULoOpcode(unsigned Opcode
) {
91 return Lanai::SUB_I_LO
;
93 return Lanai::ADD_I_LO
;
94 case Lanai::ADD_F_I_LO
:
95 return Lanai::SUB_F_I_LO
;
96 case Lanai::SUB_F_I_LO
:
97 return Lanai::ADD_F_I_LO
;
98 case Lanai::ADDC_I_LO
:
99 return Lanai::SUBB_I_LO
;
100 case Lanai::SUBB_I_LO
:
101 return Lanai::ADDC_I_LO
;
102 case Lanai::ADDC_F_I_LO
:
103 return Lanai::SUBB_F_I_LO
;
104 case Lanai::SUBB_F_I_LO
:
105 return Lanai::ADDC_F_I_LO
;
107 llvm_unreachable("Invalid ALU lo opcode");
111 static unsigned getRRMOpcodeVariant(unsigned Opcode
) {
114 return Lanai::LDBs_RR
;
116 return Lanai::LDBz_RR
;
118 return Lanai::LDHs_RR
;
120 return Lanai::LDHz_RR
;
122 return Lanai::LDW_RR
;
124 return Lanai::STB_RR
;
126 return Lanai::STH_RR
;
130 llvm_unreachable("Opcode has no RRM variant");
134 void LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
135 int SPAdj
, unsigned FIOperandNum
,
136 RegScavenger
*RS
) const {
137 assert(SPAdj
== 0 && "Unexpected");
139 MachineInstr
&MI
= *II
;
140 MachineFunction
&MF
= *MI
.getParent()->getParent();
141 const TargetInstrInfo
*TII
= MF
.getSubtarget().getInstrInfo();
142 const TargetFrameLowering
*TFI
= MF
.getSubtarget().getFrameLowering();
143 bool HasFP
= TFI
->hasFP(MF
);
144 DebugLoc DL
= MI
.getDebugLoc();
146 int FrameIndex
= MI
.getOperand(FIOperandNum
).getIndex();
148 int Offset
= MF
.getFrameInfo().getObjectOffset(FrameIndex
) +
149 MI
.getOperand(FIOperandNum
+ 1).getImm();
151 // Addressable stack objects are addressed using neg. offsets from fp
152 // or pos. offsets from sp/basepointer
153 if (!HasFP
|| (needsStackRealignment(MF
) && FrameIndex
>= 0))
154 Offset
+= MF
.getFrameInfo().getStackSize();
156 unsigned FrameReg
= getFrameRegister(MF
);
157 if (FrameIndex
>= 0) {
158 if (hasBasePointer(MF
))
159 FrameReg
= getBaseRegister();
160 else if (needsStackRealignment(MF
))
161 FrameReg
= Lanai::SP
;
164 // Replace frame index with a frame pointer reference.
165 // If the offset is small enough to fit in the immediate field, directly
167 // Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence.
168 if ((isSPLSOpcode(MI
.getOpcode()) && !isInt
<10>(Offset
)) ||
169 !isInt
<16>(Offset
)) {
170 assert(RS
&& "Register scavenging must be on");
171 unsigned Reg
= RS
->FindUnusedReg(&Lanai::GPRRegClass
);
173 Reg
= RS
->scavengeRegister(&Lanai::GPRRegClass
, II
, SPAdj
);
174 assert(Reg
&& "Register scavenger failed");
176 bool HasNegOffset
= false;
177 // ALU ops have unsigned immediate values. If the Offset is negative, we
178 // negate it here and reverse the opcode later.
184 if (!isInt
<16>(Offset
)) {
185 // Reg = hi(offset) | lo(offset)
186 BuildMI(*MI
.getParent(), II
, DL
, TII
->get(Lanai::MOVHI
), Reg
)
187 .addImm(static_cast<uint32_t>(Offset
) >> 16);
188 BuildMI(*MI
.getParent(), II
, DL
, TII
->get(Lanai::OR_I_LO
), Reg
)
190 .addImm(Offset
& 0xffffU
);
193 BuildMI(*MI
.getParent(), II
, DL
, TII
->get(Lanai::ADD_I_LO
), Reg
)
197 // Reg = FrameReg OP Reg
198 if (MI
.getOpcode() == Lanai::ADD_I_LO
) {
199 BuildMI(*MI
.getParent(), II
, DL
,
200 HasNegOffset
? TII
->get(Lanai::SUB_R
) : TII
->get(Lanai::ADD_R
),
201 MI
.getOperand(0).getReg())
204 .addImm(LPCC::ICC_T
);
205 MI
.eraseFromParent();
208 if (isSPLSOpcode(MI
.getOpcode()) || isRMOpcode(MI
.getOpcode())) {
209 MI
.setDesc(TII
->get(getRRMOpcodeVariant(MI
.getOpcode())));
211 // Change the ALU op (operand 3) from LPAC::ADD (the default) to
212 // LPAC::SUB with the already negated offset.
213 assert((MI
.getOperand(3).getImm() == LPAC::ADD
) &&
214 "Unexpected ALU op in RRM instruction");
215 MI
.getOperand(3).setImm(LPAC::SUB
);
218 llvm_unreachable("Unexpected opcode in frame index operation");
220 MI
.getOperand(FIOperandNum
).ChangeToRegister(FrameReg
, /*isDef=*/false);
221 MI
.getOperand(FIOperandNum
+ 1)
222 .ChangeToRegister(Reg
, /*isDef=*/false, /*isImp=*/false,
227 // ALU arithmetic ops take unsigned immediates. If the offset is negative,
228 // we replace the instruction with one that inverts the opcode and negates
230 if ((Offset
< 0) && isALUArithLoOpcode(MI
.getOpcode())) {
231 unsigned NewOpcode
= getOppositeALULoOpcode(MI
.getOpcode());
232 // We know this is an ALU op, so we know the operands are as follows:
233 // 0: destination register
234 // 1: source register (frame register)
236 BuildMI(*MI
.getParent(), II
, DL
, TII
->get(NewOpcode
),
237 MI
.getOperand(0).getReg())
240 MI
.eraseFromParent();
242 MI
.getOperand(FIOperandNum
).ChangeToRegister(FrameReg
, /*isDef=*/false);
243 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(Offset
);
247 bool LanaiRegisterInfo::hasBasePointer(const MachineFunction
&MF
) const {
248 const MachineFrameInfo
&MFI
= MF
.getFrameInfo();
249 // When we need stack realignment and there are dynamic allocas, we can't
250 // reference off of the stack pointer, so we reserve a base pointer.
251 if (needsStackRealignment(MF
) && MFI
.hasVarSizedObjects())
257 unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA
; }
260 LanaiRegisterInfo::getFrameRegister(const MachineFunction
& /*MF*/) const {
264 unsigned LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14
; }
267 LanaiRegisterInfo::getCallPreservedMask(const MachineFunction
& /*MF*/,
268 CallingConv::ID
/*CC*/) const {