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"
14 #include "XCoreInstrInfo.h"
15 #include "XCoreSubtarget.h"
16 #include "llvm/ADT/BitVector.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineModuleInfo.h"
21 #include "llvm/CodeGen/RegisterScavenging.h"
22 #include "llvm/CodeGen/TargetFrameLowering.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/Type.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include "llvm/Target/TargetMachine.h"
29 #include "llvm/Target/TargetOptions.h"
33 #define DEBUG_TYPE "xcore-reg-info"
35 #define GET_REGINFO_TARGET_DESC
36 #include "XCoreGenRegisterInfo.inc"
38 XCoreRegisterInfo::XCoreRegisterInfo()
39 : XCoreGenRegisterInfo(XCore::LR
) {
43 static inline bool isImmUs(unsigned val
) {
47 static inline bool isImmU6(unsigned val
) {
48 return val
< (1 << 6);
51 static inline bool isImmU16(unsigned val
) {
52 return val
< (1 << 16);
56 static void InsertFPImmInst(MachineBasicBlock::iterator II
,
57 const XCoreInstrInfo
&TII
,
58 unsigned Reg
, unsigned FrameReg
, int Offset
) {
59 MachineInstr
&MI
= *II
;
60 MachineBasicBlock
&MBB
= *MI
.getParent();
61 DebugLoc dl
= MI
.getDebugLoc();
63 switch (MI
.getOpcode()) {
65 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_2rus
), Reg
)
68 .addMemOperand(*MI
.memoperands_begin());
71 BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_2rus
))
72 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
75 .addMemOperand(*MI
.memoperands_begin());
78 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l2rus
), Reg
)
83 llvm_unreachable("Unexpected Opcode");
87 static void InsertFPConstInst(MachineBasicBlock::iterator II
,
88 const XCoreInstrInfo
&TII
,
89 unsigned Reg
, unsigned FrameReg
,
90 int Offset
, RegScavenger
*RS
) {
91 assert(RS
&& "requiresRegisterScavenging failed");
92 MachineInstr
&MI
= *II
;
93 MachineBasicBlock
&MBB
= *MI
.getParent();
94 DebugLoc dl
= MI
.getDebugLoc();
95 Register ScratchOffset
=
96 RS
->scavengeRegisterBackwards(XCore::GRRegsRegClass
, II
, false, 0);
97 RS
->setRegUsed(ScratchOffset
);
98 TII
.loadImmediate(MBB
, II
, ScratchOffset
, Offset
);
100 switch (MI
.getOpcode()) {
102 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_3r
), Reg
)
104 .addReg(ScratchOffset
, RegState::Kill
)
105 .addMemOperand(*MI
.memoperands_begin());
108 BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_l3r
))
109 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
111 .addReg(ScratchOffset
, RegState::Kill
)
112 .addMemOperand(*MI
.memoperands_begin());
115 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l3r
), Reg
)
117 .addReg(ScratchOffset
, RegState::Kill
);
120 llvm_unreachable("Unexpected Opcode");
124 static void InsertSPImmInst(MachineBasicBlock::iterator II
,
125 const XCoreInstrInfo
&TII
,
126 unsigned Reg
, int Offset
) {
127 MachineInstr
&MI
= *II
;
128 MachineBasicBlock
&MBB
= *MI
.getParent();
129 DebugLoc dl
= MI
.getDebugLoc();
130 bool isU6
= isImmU6(Offset
);
132 switch (MI
.getOpcode()) {
135 NewOpcode
= (isU6
) ? XCore::LDWSP_ru6
: XCore::LDWSP_lru6
;
136 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
), Reg
)
138 .addMemOperand(*MI
.memoperands_begin());
141 NewOpcode
= (isU6
) ? XCore::STWSP_ru6
: XCore::STWSP_lru6
;
142 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
))
143 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
145 .addMemOperand(*MI
.memoperands_begin());
148 NewOpcode
= (isU6
) ? XCore::LDAWSP_ru6
: XCore::LDAWSP_lru6
;
149 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
), Reg
)
153 llvm_unreachable("Unexpected Opcode");
157 static void InsertSPConstInst(MachineBasicBlock::iterator II
,
158 const XCoreInstrInfo
&TII
,
159 unsigned Reg
, int Offset
, RegScavenger
*RS
) {
160 assert(RS
&& "requiresRegisterScavenging failed");
161 MachineInstr
&MI
= *II
;
162 MachineBasicBlock
&MBB
= *MI
.getParent();
163 DebugLoc dl
= MI
.getDebugLoc();
164 unsigned OpCode
= MI
.getOpcode();
166 unsigned ScratchBase
;
167 if (OpCode
==XCore::STWFI
) {
169 RS
->scavengeRegisterBackwards(XCore::GRRegsRegClass
, II
, false, 0);
170 RS
->setRegUsed(ScratchBase
);
173 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWSP_ru6
), ScratchBase
).addImm(0);
174 Register ScratchOffset
=
175 RS
->scavengeRegisterBackwards(XCore::GRRegsRegClass
, II
, false, 0);
176 RS
->setRegUsed(ScratchOffset
);
177 TII
.loadImmediate(MBB
, II
, ScratchOffset
, Offset
);
181 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_3r
), Reg
)
182 .addReg(ScratchBase
, RegState::Kill
)
183 .addReg(ScratchOffset
, RegState::Kill
)
184 .addMemOperand(*MI
.memoperands_begin());
187 BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_l3r
))
188 .addReg(Reg
, getKillRegState(MI
.getOperand(0).isKill()))
189 .addReg(ScratchBase
, RegState::Kill
)
190 .addReg(ScratchOffset
, RegState::Kill
)
191 .addMemOperand(*MI
.memoperands_begin());
194 BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l3r
), Reg
)
195 .addReg(ScratchBase
, RegState::Kill
)
196 .addReg(ScratchOffset
, RegState::Kill
);
199 llvm_unreachable("Unexpected Opcode");
203 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction
&MF
) {
204 return MF
.needsFrameMoves();
208 XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF
) const {
209 // The callee saved registers LR & FP are explicitly handled during
210 // emitPrologue & emitEpilogue and related functions.
211 static const MCPhysReg CalleeSavedRegs
[] = {
212 XCore::R4
, XCore::R5
, XCore::R6
, XCore::R7
,
213 XCore::R8
, XCore::R9
, XCore::R10
,
216 static const MCPhysReg CalleeSavedRegsFP
[] = {
217 XCore::R4
, XCore::R5
, XCore::R6
, XCore::R7
,
218 XCore::R8
, XCore::R9
,
221 const XCoreFrameLowering
*TFI
= getFrameLowering(*MF
);
223 return CalleeSavedRegsFP
;
224 return CalleeSavedRegs
;
227 BitVector
XCoreRegisterInfo::getReservedRegs(const MachineFunction
&MF
) const {
228 BitVector
Reserved(getNumRegs());
229 const XCoreFrameLowering
*TFI
= getFrameLowering(MF
);
231 Reserved
.set(XCore::CP
);
232 Reserved
.set(XCore::DP
);
233 Reserved
.set(XCore::SP
);
234 Reserved
.set(XCore::LR
);
235 if (TFI
->hasFP(MF
)) {
236 Reserved
.set(XCore::R10
);
242 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction
&MF
) const {
247 XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction
&MF
) const {
252 XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
253 int SPAdj
, unsigned FIOperandNum
,
254 RegScavenger
*RS
) const {
255 assert(SPAdj
== 0 && "Unexpected");
256 MachineInstr
&MI
= *II
;
257 MachineOperand
&FrameOp
= MI
.getOperand(FIOperandNum
);
258 int FrameIndex
= FrameOp
.getIndex();
260 MachineFunction
&MF
= *MI
.getParent()->getParent();
261 const XCoreInstrInfo
&TII
=
262 *static_cast<const XCoreInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
264 const XCoreFrameLowering
*TFI
= getFrameLowering(MF
);
265 int Offset
= MF
.getFrameInfo().getObjectOffset(FrameIndex
);
266 int StackSize
= MF
.getFrameInfo().getStackSize();
269 LLVM_DEBUG(errs() << "\nFunction : " << MF
.getName() << "\n");
270 LLVM_DEBUG(errs() << "<--------->\n");
271 LLVM_DEBUG(MI
.print(errs()));
272 LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex
<< "\n");
273 LLVM_DEBUG(errs() << "FrameOffset : " << Offset
<< "\n");
274 LLVM_DEBUG(errs() << "StackSize : " << StackSize
<< "\n");
279 Register FrameReg
= getFrameRegister(MF
);
281 // Special handling of DBG_VALUE instructions.
282 if (MI
.isDebugValue()) {
283 MI
.getOperand(FIOperandNum
).ChangeToRegister(FrameReg
, false /*isDef*/);
284 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(Offset
);
288 // fold constant into offset.
289 Offset
+= MI
.getOperand(FIOperandNum
+ 1).getImm();
290 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(0);
292 assert(Offset
%4 == 0 && "Misaligned stack offset");
293 LLVM_DEBUG(errs() << "Offset : " << Offset
<< "\n"
297 Register Reg
= MI
.getOperand(0).getReg();
298 assert(XCore::GRRegsRegClass
.contains(Reg
) && "Unexpected register operand");
300 if (TFI
->hasFP(MF
)) {
302 InsertFPImmInst(II
, TII
, Reg
, FrameReg
, Offset
);
304 InsertFPConstInst(II
, TII
, Reg
, FrameReg
, Offset
, RS
);
306 if (isImmU16(Offset
))
307 InsertSPImmInst(II
, TII
, Reg
, Offset
);
309 InsertSPConstInst(II
, TII
, Reg
, Offset
, RS
);
311 // Erase old instruction.
312 MachineBasicBlock
&MBB
= *MI
.getParent();
318 Register
XCoreRegisterInfo::getFrameRegister(const MachineFunction
&MF
) const {
319 const XCoreFrameLowering
*TFI
= getFrameLowering(MF
);
321 return TFI
->hasFP(MF
) ? XCore::R10
: XCore::SP
;