1//===-- AVRFrameLowering.cpp - AVR Frame Information ----------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the AVR implementation of TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AVRFrameLowering.h"
14
15#include "AVR.h"
16#include "AVRInstrInfo.h"
17#include "AVRMachineFunctionInfo.h"
18#include "AVRTargetMachine.h"
19#include "MCTargetDesc/AVRMCTargetDesc.h"
20
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineFunctionPass.h"
24#include "llvm/CodeGen/MachineInstrBuilder.h"
25#include "llvm/CodeGen/MachineRegisterInfo.h"
26#include "llvm/IR/Function.h"
27
28namespace llvm {
29
30AVRFrameLowering::AVRFrameLowering()
31 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(1), -2) {}
32
33bool AVRFrameLowering::canSimplifyCallFramePseudos(
34 const MachineFunction &MF) const {
35 // Always simplify call frame pseudo instructions, even when
36 // hasReservedCallFrame is false.
37 return true;
38}
39
40bool AVRFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
41 // Reserve call frame memory in function prologue under the following
42 // conditions:
43 // - Y pointer is reserved to be the frame pointer.
44 // - The function does not contain variable sized objects.
45
46 const MachineFrameInfo &MFI = MF.getFrameInfo();
47 return hasFP(MF) && !MFI.hasVarSizedObjects();
48}
49
50void AVRFrameLowering::emitPrologue(MachineFunction &MF,
51 MachineBasicBlock &MBB) const {
52 MachineBasicBlock::iterator MBBI = MBB.begin();
53 DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
54 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
55 const AVRInstrInfo &TII = *STI.getInstrInfo();
56 const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
57 const MachineRegisterInfo &MRI = MF.getRegInfo();
58 bool HasFP = hasFP(MF);
59
60 // Interrupt handlers re-enable interrupts in function entry.
61 if (AFI->isInterruptHandler()) {
62 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::BSETs))
63 .addImm(Val: 0x07)
64 .setMIFlag(MachineInstr::FrameSetup);
65 }
66
67 // Emit special prologue code to save R1, R0 and SREG in interrupt/signal
68 // handlers before saving any other registers.
69 if (AFI->isInterruptOrSignalHandler()) {
70 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::PUSHRr))
71 .addReg(RegNo: STI.getTmpRegister(), flags: RegState::Kill)
72 .setMIFlag(MachineInstr::FrameSetup);
73
74 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::INRdA), DestReg: STI.getTmpRegister())
75 .addImm(Val: STI.getIORegSREG())
76 .setMIFlag(MachineInstr::FrameSetup);
77 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::PUSHRr))
78 .addReg(RegNo: STI.getTmpRegister(), flags: RegState::Kill)
79 .setMIFlag(MachineInstr::FrameSetup);
80 if (!MRI.reg_empty(RegNo: STI.getZeroRegister())) {
81 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::PUSHRr))
82 .addReg(RegNo: STI.getZeroRegister(), flags: RegState::Kill)
83 .setMIFlag(MachineInstr::FrameSetup);
84 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::EORRdRr))
85 .addReg(RegNo: STI.getZeroRegister(), flags: RegState::Define)
86 .addReg(RegNo: STI.getZeroRegister(), flags: RegState::Kill)
87 .addReg(RegNo: STI.getZeroRegister(), flags: RegState::Kill)
88 .setMIFlag(MachineInstr::FrameSetup);
89 }
90 }
91
92 // Early exit if the frame pointer is not needed in this function.
93 if (!HasFP) {
94 return;
95 }
96
97 const MachineFrameInfo &MFI = MF.getFrameInfo();
98 unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize();
99
100 // Skip the callee-saved push instructions.
101 while (
102 (MBBI != MBB.end()) && MBBI->getFlag(Flag: MachineInstr::FrameSetup) &&
103 (MBBI->getOpcode() == AVR::PUSHRr || MBBI->getOpcode() == AVR::PUSHWRr)) {
104 ++MBBI;
105 }
106
107 // Update Y with the new base value.
108 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::SPREAD), DestReg: AVR::R29R28)
109 .addReg(RegNo: AVR::SP)
110 .setMIFlag(MachineInstr::FrameSetup);
111
112 // Mark the FramePtr as live-in in every block except the entry.
113 for (MachineBasicBlock &MBBJ : llvm::drop_begin(RangeOrContainer&: MF)) {
114 MBBJ.addLiveIn(PhysReg: AVR::R29R28);
115 }
116
117 if (!FrameSize) {
118 return;
119 }
120
121 // Reserve the necessary frame memory by doing FP -= <size>.
122 unsigned Opcode = (isUInt<6>(x: FrameSize) && STI.hasADDSUBIW()) ? AVR::SBIWRdK
123 : AVR::SUBIWRdK;
124
125 MachineInstr *MI = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode), DestReg: AVR::R29R28)
126 .addReg(RegNo: AVR::R29R28, flags: RegState::Kill)
127 .addImm(Val: FrameSize)
128 .setMIFlag(MachineInstr::FrameSetup);
129 // The SREG implicit def is dead.
130 MI->getOperand(i: 3).setIsDead();
131
132 // Write back R29R28 to SP and temporarily disable interrupts.
133 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::SPWRITE), DestReg: AVR::SP)
134 .addReg(RegNo: AVR::R29R28)
135 .setMIFlag(MachineInstr::FrameSetup);
136}
137
138static void restoreStatusRegister(MachineFunction &MF, MachineBasicBlock &MBB) {
139 const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
140 const MachineRegisterInfo &MRI = MF.getRegInfo();
141
142 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
143
144 DebugLoc DL = MBBI->getDebugLoc();
145 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
146 const AVRInstrInfo &TII = *STI.getInstrInfo();
147
148 // Emit special epilogue code to restore R1, R0 and SREG in interrupt/signal
149 // handlers at the very end of the function, just before reti.
150 if (AFI->isInterruptOrSignalHandler()) {
151 if (!MRI.reg_empty(RegNo: STI.getZeroRegister())) {
152 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::POPRd), DestReg: STI.getZeroRegister());
153 }
154 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::POPRd), DestReg: STI.getTmpRegister());
155 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::OUTARr))
156 .addImm(Val: STI.getIORegSREG())
157 .addReg(RegNo: STI.getTmpRegister(), flags: RegState::Kill);
158 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::POPRd), DestReg: STI.getTmpRegister());
159 }
160}
161
162void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
163 MachineBasicBlock &MBB) const {
164 const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
165
166 // Early exit if the frame pointer is not needed in this function except for
167 // signal/interrupt handlers where special code generation is required.
168 if (!hasFP(MF) && !AFI->isInterruptOrSignalHandler()) {
169 return;
170 }
171
172 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
173 assert(MBBI->getDesc().isReturn() &&
174 "Can only insert epilog into returning blocks");
175
176 DebugLoc DL = MBBI->getDebugLoc();
177 const MachineFrameInfo &MFI = MF.getFrameInfo();
178 unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize();
179 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
180 const AVRInstrInfo &TII = *STI.getInstrInfo();
181
182 // Early exit if there is no need to restore the frame pointer.
183 if (!FrameSize && !MF.getFrameInfo().hasVarSizedObjects()) {
184 restoreStatusRegister(MF, MBB);
185 return;
186 }
187
188 // Skip the callee-saved pop instructions.
189 while (MBBI != MBB.begin()) {
190 MachineBasicBlock::iterator PI = std::prev(x: MBBI);
191 int Opc = PI->getOpcode();
192
193 if (Opc != AVR::POPRd && Opc != AVR::POPWRd && !PI->isTerminator()) {
194 break;
195 }
196
197 --MBBI;
198 }
199
200 if (FrameSize) {
201 unsigned Opcode;
202
203 // Select the optimal opcode depending on how big it is.
204 if (isUInt<6>(x: FrameSize) && STI.hasADDSUBIW()) {
205 Opcode = AVR::ADIWRdK;
206 } else {
207 Opcode = AVR::SUBIWRdK;
208 FrameSize = -FrameSize;
209 }
210
211 // Restore the frame pointer by doing FP += <size>.
212 MachineInstr *MI = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode), DestReg: AVR::R29R28)
213 .addReg(RegNo: AVR::R29R28, flags: RegState::Kill)
214 .addImm(Val: FrameSize);
215 // The SREG implicit def is dead.
216 MI->getOperand(i: 3).setIsDead();
217 }
218
219 // Write back R29R28 to SP and temporarily disable interrupts.
220 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AVR::SPWRITE), DestReg: AVR::SP)
221 .addReg(RegNo: AVR::R29R28, flags: RegState::Kill);
222
223 restoreStatusRegister(MF, MBB);
224}
225
226// Return true if the specified function should have a dedicated frame
227// pointer register. This is true if the function meets any of the following
228// conditions:
229// - a register has been spilled
230// - has allocas
231// - input arguments are passed using the stack
232//
233// Notice that strictly this is not a frame pointer because it contains SP after
234// frame allocation instead of having the original SP in function entry.
235bool AVRFrameLowering::hasFP(const MachineFunction &MF) const {
236 const AVRMachineFunctionInfo *FuncInfo = MF.getInfo<AVRMachineFunctionInfo>();
237
238 return (FuncInfo->getHasSpills() || FuncInfo->getHasAllocas() ||
239 FuncInfo->getHasStackArgs() ||
240 MF.getFrameInfo().hasVarSizedObjects());
241}
242
243bool AVRFrameLowering::spillCalleeSavedRegisters(
244 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
245 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
246 if (CSI.empty()) {
247 return false;
248 }
249
250 unsigned CalleeFrameSize = 0;
251 DebugLoc DL = MBB.findDebugLoc(MBBI: MI);
252 MachineFunction &MF = *MBB.getParent();
253 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
254 const TargetInstrInfo &TII = *STI.getInstrInfo();
255 AVRMachineFunctionInfo *AVRFI = MF.getInfo<AVRMachineFunctionInfo>();
256
257 for (const CalleeSavedInfo &I : llvm::reverse(C&: CSI)) {
258 Register Reg = I.getReg();
259 bool IsNotLiveIn = !MBB.isLiveIn(Reg);
260
261 // Check if Reg is a sub register of a 16-bit livein register, and then
262 // add it to the livein list.
263 if (IsNotLiveIn)
264 for (const auto &LiveIn : MBB.liveins())
265 if (STI.getRegisterInfo()->isSubRegister(RegA: LiveIn.PhysReg, RegB: Reg)) {
266 IsNotLiveIn = false;
267 MBB.addLiveIn(PhysReg: Reg);
268 break;
269 }
270
271 assert(TRI->getRegSizeInBits(*TRI->getMinimalPhysRegClass(Reg)) == 8 &&
272 "Invalid register size");
273
274 // Add the callee-saved register as live-in only if it is not already a
275 // live-in register, this usually happens with arguments that are passed
276 // through callee-saved registers.
277 if (IsNotLiveIn) {
278 MBB.addLiveIn(PhysReg: Reg);
279 }
280
281 // Do not kill the register when it is an input argument.
282 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AVR::PUSHRr))
283 .addReg(RegNo: Reg, flags: getKillRegState(B: IsNotLiveIn))
284 .setMIFlag(MachineInstr::FrameSetup);
285 ++CalleeFrameSize;
286 }
287
288 AVRFI->setCalleeSavedFrameSize(CalleeFrameSize);
289
290 return true;
291}
292
293bool AVRFrameLowering::restoreCalleeSavedRegisters(
294 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
295 MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
296 if (CSI.empty()) {
297 return false;
298 }
299
300 DebugLoc DL = MBB.findDebugLoc(MBBI: MI);
301 const MachineFunction &MF = *MBB.getParent();
302 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
303 const TargetInstrInfo &TII = *STI.getInstrInfo();
304
305 for (const CalleeSavedInfo &CCSI : CSI) {
306 Register Reg = CCSI.getReg();
307
308 assert(TRI->getRegSizeInBits(*TRI->getMinimalPhysRegClass(Reg)) == 8 &&
309 "Invalid register size");
310
311 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AVR::POPRd), DestReg: Reg);
312 }
313
314 return true;
315}
316
317/// Replace pseudo store instructions that pass arguments through the stack with
318/// real instructions.
319static void fixStackStores(MachineBasicBlock &MBB,
320 MachineBasicBlock::iterator StartMI,
321 const TargetInstrInfo &TII) {
322 // Iterate through the BB until we hit a call instruction or we reach the end.
323 for (MachineInstr &MI :
324 llvm::make_early_inc_range(Range: llvm::make_range(x: StartMI, y: MBB.end()))) {
325 if (MI.isCall())
326 break;
327
328 unsigned Opcode = MI.getOpcode();
329
330 // Only care of pseudo store instructions where SP is the base pointer.
331 if (Opcode != AVR::STDSPQRr && Opcode != AVR::STDWSPQRr)
332 continue;
333
334 assert(MI.getOperand(0).getReg() == AVR::SP &&
335 "SP is expected as base pointer");
336
337 // Replace this instruction with a regular store. Use Y as the base
338 // pointer since it is guaranteed to contain a copy of SP.
339 unsigned STOpc =
340 (Opcode == AVR::STDWSPQRr) ? AVR::STDWPtrQRr : AVR::STDPtrQRr;
341
342 MI.setDesc(TII.get(Opcode: STOpc));
343 MI.getOperand(i: 0).setReg(AVR::R31R30);
344 }
345}
346
347MachineBasicBlock::iterator AVRFrameLowering::eliminateCallFramePseudoInstr(
348 MachineFunction &MF, MachineBasicBlock &MBB,
349 MachineBasicBlock::iterator MI) const {
350 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
351 const AVRInstrInfo &TII = *STI.getInstrInfo();
352
353 if (hasReservedCallFrame(MF)) {
354 return MBB.erase(I: MI);
355 }
356
357 DebugLoc DL = MI->getDebugLoc();
358 unsigned int Opcode = MI->getOpcode();
359 int Amount = TII.getFrameSize(I: *MI);
360
361 if (Amount == 0) {
362 return MBB.erase(I: MI);
363 }
364
365 assert(getStackAlign() == Align(1) && "Unsupported stack alignment");
366
367 if (Opcode == TII.getCallFrameSetupOpcode()) {
368 // Update the stack pointer.
369 // In many cases this can be done far more efficiently by pushing the
370 // relevant values directly to the stack. However, doing that correctly
371 // (in the right order, possibly skipping some empty space for undef
372 // values, etc) is tricky and thus left to be optimized in the future.
373 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AVR::SPREAD), DestReg: AVR::R31R30).addReg(RegNo: AVR::SP);
374
375 MachineInstr *New =
376 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AVR::SUBIWRdK), DestReg: AVR::R31R30)
377 .addReg(RegNo: AVR::R31R30, flags: RegState::Kill)
378 .addImm(Val: Amount);
379 New->getOperand(i: 3).setIsDead();
380
381 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AVR::SPWRITE), DestReg: AVR::SP).addReg(RegNo: AVR::R31R30);
382
383 // Make sure the remaining stack stores are converted to real store
384 // instructions.
385 fixStackStores(MBB, StartMI: MI, TII);
386 } else {
387 assert(Opcode == TII.getCallFrameDestroyOpcode());
388
389 // Note that small stack changes could be implemented more efficiently
390 // with a few pop instructions instead of the 8-9 instructions now
391 // required.
392
393 // Select the best opcode to adjust SP based on the offset size.
394 unsigned AddOpcode;
395
396 if (isUInt<6>(x: Amount) && STI.hasADDSUBIW()) {
397 AddOpcode = AVR::ADIWRdK;
398 } else {
399 AddOpcode = AVR::SUBIWRdK;
400 Amount = -Amount;
401 }
402
403 // Build the instruction sequence.
404 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AVR::SPREAD), DestReg: AVR::R31R30).addReg(RegNo: AVR::SP);
405
406 MachineInstr *New = BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AddOpcode), DestReg: AVR::R31R30)
407 .addReg(RegNo: AVR::R31R30, flags: RegState::Kill)
408 .addImm(Val: Amount);
409 New->getOperand(i: 3).setIsDead();
410
411 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AVR::SPWRITE), DestReg: AVR::SP)
412 .addReg(RegNo: AVR::R31R30, flags: RegState::Kill);
413 }
414
415 return MBB.erase(I: MI);
416}
417
418void AVRFrameLowering::determineCalleeSaves(MachineFunction &MF,
419 BitVector &SavedRegs,
420 RegScavenger *RS) const {
421 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
422
423 // If we have a frame pointer, the Y register needs to be saved as well.
424 if (hasFP(MF)) {
425 SavedRegs.set(AVR::R29);
426 SavedRegs.set(AVR::R28);
427 }
428}
429/// The frame analyzer pass.
430///
431/// Scans the function for allocas and used arguments
432/// that are passed through the stack.
433struct AVRFrameAnalyzer : public MachineFunctionPass {
434 static char ID;
435 AVRFrameAnalyzer() : MachineFunctionPass(ID) {}
436
437 bool runOnMachineFunction(MachineFunction &MF) override {
438 const MachineFrameInfo &MFI = MF.getFrameInfo();
439 AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
440
441 // If there are no fixed frame indexes during this stage it means there
442 // are allocas present in the function.
443 if (MFI.getNumObjects() != MFI.getNumFixedObjects()) {
444 // Check for the type of allocas present in the function. We only care
445 // about fixed size allocas so do not give false positives if only
446 // variable sized allocas are present.
447 for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {
448 // Variable sized objects have size 0.
449 if (MFI.getObjectSize(ObjectIdx: i)) {
450 AFI->setHasAllocas(true);
451 break;
452 }
453 }
454 }
455
456 // If there are fixed frame indexes present, scan the function to see if
457 // they are really being used.
458 if (MFI.getNumFixedObjects() == 0) {
459 return false;
460 }
461
462 // Ok fixed frame indexes present, now scan the function to see if they
463 // are really being used, otherwise we can ignore them.
464 for (const MachineBasicBlock &BB : MF) {
465 for (const MachineInstr &MI : BB) {
466 int Opcode = MI.getOpcode();
467
468 if ((Opcode != AVR::LDDRdPtrQ) && (Opcode != AVR::LDDWRdPtrQ) &&
469 (Opcode != AVR::STDPtrQRr) && (Opcode != AVR::STDWPtrQRr) &&
470 (Opcode != AVR::FRMIDX)) {
471 continue;
472 }
473
474 for (const MachineOperand &MO : MI.operands()) {
475 if (!MO.isFI()) {
476 continue;
477 }
478
479 if (MFI.isFixedObjectIndex(ObjectIdx: MO.getIndex())) {
480 AFI->setHasStackArgs(true);
481 return false;
482 }
483 }
484 }
485 }
486
487 return false;
488 }
489
490 StringRef getPassName() const override { return "AVR Frame Analyzer"; }
491};
492
493char AVRFrameAnalyzer::ID = 0;
494
495/// Creates instance of the frame analyzer pass.
496FunctionPass *createAVRFrameAnalyzerPass() { return new AVRFrameAnalyzer(); }
497
498} // end of namespace llvm
499