1 //===-- XCoreRegisterInfo.cpp - XCore Register Information ----------------===//
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 XCore implementation of the MRegisterInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "XCoreRegisterInfo.h"
15 #include "XCoreInstrInfo.h"
16 #include "XCoreMachineFunctionInfo.h"
17 #include "XCoreSubtarget.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/MachineModuleInfo.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/RegisterScavenging.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/IR/Type.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/ErrorHandling.h"
30 #include "llvm/Support/MathExtras.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/CodeGen/TargetFrameLowering.h"
33 #include "llvm/Target/TargetMachine.h"
34 #include "llvm/Target/TargetOptions.h"
38 #define DEBUG_TYPE "xcore-reg-info"
40 #define GET_REGINFO_TARGET_DESC
41 #include "XCoreGenRegisterInfo.inc"
43 XCoreRegisterInfo::XCoreRegisterInfo()
44 : XCoreGenRegisterInfo(XCore::LR
) {
48 static inline bool isImmUs(unsigned val
) {
52 static inline bool isImmU6(unsigned val
) {
53 return val
< (1 << 6);
56 static inline bool isImmU16(unsigned val
) {
57 return val
< (1 << 16);
61 static void InsertFPImmInst(MachineBasicBlock::iterator II
,
62 const XCoreInstrInfo
&TII
,
63 unsigned Reg
, unsigned FrameReg
, int Offset
) {
64 MachineInstr
&MI
= *II
;
65 MachineBasicBlock
&MBB
= *MI
.getParent();
66 DebugLoc dl
= MI
.getDebugLoc();
68 switch (MI
.getOpcode()) {
70 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_2rus
), Reg
)
73 .addMemOperand(*MI
.memoperands_begin());
76 BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_2rus
))
77 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
80 .addMemOperand(*MI
.memoperands_begin());
83 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l2rus
), Reg
)
88 llvm_unreachable("Unexpected Opcode");
92 static void InsertFPConstInst(MachineBasicBlock::iterator II
,
93 const XCoreInstrInfo
&TII
,
94 unsigned Reg
, unsigned FrameReg
,
95 int Offset
, RegScavenger
*RS
) {
96 assert(RS
&& "requiresRegisterScavenging failed");
97 MachineInstr
&MI
= *II
;
98 MachineBasicBlock
&MBB
= *MI
.getParent();
99 DebugLoc dl
= MI
.getDebugLoc();
100 unsigned ScratchOffset
= RS
->scavengeRegister(&XCore::GRRegsRegClass
, II
, 0);
101 RS
->setRegUsed(ScratchOffset
);
102 TII
.loadImmediate(MBB
, II
, ScratchOffset
, Offset
);
104 switch (MI
.getOpcode()) {
106 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_3r
), Reg
)
108 .addReg(ScratchOffset
, RegState::Kill
)
109 .addMemOperand(*MI
.memoperands_begin());
112 BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_l3r
))
113 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
115 .addReg(ScratchOffset
, RegState::Kill
)
116 .addMemOperand(*MI
.memoperands_begin());
119 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l3r
), Reg
)
121 .addReg(ScratchOffset
, RegState::Kill
);
124 llvm_unreachable("Unexpected Opcode");
128 static void InsertSPImmInst(MachineBasicBlock::iterator II
,
129 const XCoreInstrInfo
&TII
,
130 unsigned Reg
, int Offset
) {
131 MachineInstr
&MI
= *II
;
132 MachineBasicBlock
&MBB
= *MI
.getParent();
133 DebugLoc dl
= MI
.getDebugLoc();
134 bool isU6
= isImmU6(Offset
);
136 switch (MI
.getOpcode()) {
139 NewOpcode
= (isU6
) ? XCore::LDWSP_ru6
: XCore::LDWSP_lru6
;
140 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
), Reg
)
142 .addMemOperand(*MI
.memoperands_begin());
145 NewOpcode
= (isU6
) ? XCore::STWSP_ru6
: XCore::STWSP_lru6
;
146 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
))
147 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
149 .addMemOperand(*MI
.memoperands_begin());
152 NewOpcode
= (isU6
) ? XCore::LDAWSP_ru6
: XCore::LDAWSP_lru6
;
153 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
), Reg
)
157 llvm_unreachable("Unexpected Opcode");
161 static void InsertSPConstInst(MachineBasicBlock::iterator II
,
162 const XCoreInstrInfo
&TII
,
163 unsigned Reg
, int Offset
, RegScavenger
*RS
) {
164 assert(RS
&& "requiresRegisterScavenging failed");
165 MachineInstr
&MI
= *II
;
166 MachineBasicBlock
&MBB
= *MI
.getParent();
167 DebugLoc dl
= MI
.getDebugLoc();
168 unsigned OpCode
= MI
.getOpcode();
170 unsigned ScratchBase
;
171 if (OpCode
==XCore::STWFI
) {
172 ScratchBase
= RS
->scavengeRegister(&XCore::GRRegsRegClass
, II
, 0);
173 RS
->setRegUsed(ScratchBase
);
176 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWSP_ru6
), ScratchBase
).addImm(0);
177 unsigned ScratchOffset
= RS
->scavengeRegister(&XCore::GRRegsRegClass
, II
, 0);
178 RS
->setRegUsed(ScratchOffset
);
179 TII
.loadImmediate(MBB
, II
, ScratchOffset
, Offset
);
183 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_3r
), Reg
)
184 .addReg(ScratchBase
, RegState::Kill
)
185 .addReg(ScratchOffset
, RegState::Kill
)
186 .addMemOperand(*MI
.memoperands_begin());
189 BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_l3r
))
190 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
191 .addReg(ScratchBase
, RegState::Kill
)
192 .addReg(ScratchOffset
, RegState::Kill
)
193 .addMemOperand(*MI
.memoperands_begin());
196 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l3r
), Reg
)
197 .addReg(ScratchBase
, RegState::Kill
)
198 .addReg(ScratchOffset
, RegState::Kill
);
201 llvm_unreachable("Unexpected Opcode");
205 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction
&MF
) {
206 return MF
.getMMI().hasDebugInfo() || MF
.getFunction().needsUnwindTableEntry();
210 XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF
) const {
211 // The callee saved registers LR & FP are explicitly handled during
212 // emitPrologue & emitEpilogue and related functions.
213 static const MCPhysReg CalleeSavedRegs
[] = {
214 XCore::R4
, XCore::R5
, XCore::R6
, XCore::R7
,
215 XCore::R8
, XCore::R9
, XCore::R10
,
218 static const MCPhysReg CalleeSavedRegsFP
[] = {
219 XCore::R4
, XCore::R5
, XCore::R6
, XCore::R7
,
220 XCore::R8
, XCore::R9
,
223 const XCoreFrameLowering
*TFI
= getFrameLowering(*MF
);
225 return CalleeSavedRegsFP
;
226 return CalleeSavedRegs
;
229 BitVector
XCoreRegisterInfo::getReservedRegs(const MachineFunction
&MF
) const {
230 BitVector
Reserved(getNumRegs());
231 const XCoreFrameLowering
*TFI
= getFrameLowering(MF
);
233 Reserved
.set(XCore::CP
);
234 Reserved
.set(XCore::DP
);
235 Reserved
.set(XCore::SP
);
236 Reserved
.set(XCore::LR
);
237 if (TFI
->hasFP(MF
)) {
238 Reserved
.set(XCore::R10
);
244 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction
&MF
) const {
249 XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction
&MF
) const {
254 XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction
&MF
) const {
259 XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
260 int SPAdj
, unsigned FIOperandNum
,
261 RegScavenger
*RS
) const {
262 assert(SPAdj
== 0 && "Unexpected");
263 MachineInstr
&MI
= *II
;
264 MachineOperand
&FrameOp
= MI
.getOperand(FIOperandNum
);
265 int FrameIndex
= FrameOp
.getIndex();
267 MachineFunction
&MF
= *MI
.getParent()->getParent();
268 const XCoreInstrInfo
&TII
=
269 *static_cast<const XCoreInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
271 const XCoreFrameLowering
*TFI
= getFrameLowering(MF
);
272 int Offset
= MF
.getFrameInfo().getObjectOffset(FrameIndex
);
273 int StackSize
= MF
.getFrameInfo().getStackSize();
276 LLVM_DEBUG(errs() << "\nFunction : " << MF
.getName() << "\n");
277 LLVM_DEBUG(errs() << "<--------->\n");
278 LLVM_DEBUG(MI
.print(errs()));
279 LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex
<< "\n");
280 LLVM_DEBUG(errs() << "FrameOffset : " << Offset
<< "\n");
281 LLVM_DEBUG(errs() << "StackSize : " << StackSize
<< "\n");
286 Register FrameReg
= getFrameRegister(MF
);
288 // Special handling of DBG_VALUE instructions.
289 if (MI
.isDebugValue()) {
290 MI
.getOperand(FIOperandNum
).ChangeToRegister(FrameReg
, false /*isDef*/);
291 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(Offset
);
295 // fold constant into offset.
296 Offset
+= MI
.getOperand(FIOperandNum
+ 1).getImm();
297 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(0);
299 assert(Offset
%4 == 0 && "Misaligned stack offset");
300 LLVM_DEBUG(errs() << "Offset : " << Offset
<< "\n"
304 Register Reg
= MI
.getOperand(0).getReg();
305 assert(XCore::GRRegsRegClass
.contains(Reg
) && "Unexpected register operand");
307 if (TFI
->hasFP(MF
)) {
309 InsertFPImmInst(II
, TII
, Reg
, FrameReg
, Offset
);
311 InsertFPConstInst(II
, TII
, Reg
, FrameReg
, Offset
, RS
);
313 if (isImmU16(Offset
))
314 InsertSPImmInst(II
, TII
, Reg
, Offset
);
316 InsertSPConstInst(II
, TII
, Reg
, Offset
, RS
);
318 // Erase old instruction.
319 MachineBasicBlock
&MBB
= *MI
.getParent();
324 Register
XCoreRegisterInfo::getFrameRegister(const MachineFunction
&MF
) const {
325 const XCoreFrameLowering
*TFI
= getFrameLowering(MF
);
327 return TFI
->hasFP(MF
) ? XCore::R10
: XCore::SP
;