1 //===-- AVRRegisterInfo.cpp - AVR 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 AVR implementation of the TargetRegisterInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "AVRRegisterInfo.h"
15 #include "llvm/ADT/BitVector.h"
16 #include "llvm/CodeGen/MachineFrameInfo.h"
17 #include "llvm/CodeGen/MachineFunction.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/CodeGen/TargetFrameLowering.h"
21 #include "llvm/IR/Function.h"
24 #include "AVRInstrInfo.h"
25 #include "AVRMachineFunctionInfo.h"
26 #include "AVRTargetMachine.h"
27 #include "MCTargetDesc/AVRMCTargetDesc.h"
29 #define GET_REGINFO_TARGET_DESC
30 #include "AVRGenRegisterInfo.inc"
34 AVRRegisterInfo::AVRRegisterInfo() : AVRGenRegisterInfo(0) {}
37 AVRRegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF
) const {
38 const AVRMachineFunctionInfo
*AFI
= MF
->getInfo
<AVRMachineFunctionInfo
>();
39 const AVRSubtarget
&STI
= MF
->getSubtarget
<AVRSubtarget
>();
40 if (STI
.hasTinyEncoding())
41 return AFI
->isInterruptOrSignalHandler() ? CSR_InterruptsTiny_SaveList
42 : CSR_NormalTiny_SaveList
;
44 return AFI
->isInterruptOrSignalHandler() ? CSR_Interrupts_SaveList
45 : CSR_Normal_SaveList
;
49 AVRRegisterInfo::getCallPreservedMask(const MachineFunction
&MF
,
50 CallingConv::ID CC
) const {
51 const AVRSubtarget
&STI
= MF
.getSubtarget
<AVRSubtarget
>();
52 return STI
.hasTinyEncoding() ? CSR_NormalTiny_RegMask
: CSR_Normal_RegMask
;
55 BitVector
AVRRegisterInfo::getReservedRegs(const MachineFunction
&MF
) const {
56 BitVector
Reserved(getNumRegs());
58 // Reserve the intermediate result registers r1 and r2
59 // The result of instructions like 'mul' is always stored here.
60 // R0/R1/R1R0 are always reserved on both avr and avrtiny.
61 Reserved
.set(AVR::R0
);
62 Reserved
.set(AVR::R1
);
63 Reserved
.set(AVR::R1R0
);
65 // Reserve the stack pointer.
66 Reserved
.set(AVR::SPL
);
67 Reserved
.set(AVR::SPH
);
68 Reserved
.set(AVR::SP
);
70 // Reserve R2~R17 only on avrtiny.
71 if (MF
.getSubtarget
<AVRSubtarget
>().hasTinyEncoding()) {
72 // Reserve 8-bit registers R2~R15, Rtmp(R16) and Zero(R17).
73 for (unsigned Reg
= AVR::R2
; Reg
<= AVR::R17
; Reg
++)
75 // Reserve 16-bit registers R3R2~R18R17.
76 for (unsigned Reg
= AVR::R3R2
; Reg
<= AVR::R18R17
; Reg
++)
80 // We tenatively reserve the frame pointer register r29:r28 because the
81 // function may require one, but we cannot tell until register allocation
82 // is complete, which can be too late.
84 // Instead we just unconditionally reserve the Y register.
86 // TODO: Write a pass to enumerate functions which reserved the Y register
87 // but didn't end up needing a frame pointer. In these, we can
88 // convert one or two of the spills inside to use the Y register.
89 Reserved
.set(AVR::R28
);
90 Reserved
.set(AVR::R29
);
91 Reserved
.set(AVR::R29R28
);
96 const TargetRegisterClass
*
97 AVRRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass
*RC
,
98 const MachineFunction
&MF
) const {
99 const TargetRegisterInfo
*TRI
= MF
.getSubtarget().getRegisterInfo();
100 if (TRI
->isTypeLegalForClass(*RC
, MVT::i16
)) {
101 return &AVR::DREGSRegClass
;
104 if (TRI
->isTypeLegalForClass(*RC
, MVT::i8
)) {
105 return &AVR::GPR8RegClass
;
108 llvm_unreachable("Invalid register size");
111 /// Fold a frame offset shared between two add instructions into a single one.
112 static void foldFrameOffset(MachineBasicBlock::iterator
&II
, int &Offset
,
114 MachineInstr
&MI
= *II
;
115 int Opcode
= MI
.getOpcode();
117 // Don't bother trying if the next instruction is not an add or a sub.
118 if ((Opcode
!= AVR::SUBIWRdK
) && (Opcode
!= AVR::ADIWRdK
)) {
122 // Check that DstReg matches with next instruction, otherwise the instruction
123 // is not related to stack address manipulation.
124 if (DstReg
!= MI
.getOperand(0).getReg()) {
128 // Add the offset in the next instruction to our offset.
131 Offset
+= -MI
.getOperand(2).getImm();
134 Offset
+= MI
.getOperand(2).getImm();
138 // Finally remove the instruction.
140 MI
.eraseFromParent();
143 bool AVRRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
144 int SPAdj
, unsigned FIOperandNum
,
145 RegScavenger
*RS
) const {
146 assert(SPAdj
== 0 && "Unexpected SPAdj value");
148 MachineInstr
&MI
= *II
;
149 DebugLoc dl
= MI
.getDebugLoc();
150 MachineBasicBlock
&MBB
= *MI
.getParent();
151 const MachineFunction
&MF
= *MBB
.getParent();
152 const AVRTargetMachine
&TM
= (const AVRTargetMachine
&)MF
.getTarget();
153 const TargetInstrInfo
&TII
= *TM
.getSubtargetImpl()->getInstrInfo();
154 const MachineFrameInfo
&MFI
= MF
.getFrameInfo();
155 const TargetFrameLowering
*TFI
= TM
.getSubtargetImpl()->getFrameLowering();
156 const AVRSubtarget
&STI
= MF
.getSubtarget
<AVRSubtarget
>();
157 int FrameIndex
= MI
.getOperand(FIOperandNum
).getIndex();
158 int Offset
= MFI
.getObjectOffset(FrameIndex
);
160 // Add one to the offset because SP points to an empty slot.
161 Offset
+= MFI
.getStackSize() - TFI
->getOffsetOfLocalArea() + 1;
162 // Fold incoming offset.
163 Offset
+= MI
.getOperand(FIOperandNum
+ 1).getImm();
165 // This is actually "load effective address" of the stack slot
166 // instruction. We have only two-address instructions, thus we need to
167 // expand it into move + add.
168 if (MI
.getOpcode() == AVR::FRMIDX
) {
169 Register DstReg
= MI
.getOperand(0).getReg();
170 assert(DstReg
!= AVR::R29R28
&& "Dest reg cannot be the frame pointer");
172 // Copy the frame pointer.
174 BuildMI(MBB
, MI
, dl
, TII
.get(AVR::MOVWRdRr
), DstReg
)
175 .addReg(AVR::R29R28
);
177 Register DstLoReg
, DstHiReg
;
178 splitReg(DstReg
, DstLoReg
, DstHiReg
);
179 BuildMI(MBB
, MI
, dl
, TII
.get(AVR::MOVRdRr
), DstLoReg
)
181 BuildMI(MBB
, MI
, dl
, TII
.get(AVR::MOVRdRr
), DstHiReg
)
185 assert(Offset
> 0 && "Invalid offset");
187 // We need to materialize the offset via an add instruction.
190 II
++; // Skip over the FRMIDX instruction.
192 // Generally, to load a frame address two add instructions are emitted that
193 // could get folded into a single one:
194 // movw r31:r30, r29:r28
198 // movw r31:r30, r29:r28
201 foldFrameOffset(II
, Offset
, DstReg
);
203 // Select the best opcode based on DstReg and the offset size.
208 if (isUInt
<6>(Offset
) && STI
.hasADDSUBIW()) {
209 Opcode
= AVR::ADIWRdK
;
215 // This opcode will get expanded into a pair of subi/sbci.
216 Opcode
= AVR::SUBIWRdK
;
222 MachineInstr
*New
= BuildMI(MBB
, II
, dl
, TII
.get(Opcode
), DstReg
)
223 .addReg(DstReg
, RegState::Kill
)
225 New
->getOperand(3).setIsDead();
227 MI
.eraseFromParent(); // remove FRMIDX
232 // On most AVRs, we can use an offset up to 62 for load/store with
233 // displacement (63 for byte values, 62 for word values). However, the
234 // "reduced tiny" cores don't support load/store with displacement. So for
235 // them, we force an offset of 0 meaning that any positive offset will require
236 // adjusting the frame pointer.
237 int MaxOffset
= STI
.hasTinyEncoding() ? 0 : 62;
239 // If the offset is too big we have to adjust and restore the frame pointer
240 // to materialize a valid load/store with displacement.
241 //: TODO: consider using only one adiw/sbiw chain for more than one frame
243 if (Offset
> MaxOffset
) {
244 unsigned AddOpc
= AVR::ADIWRdK
, SubOpc
= AVR::SBIWRdK
;
245 int AddOffset
= Offset
- MaxOffset
;
247 // For huge offsets where adiw/sbiw cannot be used use a pair of subi/sbci.
248 if ((Offset
- MaxOffset
) > 63 || !STI
.hasADDSUBIW()) {
249 AddOpc
= AVR::SUBIWRdK
;
250 SubOpc
= AVR::SUBIWRdK
;
251 AddOffset
= -AddOffset
;
254 // It is possible that the spiller places this frame instruction in between
255 // a compare and branch, invalidating the contents of SREG set by the
256 // compare instruction because of the add/sub pairs. Conservatively save and
257 // restore SREG before and after each add/sub pair.
258 BuildMI(MBB
, II
, dl
, TII
.get(AVR::INRdA
), STI
.getTmpRegister())
259 .addImm(STI
.getIORegSREG());
261 MachineInstr
*New
= BuildMI(MBB
, II
, dl
, TII
.get(AddOpc
), AVR::R29R28
)
262 .addReg(AVR::R29R28
, RegState::Kill
)
264 New
->getOperand(3).setIsDead();
267 BuildMI(MBB
, std::next(II
), dl
, TII
.get(AVR::OUTARr
))
268 .addImm(STI
.getIORegSREG())
269 .addReg(STI
.getTmpRegister(), RegState::Kill
);
271 // No need to set SREG as dead here otherwise if the next instruction is a
272 // cond branch it will be using a dead register.
273 BuildMI(MBB
, std::next(II
), dl
, TII
.get(SubOpc
), AVR::R29R28
)
274 .addReg(AVR::R29R28
, RegState::Kill
)
275 .addImm(Offset
- MaxOffset
);
280 MI
.getOperand(FIOperandNum
).ChangeToRegister(AVR::R29R28
, false);
281 assert(isUInt
<6>(Offset
) && "Offset is out of range");
282 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(Offset
);
286 Register
AVRRegisterInfo::getFrameRegister(const MachineFunction
&MF
) const {
287 const TargetFrameLowering
*TFI
= MF
.getSubtarget().getFrameLowering();
288 if (TFI
->hasFP(MF
)) {
289 // The Y pointer register
296 const TargetRegisterClass
*
297 AVRRegisterInfo::getPointerRegClass(const MachineFunction
&MF
,
298 unsigned Kind
) const {
299 // FIXME: Currently we're using avr-gcc as reference, so we restrict
300 // ptrs to Y and Z regs. Though avr-gcc has buggy implementation
301 // of memory constraint, so we can fix it and bit avr-gcc here ;-)
302 return &AVR::PTRDISPREGSRegClass
;
305 void AVRRegisterInfo::splitReg(Register Reg
, Register
&LoReg
,
306 Register
&HiReg
) const {
307 assert(AVR::DREGSRegClass
.contains(Reg
) && "can only split 16-bit registers");
309 LoReg
= getSubReg(Reg
, AVR::sub_lo
);
310 HiReg
= getSubReg(Reg
, AVR::sub_hi
);
313 bool AVRRegisterInfo::shouldCoalesce(
314 MachineInstr
*MI
, const TargetRegisterClass
*SrcRC
, unsigned SubReg
,
315 const TargetRegisterClass
*DstRC
, unsigned DstSubReg
,
316 const TargetRegisterClass
*NewRC
, LiveIntervals
&LIS
) const {
317 if (this->getRegClass(AVR::PTRDISPREGSRegClassID
)->hasSubClassEq(NewRC
)) {
321 return TargetRegisterInfo::shouldCoalesce(MI
, SrcRC
, SubReg
, DstRC
, DstSubReg
,
325 } // end of namespace llvm