10b57cec5SDimitry Andric //===-- PPCFrameLowering.h - Define frame lowering for PowerPC --*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // 100b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_POWERPC_PPCFRAMELOWERING_H 130b57cec5SDimitry Andric #define LLVM_LIB_TARGET_POWERPC_PPCFRAMELOWERING_H 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 160b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 170b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric namespace llvm { 200b57cec5SDimitry Andric class PPCSubtarget; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric class PPCFrameLowering: public TargetFrameLowering { 230b57cec5SDimitry Andric const PPCSubtarget &Subtarget; 240b57cec5SDimitry Andric const unsigned ReturnSaveOffset; 250b57cec5SDimitry Andric const unsigned TOCSaveOffset; 260b57cec5SDimitry Andric const unsigned FramePointerSaveOffset; 270b57cec5SDimitry Andric const unsigned LinkageSize; 280b57cec5SDimitry Andric const unsigned BasePointerSaveOffset; 298bcb0991SDimitry Andric const unsigned CRSaveOffset; 300b57cec5SDimitry Andric 31*fe6060f1SDimitry Andric // Map each group of one or two GPRs to corresponding VSR for spilling. 32*fe6060f1SDimitry Andric // TODO: Use local table in methods to avoid this mutable member. 33*fe6060f1SDimitry Andric mutable DenseMap<unsigned, std::pair<Register, Register>> VSRContainingGPRs; 34*fe6060f1SDimitry Andric 350b57cec5SDimitry Andric /** 360b57cec5SDimitry Andric * Find register[s] that can be used in function prologue and epilogue 370b57cec5SDimitry Andric * 380b57cec5SDimitry Andric * Find register[s] that can be use as scratch register[s] in function 390b57cec5SDimitry Andric * prologue and epilogue to save various registers (Link Register, Base 400b57cec5SDimitry Andric * Pointer, etc.). Prefer R0/R12, if available. Otherwise choose whatever 410b57cec5SDimitry Andric * register[s] are available. 420b57cec5SDimitry Andric * 430b57cec5SDimitry Andric * This method will return true if it is able to find enough unique scratch 440b57cec5SDimitry Andric * registers (1 or 2 depending on the requirement). If it is unable to find 450b57cec5SDimitry Andric * enough available registers in the block, it will return false and set 460b57cec5SDimitry Andric * any passed output parameter that corresponds to a required unique register 470b57cec5SDimitry Andric * to PPC::NoRegister. 480b57cec5SDimitry Andric * 490b57cec5SDimitry Andric * \param[in] MBB The machine basic block to find an available register for 500b57cec5SDimitry Andric * \param[in] UseAtEnd Specify whether the scratch register will be used at 510b57cec5SDimitry Andric * the end of the basic block (i.e., will the scratch 520b57cec5SDimitry Andric * register kill a register defined in the basic block) 530b57cec5SDimitry Andric * \param[in] TwoUniqueRegsRequired Specify whether this basic block will 540b57cec5SDimitry Andric * require two unique scratch registers. 550b57cec5SDimitry Andric * \param[out] SR1 The scratch register to use 560b57cec5SDimitry Andric * \param[out] SR2 The second scratch register. If this pointer is not null 570b57cec5SDimitry Andric * the function will attempt to set it to an available 580b57cec5SDimitry Andric * register regardless of whether there is a hard requirement 590b57cec5SDimitry Andric * for two unique scratch registers. 600b57cec5SDimitry Andric * \return true if the required number of registers was found. 610b57cec5SDimitry Andric * false if the required number of scratch register weren't available. 620b57cec5SDimitry Andric * If either output parameter refers to a required scratch register 630b57cec5SDimitry Andric * that isn't available, it will be set to an invalid value. 640b57cec5SDimitry Andric */ 650b57cec5SDimitry Andric bool findScratchRegister(MachineBasicBlock *MBB, 660b57cec5SDimitry Andric bool UseAtEnd, 670b57cec5SDimitry Andric bool TwoUniqueRegsRequired = false, 685ffd83dbSDimitry Andric Register *SR1 = nullptr, 695ffd83dbSDimitry Andric Register *SR2 = nullptr) const; 700b57cec5SDimitry Andric bool twoUniqueScratchRegsRequired(MachineBasicBlock *MBB) const; 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric /** 730b57cec5SDimitry Andric * Create branch instruction for PPC::TCRETURN* (tail call return) 740b57cec5SDimitry Andric * 750b57cec5SDimitry Andric * \param[in] MBB that is terminated by PPC::TCRETURN* 760b57cec5SDimitry Andric */ 770b57cec5SDimitry Andric void createTailCallBranchInstr(MachineBasicBlock &MBB) const; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /** 800b57cec5SDimitry Andric * Check if the conditions are correct to allow for the stack update 810b57cec5SDimitry Andric * to be moved past the CSR save/restore code. 820b57cec5SDimitry Andric */ 830b57cec5SDimitry Andric bool stackUpdateCanBeMoved(MachineFunction &MF) const; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric public: 860b57cec5SDimitry Andric PPCFrameLowering(const PPCSubtarget &STI); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric /** 890b57cec5SDimitry Andric * Determine the frame layout and update the machine function. 900b57cec5SDimitry Andric */ 910b57cec5SDimitry Andric unsigned determineFrameLayoutAndUpdate(MachineFunction &MF, 920b57cec5SDimitry Andric bool UseEstimate = false) const; 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric /** 950b57cec5SDimitry Andric * Determine the frame layout but do not update the machine function. 960b57cec5SDimitry Andric * The MachineFunction object can be const in this case as it is not 970b57cec5SDimitry Andric * modified. 980b57cec5SDimitry Andric */ 990b57cec5SDimitry Andric unsigned determineFrameLayout(const MachineFunction &MF, 1000b57cec5SDimitry Andric bool UseEstimate = false, 1010b57cec5SDimitry Andric unsigned *NewMaxCallFrameSize = nullptr) const; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric /// emitProlog/emitEpilog - These methods insert prolog and epilog code into 1040b57cec5SDimitry Andric /// the function. 1050b57cec5SDimitry Andric void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; 1060b57cec5SDimitry Andric void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; 1075ffd83dbSDimitry Andric void inlineStackProbe(MachineFunction &MF, 1085ffd83dbSDimitry Andric MachineBasicBlock &PrologMBB) const override; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric bool hasFP(const MachineFunction &MF) const override; 1110b57cec5SDimitry Andric bool needsFP(const MachineFunction &MF) const; 1120b57cec5SDimitry Andric void replaceFPWithRealFP(MachineFunction &MF) const; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, 1150b57cec5SDimitry Andric RegScavenger *RS = nullptr) const override; 1160b57cec5SDimitry Andric void processFunctionBeforeFrameFinalized(MachineFunction &MF, 1170b57cec5SDimitry Andric RegScavenger *RS = nullptr) const override; 1180b57cec5SDimitry Andric void addScavengingSpillSlot(MachineFunction &MF, RegScavenger *RS) const; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, 1210b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 1225ffd83dbSDimitry Andric ArrayRef<CalleeSavedInfo> CSI, 1230b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 1240b57cec5SDimitry Andric /// This function will assign callee saved gprs to volatile vector registers 1250b57cec5SDimitry Andric /// for prologue spills when applicable. It returns false if there are any 1260b57cec5SDimitry Andric /// registers which were not spilled to volatile vector registers. 1270b57cec5SDimitry Andric bool 1280b57cec5SDimitry Andric assignCalleeSavedSpillSlots(MachineFunction &MF, 1290b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 1300b57cec5SDimitry Andric std::vector<CalleeSavedInfo> &CSI) const override; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric MachineBasicBlock::iterator 1330b57cec5SDimitry Andric eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 1340b57cec5SDimitry Andric MachineBasicBlock::iterator I) const override; 1350b57cec5SDimitry Andric 1365ffd83dbSDimitry Andric bool 1375ffd83dbSDimitry Andric restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 1380b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 1395ffd83dbSDimitry Andric MutableArrayRef<CalleeSavedInfo> CSI, 1400b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric /// targetHandlesStackFrameRounding - Returns true if the target is 1430b57cec5SDimitry Andric /// responsible for rounding up the stack frame (probably at emitPrologue 1440b57cec5SDimitry Andric /// time). 1450b57cec5SDimitry Andric bool targetHandlesStackFrameRounding() const override { return true; } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric /// getReturnSaveOffset - Return the previous frame offset to save the 1480b57cec5SDimitry Andric /// return address. 1490b57cec5SDimitry Andric unsigned getReturnSaveOffset() const { return ReturnSaveOffset; } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric /// getTOCSaveOffset - Return the previous frame offset to save the 1520b57cec5SDimitry Andric /// TOC register -- 64-bit SVR4 ABI only. 1538bcb0991SDimitry Andric unsigned getTOCSaveOffset() const; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric /// getFramePointerSaveOffset - Return the previous frame offset to save the 1560b57cec5SDimitry Andric /// frame pointer. 1578bcb0991SDimitry Andric unsigned getFramePointerSaveOffset() const; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric /// getBasePointerSaveOffset - Return the previous frame offset to save the 1600b57cec5SDimitry Andric /// base pointer. 1618bcb0991SDimitry Andric unsigned getBasePointerSaveOffset() const; 1628bcb0991SDimitry Andric 1630b57cec5SDimitry Andric /// getLinkageSize - Return the size of the PowerPC ABI linkage area. 1640b57cec5SDimitry Andric /// 1650b57cec5SDimitry Andric unsigned getLinkageSize() const { return LinkageSize; } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric const SpillSlot * 1680b57cec5SDimitry Andric getCalleeSavedSpillSlots(unsigned &NumEntries) const override; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric bool enableShrinkWrapping(const MachineFunction &MF) const override; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /// Methods used by shrink wrapping to determine if MBB can be used for the 1730b57cec5SDimitry Andric /// function prologue/epilogue. 1740b57cec5SDimitry Andric bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; 1750b57cec5SDimitry Andric bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override; 1760b57cec5SDimitry Andric }; 1770b57cec5SDimitry Andric } // End llvm namespace 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric #endif 180