1b22310fdSJia Liu //===-- MSP430FrameLowering.cpp - MSP430 Frame Information ----------------===//
22f931281SAnton Korobeynikov //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62f931281SAnton Korobeynikov //
72f931281SAnton Korobeynikov //===----------------------------------------------------------------------===//
82f931281SAnton Korobeynikov //
92f931281SAnton Korobeynikov // This file contains the MSP430 implementation of TargetFrameLowering class.
102f931281SAnton Korobeynikov //
112f931281SAnton Korobeynikov //===----------------------------------------------------------------------===//
122f931281SAnton Korobeynikov
132f931281SAnton Korobeynikov #include "MSP430FrameLowering.h"
142f931281SAnton Korobeynikov #include "MSP430InstrInfo.h"
152f931281SAnton Korobeynikov #include "MSP430MachineFunctionInfo.h"
16d913448bSEric Christopher #include "MSP430Subtarget.h"
172f931281SAnton Korobeynikov #include "llvm/CodeGen/MachineFrameInfo.h"
182f931281SAnton Korobeynikov #include "llvm/CodeGen/MachineFunction.h"
192f931281SAnton Korobeynikov #include "llvm/CodeGen/MachineInstrBuilder.h"
202f931281SAnton Korobeynikov #include "llvm/CodeGen/MachineModuleInfo.h"
212f931281SAnton Korobeynikov #include "llvm/CodeGen/MachineRegisterInfo.h"
229fb823bbSChandler Carruth #include "llvm/IR/DataLayout.h"
239fb823bbSChandler Carruth #include "llvm/IR/Function.h"
24ed0881b2SChandler Carruth #include "llvm/Target/TargetOptions.h"
252f931281SAnton Korobeynikov
262f931281SAnton Korobeynikov using namespace llvm;
272f931281SAnton Korobeynikov
hasFP(const MachineFunction & MF) const282f931281SAnton Korobeynikov bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {
29941a705bSMatthias Braun const MachineFrameInfo &MFI = MF.getFrameInfo();
302f931281SAnton Korobeynikov
3150f02cb2SNick Lewycky return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
32941a705bSMatthias Braun MF.getFrameInfo().hasVarSizedObjects() ||
33941a705bSMatthias Braun MFI.isFrameAddressTaken());
342f931281SAnton Korobeynikov }
352f931281SAnton Korobeynikov
hasReservedCallFrame(const MachineFunction & MF) const362f931281SAnton Korobeynikov bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
37941a705bSMatthias Braun return !MF.getFrameInfo().hasVarSizedObjects();
382f931281SAnton Korobeynikov }
392f931281SAnton Korobeynikov
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const4061b305edSQuentin Colombet void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
4161b305edSQuentin Colombet MachineBasicBlock &MBB) const {
4261b305edSQuentin Colombet assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
43941a705bSMatthias Braun MachineFrameInfo &MFI = MF.getFrameInfo();
442f931281SAnton Korobeynikov MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
452f931281SAnton Korobeynikov const MSP430InstrInfo &TII =
46fc6de428SEric Christopher *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
472f931281SAnton Korobeynikov
482f931281SAnton Korobeynikov MachineBasicBlock::iterator MBBI = MBB.begin();
492f931281SAnton Korobeynikov DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
502f931281SAnton Korobeynikov
512f931281SAnton Korobeynikov // Get the number of bytes to allocate from the FrameInfo.
52941a705bSMatthias Braun uint64_t StackSize = MFI.getStackSize();
532f931281SAnton Korobeynikov
542f931281SAnton Korobeynikov uint64_t NumBytes = 0;
552f931281SAnton Korobeynikov if (hasFP(MF)) {
562f931281SAnton Korobeynikov // Calculate required stack adjustment
572f931281SAnton Korobeynikov uint64_t FrameSize = StackSize - 2;
582f931281SAnton Korobeynikov NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
592f931281SAnton Korobeynikov
602f931281SAnton Korobeynikov // Get the offset of the stack slot for the EBP register... which is
612f931281SAnton Korobeynikov // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
622f931281SAnton Korobeynikov // Update the frame offset adjustment.
63941a705bSMatthias Braun MFI.setOffsetAdjustment(-NumBytes);
642f931281SAnton Korobeynikov
65eb19aea4SJob Noorman // Save FP into the appropriate stack slot...
662f931281SAnton Korobeynikov BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
67cb56fa21SAnatoly Trosinenko .addReg(MSP430::R4, RegState::Kill);
682f931281SAnton Korobeynikov
69eb19aea4SJob Noorman // Update FP with the new base value...
70cb56fa21SAnatoly Trosinenko BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
71eb19aea4SJob Noorman .addReg(MSP430::SP);
722f931281SAnton Korobeynikov
732f931281SAnton Korobeynikov // Mark the FramePtr as live-in in every block except the entry.
74cfc74024SKazu Hirata for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
75cfc74024SKazu Hirata MBBJ.addLiveIn(MSP430::R4);
762f931281SAnton Korobeynikov
772f931281SAnton Korobeynikov } else
782f931281SAnton Korobeynikov NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
792f931281SAnton Korobeynikov
802f931281SAnton Korobeynikov // Skip the callee-saved push instructions.
812f931281SAnton Korobeynikov while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
822f931281SAnton Korobeynikov ++MBBI;
832f931281SAnton Korobeynikov
842f931281SAnton Korobeynikov if (MBBI != MBB.end())
852f931281SAnton Korobeynikov DL = MBBI->getDebugLoc();
862f931281SAnton Korobeynikov
87eb19aea4SJob Noorman if (NumBytes) { // adjust stack pointer: SP -= numbytes
88eb19aea4SJob Noorman // If there is an SUB16ri of SP immediately before this instruction, merge
892f931281SAnton Korobeynikov // the two.
902f931281SAnton Korobeynikov //NumBytes -= mergeSPUpdates(MBB, MBBI, true);
91eb19aea4SJob Noorman // If there is an ADD16ri or SUB16ri of SP immediately after this
922f931281SAnton Korobeynikov // instruction, merge the two instructions.
932f931281SAnton Korobeynikov // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
942f931281SAnton Korobeynikov
952f931281SAnton Korobeynikov if (NumBytes) {
962f931281SAnton Korobeynikov MachineInstr *MI =
97eb19aea4SJob Noorman BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
98eb19aea4SJob Noorman .addReg(MSP430::SP).addImm(NumBytes);
992f931281SAnton Korobeynikov // The SRW implicit def is dead.
1002f931281SAnton Korobeynikov MI->getOperand(3).setIsDead();
1012f931281SAnton Korobeynikov }
1022f931281SAnton Korobeynikov }
1032f931281SAnton Korobeynikov }
1042f931281SAnton Korobeynikov
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const1052f931281SAnton Korobeynikov void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
1062f931281SAnton Korobeynikov MachineBasicBlock &MBB) const {
107941a705bSMatthias Braun const MachineFrameInfo &MFI = MF.getFrameInfo();
1082f931281SAnton Korobeynikov MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
1092f931281SAnton Korobeynikov const MSP430InstrInfo &TII =
110fc6de428SEric Christopher *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
1112f931281SAnton Korobeynikov
1124bc5e389SJakob Stoklund Olesen MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
1132f931281SAnton Korobeynikov unsigned RetOpcode = MBBI->getOpcode();
1142f931281SAnton Korobeynikov DebugLoc DL = MBBI->getDebugLoc();
1152f931281SAnton Korobeynikov
1162f931281SAnton Korobeynikov switch (RetOpcode) {
1172f931281SAnton Korobeynikov case MSP430::RET:
1182f931281SAnton Korobeynikov case MSP430::RETI: break; // These are ok
1192f931281SAnton Korobeynikov default:
1202f931281SAnton Korobeynikov llvm_unreachable("Can only insert epilog into returning blocks");
1212f931281SAnton Korobeynikov }
1222f931281SAnton Korobeynikov
1232f931281SAnton Korobeynikov // Get the number of bytes to allocate from the FrameInfo
124941a705bSMatthias Braun uint64_t StackSize = MFI.getStackSize();
1252f931281SAnton Korobeynikov unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
1262f931281SAnton Korobeynikov uint64_t NumBytes = 0;
1272f931281SAnton Korobeynikov
1282f931281SAnton Korobeynikov if (hasFP(MF)) {
1292f931281SAnton Korobeynikov // Calculate required stack adjustment
1302f931281SAnton Korobeynikov uint64_t FrameSize = StackSize - 2;
1312f931281SAnton Korobeynikov NumBytes = FrameSize - CSSize;
1322f931281SAnton Korobeynikov
133eb19aea4SJob Noorman // pop FP.
134cb56fa21SAnatoly Trosinenko BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4);
1352f931281SAnton Korobeynikov } else
1362f931281SAnton Korobeynikov NumBytes = StackSize - CSSize;
1372f931281SAnton Korobeynikov
1382f931281SAnton Korobeynikov // Skip the callee-saved pop instructions.
1392f931281SAnton Korobeynikov while (MBBI != MBB.begin()) {
140b6d0bd48SBenjamin Kramer MachineBasicBlock::iterator PI = std::prev(MBBI);
1412f931281SAnton Korobeynikov unsigned Opc = PI->getOpcode();
1427f8e563aSEvan Cheng if (Opc != MSP430::POP16r && !PI->isTerminator())
1432f931281SAnton Korobeynikov break;
1442f931281SAnton Korobeynikov --MBBI;
1452f931281SAnton Korobeynikov }
1462f931281SAnton Korobeynikov
1472f931281SAnton Korobeynikov DL = MBBI->getDebugLoc();
1482f931281SAnton Korobeynikov
149eb19aea4SJob Noorman // If there is an ADD16ri or SUB16ri of SP immediately before this
1502f931281SAnton Korobeynikov // instruction, merge the two instructions.
151941a705bSMatthias Braun //if (NumBytes || MFI.hasVarSizedObjects())
1522f931281SAnton Korobeynikov // mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
1532f931281SAnton Korobeynikov
154941a705bSMatthias Braun if (MFI.hasVarSizedObjects()) {
1552f931281SAnton Korobeynikov BuildMI(MBB, MBBI, DL,
156cb56fa21SAnatoly Trosinenko TII.get(MSP430::MOV16rr), MSP430::SP).addReg(MSP430::R4);
1572f931281SAnton Korobeynikov if (CSSize) {
1582f931281SAnton Korobeynikov MachineInstr *MI =
1592f931281SAnton Korobeynikov BuildMI(MBB, MBBI, DL,
160eb19aea4SJob Noorman TII.get(MSP430::SUB16ri), MSP430::SP)
161eb19aea4SJob Noorman .addReg(MSP430::SP).addImm(CSSize);
1622f931281SAnton Korobeynikov // The SRW implicit def is dead.
1632f931281SAnton Korobeynikov MI->getOperand(3).setIsDead();
1642f931281SAnton Korobeynikov }
1652f931281SAnton Korobeynikov } else {
166eb19aea4SJob Noorman // adjust stack pointer back: SP += numbytes
1672f931281SAnton Korobeynikov if (NumBytes) {
1682f931281SAnton Korobeynikov MachineInstr *MI =
169eb19aea4SJob Noorman BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
170eb19aea4SJob Noorman .addReg(MSP430::SP).addImm(NumBytes);
1712f931281SAnton Korobeynikov // The SRW implicit def is dead.
1722f931281SAnton Korobeynikov MI->getOperand(3).setIsDead();
1732f931281SAnton Korobeynikov }
1742f931281SAnton Korobeynikov }
1752f931281SAnton Korobeynikov }
1762f931281SAnton Korobeynikov
1772f931281SAnton Korobeynikov // FIXME: Can we eleminate these in favour of generic code?
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,ArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const178e4230a9fSBenjamin Kramer bool MSP430FrameLowering::spillCalleeSavedRegisters(
179e4230a9fSBenjamin Kramer MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
180e4230a9fSBenjamin Kramer ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
1812f931281SAnton Korobeynikov if (CSI.empty())
1822f931281SAnton Korobeynikov return false;
1832f931281SAnton Korobeynikov
1842f931281SAnton Korobeynikov DebugLoc DL;
1852f931281SAnton Korobeynikov if (MI != MBB.end()) DL = MI->getDebugLoc();
1862f931281SAnton Korobeynikov
1872f931281SAnton Korobeynikov MachineFunction &MF = *MBB.getParent();
188fc6de428SEric Christopher const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
1892f931281SAnton Korobeynikov MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
1902f931281SAnton Korobeynikov MFI->setCalleeSavedFrameSize(CSI.size() * 2);
1912f931281SAnton Korobeynikov
19248349967SKazu Hirata for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
193*d6b07348SJim Lin Register Reg = I.getReg();
1942f931281SAnton Korobeynikov // Add the callee-saved register as live-in. It's killed at the spill.
1952f931281SAnton Korobeynikov MBB.addLiveIn(Reg);
1962f931281SAnton Korobeynikov BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
1972f931281SAnton Korobeynikov .addReg(Reg, RegState::Kill);
1982f931281SAnton Korobeynikov }
1992f931281SAnton Korobeynikov return true;
2002f931281SAnton Korobeynikov }
2012f931281SAnton Korobeynikov
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,MutableArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const202186dd631SBenjamin Kramer bool MSP430FrameLowering::restoreCalleeSavedRegisters(
203186dd631SBenjamin Kramer MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
204186dd631SBenjamin Kramer MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
2052f931281SAnton Korobeynikov if (CSI.empty())
2062f931281SAnton Korobeynikov return false;
2072f931281SAnton Korobeynikov
2082f931281SAnton Korobeynikov DebugLoc DL;
2092f931281SAnton Korobeynikov if (MI != MBB.end()) DL = MI->getDebugLoc();
2102f931281SAnton Korobeynikov
2112f931281SAnton Korobeynikov MachineFunction &MF = *MBB.getParent();
212fc6de428SEric Christopher const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
2132f931281SAnton Korobeynikov
214fc981cedSKazu Hirata for (const CalleeSavedInfo &I : CSI)
215fc981cedSKazu Hirata BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg());
2162f931281SAnton Korobeynikov
2172f931281SAnton Korobeynikov return true;
2182f931281SAnton Korobeynikov }
2190a69176cSAnton Korobeynikov
eliminateCallFramePseudoInstr(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const220e1a2e90fSHans Wennborg MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr(
221e1a2e90fSHans Wennborg MachineFunction &MF, MachineBasicBlock &MBB,
2228da87163SEli Bendersky MachineBasicBlock::iterator I) const {
2238da87163SEli Bendersky const MSP430InstrInfo &TII =
224fc6de428SEric Christopher *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
2258da87163SEli Bendersky if (!hasReservedCallFrame(MF)) {
2268da87163SEli Bendersky // If the stack pointer can be changed after prologue, turn the
227eb19aea4SJob Noorman // adjcallstackup instruction into a 'sub SP, <amt>' and the
228eb19aea4SJob Noorman // adjcallstackdown instruction into 'add SP, <amt>'
2298da87163SEli Bendersky // TODO: consider using push / pop instead of sub + store / add
2308efc5b4fSDuncan P. N. Exon Smith MachineInstr &Old = *I;
231d526b13eSSerge Pavlov uint64_t Amount = TII.getFrameSize(Old);
2328da87163SEli Bendersky if (Amount != 0) {
2338da87163SEli Bendersky // We need to keep the stack aligned properly. To do this, we round the
2348da87163SEli Bendersky // amount of space needed for the outgoing arguments up to the next
2358da87163SEli Bendersky // alignment boundary.
2363ba550a0SGuillaume Chatelet Amount = alignTo(Amount, getStackAlign());
2378da87163SEli Bendersky
238062a2baeSCraig Topper MachineInstr *New = nullptr;
2398efc5b4fSDuncan P. N. Exon Smith if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
2408efc5b4fSDuncan P. N. Exon Smith New =
2418efc5b4fSDuncan P. N. Exon Smith BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
2428efc5b4fSDuncan P. N. Exon Smith .addReg(MSP430::SP)
2438efc5b4fSDuncan P. N. Exon Smith .addImm(Amount);
2448da87163SEli Bendersky } else {
2458efc5b4fSDuncan P. N. Exon Smith assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
2468da87163SEli Bendersky // factor out the amount the callee already popped.
247d526b13eSSerge Pavlov Amount -= TII.getFramePoppedByCallee(Old);
2488da87163SEli Bendersky if (Amount)
2498efc5b4fSDuncan P. N. Exon Smith New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
2508efc5b4fSDuncan P. N. Exon Smith MSP430::SP)
2518efc5b4fSDuncan P. N. Exon Smith .addReg(MSP430::SP)
2528efc5b4fSDuncan P. N. Exon Smith .addImm(Amount);
2538da87163SEli Bendersky }
2548da87163SEli Bendersky
2558da87163SEli Bendersky if (New) {
2568da87163SEli Bendersky // The SRW implicit def is dead.
2578da87163SEli Bendersky New->getOperand(3).setIsDead();
2588da87163SEli Bendersky
2598da87163SEli Bendersky // Replace the pseudo instruction with a new instruction...
2608da87163SEli Bendersky MBB.insert(I, New);
2618da87163SEli Bendersky }
2628da87163SEli Bendersky }
2638da87163SEli Bendersky } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
2648da87163SEli Bendersky // If we are performing frame pointer elimination and if the callee pops
2658da87163SEli Bendersky // something off the stack pointer, add it back.
266d526b13eSSerge Pavlov if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
2678efc5b4fSDuncan P. N. Exon Smith MachineInstr &Old = *I;
2688da87163SEli Bendersky MachineInstr *New =
2698efc5b4fSDuncan P. N. Exon Smith BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
2708efc5b4fSDuncan P. N. Exon Smith .addReg(MSP430::SP)
2718efc5b4fSDuncan P. N. Exon Smith .addImm(CalleeAmt);
2728da87163SEli Bendersky // The SRW implicit def is dead.
2738da87163SEli Bendersky New->getOperand(3).setIsDead();
2748da87163SEli Bendersky
2758da87163SEli Bendersky MBB.insert(I, New);
2768da87163SEli Bendersky }
2778da87163SEli Bendersky }
2788da87163SEli Bendersky
279e1a2e90fSHans Wennborg return MBB.erase(I);
2808da87163SEli Bendersky }
2818da87163SEli Bendersky
2820a69176cSAnton Korobeynikov void
processFunctionBeforeFrameFinalized(MachineFunction & MF,RegScavenger *) const2835a765fddSHal Finkel MSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
2845a765fddSHal Finkel RegScavenger *) const {
285eb19aea4SJob Noorman // Create a frame entry for the FP register that must be saved.
2868da87163SEli Bendersky if (hasFP(MF)) {
287941a705bSMatthias Braun int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
2880a69176cSAnton Korobeynikov (void)FrameIdx;
289941a705bSMatthias Braun assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
290eb19aea4SJob Noorman "Slot for FP register must be last in order to be found!");
2910a69176cSAnton Korobeynikov }
2920a69176cSAnton Korobeynikov }
293