1 //===- ARCFrameLowering.cpp - ARC Frame Information -------------*- C++ -*-===//
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 ARC implementation of the TargetFrameLowering class.
11 //===----------------------------------------------------------------------===//
13 #include "ARCFrameLowering.h"
14 #include "ARCMachineFunctionInfo.h"
15 #include "ARCSubtarget.h"
16 #include "llvm/CodeGen/MachineInstrBuilder.h"
17 #include "llvm/CodeGen/MachineModuleInfo.h"
18 #include "llvm/CodeGen/RegisterScavenging.h"
19 #include "llvm/CodeGen/TargetRegisterInfo.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/Support/Debug.h"
23 #define DEBUG_TYPE "arc-frame-lowering"
28 UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden
,
29 cl::desc("Use arc callee save/restore functions"),
32 static const char *store_funclet_name
[] = {
33 "__st_r13_to_r15", "__st_r13_to_r16", "__st_r13_to_r17", "__st_r13_to_r18",
34 "__st_r13_to_r19", "__st_r13_to_r20", "__st_r13_to_r21", "__st_r13_to_r22",
35 "__st_r13_to_r23", "__st_r13_to_r24", "__st_r13_to_r25",
38 static const char *load_funclet_name
[] = {
39 "__ld_r13_to_r15", "__ld_r13_to_r16", "__ld_r13_to_r17", "__ld_r13_to_r18",
40 "__ld_r13_to_r19", "__ld_r13_to_r20", "__ld_r13_to_r21", "__ld_r13_to_r22",
41 "__ld_r13_to_r23", "__ld_r13_to_r24", "__ld_r13_to_r25",
44 static void generateStackAdjustment(MachineBasicBlock
&MBB
,
45 MachineBasicBlock::iterator MBBI
,
46 const ARCInstrInfo
&TII
, DebugLoc dl
,
47 int Amount
, int StackPtr
) {
61 LLVM_DEBUG(dbgs() << "Internal: adjust stack by: " << Amount
<< ","
62 << AbsAmount
<< "\n");
64 assert((AbsAmount
% 4 == 0) && "Stack adjustments must be 4-byte aligned.");
65 if (isUInt
<6>(AbsAmount
))
66 AdjOp
= Positive
? ARC::ADD_rru6
: ARC::SUB_rru6
;
67 else if (isInt
<12>(AbsAmount
))
68 AdjOp
= Positive
? ARC::ADD_rrs12
: ARC::SUB_rrs12
;
70 AdjOp
= Positive
? ARC::ADD_rrlimm
: ARC::SUB_rrlimm
;
72 BuildMI(MBB
, MBBI
, dl
, TII
.get(AdjOp
), StackPtr
)
78 determineLastCalleeSave(const std::vector
<CalleeSavedInfo
> &CSI
) {
80 for (auto Reg
: CSI
) {
81 assert(Reg
.getReg() >= ARC::R13
&& Reg
.getReg() <= ARC::R25
&&
82 "Unexpected callee saved reg.");
83 if (Reg
.getReg() > Last
)
89 void ARCFrameLowering::determineCalleeSaves(MachineFunction
&MF
,
91 RegScavenger
*RS
) const {
92 LLVM_DEBUG(dbgs() << "Determine Callee Saves: " << MF
.getName() << "\n");
93 TargetFrameLowering::determineCalleeSaves(MF
, SavedRegs
, RS
);
94 SavedRegs
.set(ARC::BLINK
);
97 void ARCFrameLowering::adjustStackToMatchRecords(
98 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
99 bool Allocate
) const {
100 MachineFunction
&MF
= *MBB
.getParent();
101 int ScalarAlloc
= MF
.getFrameInfo().getStackSize();
104 // Allocate by adjusting by the negative of what the record holder tracked
105 // it tracked a positive offset in a downward growing stack.
106 ScalarAlloc
= -ScalarAlloc
;
109 generateStackAdjustment(MBB
, MBBI
, *ST
.getInstrInfo(), DebugLoc(),
110 ScalarAlloc
, ARC::SP
);
113 /// Insert prolog code into the function.
114 /// For ARC, this inserts a call to a function that puts required callee saved
115 /// registers onto the stack, when enough callee saved registers are required.
116 void ARCFrameLowering::emitPrologue(MachineFunction
&MF
,
117 MachineBasicBlock
&MBB
) const {
118 LLVM_DEBUG(dbgs() << "Emit Prologue: " << MF
.getName() << "\n");
119 auto *AFI
= MF
.getInfo
<ARCFunctionInfo
>();
120 MachineModuleInfo
&MMI
= MF
.getMMI();
121 MCContext
&Context
= MMI
.getContext();
122 const MCRegisterInfo
*MRI
= Context
.getRegisterInfo();
123 const ARCInstrInfo
*TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
124 MachineBasicBlock::iterator MBBI
= MBB
.begin();
125 // Debug location must be unknown since the first debug location is used
126 // to determine the end of the prologue.
128 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
129 const std::vector
<CalleeSavedInfo
> &CSI
= MFI
.getCalleeSavedInfo();
130 unsigned Last
= determineLastCalleeSave(CSI
);
131 unsigned StackSlotsUsedByFunclet
= 0;
132 bool SavedBlink
= false;
133 unsigned AlreadyAdjusted
= 0;
134 if (MF
.getFunction().isVarArg()) {
135 // Add in the varargs area here first.
136 LLVM_DEBUG(dbgs() << "Varargs\n");
137 unsigned VarArgsBytes
= MFI
.getObjectSize(AFI
->getVarArgsFrameIndex());
138 unsigned Opc
= ARC::SUB_rrlimm
;
139 if (isUInt
<6>(VarArgsBytes
))
141 else if (isInt
<12>(VarArgsBytes
))
142 Opc
= ARC::SUB_rrs12
;
143 BuildMI(MBB
, MBBI
, dl
, TII
->get(Opc
), ARC::SP
)
145 .addImm(VarArgsBytes
);
148 LLVM_DEBUG(dbgs() << "Saving FP\n");
149 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::ST_AW_rs9
))
150 .addReg(ARC::SP
, RegState::Define
)
154 AlreadyAdjusted
+= 4;
156 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
157 LLVM_DEBUG(dbgs() << "Creating store funclet.\n");
158 // BL to __save_r13_to_<TRI->getRegAsmName()>
159 StackSlotsUsedByFunclet
= Last
- ARC::R12
;
160 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::PUSH_S_BLINK
));
161 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::SUB_rru6
))
164 .addImm(4 * StackSlotsUsedByFunclet
);
165 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::BL
))
166 .addExternalSymbol(store_funclet_name
[Last
- ARC::R15
])
167 .addReg(ARC::BLINK
, RegState::Implicit
| RegState::Kill
);
168 AlreadyAdjusted
+= 4 * (StackSlotsUsedByFunclet
+ 1);
171 // If we haven't saved BLINK, but we need to...do that now.
172 if (MFI
.hasCalls() && !SavedBlink
) {
173 LLVM_DEBUG(dbgs() << "Creating save blink.\n");
174 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::PUSH_S_BLINK
));
175 AlreadyAdjusted
+= 4;
177 if (AFI
->MaxCallStackReq
> 0)
178 MFI
.setStackSize(MFI
.getStackSize() + AFI
->MaxCallStackReq
);
179 // We have already saved some of the stack...
180 LLVM_DEBUG(dbgs() << "Adjusting stack by: "
181 << (MFI
.getStackSize() - AlreadyAdjusted
) << "\n");
182 generateStackAdjustment(MBB
, MBBI
, *ST
.getInstrInfo(), dl
,
183 -(MFI
.getStackSize() - AlreadyAdjusted
), ARC::SP
);
186 LLVM_DEBUG(dbgs() << "Setting FP from SP.\n");
187 BuildMI(MBB
, MBBI
, dl
,
188 TII
->get(isUInt
<6>(MFI
.getStackSize()) ? ARC::ADD_rru6
192 .addImm(MFI
.getStackSize());
196 // .cfi_def_cfa_offset StackSize
197 // .cfi_offset fp, -StackSize
198 // .cfi_offset blink, -StackSize+4
199 unsigned CFIIndex
= MF
.addFrameInst(
200 MCCFIInstruction::createDefCfaOffset(nullptr, -MFI
.getStackSize()));
201 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
202 .addCFIIndex(CFIIndex
)
203 .setMIFlags(MachineInstr::FrameSetup
);
207 CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createOffset(
208 nullptr, MRI
->getDwarfRegNum(ARC::FP
, true), CurOffset
));
209 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
210 .addCFIIndex(CFIIndex
)
211 .setMIFlags(MachineInstr::FrameSetup
);
215 if (MFI
.hasCalls()) {
216 CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createOffset(
217 nullptr, MRI
->getDwarfRegNum(ARC::BLINK
, true), CurOffset
));
218 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
219 .addCFIIndex(CFIIndex
)
220 .setMIFlags(MachineInstr::FrameSetup
);
222 // CFI for the rest of the registers.
223 for (const auto &Entry
: CSI
) {
224 unsigned Reg
= Entry
.getReg();
225 int FI
= Entry
.getFrameIdx();
226 // Skip BLINK and FP.
227 if ((hasFP(MF
) && Reg
== ARC::FP
) || (MFI
.hasCalls() && Reg
== ARC::BLINK
))
229 CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createOffset(
230 nullptr, MRI
->getDwarfRegNum(Reg
, true), MFI
.getObjectOffset(FI
)));
231 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
232 .addCFIIndex(CFIIndex
)
233 .setMIFlags(MachineInstr::FrameSetup
);
237 /// Insert epilog code into the function.
238 /// For ARC, this inserts a call to a function that restores callee saved
239 /// registers onto the stack, when enough callee saved registers are required.
240 void ARCFrameLowering::emitEpilogue(MachineFunction
&MF
,
241 MachineBasicBlock
&MBB
) const {
242 LLVM_DEBUG(dbgs() << "Emit Epilogue: " << MF
.getName() << "\n");
243 auto *AFI
= MF
.getInfo
<ARCFunctionInfo
>();
244 const ARCInstrInfo
*TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
245 MachineBasicBlock::iterator MBBI
= MBB
.getFirstTerminator();
246 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
247 uint64_t StackSize
= MF
.getFrameInfo().getStackSize();
248 bool SavedBlink
= false;
249 unsigned AmountAboveFunclet
= 0;
250 // If we have variable sized frame objects, then we have to move
251 // the stack pointer to a known spot (fp - StackSize).
252 // Then, replace the frame pointer by (new) [sp,StackSize-4].
253 // Then, move the stack pointer the rest of the way (sp = sp + StackSize).
255 unsigned Opc
= ARC::SUB_rrlimm
;
256 if (isUInt
<6>(StackSize
))
258 BuildMI(MBB
, MBBI
, DebugLoc(), TII
->get(Opc
), ARC::SP
)
261 AmountAboveFunclet
+= 4;
264 // Now, move the stack pointer to the bottom of the save area for the funclet.
265 const std::vector
<CalleeSavedInfo
> &CSI
= MFI
.getCalleeSavedInfo();
266 unsigned Last
= determineLastCalleeSave(CSI
);
267 unsigned StackSlotsUsedByFunclet
= 0;
268 // Now, restore the callee save registers.
269 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
270 // BL to __ld_r13_to_<TRI->getRegAsmName()>
271 StackSlotsUsedByFunclet
= Last
- ARC::R12
;
272 AmountAboveFunclet
+= 4 * (StackSlotsUsedByFunclet
+ 1);
276 if (MFI
.hasCalls() && !SavedBlink
) {
277 AmountAboveFunclet
+= 4;
281 // Move the stack pointer up to the point of the funclet.
282 if (unsigned MoveAmount
= StackSize
- AmountAboveFunclet
) {
283 unsigned Opc
= ARC::ADD_rrlimm
;
284 if (isUInt
<6>(MoveAmount
))
286 else if (isInt
<12>(MoveAmount
))
287 Opc
= ARC::ADD_rrs12
;
288 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(Opc
), ARC::SP
)
290 .addImm(StackSize
- AmountAboveFunclet
);
293 if (StackSlotsUsedByFunclet
) {
294 // This part of the adjustment will always be < 64 bytes.
295 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(ARC::BL
))
296 .addExternalSymbol(load_funclet_name
[Last
- ARC::R15
])
297 .addReg(ARC::BLINK
, RegState::Implicit
| RegState::Kill
);
298 unsigned Opc
= ARC::ADD_rrlimm
;
299 if (isUInt
<6>(4 * StackSlotsUsedByFunclet
))
301 else if (isInt
<12>(4 * StackSlotsUsedByFunclet
))
302 Opc
= ARC::ADD_rrs12
;
303 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(Opc
), ARC::SP
)
305 .addImm(4 * (StackSlotsUsedByFunclet
));
307 // Now, pop blink if necessary.
309 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(ARC::POP_S_BLINK
));
311 // Now, pop fp if necessary.
313 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(ARC::LD_AB_rs9
))
314 .addReg(ARC::FP
, RegState::Define
)
315 .addReg(ARC::SP
, RegState::Define
)
320 // Relieve the varargs area if necessary.
321 if (MF
.getFunction().isVarArg()) {
322 // Add in the varargs area here first.
323 LLVM_DEBUG(dbgs() << "Varargs\n");
324 unsigned VarArgsBytes
= MFI
.getObjectSize(AFI
->getVarArgsFrameIndex());
325 unsigned Opc
= ARC::ADD_rrlimm
;
326 if (isUInt
<6>(VarArgsBytes
))
328 else if (isInt
<12>(VarArgsBytes
))
329 Opc
= ARC::ADD_rrs12
;
330 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(Opc
))
333 .addImm(VarArgsBytes
);
337 static std::vector
<CalleeSavedInfo
>::iterator
338 getSavedReg(std::vector
<CalleeSavedInfo
> &V
, unsigned reg
) {
339 for (auto I
= V
.begin(), E
= V
.end(); I
!= E
; ++I
) {
340 if (reg
== I
->getReg())
346 bool ARCFrameLowering::assignCalleeSavedSpillSlots(
347 MachineFunction
&MF
, const TargetRegisterInfo
*TRI
,
348 std::vector
<CalleeSavedInfo
> &CSI
) const {
349 // Use this opportunity to assign the spill slots for all of the potential
350 // callee save registers (blink, fp, r13->r25) that we care about the
351 // placement for. We can calculate all of that data here.
353 unsigned Last
= determineLastCalleeSave(CSI
);
354 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
356 // Create a fixed slot at for FP
357 int StackObj
= MFI
.CreateFixedSpillStackObject(4, CurOffset
, true);
358 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj
<< ") for FP at "
359 << CurOffset
<< "\n");
363 if (MFI
.hasCalls() || (UseSaveRestoreFunclet
&& Last
> ARC::R14
)) {
364 // Create a fixed slot for BLINK.
365 int StackObj
= MFI
.CreateFixedSpillStackObject(4, CurOffset
, true);
366 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj
367 << ") for BLINK at " << CurOffset
<< "\n");
372 // Create slots for last down to r13.
373 for (unsigned Which
= Last
; Which
> ARC::R12
; Which
--) {
374 auto RegI
= getSavedReg(CSI
, Which
);
375 if (RegI
== CSI
.end() || RegI
->getFrameIdx() == 0) {
376 // Always create the stack slot. If for some reason the register isn't in
377 // the save list, then don't worry about it.
378 int FI
= MFI
.CreateFixedSpillStackObject(4, CurOffset
, true);
379 if (RegI
!= CSI
.end())
380 RegI
->setFrameIdx(FI
);
382 MFI
.setObjectOffset(RegI
->getFrameIdx(), CurOffset
);
385 for (auto &I
: CSI
) {
386 if (I
.getReg() > ARC::R12
)
388 if (I
.getFrameIdx() == 0) {
389 I
.setFrameIdx(MFI
.CreateFixedSpillStackObject(4, CurOffset
, true));
390 LLVM_DEBUG(dbgs() << "Creating fixed object (" << I
.getFrameIdx()
391 << ") for other register at " << CurOffset
<< "\n");
393 MFI
.setObjectOffset(I
.getFrameIdx(), CurOffset
);
394 LLVM_DEBUG(dbgs() << "Updating fixed object (" << I
.getFrameIdx()
395 << ") for other register at " << CurOffset
<< "\n");
402 bool ARCFrameLowering::spillCalleeSavedRegisters(
403 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
404 const std::vector
<CalleeSavedInfo
> &CSI
,
405 const TargetRegisterInfo
*TRI
) const {
406 LLVM_DEBUG(dbgs() << "Spill callee saved registers: "
407 << MBB
.getParent()->getName() << "\n");
408 // There are routines for saving at least 3 registers (r13 to r15, etc.)
409 unsigned Last
= determineLastCalleeSave(CSI
);
410 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
411 // Use setObjectOffset for these registers.
412 // Needs to be in or before processFunctionBeforeFrameFinalized.
413 // Or, do assignCalleeSaveSpillSlots?
414 // Will be handled in prolog.
420 bool ARCFrameLowering::restoreCalleeSavedRegisters(
421 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
422 std::vector
<CalleeSavedInfo
> &CSI
, const TargetRegisterInfo
*TRI
) const {
423 LLVM_DEBUG(dbgs() << "Restore callee saved registers: "
424 << MBB
.getParent()->getName() << "\n");
425 // There are routines for saving at least 3 registers (r13 to r15, etc.)
426 unsigned Last
= determineLastCalleeSave(CSI
);
427 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
428 // Will be handled in epilog.
434 // Adjust local variables that are 4-bytes or larger to 4-byte boundary
435 void ARCFrameLowering::processFunctionBeforeFrameFinalized(
436 MachineFunction
&MF
, RegScavenger
*RS
) const {
437 const TargetRegisterInfo
*RegInfo
= MF
.getSubtarget().getRegisterInfo();
438 LLVM_DEBUG(dbgs() << "Process function before frame finalized: "
439 << MF
.getName() << "\n");
440 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
441 LLVM_DEBUG(dbgs() << "Current stack size: " << MFI
.getStackSize() << "\n");
442 const TargetRegisterClass
*RC
= &ARC::GPR32RegClass
;
443 if (MFI
.hasStackObjects()) {
444 int RegScavFI
= MFI
.CreateStackObject(
445 RegInfo
->getSpillSize(*RC
), RegInfo
->getSpillAlignment(*RC
), false);
446 RS
->addScavengingFrameIndex(RegScavFI
);
447 LLVM_DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI
452 static void emitRegUpdate(MachineBasicBlock
&MBB
,
453 MachineBasicBlock::iterator
&MBBI
, DebugLoc dl
,
454 unsigned Reg
, int NumBytes
, bool IsAdd
,
455 const ARCInstrInfo
*TII
) {
457 if (isUInt
<6>(NumBytes
))
458 Opc
= IsAdd
? ARC::ADD_rru6
: ARC::SUB_rru6
;
459 else if (isInt
<12>(NumBytes
))
460 Opc
= IsAdd
? ARC::ADD_rrs12
: ARC::SUB_rrs12
;
462 Opc
= IsAdd
? ARC::ADD_rrlimm
: ARC::SUB_rrlimm
;
464 BuildMI(MBB
, MBBI
, dl
, TII
->get(Opc
), Reg
)
465 .addReg(Reg
, RegState::Kill
)
469 MachineBasicBlock::iterator
ARCFrameLowering::eliminateCallFramePseudoInstr(
470 MachineFunction
&MF
, MachineBasicBlock
&MBB
,
471 MachineBasicBlock::iterator I
) const {
472 LLVM_DEBUG(dbgs() << "EmitCallFramePseudo: " << MF
.getName() << "\n");
473 const ARCInstrInfo
*TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
474 MachineInstr
&Old
= *I
;
475 DebugLoc dl
= Old
.getDebugLoc();
476 unsigned Amt
= Old
.getOperand(0).getImm();
477 auto *AFI
= MF
.getInfo
<ARCFunctionInfo
>();
479 if (Amt
> AFI
->MaxCallStackReq
&& Old
.getOpcode() == ARC::ADJCALLSTACKDOWN
)
480 AFI
->MaxCallStackReq
= Amt
;
483 assert((Old
.getOpcode() == ARC::ADJCALLSTACKDOWN
||
484 Old
.getOpcode() == ARC::ADJCALLSTACKUP
) &&
485 "Unknown Frame Pseudo.");
486 bool IsAdd
= (Old
.getOpcode() == ARC::ADJCALLSTACKUP
);
487 emitRegUpdate(MBB
, I
, dl
, ARC::SP
, Amt
, IsAdd
, TII
);
493 bool ARCFrameLowering::hasFP(const MachineFunction
&MF
) const {
494 const TargetRegisterInfo
*RegInfo
= MF
.getSubtarget().getRegisterInfo();
495 bool HasFP
= MF
.getTarget().Options
.DisableFramePointerElim(MF
) ||
496 MF
.getFrameInfo().hasVarSizedObjects() ||
497 MF
.getFrameInfo().isFrameAddressTaken() ||
498 RegInfo
->needsStackRealignment(MF
);