1 //===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //
9 //===----------------------------------------------------------------------===//
10
11 #include "HexagonFrameLowering.h"
12 #include "Hexagon.h"
13 #include "HexagonInstrInfo.h"
14 #include "HexagonRegisterInfo.h"
15 #include "HexagonSubtarget.h"
16 #include "HexagonTargetMachine.h"
17 #include "HexagonMachineFunctionInfo.h"
18 #include "llvm/Function.h"
19 #include "llvm/Type.h"
20 #include "llvm/ADT/BitVector.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineFunctionPass.h"
26 #include "llvm/CodeGen/MachineFrameInfo.h"
27 #include "llvm/CodeGen/MachineModuleInfo.h"
28 #include "llvm/CodeGen/MachineRegisterInfo.h"
29 #include "llvm/CodeGen/RegisterScavenging.h"
30 #include "llvm/MC/MachineLocation.h"
31 #include "llvm/MC/MCAsmInfo.h"
32 #include "llvm/Target/TargetInstrInfo.h"
33 #include "llvm/Target/TargetMachine.h"
34 #include "llvm/Target/TargetOptions.h"
35 #include "llvm/Support/CommandLine.h"
36
37 using namespace llvm;
38
39 static cl::opt<bool> DisableDeallocRet(
40 "disable-hexagon-dealloc-ret",
41 cl::Hidden,
42 cl::desc("Disable Dealloc Return for Hexagon target"));
43
44 /// determineFrameLayout - Determine the size of the frame and maximum call
45 /// frame size.
determineFrameLayout(MachineFunction & MF) const46 void HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const {
47 MachineFrameInfo *MFI = MF.getFrameInfo();
48
49 // Get the number of bytes to allocate from the FrameInfo.
50 unsigned FrameSize = MFI->getStackSize();
51
52 // Get the alignments provided by the target.
53 unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment();
54 // Get the maximum call frame size of all the calls.
55 unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
56
57 // If we have dynamic alloca then maxCallFrameSize needs to be aligned so
58 // that allocations will be aligned.
59 if (MFI->hasVarSizedObjects())
60 maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign);
61
62 // Update maximum call frame size.
63 MFI->setMaxCallFrameSize(maxCallFrameSize);
64
65 // Include call frame size in total.
66 FrameSize += maxCallFrameSize;
67
68 // Make sure the frame is aligned.
69 FrameSize = RoundUpToAlignment(FrameSize, TargetAlign);
70
71 // Update frame info.
72 MFI->setStackSize(FrameSize);
73 }
74
75
emitPrologue(MachineFunction & MF) const76 void HexagonFrameLowering::emitPrologue(MachineFunction &MF) const {
77 MachineBasicBlock &MBB = MF.front();
78 MachineFrameInfo *MFI = MF.getFrameInfo();
79 MachineModuleInfo &MMI = MF.getMMI();
80 MachineBasicBlock::iterator MBBI = MBB.begin();
81 const HexagonRegisterInfo *QRI =
82 static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
83 DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
84 determineFrameLayout(MF);
85
86 // Check if frame moves are needed for EH.
87 bool needsFrameMoves = MMI.hasDebugInfo() ||
88 !MF.getFunction()->needsUnwindTableEntry();
89
90 // Get the number of bytes to allocate from the FrameInfo.
91 int NumBytes = (int) MFI->getStackSize();
92
93 // LLVM expects allocframe not to be the first instruction in the
94 // basic block.
95 MachineBasicBlock::iterator InsertPt = MBB.begin();
96
97 //
98 // ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset.
99 //
100 HexagonMachineFunctionInfo *FuncInfo =
101 MF.getInfo<HexagonMachineFunctionInfo>();
102 const std::vector<MachineInstr*>& AdjustRegs =
103 FuncInfo->getAllocaAdjustInsts();
104 for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(),
105 e = AdjustRegs.end();
106 i != e; ++i) {
107 MachineInstr* MI = *i;
108 assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) &&
109 "Expected adjust alloca node");
110
111 MachineOperand& MO = MI->getOperand(2);
112 assert(MO.isImm() && "Expected immediate");
113 MO.setImm(MFI->getMaxCallFrameSize());
114 }
115
116 std::vector<MachineMove> &Moves = MMI.getFrameMoves();
117
118 if (needsFrameMoves) {
119 // Advance CFA. DW_CFA_def_cfa
120 unsigned FPReg = QRI->getFrameRegister();
121 unsigned RAReg = QRI->getRARegister();
122
123 MachineLocation Dst(MachineLocation::VirtualFP);
124 MachineLocation Src(FPReg, -8);
125 Moves.push_back(MachineMove(0, Dst, Src));
126
127 // R31 = (R31 - #4)
128 MachineLocation LRDst(RAReg, -4);
129 MachineLocation LRSrc(RAReg);
130 Moves.push_back(MachineMove(0, LRDst, LRSrc));
131
132 // R30 = (R30 - #8)
133 MachineLocation SPDst(FPReg, -8);
134 MachineLocation SPSrc(FPReg);
135 Moves.push_back(MachineMove(0, SPDst, SPSrc));
136 }
137
138 //
139 // Only insert ALLOCFRAME if we need to.
140 //
141 if (hasFP(MF)) {
142 // Check for overflow.
143 // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used?
144 const int ALLOCFRAME_MAX = 16384;
145 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
146
147 if (NumBytes >= ALLOCFRAME_MAX) {
148 // Emit allocframe(#0).
149 BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0);
150
151 // Subtract offset from frame pointer.
152 BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real),
153 HEXAGON_RESERVED_REG_1).addImm(NumBytes);
154 BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr),
155 QRI->getStackRegister()).
156 addReg(QRI->getStackRegister()).
157 addReg(HEXAGON_RESERVED_REG_1);
158 } else {
159 BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes);
160 }
161 }
162 }
163 // Returns true if MBB has a machine instructions that indicates a tail call
164 // in the block.
hasTailCall(MachineBasicBlock & MBB) const165 bool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const {
166 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
167 unsigned RetOpcode = MBBI->getOpcode();
168
169 return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;}
170
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const171 void HexagonFrameLowering::emitEpilogue(MachineFunction &MF,
172 MachineBasicBlock &MBB) const {
173 MachineBasicBlock::iterator MBBI = prior(MBB.end());
174 DebugLoc dl = MBBI->getDebugLoc();
175 //
176 // Only insert deallocframe if we need to.
177 //
178 if (hasFP(MF)) {
179 MachineBasicBlock::iterator MBBI = prior(MBB.end());
180 MachineBasicBlock::iterator MBBI_end = MBB.end();
181 //
182 // For Hexagon, we don't need the frame size.
183 //
184 MachineFrameInfo *MFI = MF.getFrameInfo();
185 int NumBytes = (int) MFI->getStackSize();
186
187 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
188
189 // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher
190 // versions.
191 if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR
192 && !DisableDeallocRet) {
193 // Remove jumpr node.
194 MBB.erase(MBBI);
195 // Add dealloc_return.
196 BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4))
197 .addImm(NumBytes);
198 } else { // Add deallocframe for V2 and V3.
199 BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes);
200 }
201 }
202 }
203
hasFP(const MachineFunction & MF) const204 bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
205 const MachineFrameInfo *MFI = MF.getFrameInfo();
206 const HexagonMachineFunctionInfo *FuncInfo =
207 MF.getInfo<HexagonMachineFunctionInfo>();
208 return (MFI->hasCalls() || (MFI->getStackSize() > 0) ||
209 FuncInfo->hasClobberLR() );
210 }
211
212 static inline
uniqueSuperReg(unsigned Reg,const TargetRegisterInfo * TRI)213 unsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) {
214 MCSuperRegIterator SRI(Reg, TRI);
215 assert(SRI.isValid() && "Expected a superreg");
216 unsigned SuperReg = *SRI;
217 ++SRI;
218 assert(!SRI.isValid() && "Expected exactly one superreg");
219 return SuperReg;
220 }
221
222 bool
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const223 HexagonFrameLowering::spillCalleeSavedRegisters(
224 MachineBasicBlock &MBB,
225 MachineBasicBlock::iterator MI,
226 const std::vector<CalleeSavedInfo> &CSI,
227 const TargetRegisterInfo *TRI) const {
228 MachineFunction *MF = MBB.getParent();
229 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
230
231 if (CSI.empty()) {
232 return false;
233 }
234
235 // We can only schedule double loads if we spill contiguous callee-saved regs
236 // For instance, we cannot scheduled double-word loads if we spill r24,
237 // r26, and r27.
238 // Hexagon_TODO: We can try to double-word align odd registers for -O2 and
239 // above.
240 bool ContiguousRegs = true;
241
242 for (unsigned i = 0; i < CSI.size(); ++i) {
243 unsigned Reg = CSI[i].getReg();
244
245 //
246 // Check if we can use a double-word store.
247 //
248 unsigned SuperReg = uniqueSuperReg(Reg, TRI);
249 bool CanUseDblStore = false;
250 const TargetRegisterClass* SuperRegClass = 0;
251
252 if (ContiguousRegs && (i < CSI.size()-1)) {
253 unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI);
254 SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg);
255 CanUseDblStore = (SuperRegNext == SuperReg);
256 }
257
258
259 if (CanUseDblStore) {
260 TII.storeRegToStackSlot(MBB, MI, SuperReg, true,
261 CSI[i+1].getFrameIdx(), SuperRegClass, TRI);
262 MBB.addLiveIn(SuperReg);
263 ++i;
264 } else {
265 // Cannot use a double-word store.
266 ContiguousRegs = false;
267 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
268 TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC,
269 TRI);
270 MBB.addLiveIn(Reg);
271 }
272 }
273 return true;
274 }
275
276
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const277 bool HexagonFrameLowering::restoreCalleeSavedRegisters(
278 MachineBasicBlock &MBB,
279 MachineBasicBlock::iterator MI,
280 const std::vector<CalleeSavedInfo> &CSI,
281 const TargetRegisterInfo *TRI) const {
282
283 MachineFunction *MF = MBB.getParent();
284 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
285
286 if (CSI.empty()) {
287 return false;
288 }
289
290 // We can only schedule double loads if we spill contiguous callee-saved regs
291 // For instance, we cannot scheduled double-word loads if we spill r24,
292 // r26, and r27.
293 // Hexagon_TODO: We can try to double-word align odd registers for -O2 and
294 // above.
295 bool ContiguousRegs = true;
296
297 for (unsigned i = 0; i < CSI.size(); ++i) {
298 unsigned Reg = CSI[i].getReg();
299
300 //
301 // Check if we can use a double-word load.
302 //
303 unsigned SuperReg = uniqueSuperReg(Reg, TRI);
304 const TargetRegisterClass* SuperRegClass = 0;
305 bool CanUseDblLoad = false;
306 if (ContiguousRegs && (i < CSI.size()-1)) {
307 unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI);
308 SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg);
309 CanUseDblLoad = (SuperRegNext == SuperReg);
310 }
311
312
313 if (CanUseDblLoad) {
314 TII.loadRegFromStackSlot(MBB, MI, SuperReg, CSI[i+1].getFrameIdx(),
315 SuperRegClass, TRI);
316 MBB.addLiveIn(SuperReg);
317 ++i;
318 } else {
319 // Cannot use a double-word load.
320 ContiguousRegs = false;
321 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
322 TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI);
323 MBB.addLiveIn(Reg);
324 }
325 }
326 return true;
327 }
328
getFrameIndexOffset(const MachineFunction & MF,int FI) const329 int HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
330 int FI) const {
331 return MF.getFrameInfo()->getObjectOffset(FI);
332 }
333