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
)
77 static unsigned determineLastCalleeSave(ArrayRef
<CalleeSavedInfo
> CSI
) {
79 for (auto Reg
: CSI
) {
80 assert(Reg
.getReg() >= ARC::R13
&& Reg
.getReg() <= ARC::R25
&&
81 "Unexpected callee saved reg.");
82 if (Reg
.getReg() > Last
)
88 void ARCFrameLowering::determineCalleeSaves(MachineFunction
&MF
,
90 RegScavenger
*RS
) const {
91 LLVM_DEBUG(dbgs() << "Determine Callee Saves: " << MF
.getName() << "\n");
92 TargetFrameLowering::determineCalleeSaves(MF
, SavedRegs
, RS
);
93 SavedRegs
.set(ARC::BLINK
);
96 void ARCFrameLowering::adjustStackToMatchRecords(
97 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
98 bool Allocate
) const {
99 MachineFunction
&MF
= *MBB
.getParent();
100 int ScalarAlloc
= MF
.getFrameInfo().getStackSize();
103 // Allocate by adjusting by the negative of what the record holder tracked
104 // it tracked a positive offset in a downward growing stack.
105 ScalarAlloc
= -ScalarAlloc
;
108 generateStackAdjustment(MBB
, MBBI
, *ST
.getInstrInfo(), DebugLoc(),
109 ScalarAlloc
, ARC::SP
);
112 /// Insert prolog code into the function.
113 /// For ARC, this inserts a call to a function that puts required callee saved
114 /// registers onto the stack, when enough callee saved registers are required.
115 void ARCFrameLowering::emitPrologue(MachineFunction
&MF
,
116 MachineBasicBlock
&MBB
) const {
117 LLVM_DEBUG(dbgs() << "Emit Prologue: " << MF
.getName() << "\n");
118 auto *AFI
= MF
.getInfo
<ARCFunctionInfo
>();
119 MCContext
&Context
= MF
.getContext();
120 const MCRegisterInfo
*MRI
= Context
.getRegisterInfo();
121 const ARCInstrInfo
*TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
122 MachineBasicBlock::iterator MBBI
= MBB
.begin();
123 // Debug location must be unknown since the first debug location is used
124 // to determine the end of the prologue.
126 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
127 const std::vector
<CalleeSavedInfo
> &CSI
= MFI
.getCalleeSavedInfo();
128 unsigned Last
= determineLastCalleeSave(CSI
);
129 unsigned StackSlotsUsedByFunclet
= 0;
130 bool SavedBlink
= false;
131 unsigned AlreadyAdjusted
= 0;
132 if (MF
.getFunction().isVarArg()) {
133 // Add in the varargs area here first.
134 LLVM_DEBUG(dbgs() << "Varargs\n");
135 unsigned VarArgsBytes
= MFI
.getObjectSize(AFI
->getVarArgsFrameIndex());
136 unsigned Opc
= ARC::SUB_rrlimm
;
137 if (isUInt
<6>(VarArgsBytes
))
139 else if (isInt
<12>(VarArgsBytes
))
140 Opc
= ARC::SUB_rrs12
;
141 BuildMI(MBB
, MBBI
, dl
, TII
->get(Opc
), ARC::SP
)
143 .addImm(VarArgsBytes
);
146 LLVM_DEBUG(dbgs() << "Saving FP\n");
147 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::ST_AW_rs9
))
148 .addReg(ARC::SP
, RegState::Define
)
152 AlreadyAdjusted
+= 4;
154 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
155 LLVM_DEBUG(dbgs() << "Creating store funclet.\n");
156 // BL to __save_r13_to_<TRI->getRegAsmName()>
157 StackSlotsUsedByFunclet
= Last
- ARC::R12
;
158 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::PUSH_S_BLINK
));
159 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::SUB_rru6
))
162 .addImm(4 * StackSlotsUsedByFunclet
);
163 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::BL
))
164 .addExternalSymbol(store_funclet_name
[Last
- ARC::R15
])
165 .addReg(ARC::BLINK
, RegState::Implicit
| RegState::Kill
);
166 AlreadyAdjusted
+= 4 * (StackSlotsUsedByFunclet
+ 1);
169 // If we haven't saved BLINK, but we need to...do that now.
170 if (MFI
.hasCalls() && !SavedBlink
) {
171 LLVM_DEBUG(dbgs() << "Creating save blink.\n");
172 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::PUSH_S_BLINK
));
173 AlreadyAdjusted
+= 4;
175 if (AFI
->MaxCallStackReq
> 0)
176 MFI
.setStackSize(MFI
.getStackSize() + AFI
->MaxCallStackReq
);
177 // We have already saved some of the stack...
178 LLVM_DEBUG(dbgs() << "Adjusting stack by: "
179 << (MFI
.getStackSize() - AlreadyAdjusted
) << "\n");
180 generateStackAdjustment(MBB
, MBBI
, *ST
.getInstrInfo(), dl
,
181 -(MFI
.getStackSize() - AlreadyAdjusted
), ARC::SP
);
184 LLVM_DEBUG(dbgs() << "Setting FP from SP.\n");
185 BuildMI(MBB
, MBBI
, dl
,
186 TII
->get(isUInt
<6>(MFI
.getStackSize()) ? ARC::ADD_rru6
190 .addImm(MFI
.getStackSize());
194 // .cfi_def_cfa_offset StackSize
195 // .cfi_offset fp, -StackSize
196 // .cfi_offset blink, -StackSize+4
197 unsigned CFIIndex
= MF
.addFrameInst(
198 MCCFIInstruction::cfiDefCfaOffset(nullptr, MFI
.getStackSize()));
199 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
200 .addCFIIndex(CFIIndex
)
201 .setMIFlags(MachineInstr::FrameSetup
);
205 CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createOffset(
206 nullptr, MRI
->getDwarfRegNum(ARC::FP
, true), CurOffset
));
207 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
208 .addCFIIndex(CFIIndex
)
209 .setMIFlags(MachineInstr::FrameSetup
);
213 if (MFI
.hasCalls()) {
214 CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createOffset(
215 nullptr, MRI
->getDwarfRegNum(ARC::BLINK
, true), CurOffset
));
216 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
217 .addCFIIndex(CFIIndex
)
218 .setMIFlags(MachineInstr::FrameSetup
);
220 // CFI for the rest of the registers.
221 for (const auto &Entry
: CSI
) {
222 unsigned Reg
= Entry
.getReg();
223 int FI
= Entry
.getFrameIdx();
224 // Skip BLINK and FP.
225 if ((hasFP(MF
) && Reg
== ARC::FP
) || (MFI
.hasCalls() && Reg
== ARC::BLINK
))
227 CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createOffset(
228 nullptr, MRI
->getDwarfRegNum(Reg
, true), MFI
.getObjectOffset(FI
)));
229 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
230 .addCFIIndex(CFIIndex
)
231 .setMIFlags(MachineInstr::FrameSetup
);
235 /// Insert epilog code into the function.
236 /// For ARC, this inserts a call to a function that restores callee saved
237 /// registers onto the stack, when enough callee saved registers are required.
238 void ARCFrameLowering::emitEpilogue(MachineFunction
&MF
,
239 MachineBasicBlock
&MBB
) const {
240 LLVM_DEBUG(dbgs() << "Emit Epilogue: " << MF
.getName() << "\n");
241 auto *AFI
= MF
.getInfo
<ARCFunctionInfo
>();
242 const ARCInstrInfo
*TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
243 MachineBasicBlock::iterator MBBI
= MBB
.getFirstTerminator();
244 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
245 uint64_t StackSize
= MF
.getFrameInfo().getStackSize();
246 bool SavedBlink
= false;
247 unsigned AmountAboveFunclet
= 0;
248 // If we have variable sized frame objects, then we have to move
249 // the stack pointer to a known spot (fp - StackSize).
250 // Then, replace the frame pointer by (new) [sp,StackSize-4].
251 // Then, move the stack pointer the rest of the way (sp = sp + StackSize).
253 unsigned Opc
= ARC::SUB_rrlimm
;
254 if (isUInt
<6>(StackSize
))
256 BuildMI(MBB
, MBBI
, DebugLoc(), TII
->get(Opc
), ARC::SP
)
259 AmountAboveFunclet
+= 4;
262 // Now, move the stack pointer to the bottom of the save area for the funclet.
263 const std::vector
<CalleeSavedInfo
> &CSI
= MFI
.getCalleeSavedInfo();
264 unsigned Last
= determineLastCalleeSave(CSI
);
265 unsigned StackSlotsUsedByFunclet
= 0;
266 // Now, restore the callee save registers.
267 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
268 // BL to __ld_r13_to_<TRI->getRegAsmName()>
269 StackSlotsUsedByFunclet
= Last
- ARC::R12
;
270 AmountAboveFunclet
+= 4 * (StackSlotsUsedByFunclet
+ 1);
274 if (MFI
.hasCalls() && !SavedBlink
) {
275 AmountAboveFunclet
+= 4;
279 // Move the stack pointer up to the point of the funclet.
280 if (unsigned MoveAmount
= StackSize
- AmountAboveFunclet
) {
281 unsigned Opc
= ARC::ADD_rrlimm
;
282 if (isUInt
<6>(MoveAmount
))
284 else if (isInt
<12>(MoveAmount
))
285 Opc
= ARC::ADD_rrs12
;
286 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(Opc
), ARC::SP
)
288 .addImm(StackSize
- AmountAboveFunclet
);
291 if (StackSlotsUsedByFunclet
) {
292 // This part of the adjustment will always be < 64 bytes.
293 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(ARC::BL
))
294 .addExternalSymbol(load_funclet_name
[Last
- ARC::R15
])
295 .addReg(ARC::BLINK
, RegState::Implicit
| RegState::Kill
);
296 unsigned Opc
= ARC::ADD_rrlimm
;
297 if (isUInt
<6>(4 * StackSlotsUsedByFunclet
))
299 else if (isInt
<12>(4 * StackSlotsUsedByFunclet
))
300 Opc
= ARC::ADD_rrs12
;
301 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(Opc
), ARC::SP
)
303 .addImm(4 * (StackSlotsUsedByFunclet
));
305 // Now, pop blink if necessary.
307 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(ARC::POP_S_BLINK
));
309 // Now, pop fp if necessary.
311 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(ARC::LD_AB_rs9
))
312 .addReg(ARC::FP
, RegState::Define
)
313 .addReg(ARC::SP
, RegState::Define
)
318 // Relieve the varargs area if necessary.
319 if (MF
.getFunction().isVarArg()) {
320 // Add in the varargs area here first.
321 LLVM_DEBUG(dbgs() << "Varargs\n");
322 unsigned VarArgsBytes
= MFI
.getObjectSize(AFI
->getVarArgsFrameIndex());
323 unsigned Opc
= ARC::ADD_rrlimm
;
324 if (isUInt
<6>(VarArgsBytes
))
326 else if (isInt
<12>(VarArgsBytes
))
327 Opc
= ARC::ADD_rrs12
;
328 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(Opc
))
331 .addImm(VarArgsBytes
);
335 static std::vector
<CalleeSavedInfo
>::iterator
336 getSavedReg(std::vector
<CalleeSavedInfo
> &V
, unsigned reg
) {
337 for (auto I
= V
.begin(), E
= V
.end(); I
!= E
; ++I
) {
338 if (reg
== I
->getReg())
344 bool ARCFrameLowering::assignCalleeSavedSpillSlots(
345 MachineFunction
&MF
, const TargetRegisterInfo
*TRI
,
346 std::vector
<CalleeSavedInfo
> &CSI
) const {
347 // Use this opportunity to assign the spill slots for all of the potential
348 // callee save registers (blink, fp, r13->r25) that we care about the
349 // placement for. We can calculate all of that data here.
351 unsigned Last
= determineLastCalleeSave(CSI
);
352 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
354 // Create a fixed slot at for FP
355 int StackObj
= MFI
.CreateFixedSpillStackObject(4, CurOffset
, true);
356 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj
<< ") for FP at "
357 << CurOffset
<< "\n");
361 if (MFI
.hasCalls() || (UseSaveRestoreFunclet
&& Last
> ARC::R14
)) {
362 // Create a fixed slot for BLINK.
363 int StackObj
= MFI
.CreateFixedSpillStackObject(4, CurOffset
, true);
364 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj
365 << ") for BLINK at " << CurOffset
<< "\n");
370 // Create slots for last down to r13.
371 for (unsigned Which
= Last
; Which
> ARC::R12
; Which
--) {
372 auto RegI
= getSavedReg(CSI
, Which
);
373 if (RegI
== CSI
.end() || RegI
->getFrameIdx() == 0) {
374 // Always create the stack slot. If for some reason the register isn't in
375 // the save list, then don't worry about it.
376 int FI
= MFI
.CreateFixedSpillStackObject(4, CurOffset
, true);
377 if (RegI
!= CSI
.end())
378 RegI
->setFrameIdx(FI
);
380 MFI
.setObjectOffset(RegI
->getFrameIdx(), CurOffset
);
383 for (auto &I
: CSI
) {
384 if (I
.getReg() > ARC::R12
)
386 if (I
.getFrameIdx() == 0) {
387 I
.setFrameIdx(MFI
.CreateFixedSpillStackObject(4, CurOffset
, true));
388 LLVM_DEBUG(dbgs() << "Creating fixed object (" << I
.getFrameIdx()
389 << ") for other register at " << CurOffset
<< "\n");
391 MFI
.setObjectOffset(I
.getFrameIdx(), CurOffset
);
392 LLVM_DEBUG(dbgs() << "Updating fixed object (" << I
.getFrameIdx()
393 << ") for other register at " << CurOffset
<< "\n");
400 bool ARCFrameLowering::spillCalleeSavedRegisters(
401 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
402 ArrayRef
<CalleeSavedInfo
> CSI
, const TargetRegisterInfo
*TRI
) const {
403 LLVM_DEBUG(dbgs() << "Spill callee saved registers: "
404 << MBB
.getParent()->getName() << "\n");
405 // There are routines for saving at least 3 registers (r13 to r15, etc.)
406 unsigned Last
= determineLastCalleeSave(CSI
);
407 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
408 // Use setObjectOffset for these registers.
409 // Needs to be in or before processFunctionBeforeFrameFinalized.
410 // Or, do assignCalleeSaveSpillSlots?
411 // Will be handled in prolog.
417 bool ARCFrameLowering::restoreCalleeSavedRegisters(
418 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
419 MutableArrayRef
<CalleeSavedInfo
> CSI
, const TargetRegisterInfo
*TRI
) const {
420 LLVM_DEBUG(dbgs() << "Restore callee saved registers: "
421 << MBB
.getParent()->getName() << "\n");
422 // There are routines for saving at least 3 registers (r13 to r15, etc.)
423 unsigned Last
= determineLastCalleeSave(CSI
);
424 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
425 // Will be handled in epilog.
431 // Adjust local variables that are 4-bytes or larger to 4-byte boundary
432 void ARCFrameLowering::processFunctionBeforeFrameFinalized(
433 MachineFunction
&MF
, RegScavenger
*RS
) const {
434 const TargetRegisterInfo
*RegInfo
= MF
.getSubtarget().getRegisterInfo();
435 LLVM_DEBUG(dbgs() << "Process function before frame finalized: "
436 << MF
.getName() << "\n");
437 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
438 LLVM_DEBUG(dbgs() << "Current stack size: " << MFI
.getStackSize() << "\n");
439 const TargetRegisterClass
*RC
= &ARC::GPR32RegClass
;
440 if (MFI
.hasStackObjects()) {
441 int RegScavFI
= MFI
.CreateStackObject(RegInfo
->getSpillSize(*RC
),
442 RegInfo
->getSpillAlign(*RC
), false);
443 RS
->addScavengingFrameIndex(RegScavFI
);
444 LLVM_DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI
449 static void emitRegUpdate(MachineBasicBlock
&MBB
,
450 MachineBasicBlock::iterator
&MBBI
, DebugLoc dl
,
451 unsigned Reg
, int NumBytes
, bool IsAdd
,
452 const ARCInstrInfo
*TII
) {
454 if (isUInt
<6>(NumBytes
))
455 Opc
= IsAdd
? ARC::ADD_rru6
: ARC::SUB_rru6
;
456 else if (isInt
<12>(NumBytes
))
457 Opc
= IsAdd
? ARC::ADD_rrs12
: ARC::SUB_rrs12
;
459 Opc
= IsAdd
? ARC::ADD_rrlimm
: ARC::SUB_rrlimm
;
461 BuildMI(MBB
, MBBI
, dl
, TII
->get(Opc
), Reg
)
462 .addReg(Reg
, RegState::Kill
)
466 MachineBasicBlock::iterator
ARCFrameLowering::eliminateCallFramePseudoInstr(
467 MachineFunction
&MF
, MachineBasicBlock
&MBB
,
468 MachineBasicBlock::iterator I
) const {
469 LLVM_DEBUG(dbgs() << "EmitCallFramePseudo: " << MF
.getName() << "\n");
470 const ARCInstrInfo
*TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
471 MachineInstr
&Old
= *I
;
472 DebugLoc dl
= Old
.getDebugLoc();
473 unsigned Amt
= Old
.getOperand(0).getImm();
474 auto *AFI
= MF
.getInfo
<ARCFunctionInfo
>();
476 if (Amt
> AFI
->MaxCallStackReq
&& Old
.getOpcode() == ARC::ADJCALLSTACKDOWN
)
477 AFI
->MaxCallStackReq
= Amt
;
480 assert((Old
.getOpcode() == ARC::ADJCALLSTACKDOWN
||
481 Old
.getOpcode() == ARC::ADJCALLSTACKUP
) &&
482 "Unknown Frame Pseudo.");
483 bool IsAdd
= (Old
.getOpcode() == ARC::ADJCALLSTACKUP
);
484 emitRegUpdate(MBB
, I
, dl
, ARC::SP
, Amt
, IsAdd
, TII
);
490 bool ARCFrameLowering::hasFP(const MachineFunction
&MF
) const {
491 const TargetRegisterInfo
*RegInfo
= MF
.getSubtarget().getRegisterInfo();
492 bool HasFP
= MF
.getTarget().Options
.DisableFramePointerElim(MF
) ||
493 MF
.getFrameInfo().hasVarSizedObjects() ||
494 MF
.getFrameInfo().isFrameAddressTaken() ||
495 RegInfo
->hasStackRealignment(MF
);