LLVM 17.0.0git
MSP430FrameLowering.cpp
Go to the documentation of this file.
1//===-- MSP430FrameLowering.cpp - MSP430 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 MSP430 implementation of TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MSP430FrameLowering.h"
14#include "MSP430InstrInfo.h"
16#include "MSP430Subtarget.h"
22#include "llvm/IR/DataLayout.h"
23#include "llvm/IR/Function.h"
25
26using namespace llvm;
27
29 const MachineFrameInfo &MFI = MF.getFrameInfo();
30
31 return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
34}
35
37 return !MF.getFrameInfo().hasVarSizedObjects();
38}
39
41 MachineBasicBlock &MBB) const {
42 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
45 const MSP430InstrInfo &TII =
46 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
47
49 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
50
51 // Get the number of bytes to allocate from the FrameInfo.
52 uint64_t StackSize = MFI.getStackSize();
53
54 uint64_t NumBytes = 0;
55 if (hasFP(MF)) {
56 // Calculate required stack adjustment
57 uint64_t FrameSize = StackSize - 2;
58 NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
59
60 // Get the offset of the stack slot for the EBP register... which is
61 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
62 // Update the frame offset adjustment.
63 MFI.setOffsetAdjustment(-NumBytes);
64
65 // Save FP into the appropriate stack slot...
66 BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
67 .addReg(MSP430::R4, RegState::Kill);
68
69 // Update FP with the new base value...
70 BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
71 .addReg(MSP430::SP);
72
73 // Mark the FramePtr as live-in in every block except the entry.
74 for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
75 MBBJ.addLiveIn(MSP430::R4);
76
77 } else
78 NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
79
80 // Skip the callee-saved push instructions.
81 while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
82 ++MBBI;
83
84 if (MBBI != MBB.end())
85 DL = MBBI->getDebugLoc();
86
87 if (NumBytes) { // adjust stack pointer: SP -= numbytes
88 // If there is an SUB16ri of SP immediately before this instruction, merge
89 // the two.
90 //NumBytes -= mergeSPUpdates(MBB, MBBI, true);
91 // If there is an ADD16ri or SUB16ri of SP immediately after this
92 // instruction, merge the two instructions.
93 // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
94
95 if (NumBytes) {
97 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
98 .addReg(MSP430::SP).addImm(NumBytes);
99 // The SRW implicit def is dead.
100 MI->getOperand(3).setIsDead();
101 }
102 }
103}
104
106 MachineBasicBlock &MBB) const {
107 const MachineFrameInfo &MFI = MF.getFrameInfo();
109 const MSP430InstrInfo &TII =
110 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
111
113 unsigned RetOpcode = MBBI->getOpcode();
114 DebugLoc DL = MBBI->getDebugLoc();
115
116 switch (RetOpcode) {
117 case MSP430::RET:
118 case MSP430::RETI: break; // These are ok
119 default:
120 llvm_unreachable("Can only insert epilog into returning blocks");
121 }
122
123 // Get the number of bytes to allocate from the FrameInfo
124 uint64_t StackSize = MFI.getStackSize();
125 unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
126 uint64_t NumBytes = 0;
127
128 if (hasFP(MF)) {
129 // Calculate required stack adjustment
130 uint64_t FrameSize = StackSize - 2;
131 NumBytes = FrameSize - CSSize;
132
133 // pop FP.
134 BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4);
135 } else
136 NumBytes = StackSize - CSSize;
137
138 // Skip the callee-saved pop instructions.
139 while (MBBI != MBB.begin()) {
140 MachineBasicBlock::iterator PI = std::prev(MBBI);
141 unsigned Opc = PI->getOpcode();
142 if (Opc != MSP430::POP16r && !PI->isTerminator())
143 break;
144 --MBBI;
145 }
146
147 DL = MBBI->getDebugLoc();
148
149 // If there is an ADD16ri or SUB16ri of SP immediately before this
150 // instruction, merge the two instructions.
151 //if (NumBytes || MFI.hasVarSizedObjects())
152 // mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
153
154 if (MFI.hasVarSizedObjects()) {
155 BuildMI(MBB, MBBI, DL,
156 TII.get(MSP430::MOV16rr), MSP430::SP).addReg(MSP430::R4);
157 if (CSSize) {
159 BuildMI(MBB, MBBI, DL,
160 TII.get(MSP430::SUB16ri), MSP430::SP)
161 .addReg(MSP430::SP).addImm(CSSize);
162 // The SRW implicit def is dead.
163 MI->getOperand(3).setIsDead();
164 }
165 } else {
166 // adjust stack pointer back: SP += numbytes
167 if (NumBytes) {
169 BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
170 .addReg(MSP430::SP).addImm(NumBytes);
171 // The SRW implicit def is dead.
172 MI->getOperand(3).setIsDead();
173 }
174 }
175}
176
177// FIXME: Can we eleminate these in favour of generic code?
181 if (CSI.empty())
182 return false;
183
184 DebugLoc DL;
185 if (MI != MBB.end()) DL = MI->getDebugLoc();
186
190 MFI->setCalleeSavedFrameSize(CSI.size() * 2);
191
192 for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
193 Register Reg = I.getReg();
194 // Add the callee-saved register as live-in. It's killed at the spill.
195 MBB.addLiveIn(Reg);
196 BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
197 .addReg(Reg, RegState::Kill);
198 }
199 return true;
200}
201
205 if (CSI.empty())
206 return false;
207
208 DebugLoc DL;
209 if (MI != MBB.end()) DL = MI->getDebugLoc();
210
213
214 for (const CalleeSavedInfo &I : CSI)
215 BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg());
216
217 return true;
218}
219
223 const MSP430InstrInfo &TII =
224 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
225 if (!hasReservedCallFrame(MF)) {
226 // If the stack pointer can be changed after prologue, turn the
227 // adjcallstackup instruction into a 'sub SP, <amt>' and the
228 // adjcallstackdown instruction into 'add SP, <amt>'
229 // TODO: consider using push / pop instead of sub + store / add
230 MachineInstr &Old = *I;
231 uint64_t Amount = TII.getFrameSize(Old);
232 if (Amount != 0) {
233 // We need to keep the stack aligned properly. To do this, we round the
234 // amount of space needed for the outgoing arguments up to the next
235 // alignment boundary.
236 Amount = alignTo(Amount, getStackAlign());
237
238 MachineInstr *New = nullptr;
239 if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
240 New =
241 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
242 .addReg(MSP430::SP)
243 .addImm(Amount);
244 } else {
245 assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
246 // factor out the amount the callee already popped.
247 Amount -= TII.getFramePoppedByCallee(Old);
248 if (Amount)
249 New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
250 MSP430::SP)
251 .addReg(MSP430::SP)
252 .addImm(Amount);
253 }
254
255 if (New) {
256 // The SRW implicit def is dead.
257 New->getOperand(3).setIsDead();
258
259 // Replace the pseudo instruction with a new instruction...
260 MBB.insert(I, New);
261 }
262 }
263 } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
264 // If we are performing frame pointer elimination and if the callee pops
265 // something off the stack pointer, add it back.
266 if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
267 MachineInstr &Old = *I;
268 MachineInstr *New =
269 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
270 .addReg(MSP430::SP)
271 .addImm(CalleeAmt);
272 // The SRW implicit def is dead.
273 New->getOperand(3).setIsDead();
274
275 MBB.insert(I, New);
276 }
277 }
278
279 return MBB.erase(I);
280}
281
282void
284 RegScavenger *) const {
285 // Create a frame entry for the FP register that must be saved.
286 if (hasFP(MF)) {
287 int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
288 (void)FrameIdx;
289 assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
290 "Slot for FP register must be last in order to be found!");
291 }
292}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:158
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
A debug info location.
Definition: DebugLoc.h:33
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
MSP430MachineFunctionInfo - This class is derived from MachineFunction and contains private MSP430 ta...
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
void setOffsetAdjustment(int Adj)
Set the correction for frame offsets.
int getObjectIndexBegin() const
Return the minimum frame object index.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Definition: MachineInstr.h:68
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:516
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:445
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:305
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
TargetInstrInfo - Interface to description of machine instruction set.
TargetOptions Options
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:413
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:511
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155