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