xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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;
24349cc55cSDimitry Andric   const uint64_t ReturnSaveOffset;
25349cc55cSDimitry Andric   const uint64_t TOCSaveOffset;
26349cc55cSDimitry Andric   const uint64_t FramePointerSaveOffset;
270b57cec5SDimitry Andric   const unsigned LinkageSize;
28349cc55cSDimitry Andric   const uint64_t BasePointerSaveOffset;
29349cc55cSDimitry Andric   const uint64_t CRSaveOffset;
300b57cec5SDimitry Andric 
31fe6060f1SDimitry Andric   // Map each group of one or two GPRs to corresponding VSR for spilling.
32fe6060f1SDimitry Andric   // TODO: Use local table in methods to avoid this mutable member.
33fe6060f1SDimitry Andric   mutable DenseMap<unsigned, std::pair<Register, Register>> VSRContainingGPRs;
34fe6060f1SDimitry 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    */
91349cc55cSDimitry Andric   uint64_t 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    */
99349cc55cSDimitry Andric   uint64_t 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).
targetHandlesStackFrameRounding()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.
getReturnSaveOffset()149349cc55cSDimitry Andric   uint64_t 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.
153349cc55cSDimitry Andric   uint64_t getTOCSaveOffset() const;
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   /// getFramePointerSaveOffset - Return the previous frame offset to save the
1560b57cec5SDimitry Andric   /// frame pointer.
157349cc55cSDimitry Andric   uint64_t getFramePointerSaveOffset() const;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   /// getBasePointerSaveOffset - Return the previous frame offset to save the
1600b57cec5SDimitry Andric   /// base pointer.
161349cc55cSDimitry Andric   uint64_t getBasePointerSaveOffset() const;
1628bcb0991SDimitry Andric 
1630b57cec5SDimitry Andric   /// getLinkageSize - Return the size of the PowerPC ABI linkage area.
1640b57cec5SDimitry Andric   ///
getLinkageSize()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;
176*0fca6ea1SDimitry Andric   void updateCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const;
1775f757f3fSDimitry Andric 
1785f757f3fSDimitry Andric   uint64_t getStackThreshold() const override;
1790b57cec5SDimitry Andric };
1800b57cec5SDimitry Andric } // End llvm namespace
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric #endif
183