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 | bool hasFP(const MachineFunction &MF) const override; |
93 | |
94 | const SpillSlot *getCalleeSavedSpillSlots(unsigned &NumEntries) |
95 | const override { |
96 | static const SpillSlot Offsets[] = { |
97 | { .Reg: Hexagon::R17, .Offset: -4 }, { .Reg: Hexagon::R16, .Offset: -8 }, { .Reg: Hexagon::D8, .Offset: -8 }, |
98 | { .Reg: Hexagon::R19, .Offset: -12 }, { .Reg: Hexagon::R18, .Offset: -16 }, { .Reg: Hexagon::D9, .Offset: -16 }, |
99 | { .Reg: Hexagon::R21, .Offset: -20 }, { .Reg: Hexagon::R20, .Offset: -24 }, { .Reg: Hexagon::D10, .Offset: -24 }, |
100 | { .Reg: Hexagon::R23, .Offset: -28 }, { .Reg: Hexagon::R22, .Offset: -32 }, { .Reg: Hexagon::D11, .Offset: -32 }, |
101 | { .Reg: Hexagon::R25, .Offset: -36 }, { .Reg: Hexagon::R24, .Offset: -40 }, { .Reg: Hexagon::D12, .Offset: -40 }, |
102 | { .Reg: Hexagon::R27, .Offset: -44 }, { .Reg: Hexagon::R26, .Offset: -48 }, { .Reg: Hexagon::D13, .Offset: -48 } |
103 | }; |
104 | NumEntries = std::size(Offsets); |
105 | return Offsets; |
106 | } |
107 | |
108 | bool assignCalleeSavedSpillSlots(MachineFunction &MF, |
109 | const TargetRegisterInfo *TRI, std::vector<CalleeSavedInfo> &CSI) |
110 | const override; |
111 | |
112 | bool needsAligna(const MachineFunction &MF) const; |
113 | const MachineInstr *getAlignaInstr(const MachineFunction &MF) const; |
114 | |
115 | void insertCFIInstructions(MachineFunction &MF) const; |
116 | |
117 | private: |
118 | using CSIVect = std::vector<CalleeSavedInfo>; |
119 | |
120 | void expandAlloca(MachineInstr *AI, const HexagonInstrInfo &TII, |
121 | Register SP, unsigned CF) const; |
122 | void insertPrologueInBlock(MachineBasicBlock &MBB, bool PrologueStubs) const; |
123 | void insertEpilogueInBlock(MachineBasicBlock &MBB) const; |
124 | void insertAllocframe(MachineBasicBlock &MBB, |
125 | MachineBasicBlock::iterator InsertPt, unsigned NumBytes) const; |
126 | bool insertCSRSpillsInBlock(MachineBasicBlock &MBB, const CSIVect &CSI, |
127 | const HexagonRegisterInfo &HRI, bool &PrologueStubs) const; |
128 | bool insertCSRRestoresInBlock(MachineBasicBlock &MBB, const CSIVect &CSI, |
129 | const HexagonRegisterInfo &HRI) const; |
130 | void updateEntryPaths(MachineFunction &MF, MachineBasicBlock &SaveB) const; |
131 | bool updateExitPaths(MachineBasicBlock &MBB, MachineBasicBlock &RestoreB, |
132 | BitVector &DoneT, BitVector &DoneF, BitVector &Path) const; |
133 | void insertCFIInstructionsAt(MachineBasicBlock &MBB, |
134 | MachineBasicBlock::iterator At) const; |
135 | |
136 | bool expandCopy(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
137 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
138 | SmallVectorImpl<Register> &NewRegs) const; |
139 | bool expandStoreInt(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
140 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
141 | SmallVectorImpl<Register> &NewRegs) const; |
142 | bool expandLoadInt(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
143 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
144 | SmallVectorImpl<Register> &NewRegs) const; |
145 | bool expandStoreVecPred(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
146 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
147 | SmallVectorImpl<Register> &NewRegs) const; |
148 | bool expandLoadVecPred(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
149 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
150 | SmallVectorImpl<Register> &NewRegs) const; |
151 | bool expandStoreVec2(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
152 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
153 | SmallVectorImpl<Register> &NewRegs) const; |
154 | bool expandLoadVec2(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
155 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
156 | SmallVectorImpl<Register> &NewRegs) const; |
157 | bool expandStoreVec(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
158 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
159 | SmallVectorImpl<Register> &NewRegs) const; |
160 | bool expandLoadVec(MachineBasicBlock &B, MachineBasicBlock::iterator It, |
161 | MachineRegisterInfo &MRI, const HexagonInstrInfo &HII, |
162 | SmallVectorImpl<Register> &NewRegs) const; |
163 | bool expandSpillMacros(MachineFunction &MF, |
164 | SmallVectorImpl<Register> &NewRegs) const; |
165 | |
166 | Register findPhysReg(MachineFunction &MF, HexagonBlockRanges::IndexRange &FIR, |
167 | HexagonBlockRanges::InstrIndexMap &IndexMap, |
168 | HexagonBlockRanges::RegToRangeMap &DeadMap, |
169 | const TargetRegisterClass *RC) const; |
170 | void optimizeSpillSlots(MachineFunction &MF, |
171 | SmallVectorImpl<Register> &VRegs) const; |
172 | |
173 | void findShrunkPrologEpilog(MachineFunction &MF, MachineBasicBlock *&PrologB, |
174 | MachineBasicBlock *&EpilogB) const; |
175 | |
176 | void addCalleeSaveRegistersAsImpOperand(MachineInstr *MI, const CSIVect &CSI, |
177 | bool IsDef, bool IsKill) const; |
178 | bool shouldInlineCSR(const MachineFunction &MF, const CSIVect &CSI) const; |
179 | bool useSpillFunction(const MachineFunction &MF, const CSIVect &CSI) const; |
180 | bool useRestoreFunction(const MachineFunction &MF, const CSIVect &CSI) const; |
181 | bool mayOverflowFrameOffset(MachineFunction &MF) const; |
182 | }; |
183 | |
184 | } // end namespace llvm |
185 | |
186 | #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONFRAMELOWERING_H |
187 | |