xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64FrameLowering.h (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
10b57cec5SDimitry Andric //==-- AArch64FrameLowering.h - TargetFrameLowering for AArch64 --*- 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 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H
140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H
150b57cec5SDimitry Andric 
16*62987288SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
18*62987288SDimitry Andric #include "llvm/Support/TypeSize.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace llvm {
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric class AArch64FrameLowering : public TargetFrameLowering {
230b57cec5SDimitry Andric public:
AArch64FrameLowering()240b57cec5SDimitry Andric   explicit AArch64FrameLowering()
258bcb0991SDimitry Andric       : TargetFrameLowering(StackGrowsDown, Align(16), 0, Align(16),
260b57cec5SDimitry Andric                             true /*StackRealignable*/) {}
270b57cec5SDimitry Andric 
2881ad6265SDimitry Andric   void resetCFIToInitialState(MachineBasicBlock &MBB) const override;
2981ad6265SDimitry Andric 
300b57cec5SDimitry Andric   MachineBasicBlock::iterator
310b57cec5SDimitry Andric   eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
320b57cec5SDimitry Andric                                 MachineBasicBlock::iterator I) const override;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric   /// emitProlog/emitEpilog - These methods insert prolog and epilog code into
350b57cec5SDimitry Andric   /// the function.
360b57cec5SDimitry Andric   void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
370b57cec5SDimitry Andric   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
380b57cec5SDimitry Andric 
3906c3fb27SDimitry Andric   bool enableCFIFixup(MachineFunction &MF) const override;
4006c3fb27SDimitry Andric 
410b57cec5SDimitry Andric   bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;
420b57cec5SDimitry Andric 
43e8d8bef9SDimitry Andric   StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
445ffd83dbSDimitry Andric                                      Register &FrameReg) const override;
4552418fc2SDimitry Andric   StackOffset getFrameIndexReferenceFromSP(const MachineFunction &MF,
4652418fc2SDimitry Andric                                            int FI) const override;
478bcb0991SDimitry Andric   StackOffset resolveFrameIndexReference(const MachineFunction &MF, int FI,
485ffd83dbSDimitry Andric                                          Register &FrameReg, bool PreferFP,
490b57cec5SDimitry Andric                                          bool ForSimm) const;
508bcb0991SDimitry Andric   StackOffset resolveFrameOffsetReference(const MachineFunction &MF,
51480093f4SDimitry Andric                                           int64_t ObjectOffset, bool isFixed,
525ffd83dbSDimitry Andric                                           bool isSVE, Register &FrameReg,
530b57cec5SDimitry Andric                                           bool PreferFP, bool ForSimm) const;
540b57cec5SDimitry Andric   bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
550b57cec5SDimitry Andric                                  MachineBasicBlock::iterator MI,
565ffd83dbSDimitry Andric                                  ArrayRef<CalleeSavedInfo> CSI,
570b57cec5SDimitry Andric                                  const TargetRegisterInfo *TRI) const override;
580b57cec5SDimitry Andric 
595ffd83dbSDimitry Andric   bool
605ffd83dbSDimitry Andric   restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
610b57cec5SDimitry Andric                               MachineBasicBlock::iterator MI,
625ffd83dbSDimitry Andric                               MutableArrayRef<CalleeSavedInfo> CSI,
630b57cec5SDimitry Andric                               const TargetRegisterInfo *TRI) const override;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   /// Can this function use the red zone for local allocations.
660b57cec5SDimitry Andric   bool canUseRedZone(const MachineFunction &MF) const;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   bool hasFP(const MachineFunction &MF) const override;
690b57cec5SDimitry Andric   bool hasReservedCallFrame(const MachineFunction &MF) const override;
700b57cec5SDimitry Andric 
71fe6060f1SDimitry Andric   bool assignCalleeSavedSpillSlots(MachineFunction &MF,
72e8d8bef9SDimitry Andric                                    const TargetRegisterInfo *TRI,
73fe6060f1SDimitry Andric                                    std::vector<CalleeSavedInfo> &CSI,
74fe6060f1SDimitry Andric                                    unsigned &MinCSFrameIndex,
75fe6060f1SDimitry Andric                                    unsigned &MaxCSFrameIndex) const override;
76e8d8bef9SDimitry Andric 
770b57cec5SDimitry Andric   void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
780b57cec5SDimitry Andric                             RegScavenger *RS) const override;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   /// Returns true if the target will correctly handle shrink wrapping.
enableShrinkWrapping(const MachineFunction & MF)810b57cec5SDimitry Andric   bool enableShrinkWrapping(const MachineFunction &MF) const override {
820b57cec5SDimitry Andric     return true;
830b57cec5SDimitry Andric   }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   bool enableStackSlotScavenging(const MachineFunction &MF) const override;
86480093f4SDimitry Andric   TargetStackID::Value getStackIDForScalableVectors() const override;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   void processFunctionBeforeFrameFinalized(MachineFunction &MF,
890b57cec5SDimitry Andric                                            RegScavenger *RS) const override;
900b57cec5SDimitry Andric 
915ffd83dbSDimitry Andric   void
925ffd83dbSDimitry Andric   processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF,
935ffd83dbSDimitry Andric                                             RegScavenger *RS) const override;
945ffd83dbSDimitry Andric 
950b57cec5SDimitry Andric   unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override;
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const;
980b57cec5SDimitry Andric 
99e8d8bef9SDimitry Andric   StackOffset
100e8d8bef9SDimitry Andric   getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,
1015ffd83dbSDimitry Andric                                  Register &FrameReg,
1020b57cec5SDimitry Andric                                  bool IgnoreSPUpdates) const override;
103e8d8bef9SDimitry Andric   StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF,
1040b57cec5SDimitry Andric                                              int FI) const override;
1050b57cec5SDimitry Andric   int getSEHFrameIndexOffset(const MachineFunction &MF, int FI) const;
1060b57cec5SDimitry Andric 
isSupportedStackID(TargetStackID::Value ID)1078bcb0991SDimitry Andric   bool isSupportedStackID(TargetStackID::Value ID) const override {
1088bcb0991SDimitry Andric     switch (ID) {
1098bcb0991SDimitry Andric     default:
1108bcb0991SDimitry Andric       return false;
1118bcb0991SDimitry Andric     case TargetStackID::Default:
112e8d8bef9SDimitry Andric     case TargetStackID::ScalableVector:
1138bcb0991SDimitry Andric     case TargetStackID::NoAlloc:
1148bcb0991SDimitry Andric       return true;
1158bcb0991SDimitry Andric     }
1168bcb0991SDimitry Andric   }
1178bcb0991SDimitry Andric 
isStackIdSafeForLocalArea(unsigned StackId)118979e22ffSDimitry Andric   bool isStackIdSafeForLocalArea(unsigned StackId) const override {
119979e22ffSDimitry Andric     // We don't support putting SVE objects into the pre-allocated local
120979e22ffSDimitry Andric     // frame block at the moment.
121e8d8bef9SDimitry Andric     return StackId != TargetStackID::ScalableVector;
122979e22ffSDimitry Andric   }
123979e22ffSDimitry Andric 
124e8d8bef9SDimitry Andric   void
125e8d8bef9SDimitry Andric   orderFrameObjects(const MachineFunction &MF,
126e8d8bef9SDimitry Andric                     SmallVectorImpl<int> &ObjectsToAllocate) const override;
127e8d8bef9SDimitry Andric 
1280b57cec5SDimitry Andric private:
129fe6060f1SDimitry Andric   /// Returns true if a homogeneous prolog or epilog code can be emitted
130fe6060f1SDimitry Andric   /// for the size optimization. If so, HOM_Prolog/HOM_Epilog pseudo
131fe6060f1SDimitry Andric   /// instructions are emitted in place. When Exit block is given, this check is
132fe6060f1SDimitry Andric   /// for epilog.
133fe6060f1SDimitry Andric   bool homogeneousPrologEpilog(MachineFunction &MF,
134fe6060f1SDimitry Andric                                MachineBasicBlock *Exit = nullptr) const;
135fe6060f1SDimitry Andric 
136fe6060f1SDimitry Andric   /// Returns true if CSRs should be paired.
137fe6060f1SDimitry Andric   bool producePairRegisters(MachineFunction &MF) const;
138fe6060f1SDimitry Andric 
1390b57cec5SDimitry Andric   bool shouldCombineCSRLocalStackBump(MachineFunction &MF,
140480093f4SDimitry Andric                                       uint64_t StackBumpBytes) const;
141480093f4SDimitry Andric 
142480093f4SDimitry Andric   int64_t estimateSVEStackObjectOffsets(MachineFrameInfo &MF) const;
143480093f4SDimitry Andric   int64_t assignSVEStackObjectOffsets(MachineFrameInfo &MF,
144480093f4SDimitry Andric                                       int &MinCSFrameIndex,
145480093f4SDimitry Andric                                       int &MaxCSFrameIndex) const;
1465ffd83dbSDimitry Andric   bool shouldCombineCSRLocalStackBumpInEpilogue(MachineBasicBlock &MBB,
1475ffd83dbSDimitry Andric                                                 unsigned StackBumpBytes) const;
14881ad6265SDimitry Andric   void emitCalleeSavedGPRLocations(MachineBasicBlock &MBB,
14981ad6265SDimitry Andric                                    MachineBasicBlock::iterator MBBI) const;
15081ad6265SDimitry Andric   void emitCalleeSavedSVELocations(MachineBasicBlock &MBB,
15181ad6265SDimitry Andric                                    MachineBasicBlock::iterator MBBI) const;
15281ad6265SDimitry Andric   void emitCalleeSavedGPRRestores(MachineBasicBlock &MBB,
15381ad6265SDimitry Andric                                   MachineBasicBlock::iterator MBBI) const;
15481ad6265SDimitry Andric   void emitCalleeSavedSVERestores(MachineBasicBlock &MBB,
15581ad6265SDimitry Andric                                   MachineBasicBlock::iterator MBBI) const;
1565f757f3fSDimitry Andric   void allocateStackSpace(MachineBasicBlock &MBB,
1575f757f3fSDimitry Andric                           MachineBasicBlock::iterator MBBI,
1585f757f3fSDimitry Andric                           int64_t RealignmentPadding, StackOffset AllocSize,
1595f757f3fSDimitry Andric                           bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFI,
1605f757f3fSDimitry Andric                           StackOffset InitialOffset, bool FollowupAllocs) const;
1610fca6ea1SDimitry Andric   /// Make a determination whether a Hazard slot is used and create it if
1620fca6ea1SDimitry Andric   /// needed.
1630fca6ea1SDimitry Andric   void determineStackHazardSlot(MachineFunction &MF,
1640fca6ea1SDimitry Andric                                 BitVector &SavedRegs) const;
16581ad6265SDimitry Andric 
16681ad6265SDimitry Andric   /// Emit target zero call-used regs.
16781ad6265SDimitry Andric   void emitZeroCallUsedRegs(BitVector RegsToZero,
16881ad6265SDimitry Andric                             MachineBasicBlock &MBB) const override;
1695f757f3fSDimitry Andric 
1705f757f3fSDimitry Andric   /// Replace a StackProbe stub (if any) with the actual probe code inline
1715f757f3fSDimitry Andric   void inlineStackProbe(MachineFunction &MF,
1725f757f3fSDimitry Andric                         MachineBasicBlock &PrologueMBB) const override;
1735f757f3fSDimitry Andric 
1745f757f3fSDimitry Andric   void inlineStackProbeFixed(MachineBasicBlock::iterator MBBI,
1755f757f3fSDimitry Andric                              Register ScratchReg, int64_t FrameSize,
1765f757f3fSDimitry Andric                              StackOffset CFAOffset) const;
1775f757f3fSDimitry Andric 
1785f757f3fSDimitry Andric   MachineBasicBlock::iterator
1795f757f3fSDimitry Andric   inlineStackProbeLoopExactMultiple(MachineBasicBlock::iterator MBBI,
1805f757f3fSDimitry Andric                                     int64_t NegProbeSize,
1815f757f3fSDimitry Andric                                     Register TargetReg) const;
182*62987288SDimitry Andric 
183*62987288SDimitry Andric   void emitRemarks(const MachineFunction &MF,
184*62987288SDimitry Andric                    MachineOptimizationRemarkEmitter *ORE) const override;
1850b57cec5SDimitry Andric };
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric } // End llvm namespace
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric #endif
190