1 //===- XCoreRegisterInfo.cpp - XCore Register Information -------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains the XCore implementation of the MRegisterInfo class.
12 //===----------------------------------------------------------------------===//
14 #include "XCoreRegisterInfo.h"
15 #include "XCoreMachineFunctionInfo.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineLocation.h"
21 #include "llvm/CodeGen/MachineModuleInfo.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/CodeGen/RegisterScavenging.h"
24 #include "llvm/Target/TargetFrameInfo.h"
25 #include "llvm/Target/TargetMachine.h"
26 #include "llvm/Target/TargetOptions.h"
27 #include "llvm/Target/TargetInstrInfo.h"
28 #include "llvm/Type.h"
29 #include "llvm/Function.h"
30 #include "llvm/ADT/BitVector.h"
31 #include "llvm/ADT/STLExtras.h"
32 #include "llvm/Support/Debug.h"
36 XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo
&tii
)
37 : XCoreGenRegisterInfo(XCore::ADJCALLSTACKDOWN
, XCore::ADJCALLSTACKUP
),
42 static inline bool isImmUs(unsigned val
) {
46 static inline bool isImmU6(unsigned val
) {
47 return val
< (1 << 6);
50 static inline bool isImmU16(unsigned val
) {
51 return val
< (1 << 16);
54 static const unsigned XCore_ArgRegs
[] = {
55 XCore::R0
, XCore::R1
, XCore::R2
, XCore::R3
58 const unsigned * XCoreRegisterInfo::getArgRegs(const MachineFunction
*MF
)
63 unsigned XCoreRegisterInfo::getNumArgRegs(const MachineFunction
*MF
)
65 return array_lengthof(XCore_ArgRegs
);
68 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction
&MF
)
70 const MachineFrameInfo
*MFI
= MF
.getFrameInfo();
71 MachineModuleInfo
*MMI
= MFI
->getMachineModuleInfo();
72 return (MMI
&& MMI
->hasDebugInfo()) ||
73 !MF
.getFunction()->doesNotThrow() ||
74 UnwindTablesMandatory
;
77 const unsigned* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF
)
79 static const unsigned CalleeSavedRegs
[] = {
80 XCore::R4
, XCore::R5
, XCore::R6
, XCore::R7
,
81 XCore::R8
, XCore::R9
, XCore::R10
, XCore::LR
,
84 return CalleeSavedRegs
;
87 const TargetRegisterClass
* const*
88 XCoreRegisterInfo::getCalleeSavedRegClasses(const MachineFunction
*MF
) const {
89 static const TargetRegisterClass
* const CalleeSavedRegClasses
[] = {
90 XCore::GRRegsRegisterClass
, XCore::GRRegsRegisterClass
,
91 XCore::GRRegsRegisterClass
, XCore::GRRegsRegisterClass
,
92 XCore::GRRegsRegisterClass
, XCore::GRRegsRegisterClass
,
93 XCore::GRRegsRegisterClass
, XCore::RRegsRegisterClass
,
96 return CalleeSavedRegClasses
;
99 BitVector
XCoreRegisterInfo::getReservedRegs(const MachineFunction
&MF
) const {
100 BitVector
Reserved(getNumRegs());
101 Reserved
.set(XCore::CP
);
102 Reserved
.set(XCore::DP
);
103 Reserved
.set(XCore::SP
);
104 Reserved
.set(XCore::LR
);
106 Reserved
.set(XCore::R10
);
112 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction
&MF
) const {
113 // TODO can we estimate stack size?
117 bool XCoreRegisterInfo::hasFP(const MachineFunction
&MF
) const {
118 return NoFramePointerElim
|| MF
.getFrameInfo()->hasVarSizedObjects();
121 // This function eliminates ADJCALLSTACKDOWN,
122 // ADJCALLSTACKUP pseudo instructions
123 void XCoreRegisterInfo::
124 eliminateCallFramePseudoInstr(MachineFunction
&MF
, MachineBasicBlock
&MBB
,
125 MachineBasicBlock::iterator I
) const {
126 if (!hasReservedCallFrame(MF
)) {
127 // Turn the adjcallstackdown instruction into 'extsp <amt>' and the
128 // adjcallstackup instruction into 'ldaw sp, sp[<amt>]'
129 MachineInstr
*Old
= I
;
130 uint64_t Amount
= Old
->getOperand(0).getImm();
132 // We need to keep the stack aligned properly. To do this, we round the
133 // amount of space needed for the outgoing arguments up to the next
134 // alignment boundary.
135 unsigned Align
= MF
.getTarget().getFrameInfo()->getStackAlignment();
136 Amount
= (Amount
+Align
-1)/Align
*Align
;
138 assert(Amount
%4 == 0);
141 bool isU6
= isImmU6(Amount
);
143 if (!isU6
&& !isImmU16(Amount
)) {
144 // FIX could emit multiple instructions in this case.
145 cerr
<< "eliminateCallFramePseudoInstr size too big: "
151 if (Old
->getOpcode() == XCore::ADJCALLSTACKDOWN
) {
152 int Opcode
= isU6
? XCore::EXTSP_u6
: XCore::EXTSP_lu6
;
153 New
=BuildMI(MF
, Old
->getDebugLoc(), TII
.get(Opcode
))
156 assert(Old
->getOpcode() == XCore::ADJCALLSTACKUP
);
157 int Opcode
= isU6
? XCore::LDAWSP_ru6_RRegs
: XCore::LDAWSP_lru6_RRegs
;
158 New
=BuildMI(MF
, Old
->getDebugLoc(), TII
.get(Opcode
), XCore::SP
)
162 // Replace the pseudo instruction with a new instruction...
170 void XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
171 int SPAdj
, RegScavenger
*RS
) const {
172 assert(SPAdj
== 0 && "Unexpected");
173 MachineInstr
&MI
= *II
;
174 DebugLoc dl
= MI
.getDebugLoc();
177 while (!MI
.getOperand(i
).isFI()) {
179 assert(i
< MI
.getNumOperands() && "Instr doesn't have FrameIndex operand!");
182 MachineOperand
&FrameOp
= MI
.getOperand(i
);
183 int FrameIndex
= FrameOp
.getIndex();
185 MachineFunction
&MF
= *MI
.getParent()->getParent();
186 int Offset
= MF
.getFrameInfo()->getObjectOffset(FrameIndex
);
187 int StackSize
= MF
.getFrameInfo()->getStackSize();
190 DOUT
<< "\nFunction : " << MF
.getFunction()->getName() << "\n";
191 DOUT
<< "<--------->\n";
193 DOUT
<< "FrameIndex : " << FrameIndex
<< "\n";
194 DOUT
<< "FrameOffset : " << Offset
<< "\n";
195 DOUT
<< "StackSize : " << StackSize
<< "\n";
200 // fold constant into offset.
201 Offset
+= MI
.getOperand(i
+ 1).getImm();
202 MI
.getOperand(i
+ 1).ChangeToImmediate(0);
204 assert(Offset
%4 == 0 && "Misaligned stack offset");
207 DOUT
<< "Offset : " << Offset
<< "\n";
208 DOUT
<< "<--------->\n";
215 unsigned Reg
= MI
.getOperand(0).getReg();
216 bool isKill
= MI
.getOpcode() == XCore::STWFI
&& MI
.getOperand(0).isKill();
218 assert(XCore::GRRegsRegisterClass
->contains(Reg
) &&
219 "Unexpected register operand");
221 MachineBasicBlock
&MBB
= *MI
.getParent();
224 bool isUs
= isImmUs(Offset
);
225 unsigned FramePtr
= XCore::R10
;
227 MachineInstr
*New
= 0;
230 cerr
<< "eliminateFrameIndex Frame size too big: " << Offset
<< "\n";
233 unsigned ScratchReg
= RS
->scavengeRegister(XCore::GRRegsRegisterClass
, II
,
235 loadConstant(MBB
, II
, ScratchReg
, Offset
, dl
);
236 switch (MI
.getOpcode()) {
238 New
= BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_3r
), Reg
)
240 .addReg(ScratchReg
, false, false, true);
243 New
= BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_3r
))
244 .addReg(Reg
, false, false, isKill
)
246 .addReg(ScratchReg
, false, false, true);
249 New
= BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l3r
), Reg
)
251 .addReg(ScratchReg
, false, false, true);
254 assert(0 && "Unexpected Opcode\n");
257 switch (MI
.getOpcode()) {
259 New
= BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDW_2rus
), Reg
)
264 New
= BuildMI(MBB
, II
, dl
, TII
.get(XCore::STW_2rus
))
265 .addReg(Reg
, false, false, isKill
)
270 New
= BuildMI(MBB
, II
, dl
, TII
.get(XCore::LDAWF_l2rus
), Reg
)
275 assert(0 && "Unexpected Opcode\n");
279 bool isU6
= isImmU6(Offset
);
280 if (!isU6
&& !isImmU16(Offset
)) {
281 // FIXME could make this work for LDWSP, LDAWSP.
282 cerr
<< "eliminateFrameIndex Frame size too big: " << Offset
<< "\n";
286 switch (MI
.getOpcode()) {
289 NewOpcode
= (isU6
) ? XCore::LDWSP_ru6
: XCore::LDWSP_lru6
;
290 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
), Reg
)
294 NewOpcode
= (isU6
) ? XCore::STWSP_ru6
: XCore::STWSP_lru6
;
295 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
))
296 .addReg(Reg
, false, false, isKill
)
300 NewOpcode
= (isU6
) ? XCore::LDAWSP_ru6
: XCore::LDAWSP_lru6
;
301 BuildMI(MBB
, II
, dl
, TII
.get(NewOpcode
), Reg
)
305 assert(0 && "Unexpected Opcode\n");
308 // Erase old instruction.
313 XCoreRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction
&MF
,
314 RegScavenger
*RS
) const {
315 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
316 bool LRUsed
= MF
.getRegInfo().isPhysRegUsed(XCore::LR
);
317 const TargetRegisterClass
*RC
= XCore::GRRegsRegisterClass
;
318 XCoreFunctionInfo
*XFI
= MF
.getInfo
<XCoreFunctionInfo
>();
320 MF
.getRegInfo().setPhysRegUnused(XCore::LR
);
322 bool isVarArg
= MF
.getFunction()->isVarArg();
325 // A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
326 FrameIdx
= MFI
->CreateFixedObject(RC
->getSize(), 0);
328 FrameIdx
= MFI
->CreateStackObject(RC
->getSize(), RC
->getAlignment());
330 XFI
->setUsesLR(FrameIdx
);
331 XFI
->setLRSpillSlot(FrameIdx
);
333 if (requiresRegisterScavenging(MF
)) {
334 // Reserve a slot close to SP or frame pointer.
335 RS
->setScavengingFrameIndex(MFI
->CreateStackObject(RC
->getSize(),
336 RC
->getAlignment()));
339 // A callee save register is used to hold the FP.
340 // This needs saving / restoring in the epilogue / prologue.
341 XFI
->setFPSpillSlot(MFI
->CreateStackObject(RC
->getSize(),
342 RC
->getAlignment()));
346 void XCoreRegisterInfo::
347 processFunctionBeforeFrameFinalized(MachineFunction
&MF
) const {
351 void XCoreRegisterInfo::
352 loadConstant(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
353 unsigned DstReg
, int64_t Value
, DebugLoc dl
) const {
354 // TODO use mkmsk if possible.
355 if (!isImmU16(Value
)) {
356 // TODO use constant pool.
357 cerr
<< "loadConstant value too big " << Value
<< "\n";
360 int Opcode
= isImmU6(Value
) ? XCore::LDC_ru6
: XCore::LDC_lru6
;
361 BuildMI(MBB
, I
, dl
, TII
.get(Opcode
), DstReg
).addImm(Value
);
364 void XCoreRegisterInfo::
365 storeToStack(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
366 unsigned SrcReg
, int Offset
, DebugLoc dl
) const {
367 assert(Offset
%4 == 0 && "Misaligned stack offset");
369 bool isU6
= isImmU6(Offset
);
370 if (!isU6
&& !isImmU16(Offset
)) {
371 cerr
<< "storeToStack offset too big " << Offset
<< "\n";
374 int Opcode
= isU6
? XCore::STWSP_ru6
: XCore::STWSP_lru6
;
375 BuildMI(MBB
, I
, dl
, TII
.get(Opcode
))
380 void XCoreRegisterInfo::
381 loadFromStack(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
382 unsigned DstReg
, int Offset
, DebugLoc dl
) const {
383 assert(Offset
%4 == 0 && "Misaligned stack offset");
385 bool isU6
= isImmU6(Offset
);
386 if (!isU6
&& !isImmU16(Offset
)) {
387 cerr
<< "loadFromStack offset too big " << Offset
<< "\n";
390 int Opcode
= isU6
? XCore::LDWSP_ru6
: XCore::LDWSP_lru6
;
391 BuildMI(MBB
, I
, dl
, TII
.get(Opcode
), DstReg
)
395 void XCoreRegisterInfo::emitPrologue(MachineFunction
&MF
) const {
396 MachineBasicBlock
&MBB
= MF
.front(); // Prolog goes in entry BB
397 MachineBasicBlock::iterator MBBI
= MBB
.begin();
398 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
399 MachineModuleInfo
*MMI
= MFI
->getMachineModuleInfo();
400 XCoreFunctionInfo
*XFI
= MF
.getInfo
<XCoreFunctionInfo
>();
401 DebugLoc dl
= (MBBI
!= MBB
.end() ?
402 MBBI
->getDebugLoc() : DebugLoc::getUnknownLoc());
406 // Work out frame sizes.
407 int FrameSize
= MFI
->getStackSize();
409 assert(FrameSize
%4 == 0 && "Misaligned frame size");
413 bool isU6
= isImmU6(FrameSize
);
415 if (!isU6
&& !isImmU16(FrameSize
)) {
416 // FIXME could emit multiple instructions.
417 cerr
<< "emitPrologue Frame size too big: " << FrameSize
<< "\n";
420 bool emitFrameMoves
= needsFrameMoves(MF
);
422 // Do we need to allocate space on the stack?
424 bool saveLR
= XFI
->getUsesLR();
425 bool LRSavedOnEntry
= false;
427 if (saveLR
&& (MFI
->getObjectOffset(XFI
->getLRSpillSlot()) == 0)) {
428 Opcode
= (isU6
) ? XCore::ENTSP_u6
: XCore::ENTSP_lu6
;
429 MBB
.addLiveIn(XCore::LR
);
431 LRSavedOnEntry
= true;
433 Opcode
= (isU6
) ? XCore::EXTSP_u6
: XCore::EXTSP_lu6
;
435 BuildMI(MBB
, MBBI
, dl
, TII
.get(Opcode
)).addImm(FrameSize
);
437 if (emitFrameMoves
) {
438 std::vector
<MachineMove
> &Moves
= MMI
->getFrameMoves();
440 // Show update of SP.
441 unsigned FrameLabelId
= MMI
->NextLabelID();
442 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::DBG_LABEL
)).addImm(FrameLabelId
);
444 MachineLocation
SPDst(MachineLocation::VirtualFP
);
445 MachineLocation
SPSrc(MachineLocation::VirtualFP
, -FrameSize
* 4);
446 Moves
.push_back(MachineMove(FrameLabelId
, SPDst
, SPSrc
));
448 if (LRSavedOnEntry
) {
449 MachineLocation
CSDst(MachineLocation::VirtualFP
, 0);
450 MachineLocation
CSSrc(XCore::LR
);
451 Moves
.push_back(MachineMove(FrameLabelId
, CSDst
, CSSrc
));
455 int LRSpillOffset
= MFI
->getObjectOffset(XFI
->getLRSpillSlot());
456 storeToStack(MBB
, MBBI
, XCore::LR
, LRSpillOffset
+ FrameSize
*4, dl
);
457 MBB
.addLiveIn(XCore::LR
);
459 if (emitFrameMoves
) {
460 unsigned SaveLRLabelId
= MMI
->NextLabelID();
461 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::DBG_LABEL
)).addImm(SaveLRLabelId
);
462 MachineLocation
CSDst(MachineLocation::VirtualFP
, LRSpillOffset
);
463 MachineLocation
CSSrc(XCore::LR
);
464 MMI
->getFrameMoves().push_back(MachineMove(SaveLRLabelId
,
471 // Save R10 to the stack.
472 int FPSpillOffset
= MFI
->getObjectOffset(XFI
->getFPSpillSlot());
473 storeToStack(MBB
, MBBI
, XCore::R10
, FPSpillOffset
+ FrameSize
*4, dl
);
474 // R10 is live-in. It is killed at the spill.
475 MBB
.addLiveIn(XCore::R10
);
476 if (emitFrameMoves
) {
477 unsigned SaveR10LabelId
= MMI
->NextLabelID();
478 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::DBG_LABEL
)).addImm(SaveR10LabelId
);
479 MachineLocation
CSDst(MachineLocation::VirtualFP
, FPSpillOffset
);
480 MachineLocation
CSSrc(XCore::R10
);
481 MMI
->getFrameMoves().push_back(MachineMove(SaveR10LabelId
,
484 // Set the FP from the SP.
485 unsigned FramePtr
= XCore::R10
;
486 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::LDAWSP_ru6
), FramePtr
)
488 if (emitFrameMoves
) {
489 // Show FP is now valid.
490 unsigned FrameLabelId
= MMI
->NextLabelID();
491 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::DBG_LABEL
)).addImm(FrameLabelId
);
492 MachineLocation
SPDst(FramePtr
);
493 MachineLocation
SPSrc(MachineLocation::VirtualFP
);
494 MMI
->getFrameMoves().push_back(MachineMove(FrameLabelId
, SPDst
, SPSrc
));
498 if (emitFrameMoves
) {
499 // Frame moves for callee saved.
500 std::vector
<MachineMove
> &Moves
= MMI
->getFrameMoves();
501 std::vector
<std::pair
<unsigned, CalleeSavedInfo
> >&SpillLabels
=
502 XFI
->getSpillLabels();
503 for (unsigned I
= 0, E
= SpillLabels
.size(); I
!= E
; ++I
) {
504 unsigned SpillLabel
= SpillLabels
[I
].first
;
505 CalleeSavedInfo
&CSI
= SpillLabels
[I
].second
;
506 int Offset
= MFI
->getObjectOffset(CSI
.getFrameIdx());
507 unsigned Reg
= CSI
.getReg();
508 MachineLocation
CSDst(MachineLocation::VirtualFP
, Offset
);
509 MachineLocation
CSSrc(Reg
);
510 Moves
.push_back(MachineMove(SpillLabel
, CSDst
, CSSrc
));
515 void XCoreRegisterInfo::emitEpilogue(MachineFunction
&MF
,
516 MachineBasicBlock
&MBB
) const {
517 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
518 MachineBasicBlock::iterator MBBI
= prior(MBB
.end());
519 DebugLoc dl
= MBBI
->getDebugLoc();
524 // Restore the stack pointer.
525 unsigned FramePtr
= XCore::R10
;
526 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::SETSP_1r
))
530 // Work out frame sizes.
531 int FrameSize
= MFI
->getStackSize();
533 assert(FrameSize
%4 == 0 && "Misaligned frame size");
537 bool isU6
= isImmU6(FrameSize
);
539 if (!isU6
&& !isImmU16(FrameSize
)) {
540 // FIXME could emit multiple instructions.
541 cerr
<< "emitEpilogue Frame size too big: " << FrameSize
<< "\n";
546 XCoreFunctionInfo
*XFI
= MF
.getInfo
<XCoreFunctionInfo
>();
550 int FPSpillOffset
= MFI
->getObjectOffset(XFI
->getFPSpillSlot());
551 FPSpillOffset
+= FrameSize
*4;
552 loadFromStack(MBB
, MBBI
, XCore::R10
, FPSpillOffset
, dl
);
554 bool restoreLR
= XFI
->getUsesLR();
555 if (restoreLR
&& MFI
->getObjectOffset(XFI
->getLRSpillSlot()) != 0) {
556 int LRSpillOffset
= MFI
->getObjectOffset(XFI
->getLRSpillSlot());
557 LRSpillOffset
+= FrameSize
*4;
558 loadFromStack(MBB
, MBBI
, XCore::LR
, LRSpillOffset
, dl
);
562 // Fold prologue into return instruction
563 assert(MBBI
->getOpcode() == XCore::RETSP_u6
564 || MBBI
->getOpcode() == XCore::RETSP_lu6
);
565 int Opcode
= (isU6
) ? XCore::RETSP_u6
: XCore::RETSP_lu6
;
566 BuildMI(MBB
, MBBI
, dl
, TII
.get(Opcode
)).addImm(FrameSize
);
569 int Opcode
= (isU6
) ? XCore::LDAWSP_ru6_RRegs
: XCore::LDAWSP_lru6_RRegs
;
570 BuildMI(MBB
, MBBI
, dl
, TII
.get(Opcode
), XCore::SP
).addImm(FrameSize
);
575 int XCoreRegisterInfo::getDwarfRegNum(unsigned RegNum
, bool isEH
) const {
576 return XCoreGenRegisterInfo::getDwarfRegNumFull(RegNum
, 0);
579 unsigned XCoreRegisterInfo::getFrameRegister(MachineFunction
&MF
) const {
582 return FP
? XCore::R10
: XCore::SP
;
585 unsigned XCoreRegisterInfo::getRARegister() const {
589 void XCoreRegisterInfo::getInitialFrameState(std::vector
<MachineMove
> &Moves
)
591 // Initial state of the frame pointer is SP.
592 MachineLocation
Dst(MachineLocation::VirtualFP
);
593 MachineLocation
Src(XCore::SP
, 0);
594 Moves
.push_back(MachineMove(0, Dst
, Src
));
597 #include "XCoreGenRegisterInfo.inc"