1 | //==- HexagonFrameLowering.h - Define frame lowering for Hexagon -*- C++ -*-==// |
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 | #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONFRAMELOWERING_H |
10 | #define LLVM_LIB_TARGET_HEXAGON_HEXAGONFRAMELOWERING_H |
11 | |
12 | #include "Hexagon.h" |
13 | #include "HexagonBlockRanges.h" |
14 | #include "MCTargetDesc/HexagonMCTargetDesc.h" |
15 | #include "llvm/ADT/STLExtras.h" |
16 | #include "llvm/CodeGen/MachineBasicBlock.h" |
17 | #include "llvm/CodeGen/MachineFrameInfo.h" |
18 | #include "llvm/CodeGen/TargetFrameLowering.h" |
19 | #include <vector> |
20 | |
21 | namespace llvm { |
22 | |
23 | class BitVector; |
24 | class HexagonInstrInfo; |
25 | class HexagonRegisterInfo; |
26 | class MachineFunction; |
27 | class MachineInstr; |
28 | class MachineRegisterInfo; |
29 | class TargetRegisterClass; |
30 | |
31 | class HexagonFrameLowering : public TargetFrameLowering { |
32 | public: |
33 | // First register which could possibly hold a variable argument. |
34 | int FirstVarArgSavedReg; |
35 | explicit HexagonFrameLowering() |
36 | : TargetFrameLowering(StackGrowsDown, Align(8), 0, Align(1), true) {} |
37 | |
38 | void |
39 | orderFrameObjects(const MachineFunction &MF, |
40 | SmallVectorImpl<int> &ObjectsToAllocate) const override; |
41 | |
42 | // All of the prolog/epilog functionality, including saving and restoring |
43 | // callee-saved registers is handled in emitPrologue. This is to have the |
44 | // logic for shrink-wrapping in one place. |
45 | void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const |
46 | override; |
47 | void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const |
48 | override {} |
49 | |
50 | bool enableCalleeSaveSkip(const MachineFunction &MF) const override; |
51 | |
52 | bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, |
53 | MachineBasicBlock::iterator MI, |
54 | ArrayRef<CalleeSavedInfo> CSI, |
55 | const TargetRegisterInfo *TRI) const override { |
56 | return true; |
57 | } |
58 | |
59 | bool |
60 | restoreCalleeSavedRegisters(MachineBasicBlock &MBB, |
61 | MachineBasicBlock::iterator MI, |
62 | MutableArrayRef<CalleeSavedInfo> CSI, |
63 | const TargetRegisterInfo *TRI) const override { |
64 | return true; |
65 | } |
66 | |
67 | bool hasReservedCallFrame(const MachineFunction &MF) const override { |
68 | // We always reserve call frame as a part of the initial stack allocation. |
69 | return true; |
70 | } |
71 | |
72 | bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override { |
73 | // Override this function to avoid calling hasFP before CSI is set |
74 | // (the default implementation calls hasFP). |
75 | return true; |
76 | } |
77 | |
78 | MachineBasicBlock::iterator |
79 | eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, |
80 | MachineBasicBlock::iterator I) const override; |
81 | void processFunctionBeforeFrameFinalized(MachineFunction &MF, |
82 | RegScavenger *RS = nullptr) const override; |
83 | void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, |
84 | RegScavenger *RS) const override; |
85 | |
86 | bool targetHandlesStackFrameRounding() const override { |
87 | return true; |
88 | } |
89 | |
90 | StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, |
91 | Register &FrameReg) const override; |
92 | |
93 | const SpillSlot *getCalleeSavedSpillSlots(unsigned &NumEntries) |
94 | const override { |
95 | static const SpillSlot Offsets[] = { |
96 | { .Reg: Hexagon::R17, .Offset: -4 }, { .Reg: Hexagon::R16, .Offset: -8 }, { .Reg: Hexagon::D8, .Offset: -8 }, |
97 | { .Reg: Hexagon::R19, .Offset: -12 }, { .Reg: Hexagon::R18, .Offset: -16 }, { .Reg: Hexagon::D9, .Offset: -16 }, |
98 | { .Reg: Hexagon::R21, .Offset: -20 }, { .Reg: Hexagon::R20, .Offset: -24 }, { .Reg: Hexagon::D10, .Offset: -24 }, |
99 | { .Reg: Hexagon::R23, .Offset: -28 }, { .Reg: Hexagon::R22, .Offset: -32 }, { .Reg: Hexagon::D11, .Offset: -32 }, |
100 | { .Reg: Hexagon::R25, .Offset: -36 }, { .Reg: Hexagon::R24, .Offset: -40 }, { .Reg: Hexagon::D12, .Offset: -40 }, |
101 | { .Reg: Hexagon::R27, .Offset: -44 }, { .Reg: Hexagon::R26, .Offset: -48 }, { .Reg: Hexagon::D13, .Offset: -48 } |
102 | }; |
103 | NumEntries = std::size(Offsets); |
104 | return Offsets; |
105 | } |
106 | |
107 | bool assignCalleeSavedSpillSlots(MachineFunction &MF, |
108 | const TargetRegisterInfo *TRI, std::vector<CalleeSavedInfo> &CSI) |
109 | const override; |
110 | |
111 | bool needsAligna(const MachineFunction &MF) const; |
112 | const MachineInstr *getAlignaInstr(const MachineFunction &MF) const; |
113 | |
114 | void insertCFIInstructions(MachineFunction &MF) const; |
115 | |
116 | protected: |
117 | bool hasFPImpl(const MachineFunction &MF) const override; |
118 | |
119 | private: |
120 | using CSIVect = std::vector<CalleeSavedInfo>; |
121 | |
122 | void expandAlloca(MachineInstr *AI, const HexagonInstrInfo &TII, |
123 | Register SP, unsigned CF) const; |
124 | void insertPrologueInBlock(MachineBasicBlock &MBB, bool PrologueStubs) const; |
125 | void insertEpilogueInBlock(MachineBasicBlock &MBB) const; |
126 | void insertAllocframe(MachineBasicBlock &MBB, |
127 | MachineBasicBlock::iterator InsertPt, unsigned NumBytes) const; |
128 | bool insertCSRSpillsInBlock(MachineBasicBlock &MBB, const CSIVect &CSI, |
129 | const HexagonRegisterInfo &HRI, bool &PrologueStubs) const; |
130 | bool insertCSRRestoresInBlock(MachineBasicBlock &MBB, const CSIVect &CSI, |
131 | const HexagonRegisterInfo &HRI) const; |
132 | void updateEntryPaths(MachineFunction &MF, MachineBasicBlock &SaveB) const; |
133 | bool updateExitPaths(MachineBasicBlock &MBB, MachineBasicBlock &RestoreB, |
134 | BitVector &DoneT, BitVector &DoneF, BitVector &Path) const; |
135 | void insertCFIInstructionsAt(MachineBasicBlock &MBB, |
136 | MachineBasicBlock::iterator At) const; |
137 | |
138 | bool expandCopy(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
139 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
140 | SmallVectorImpl<Register> &NewRegs) const; |
141 | bool expandStoreInt(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
142 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
143 | SmallVectorImpl<Register> &NewRegs) const; |
144 | bool expandLoadInt(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
145 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
146 | SmallVectorImpl<Register> &NewRegs) const; |
147 | bool expandStoreVecPred(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
148 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
149 | SmallVectorImpl<Register> &NewRegs) const; |
150 | bool expandLoadVecPred(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
151 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
152 | SmallVectorImpl<Register> &NewRegs) const; |
153 | bool expandStoreVec2(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
154 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
155 | SmallVectorImpl<Register> &NewRegs) const; |
156 | bool expandLoadVec2(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
157 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
158 | SmallVectorImpl<Register> &NewRegs) const; |
159 | bool expandStoreVec(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
160 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
161 | SmallVectorImpl<Register> &NewRegs) const; |
162 | bool expandLoadVec(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
163 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
164 | SmallVectorImpl<Register> &NewRegs) const; |
165 | bool expandSpillMacros(MachineFunction &MF, |
166 | SmallVectorImpl<Register> &NewRegs) const; |
167 | |
168 | Register findPhysReg(MachineFunction &MF, HexagonBlockRanges::IndexRange &FIR, |
169 | HexagonBlockRanges::InstrIndexMap &IndexMap, |
170 | HexagonBlockRanges::RegToRangeMap &DeadMap, |
171 | const TargetRegisterClass *RC) const; |
172 | void optimizeSpillSlots(MachineFunction &MF, |
173 | SmallVectorImpl<Register> &VRegs) const; |
174 | |
175 | void findShrunkPrologEpilog(MachineFunction &MF, MachineBasicBlock *&PrologB, |
176 | MachineBasicBlock *&EpilogB) const; |
177 | |
178 | void addCalleeSaveRegistersAsImpOperand(MachineInstr *MI, const CSIVect &CSI, |
179 | bool IsDef, bool IsKill) const; |
180 | bool shouldInlineCSR(const MachineFunction &MF, const CSIVect &CSI) const; |
181 | bool useSpillFunction(const MachineFunction &MF, const CSIVect &CSI) const; |
182 | bool useRestoreFunction(const MachineFunction &MF, const CSIVect &CSI) const; |
183 | bool mayOverflowFrameOffset(MachineFunction &MF) const; |
184 | }; |
185 | |
186 | } // end namespace llvm |
187 | |
188 | #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONFRAMELOWERING_H |
189 | |