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 Register ScratchOffset
=
101 RS
->scavengeRegisterBackwards(XCore::GRRegsRegClass
, II
, false, 0);
102 RS
->setRegUsed(ScratchOffset
);
103 TII
.loadImmediate(MBB
, II
, ScratchOffset
, Offset
);
105 switch (MI
.getOpcode()) {
107 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_3r
), Reg
)
109 .addReg(ScratchOffset
, RegState::Kill
)
110 .addMemOperand(*MI
.memoperands_begin());
113 BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_l3r
))
114 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
116 .addReg(ScratchOffset
, RegState::Kill
)
117 .addMemOperand(*MI
.memoperands_begin());
120 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l3r
), Reg
)
122 .addReg(ScratchOffset
, RegState::Kill
);
125 llvm_unreachable("Unexpected Opcode");
129 static void InsertSPImmInst(MachineBasicBlock::iterator II
,
130 const XCoreInstrInfo
&TII
,
131 unsigned Reg
, int Offset
) {
132 MachineInstr
&MI
= *II
;
133 MachineBasicBlock
&MBB
= *MI
.getParent();
134 DebugLoc dl
= MI
.getDebugLoc();
135 bool isU6
= isImmU6(Offset
);
137 switch (MI
.getOpcode()) {
140 NewOpcode
= (isU6
) ? XCore::LDWSP_ru6
: XCore::LDWSP_lru6
;
141 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
), Reg
)
143 .addMemOperand(*MI
.memoperands_begin());
146 NewOpcode
= (isU6
) ? XCore::STWSP_ru6
: XCore::STWSP_lru6
;
147 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
))
148 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
150 .addMemOperand(*MI
.memoperands_begin());
153 NewOpcode
= (isU6
) ? XCore::LDAWSP_ru6
: XCore::LDAWSP_lru6
;
154 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
), Reg
)
158 llvm_unreachable("Unexpected Opcode");
162 static void InsertSPConstInst(MachineBasicBlock::iterator II
,
163 const XCoreInstrInfo
&TII
,
164 unsigned Reg
, int Offset
, RegScavenger
*RS
) {
165 assert(RS
&& "requiresRegisterScavenging failed");
166 MachineInstr
&MI
= *II
;
167 MachineBasicBlock
&MBB
= *MI
.getParent();
168 DebugLoc dl
= MI
.getDebugLoc();
169 unsigned OpCode
= MI
.getOpcode();
171 unsigned ScratchBase
;
172 if (OpCode
==XCore::STWFI
) {
174 RS
->scavengeRegisterBackwards(XCore::GRRegsRegClass
, II
, false, 0);
175 RS
->setRegUsed(ScratchBase
);
178 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWSP_ru6
), ScratchBase
).addImm(0);
179 Register ScratchOffset
=
180 RS
->scavengeRegisterBackwards(XCore::GRRegsRegClass
, II
, false, 0);
181 RS
->setRegUsed(ScratchOffset
);
182 TII
.loadImmediate(MBB
, II
, ScratchOffset
, Offset
);
186 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_3r
), Reg
)
187 .addReg(ScratchBase
, RegState::Kill
)
188 .addReg(ScratchOffset
, RegState::Kill
)
189 .addMemOperand(*MI
.memoperands_begin());
192 BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_l3r
))
193 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
194 .addReg(ScratchBase
, RegState::Kill
)
195 .addReg(ScratchOffset
, RegState::Kill
)
196 .addMemOperand(*MI
.memoperands_begin());
199 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l3r
), Reg
)
200 .addReg(ScratchBase
, RegState::Kill
)
201 .addReg(ScratchOffset
, RegState::Kill
);
204 llvm_unreachable("Unexpected Opcode");
208 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction
&MF
) {
209 return MF
.needsFrameMoves();
213 XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF
) const {
214 // The callee saved registers LR & FP are explicitly handled during
215 // emitPrologue & emitEpilogue and related functions.
216 static const MCPhysReg CalleeSavedRegs
[] = {
217 XCore::R4
, XCore::R5
, XCore::R6
, XCore::R7
,
218 XCore::R8
, XCore::R9
, XCore::R10
,
221 static const MCPhysReg CalleeSavedRegsFP
[] = {
222 XCore::R4
, XCore::R5
, XCore::R6
, XCore::R7
,
223 XCore::R8
, XCore::R9
,
226 const XCoreFrameLowering
*TFI
= getFrameLowering(*MF
);
228 return CalleeSavedRegsFP
;
229 return CalleeSavedRegs
;
232 BitVector
XCoreRegisterInfo::getReservedRegs(const MachineFunction
&MF
) const {
233 BitVector
Reserved(getNumRegs());
234 const XCoreFrameLowering
*TFI
= getFrameLowering(MF
);
236 Reserved
.set(XCore::CP
);
237 Reserved
.set(XCore::DP
);
238 Reserved
.set(XCore::SP
);
239 Reserved
.set(XCore::LR
);
240 if (TFI
->hasFP(MF
)) {
241 Reserved
.set(XCore::R10
);
247 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction
&MF
) const {
252 XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction
&MF
) const {
257 XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
258 int SPAdj
, unsigned FIOperandNum
,
259 RegScavenger
*RS
) const {
260 assert(SPAdj
== 0 && "Unexpected");
261 MachineInstr
&MI
= *II
;
262 MachineOperand
&FrameOp
= MI
.getOperand(FIOperandNum
);
263 int FrameIndex
= FrameOp
.getIndex();
265 MachineFunction
&MF
= *MI
.getParent()->getParent();
266 const XCoreInstrInfo
&TII
=
267 *static_cast<const XCoreInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
269 const XCoreFrameLowering
*TFI
= getFrameLowering(MF
);
270 int Offset
= MF
.getFrameInfo().getObjectOffset(FrameIndex
);
271 int StackSize
= MF
.getFrameInfo().getStackSize();
274 LLVM_DEBUG(errs() << "\nFunction : " << MF
.getName() << "\n");
275 LLVM_DEBUG(errs() << "<--------->\n");
276 LLVM_DEBUG(MI
.print(errs()));
277 LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex
<< "\n");
278 LLVM_DEBUG(errs() << "FrameOffset : " << Offset
<< "\n");
279 LLVM_DEBUG(errs() << "StackSize : " << StackSize
<< "\n");
284 Register FrameReg
= getFrameRegister(MF
);
286 // Special handling of DBG_VALUE instructions.
287 if (MI
.isDebugValue()) {
288 MI
.getOperand(FIOperandNum
).ChangeToRegister(FrameReg
, false /*isDef*/);
289 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(Offset
);
293 // fold constant into offset.
294 Offset
+= MI
.getOperand(FIOperandNum
+ 1).getImm();
295 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(0);
297 assert(Offset
%4 == 0 && "Misaligned stack offset");
298 LLVM_DEBUG(errs() << "Offset : " << Offset
<< "\n"
302 Register Reg
= MI
.getOperand(0).getReg();
303 assert(XCore::GRRegsRegClass
.contains(Reg
) && "Unexpected register operand");
305 if (TFI
->hasFP(MF
)) {
307 InsertFPImmInst(II
, TII
, Reg
, FrameReg
, Offset
);
309 InsertFPConstInst(II
, TII
, Reg
, FrameReg
, Offset
, RS
);
311 if (isImmU16(Offset
))
312 InsertSPImmInst(II
, TII
, Reg
, Offset
);
314 InsertSPConstInst(II
, TII
, Reg
, Offset
, RS
);
316 // Erase old instruction.
317 MachineBasicBlock
&MBB
= *MI
.getParent();
323 Register
XCoreRegisterInfo::getFrameRegister(const MachineFunction
&MF
) const {
324 const XCoreFrameLowering
*TFI
= getFrameLowering(MF
);
326 return TFI
->hasFP(MF
) ? XCore::R10
: XCore::SP
;