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 MachineModuleInfo
&MMI
= MF
.getMMI();
120 MCContext
&Context
= MMI
.getContext();
121 const MCRegisterInfo
*MRI
= Context
.getRegisterInfo();
122 const ARCInstrInfo
*TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
123 MachineBasicBlock::iterator MBBI
= MBB
.begin();
124 // Debug location must be unknown since the first debug location is used
125 // to determine the end of the prologue.
127 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
128 const std::vector
<CalleeSavedInfo
> &CSI
= MFI
.getCalleeSavedInfo();
129 unsigned Last
= determineLastCalleeSave(CSI
);
130 unsigned StackSlotsUsedByFunclet
= 0;
131 bool SavedBlink
= false;
132 unsigned AlreadyAdjusted
= 0;
133 if (MF
.getFunction().isVarArg()) {
134 // Add in the varargs area here first.
135 LLVM_DEBUG(dbgs() << "Varargs\n");
136 unsigned VarArgsBytes
= MFI
.getObjectSize(AFI
->getVarArgsFrameIndex());
137 unsigned Opc
= ARC::SUB_rrlimm
;
138 if (isUInt
<6>(VarArgsBytes
))
140 else if (isInt
<12>(VarArgsBytes
))
141 Opc
= ARC::SUB_rrs12
;
142 BuildMI(MBB
, MBBI
, dl
, TII
->get(Opc
), ARC::SP
)
144 .addImm(VarArgsBytes
);
147 LLVM_DEBUG(dbgs() << "Saving FP\n");
148 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::ST_AW_rs9
))
149 .addReg(ARC::SP
, RegState::Define
)
153 AlreadyAdjusted
+= 4;
155 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
156 LLVM_DEBUG(dbgs() << "Creating store funclet.\n");
157 // BL to __save_r13_to_<TRI->getRegAsmName()>
158 StackSlotsUsedByFunclet
= Last
- ARC::R12
;
159 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::PUSH_S_BLINK
));
160 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::SUB_rru6
))
163 .addImm(4 * StackSlotsUsedByFunclet
);
164 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::BL
))
165 .addExternalSymbol(store_funclet_name
[Last
- ARC::R15
])
166 .addReg(ARC::BLINK
, RegState::Implicit
| RegState::Kill
);
167 AlreadyAdjusted
+= 4 * (StackSlotsUsedByFunclet
+ 1);
170 // If we haven't saved BLINK, but we need to...do that now.
171 if (MFI
.hasCalls() && !SavedBlink
) {
172 LLVM_DEBUG(dbgs() << "Creating save blink.\n");
173 BuildMI(MBB
, MBBI
, dl
, TII
->get(ARC::PUSH_S_BLINK
));
174 AlreadyAdjusted
+= 4;
176 if (AFI
->MaxCallStackReq
> 0)
177 MFI
.setStackSize(MFI
.getStackSize() + AFI
->MaxCallStackReq
);
178 // We have already saved some of the stack...
179 LLVM_DEBUG(dbgs() << "Adjusting stack by: "
180 << (MFI
.getStackSize() - AlreadyAdjusted
) << "\n");
181 generateStackAdjustment(MBB
, MBBI
, *ST
.getInstrInfo(), dl
,
182 -(MFI
.getStackSize() - AlreadyAdjusted
), ARC::SP
);
185 LLVM_DEBUG(dbgs() << "Setting FP from SP.\n");
186 BuildMI(MBB
, MBBI
, dl
,
187 TII
->get(isUInt
<6>(MFI
.getStackSize()) ? ARC::ADD_rru6
191 .addImm(MFI
.getStackSize());
195 // .cfi_def_cfa_offset StackSize
196 // .cfi_offset fp, -StackSize
197 // .cfi_offset blink, -StackSize+4
198 unsigned CFIIndex
= MF
.addFrameInst(
199 MCCFIInstruction::cfiDefCfaOffset(nullptr, MFI
.getStackSize()));
200 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
201 .addCFIIndex(CFIIndex
)
202 .setMIFlags(MachineInstr::FrameSetup
);
206 CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createOffset(
207 nullptr, MRI
->getDwarfRegNum(ARC::FP
, true), CurOffset
));
208 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
209 .addCFIIndex(CFIIndex
)
210 .setMIFlags(MachineInstr::FrameSetup
);
214 if (MFI
.hasCalls()) {
215 CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createOffset(
216 nullptr, MRI
->getDwarfRegNum(ARC::BLINK
, true), CurOffset
));
217 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
218 .addCFIIndex(CFIIndex
)
219 .setMIFlags(MachineInstr::FrameSetup
);
221 // CFI for the rest of the registers.
222 for (const auto &Entry
: CSI
) {
223 unsigned Reg
= Entry
.getReg();
224 int FI
= Entry
.getFrameIdx();
225 // Skip BLINK and FP.
226 if ((hasFP(MF
) && Reg
== ARC::FP
) || (MFI
.hasCalls() && Reg
== ARC::BLINK
))
228 CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createOffset(
229 nullptr, MRI
->getDwarfRegNum(Reg
, true), MFI
.getObjectOffset(FI
)));
230 BuildMI(MBB
, MBBI
, dl
, TII
->get(TargetOpcode::CFI_INSTRUCTION
))
231 .addCFIIndex(CFIIndex
)
232 .setMIFlags(MachineInstr::FrameSetup
);
236 /// Insert epilog code into the function.
237 /// For ARC, this inserts a call to a function that restores callee saved
238 /// registers onto the stack, when enough callee saved registers are required.
239 void ARCFrameLowering::emitEpilogue(MachineFunction
&MF
,
240 MachineBasicBlock
&MBB
) const {
241 LLVM_DEBUG(dbgs() << "Emit Epilogue: " << MF
.getName() << "\n");
242 auto *AFI
= MF
.getInfo
<ARCFunctionInfo
>();
243 const ARCInstrInfo
*TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
244 MachineBasicBlock::iterator MBBI
= MBB
.getFirstTerminator();
245 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
246 uint64_t StackSize
= MF
.getFrameInfo().getStackSize();
247 bool SavedBlink
= false;
248 unsigned AmountAboveFunclet
= 0;
249 // If we have variable sized frame objects, then we have to move
250 // the stack pointer to a known spot (fp - StackSize).
251 // Then, replace the frame pointer by (new) [sp,StackSize-4].
252 // Then, move the stack pointer the rest of the way (sp = sp + StackSize).
254 unsigned Opc
= ARC::SUB_rrlimm
;
255 if (isUInt
<6>(StackSize
))
257 BuildMI(MBB
, MBBI
, DebugLoc(), TII
->get(Opc
), ARC::SP
)
260 AmountAboveFunclet
+= 4;
263 // Now, move the stack pointer to the bottom of the save area for the funclet.
264 const std::vector
<CalleeSavedInfo
> &CSI
= MFI
.getCalleeSavedInfo();
265 unsigned Last
= determineLastCalleeSave(CSI
);
266 unsigned StackSlotsUsedByFunclet
= 0;
267 // Now, restore the callee save registers.
268 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
269 // BL to __ld_r13_to_<TRI->getRegAsmName()>
270 StackSlotsUsedByFunclet
= Last
- ARC::R12
;
271 AmountAboveFunclet
+= 4 * (StackSlotsUsedByFunclet
+ 1);
275 if (MFI
.hasCalls() && !SavedBlink
) {
276 AmountAboveFunclet
+= 4;
280 // Move the stack pointer up to the point of the funclet.
281 if (unsigned MoveAmount
= StackSize
- AmountAboveFunclet
) {
282 unsigned Opc
= ARC::ADD_rrlimm
;
283 if (isUInt
<6>(MoveAmount
))
285 else if (isInt
<12>(MoveAmount
))
286 Opc
= ARC::ADD_rrs12
;
287 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(Opc
), ARC::SP
)
289 .addImm(StackSize
- AmountAboveFunclet
);
292 if (StackSlotsUsedByFunclet
) {
293 // This part of the adjustment will always be < 64 bytes.
294 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(ARC::BL
))
295 .addExternalSymbol(load_funclet_name
[Last
- ARC::R15
])
296 .addReg(ARC::BLINK
, RegState::Implicit
| RegState::Kill
);
297 unsigned Opc
= ARC::ADD_rrlimm
;
298 if (isUInt
<6>(4 * StackSlotsUsedByFunclet
))
300 else if (isInt
<12>(4 * StackSlotsUsedByFunclet
))
301 Opc
= ARC::ADD_rrs12
;
302 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(Opc
), ARC::SP
)
304 .addImm(4 * (StackSlotsUsedByFunclet
));
306 // Now, pop blink if necessary.
308 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(ARC::POP_S_BLINK
));
310 // Now, pop fp if necessary.
312 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(ARC::LD_AB_rs9
))
313 .addReg(ARC::FP
, RegState::Define
)
314 .addReg(ARC::SP
, RegState::Define
)
319 // Relieve the varargs area if necessary.
320 if (MF
.getFunction().isVarArg()) {
321 // Add in the varargs area here first.
322 LLVM_DEBUG(dbgs() << "Varargs\n");
323 unsigned VarArgsBytes
= MFI
.getObjectSize(AFI
->getVarArgsFrameIndex());
324 unsigned Opc
= ARC::ADD_rrlimm
;
325 if (isUInt
<6>(VarArgsBytes
))
327 else if (isInt
<12>(VarArgsBytes
))
328 Opc
= ARC::ADD_rrs12
;
329 BuildMI(MBB
, MBBI
, MBB
.findDebugLoc(MBBI
), TII
->get(Opc
))
332 .addImm(VarArgsBytes
);
336 static std::vector
<CalleeSavedInfo
>::iterator
337 getSavedReg(std::vector
<CalleeSavedInfo
> &V
, unsigned reg
) {
338 for (auto I
= V
.begin(), E
= V
.end(); I
!= E
; ++I
) {
339 if (reg
== I
->getReg())
345 bool ARCFrameLowering::assignCalleeSavedSpillSlots(
346 MachineFunction
&MF
, const TargetRegisterInfo
*TRI
,
347 std::vector
<CalleeSavedInfo
> &CSI
) const {
348 // Use this opportunity to assign the spill slots for all of the potential
349 // callee save registers (blink, fp, r13->r25) that we care about the
350 // placement for. We can calculate all of that data here.
352 unsigned Last
= determineLastCalleeSave(CSI
);
353 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
355 // Create a fixed slot at for FP
356 int StackObj
= MFI
.CreateFixedSpillStackObject(4, CurOffset
, true);
357 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj
<< ") for FP at "
358 << CurOffset
<< "\n");
362 if (MFI
.hasCalls() || (UseSaveRestoreFunclet
&& Last
> ARC::R14
)) {
363 // Create a fixed slot for BLINK.
364 int StackObj
= MFI
.CreateFixedSpillStackObject(4, CurOffset
, true);
365 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj
366 << ") for BLINK at " << CurOffset
<< "\n");
371 // Create slots for last down to r13.
372 for (unsigned Which
= Last
; Which
> ARC::R12
; Which
--) {
373 auto RegI
= getSavedReg(CSI
, Which
);
374 if (RegI
== CSI
.end() || RegI
->getFrameIdx() == 0) {
375 // Always create the stack slot. If for some reason the register isn't in
376 // the save list, then don't worry about it.
377 int FI
= MFI
.CreateFixedSpillStackObject(4, CurOffset
, true);
378 if (RegI
!= CSI
.end())
379 RegI
->setFrameIdx(FI
);
381 MFI
.setObjectOffset(RegI
->getFrameIdx(), CurOffset
);
384 for (auto &I
: CSI
) {
385 if (I
.getReg() > ARC::R12
)
387 if (I
.getFrameIdx() == 0) {
388 I
.setFrameIdx(MFI
.CreateFixedSpillStackObject(4, CurOffset
, true));
389 LLVM_DEBUG(dbgs() << "Creating fixed object (" << I
.getFrameIdx()
390 << ") for other register at " << CurOffset
<< "\n");
392 MFI
.setObjectOffset(I
.getFrameIdx(), CurOffset
);
393 LLVM_DEBUG(dbgs() << "Updating fixed object (" << I
.getFrameIdx()
394 << ") for other register at " << CurOffset
<< "\n");
401 bool ARCFrameLowering::spillCalleeSavedRegisters(
402 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
403 ArrayRef
<CalleeSavedInfo
> CSI
, const TargetRegisterInfo
*TRI
) const {
404 LLVM_DEBUG(dbgs() << "Spill callee saved registers: "
405 << MBB
.getParent()->getName() << "\n");
406 // There are routines for saving at least 3 registers (r13 to r15, etc.)
407 unsigned Last
= determineLastCalleeSave(CSI
);
408 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
409 // Use setObjectOffset for these registers.
410 // Needs to be in or before processFunctionBeforeFrameFinalized.
411 // Or, do assignCalleeSaveSpillSlots?
412 // Will be handled in prolog.
418 bool ARCFrameLowering::restoreCalleeSavedRegisters(
419 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
420 MutableArrayRef
<CalleeSavedInfo
> CSI
, const TargetRegisterInfo
*TRI
) const {
421 LLVM_DEBUG(dbgs() << "Restore callee saved registers: "
422 << MBB
.getParent()->getName() << "\n");
423 // There are routines for saving at least 3 registers (r13 to r15, etc.)
424 unsigned Last
= determineLastCalleeSave(CSI
);
425 if (UseSaveRestoreFunclet
&& Last
> ARC::R14
) {
426 // Will be handled in epilog.
432 // Adjust local variables that are 4-bytes or larger to 4-byte boundary
433 void ARCFrameLowering::processFunctionBeforeFrameFinalized(
434 MachineFunction
&MF
, RegScavenger
*RS
) const {
435 const TargetRegisterInfo
*RegInfo
= MF
.getSubtarget().getRegisterInfo();
436 LLVM_DEBUG(dbgs() << "Process function before frame finalized: "
437 << MF
.getName() << "\n");
438 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
439 LLVM_DEBUG(dbgs() << "Current stack size: " << MFI
.getStackSize() << "\n");
440 const TargetRegisterClass
*RC
= &ARC::GPR32RegClass
;
441 if (MFI
.hasStackObjects()) {
442 int RegScavFI
= MFI
.CreateStackObject(RegInfo
->getSpillSize(*RC
),
443 RegInfo
->getSpillAlign(*RC
), false);
444 RS
->addScavengingFrameIndex(RegScavFI
);
445 LLVM_DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI
450 static void emitRegUpdate(MachineBasicBlock
&MBB
,
451 MachineBasicBlock::iterator
&MBBI
, DebugLoc dl
,
452 unsigned Reg
, int NumBytes
, bool IsAdd
,
453 const ARCInstrInfo
*TII
) {
455 if (isUInt
<6>(NumBytes
))
456 Opc
= IsAdd
? ARC::ADD_rru6
: ARC::SUB_rru6
;
457 else if (isInt
<12>(NumBytes
))
458 Opc
= IsAdd
? ARC::ADD_rrs12
: ARC::SUB_rrs12
;
460 Opc
= IsAdd
? ARC::ADD_rrlimm
: ARC::SUB_rrlimm
;
462 BuildMI(MBB
, MBBI
, dl
, TII
->get(Opc
), Reg
)
463 .addReg(Reg
, RegState::Kill
)
467 MachineBasicBlock::iterator
ARCFrameLowering::eliminateCallFramePseudoInstr(
468 MachineFunction
&MF
, MachineBasicBlock
&MBB
,
469 MachineBasicBlock::iterator I
) const {
470 LLVM_DEBUG(dbgs() << "EmitCallFramePseudo: " << MF
.getName() << "\n");
471 const ARCInstrInfo
*TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
472 MachineInstr
&Old
= *I
;
473 DebugLoc dl
= Old
.getDebugLoc();
474 unsigned Amt
= Old
.getOperand(0).getImm();
475 auto *AFI
= MF
.getInfo
<ARCFunctionInfo
>();
477 if (Amt
> AFI
->MaxCallStackReq
&& Old
.getOpcode() == ARC::ADJCALLSTACKDOWN
)
478 AFI
->MaxCallStackReq
= Amt
;
481 assert((Old
.getOpcode() == ARC::ADJCALLSTACKDOWN
||
482 Old
.getOpcode() == ARC::ADJCALLSTACKUP
) &&
483 "Unknown Frame Pseudo.");
484 bool IsAdd
= (Old
.getOpcode() == ARC::ADJCALLSTACKUP
);
485 emitRegUpdate(MBB
, I
, dl
, ARC::SP
, Amt
, IsAdd
, TII
);
491 bool ARCFrameLowering::hasFP(const MachineFunction
&MF
) const {
492 const TargetRegisterInfo
*RegInfo
= MF
.getSubtarget().getRegisterInfo();
493 bool HasFP
= MF
.getTarget().Options
.DisableFramePointerElim(MF
) ||
494 MF
.getFrameInfo().hasVarSizedObjects() ||
495 MF
.getFrameInfo().isFrameAddressTaken() ||
496 RegInfo
->hasStackRealignment(MF
);