LLVM 20.0.0git
LanaiRegisterInfo.cpp
Go to the documentation of this file.
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"
26
27#define GET_REGINFO_TARGET_DESC
28#include "LanaiGenRegisterInfo.inc"
29
30using namespace llvm;
31
33
34const uint16_t *
36 return CSR_SaveList;
37}
38
40 BitVector Reserved(getNumRegs());
41
42 Reserved.set(Lanai::R0);
43 Reserved.set(Lanai::R1);
44 Reserved.set(Lanai::PC);
45 Reserved.set(Lanai::R2);
46 Reserved.set(Lanai::SP);
47 Reserved.set(Lanai::R4);
48 Reserved.set(Lanai::FP);
49 Reserved.set(Lanai::R5);
50 Reserved.set(Lanai::RR1);
51 Reserved.set(Lanai::R10);
52 Reserved.set(Lanai::RR2);
53 Reserved.set(Lanai::R11);
54 Reserved.set(Lanai::RCA);
55 Reserved.set(Lanai::R15);
56 if (hasBasePointer(MF))
58 return Reserved;
59}
60
62 const MachineFunction & /*MF*/) const {
63 return true;
64}
65
66static bool isALUArithLoOpcode(unsigned Opcode) {
67 switch (Opcode) {
68 case Lanai::ADD_I_LO:
69 case Lanai::SUB_I_LO:
70 case Lanai::ADD_F_I_LO:
71 case Lanai::SUB_F_I_LO:
72 case Lanai::ADDC_I_LO:
73 case Lanai::SUBB_I_LO:
74 case Lanai::ADDC_F_I_LO:
75 case Lanai::SUBB_F_I_LO:
76 return true;
77 default:
78 return false;
79 }
80}
81
82static unsigned getOppositeALULoOpcode(unsigned Opcode) {
83 switch (Opcode) {
84 case Lanai::ADD_I_LO:
85 return Lanai::SUB_I_LO;
86 case Lanai::SUB_I_LO:
87 return Lanai::ADD_I_LO;
88 case Lanai::ADD_F_I_LO:
89 return Lanai::SUB_F_I_LO;
90 case Lanai::SUB_F_I_LO:
91 return Lanai::ADD_F_I_LO;
92 case Lanai::ADDC_I_LO:
93 return Lanai::SUBB_I_LO;
94 case Lanai::SUBB_I_LO:
95 return Lanai::ADDC_I_LO;
96 case Lanai::ADDC_F_I_LO:
97 return Lanai::SUBB_F_I_LO;
98 case Lanai::SUBB_F_I_LO:
99 return Lanai::ADDC_F_I_LO;
100 default:
101 llvm_unreachable("Invalid ALU lo opcode");
102 }
103}
104
105static unsigned getRRMOpcodeVariant(unsigned Opcode) {
106 switch (Opcode) {
107 case Lanai::LDBs_RI:
108 return Lanai::LDBs_RR;
109 case Lanai::LDBz_RI:
110 return Lanai::LDBz_RR;
111 case Lanai::LDHs_RI:
112 return Lanai::LDHs_RR;
113 case Lanai::LDHz_RI:
114 return Lanai::LDHz_RR;
115 case Lanai::LDW_RI:
116 return Lanai::LDW_RR;
117 case Lanai::STB_RI:
118 return Lanai::STB_RR;
119 case Lanai::STH_RI:
120 return Lanai::STH_RR;
121 case Lanai::SW_RI:
122 return Lanai::SW_RR;
123 default:
124 llvm_unreachable("Opcode has no RRM variant");
125 }
126}
127
129 int SPAdj, unsigned FIOperandNum,
130 RegScavenger *RS) const {
131 assert(SPAdj == 0 && "Unexpected");
132
133 MachineInstr &MI = *II;
134 MachineFunction &MF = *MI.getParent()->getParent();
137 bool HasFP = TFI->hasFP(MF);
138 DebugLoc DL = MI.getDebugLoc();
139
140 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
141
142 int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) +
143 MI.getOperand(FIOperandNum + 1).getImm();
144
145 // Addressable stack objects are addressed using neg. offsets from fp
146 // or pos. offsets from sp/basepointer
147 if (!HasFP || (hasStackRealignment(MF) && FrameIndex >= 0))
149
150 Register FrameReg = getFrameRegister(MF);
151 if (FrameIndex >= 0) {
152 if (hasBasePointer(MF))
153 FrameReg = getBaseRegister();
154 else if (hasStackRealignment(MF))
155 FrameReg = Lanai::SP;
156 }
157
158 // Replace frame index with a frame pointer reference.
159 // If the offset is small enough to fit in the immediate field, directly
160 // encode it.
161 // Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence.
162 if ((isSPLSOpcode(MI.getOpcode()) && !isInt<10>(Offset)) ||
163 !isInt<16>(Offset)) {
164 assert(RS && "Register scavenging must be on");
165 Register Reg = RS->FindUnusedReg(&Lanai::GPRRegClass);
166 if (!Reg)
167 Reg = RS->scavengeRegisterBackwards(Lanai::GPRRegClass, II, false, SPAdj);
168 assert(Reg && "Register scavenger failed");
169
170 bool HasNegOffset = false;
171 // ALU ops have unsigned immediate values. If the Offset is negative, we
172 // negate it here and reverse the opcode later.
173 if (Offset < 0) {
174 HasNegOffset = true;
175 Offset = -Offset;
176 }
177
178 if (!isInt<16>(Offset)) {
179 // Reg = hi(offset) | lo(offset)
180 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::MOVHI), Reg)
181 .addImm(static_cast<uint32_t>(Offset) >> 16);
182 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::OR_I_LO), Reg)
183 .addReg(Reg)
184 .addImm(Offset & 0xffffU);
185 } else {
186 // Reg = mov(offset)
187 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::ADD_I_LO), Reg)
188 .addImm(0)
189 .addImm(Offset);
190 }
191 // Reg = FrameReg OP Reg
192 if (MI.getOpcode() == Lanai::ADD_I_LO) {
193 BuildMI(*MI.getParent(), II, DL,
194 HasNegOffset ? TII->get(Lanai::SUB_R) : TII->get(Lanai::ADD_R),
195 MI.getOperand(0).getReg())
196 .addReg(FrameReg)
197 .addReg(Reg)
199 MI.eraseFromParent();
200 return true;
201 }
202 if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) {
203 MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode())));
204 if (HasNegOffset) {
205 // Change the ALU op (operand 3) from LPAC::ADD (the default) to
206 // LPAC::SUB with the already negated offset.
207 assert((MI.getOperand(3).getImm() == LPAC::ADD) &&
208 "Unexpected ALU op in RRM instruction");
209 MI.getOperand(3).setImm(LPAC::SUB);
210 }
211 } else
212 llvm_unreachable("Unexpected opcode in frame index operation");
213
214 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
215 MI.getOperand(FIOperandNum + 1)
216 .ChangeToRegister(Reg, /*isDef=*/false, /*isImp=*/false,
217 /*isKill=*/true);
218 return false;
219 }
220
221 // ALU arithmetic ops take unsigned immediates. If the offset is negative,
222 // we replace the instruction with one that inverts the opcode and negates
223 // the immediate.
224 if ((Offset < 0) && isALUArithLoOpcode(MI.getOpcode())) {
225 unsigned NewOpcode = getOppositeALULoOpcode(MI.getOpcode());
226 // We know this is an ALU op, so we know the operands are as follows:
227 // 0: destination register
228 // 1: source register (frame register)
229 // 2: immediate
230 BuildMI(*MI.getParent(), II, DL, TII->get(NewOpcode),
231 MI.getOperand(0).getReg())
232 .addReg(FrameReg)
233 .addImm(-Offset);
234 MI.eraseFromParent();
235 return true;
236 }
237
238 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
239 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
240 return false;
241}
242
244 const MachineFrameInfo &MFI = MF.getFrameInfo();
245 // When we need stack realignment and there are dynamic allocas, we can't
246 // reference off of the stack pointer, so we reserve a base pointer.
247 if (hasStackRealignment(MF) && MFI.hasVarSizedObjects())
248 return true;
249
250 return false;
251}
252
253unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; }
254
257 return Lanai::FP;
258}
259
260Register LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; }
261
262const uint32_t *
264 CallingConv::ID /*CC*/) const {
265 return CSR_RegMask;
266}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the BitVector class.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static unsigned getRRMOpcodeVariant(unsigned Opcode)
static bool isALUArithLoOpcode(unsigned Opcode)
static unsigned getOppositeALULoOpcode(unsigned Opcode)
uint64_t IntrinsicInst * II
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A debug info location.
Definition: DebugLoc.h:33
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Definition: MachineInstr.h:69
Register FindUnusedReg(const TargetRegisterClass *RC) const
Find an unused register of the specified register class.
Register scavengeRegisterBackwards(const TargetRegisterClass &RC, MachineBasicBlock::iterator To, bool RestoreAfter, int SPAdj, bool AllowSpill=true)
Make a register of the specific register class available from the current position backwards to the p...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static bool isRMOpcode(unsigned Opcode)
static bool isSPLSOpcode(unsigned Opcode)
Register getBaseRegister() const
unsigned getRARegister() const
bool hasBasePointer(const MachineFunction &MF) const
bool requiresRegisterScavenging(const MachineFunction &MF) const override
const uint16_t * getCalleeSavedRegs(const MachineFunction *MF=nullptr) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=nullptr) const override
Register getFrameRegister(const MachineFunction &MF) const override
BitVector getReservedRegs(const MachineFunction &MF) const override