1 //===- IA64RegisterInfo.cpp - IA64 Register Information ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Duraid Madina and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains the IA64 implementation of the MRegisterInfo class. This
11 // file is responsible for the frame pointer elimination optimization on IA64.
13 //===----------------------------------------------------------------------===//
16 #include "IA64RegisterInfo.h"
17 #include "IA64InstrBuilder.h"
18 #include "IA64MachineFunctionInfo.h"
19 #include "llvm/Constants.h"
20 #include "llvm/Type.h"
21 #include "llvm/CodeGen/ValueTypes.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/CodeGen/MachineFrameInfo.h"
25 #include "llvm/CodeGen/MachineLocation.h"
26 #include "llvm/Target/TargetFrameInfo.h"
27 #include "llvm/Target/TargetMachine.h"
28 #include "llvm/Target/TargetOptions.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/ADT/STLExtras.h"
35 IA64RegisterInfo::IA64RegisterInfo()
36 : IA64GenRegisterInfo(IA64::ADJUSTCALLSTACKDOWN
, IA64::ADJUSTCALLSTACKUP
) {}
38 void IA64RegisterInfo::storeRegToStackSlot(MachineBasicBlock
&MBB
,
39 MachineBasicBlock::iterator MI
,
40 unsigned SrcReg
, int FrameIdx
,
41 const TargetRegisterClass
*RC
) const{
43 if (RC
== IA64::FPRegisterClass
) {
44 BuildMI(MBB
, MI
, IA64::STF_SPILL
, 2).addFrameIndex(FrameIdx
).addReg(SrcReg
);
45 } else if (RC
== IA64::GRRegisterClass
) {
46 BuildMI(MBB
, MI
, IA64::ST8
, 2).addFrameIndex(FrameIdx
).addReg(SrcReg
);
48 else if (RC
== IA64::PRRegisterClass
) {
49 /* we use IA64::r2 as a temporary register for doing this hackery. */
51 BuildMI(MBB
, MI
, IA64::MOV
, 1, IA64::r2
).addReg(IA64::r0
);
52 // then conditionally add 1:
53 BuildMI(MBB
, MI
, IA64::CADDIMM22
, 3, IA64::r2
).addReg(IA64::r2
)
54 .addImm(1).addReg(SrcReg
);
55 // and then store it to the stack
56 BuildMI(MBB
, MI
, IA64::ST8
, 2).addFrameIndex(FrameIdx
).addReg(IA64::r2
);
58 "sorry, I don't know how to store this sort of reg in the stack\n");
61 void IA64RegisterInfo::loadRegFromStackSlot(MachineBasicBlock
&MBB
,
62 MachineBasicBlock::iterator MI
,
63 unsigned DestReg
, int FrameIdx
,
64 const TargetRegisterClass
*RC
)const{
66 if (RC
== IA64::FPRegisterClass
) {
67 BuildMI(MBB
, MI
, IA64::LDF_FILL
, 1, DestReg
).addFrameIndex(FrameIdx
);
68 } else if (RC
== IA64::GRRegisterClass
) {
69 BuildMI(MBB
, MI
, IA64::LD8
, 1, DestReg
).addFrameIndex(FrameIdx
);
70 } else if (RC
== IA64::PRRegisterClass
) {
71 // first we load a byte from the stack into r2, our 'predicate hackery'
73 BuildMI(MBB
, MI
, IA64::LD8
, 1, IA64::r2
).addFrameIndex(FrameIdx
);
74 // then we compare it to zero. If it _is_ zero, compare-not-equal to
75 // r0 gives us 0, which is what we want, so that's nice.
76 BuildMI(MBB
, MI
, IA64::CMPNE
, 2, DestReg
).addReg(IA64::r2
).addReg(IA64::r0
);
78 "sorry, I don't know how to load this sort of reg from the stack\n");
81 void IA64RegisterInfo::copyRegToReg(MachineBasicBlock
&MBB
,
82 MachineBasicBlock::iterator MI
,
83 unsigned DestReg
, unsigned SrcReg
,
84 const TargetRegisterClass
*RC
) const {
86 if(RC
== IA64::PRRegisterClass
) // if a bool, we use pseudocode
87 // (SrcReg) DestReg = cmp.eq.unc(r0, r0)
88 BuildMI(MBB
, MI
, IA64::PCMPEQUNC
, 3, DestReg
).addReg(IA64::r0
).addReg(IA64::r0
).addReg(SrcReg
);
89 else // otherwise, MOV works (for both gen. regs and FP regs)
90 BuildMI(MBB
, MI
, IA64::MOV
, 1, DestReg
).addReg(SrcReg
);
93 //===----------------------------------------------------------------------===//
94 // Stack Frame Processing methods
95 //===----------------------------------------------------------------------===//
97 // hasFP - Return true if the specified function should have a dedicated frame
98 // pointer register. This is true if the function has variable sized allocas or
99 // if frame pointer elimination is disabled.
101 static bool hasFP(MachineFunction
&MF
) {
102 return NoFramePointerElim
|| MF
.getFrameInfo()->hasVarSizedObjects();
105 void IA64RegisterInfo::
106 eliminateCallFramePseudoInstr(MachineFunction
&MF
, MachineBasicBlock
&MBB
,
107 MachineBasicBlock::iterator I
) const {
110 // If we have a frame pointer, turn the adjcallstackup instruction into a
111 // 'sub SP, <amt>' and the adjcallstackdown instruction into 'add SP,
113 MachineInstr
*Old
= I
;
114 unsigned Amount
= Old
->getOperand(0).getImmedValue();
116 // We need to keep the stack aligned properly. To do this, we round the
117 // amount of space needed for the outgoing arguments up to the next
118 // alignment boundary.
119 unsigned Align
= MF
.getTarget().getFrameInfo()->getStackAlignment();
120 Amount
= (Amount
+Align
-1)/Align
*Align
;
123 if (Old
->getOpcode() == IA64::ADJUSTCALLSTACKDOWN
) {
124 New
=BuildMI(IA64::ADDIMM22
, 2, IA64::r12
).addReg(IA64::r12
)
127 assert(Old
->getOpcode() == IA64::ADJUSTCALLSTACKUP
);
128 New
=BuildMI(IA64::ADDIMM22
, 2, IA64::r12
).addReg(IA64::r12
)
132 // Replace the pseudo instruction with a new instruction...
140 void IA64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
) const{
142 MachineInstr
&MI
= *II
;
143 MachineBasicBlock
&MBB
= *MI
.getParent();
144 MachineFunction
&MF
= *MBB
.getParent();
148 while (!MI
.getOperand(i
).isFrameIndex()) {
150 assert(i
< MI
.getNumOperands() && "Instr doesn't have FrameIndex operand!");
153 int FrameIndex
= MI
.getOperand(i
).getFrameIndex();
155 // choose a base register: ( hasFP? framepointer : stack pointer )
156 unsigned BaseRegister
= FP
? IA64::r5
: IA64::r12
;
157 // Add the base register
158 MI
.SetMachineOperandReg(i
, BaseRegister
);
160 // Now add the frame object offset to the offset from r1.
161 int Offset
= MF
.getFrameInfo()->getObjectOffset(FrameIndex
);
163 // If we're not using a Frame Pointer that has been set to the value of the
164 // SP before having the stack size subtracted from it, then add the stack size
165 // to Offset to get the correct offset.
166 Offset
+= MF
.getFrameInfo()->getStackSize();
168 // XXX: we use 'r22' as another hack+slash temporary register here :(
169 if ( Offset
<= 8191 && Offset
>= -8192) { // smallish offset
171 MI
.SetMachineOperandReg(i
, IA64::r22
);
172 MI
.getOperand(i
).setUse(); // mark r22 as being used
173 // (the bundler wants to know this)
175 MachineInstr
* nMI
=BuildMI(IA64::ADDIMM22
, 2, IA64::r22
)
176 .addReg(BaseRegister
).addSImm(Offset
);
180 MI
.SetMachineOperandReg(i
, IA64::r22
);
181 MI
.getOperand(i
).setUse(); // mark r22 as being used
182 // (the bundler wants to know this)
184 nMI
=BuildMI(IA64::MOVLIMM64
, 1, IA64::r22
).addSImm(Offset
);
186 nMI
=BuildMI(IA64::ADD
, 2, IA64::r22
).addReg(BaseRegister
)
193 void IA64RegisterInfo::emitPrologue(MachineFunction
&MF
) const {
194 MachineBasicBlock
&MBB
= MF
.front(); // Prolog goes in entry BB
195 MachineBasicBlock::iterator MBBI
= MBB
.begin();
196 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
200 // first, we handle the 'alloc' instruction, that should be right up the
201 // top of any function
202 static const unsigned RegsInOrder
[96] = { // there are 96 GPRs the
204 IA64::r32
, IA64::r33
, IA64::r34
, IA64::r35
,
205 IA64::r36
, IA64::r37
, IA64::r38
, IA64::r39
, IA64::r40
, IA64::r41
,
206 IA64::r42
, IA64::r43
, IA64::r44
, IA64::r45
, IA64::r46
, IA64::r47
,
207 IA64::r48
, IA64::r49
, IA64::r50
, IA64::r51
, IA64::r52
, IA64::r53
,
208 IA64::r54
, IA64::r55
, IA64::r56
, IA64::r57
, IA64::r58
, IA64::r59
,
209 IA64::r60
, IA64::r61
, IA64::r62
, IA64::r63
, IA64::r64
, IA64::r65
,
210 IA64::r66
, IA64::r67
, IA64::r68
, IA64::r69
, IA64::r70
, IA64::r71
,
211 IA64::r72
, IA64::r73
, IA64::r74
, IA64::r75
, IA64::r76
, IA64::r77
,
212 IA64::r78
, IA64::r79
, IA64::r80
, IA64::r81
, IA64::r82
, IA64::r83
,
213 IA64::r84
, IA64::r85
, IA64::r86
, IA64::r87
, IA64::r88
, IA64::r89
,
214 IA64::r90
, IA64::r91
, IA64::r92
, IA64::r93
, IA64::r94
, IA64::r95
,
215 IA64::r96
, IA64::r97
, IA64::r98
, IA64::r99
, IA64::r100
, IA64::r101
,
216 IA64::r102
, IA64::r103
, IA64::r104
, IA64::r105
, IA64::r106
, IA64::r107
,
217 IA64::r108
, IA64::r109
, IA64::r110
, IA64::r111
, IA64::r112
, IA64::r113
,
218 IA64::r114
, IA64::r115
, IA64::r116
, IA64::r117
, IA64::r118
, IA64::r119
,
219 IA64::r120
, IA64::r121
, IA64::r122
, IA64::r123
, IA64::r124
, IA64::r125
,
220 IA64::r126
, IA64::r127
};
222 unsigned numStackedGPRsUsed
=0;
223 for(int i
=0; i
<96; i
++) {
224 if(MF
.isPhysRegUsed(RegsInOrder
[i
]))
225 numStackedGPRsUsed
=i
+1; // (i+1 and not ++ - consider fn(fp, fp, int)
228 unsigned numOutRegsUsed
=MF
.getInfo
<IA64FunctionInfo
>()->outRegsUsed
;
230 // XXX FIXME : this code should be a bit more reliable (in case there _isn't_ a pseudo_alloc in the MBB)
231 unsigned dstRegOfPseudoAlloc
;
232 for(MBBI
= MBB
.begin(); /*MBBI->getOpcode() != IA64::PSEUDO_ALLOC*/; ++MBBI
) {
233 assert(MBBI
!= MBB
.end());
234 if(MBBI
->getOpcode() == IA64::PSEUDO_ALLOC
) {
235 dstRegOfPseudoAlloc
=MBBI
->getOperand(0).getReg();
240 MI
=BuildMI(IA64::ALLOC
,5).addReg(dstRegOfPseudoAlloc
).addImm(0).\
241 addImm(numStackedGPRsUsed
).addImm(numOutRegsUsed
).addImm(0);
242 MBB
.insert(MBBI
, MI
);
244 // Get the number of bytes to allocate from the FrameInfo
245 unsigned NumBytes
= MFI
->getStackSize();
247 if (MFI
->hasCalls() && !FP
) {
248 // We reserve argument space for call sites in the function immediately on
249 // entry to the current function. This eliminates the need for add/sub
250 // brackets around call sites.
251 NumBytes
+= MFI
->getMaxCallFrameSize();
255 NumBytes
+= 8; // reserve space for the old FP
257 // Do we need to allocate space on the stack?
261 // Add 16 bytes at the bottom of the stack (scratch area)
262 // and round the size to a multiple of the alignment.
263 unsigned Align
= MF
.getTarget().getFrameInfo()->getStackAlignment();
264 unsigned Size
= 16 + (FP
? 8 : 0);
265 NumBytes
= (NumBytes
+Size
+Align
-1)/Align
*Align
;
267 // Update frame info to pretend that this is part of the stack...
268 MFI
->setStackSize(NumBytes
);
270 // adjust stack pointer: r12 -= numbytes
271 if (NumBytes
<= 8191) {
272 MI
=BuildMI(IA64::ADDIMM22
, 2, IA64::r12
).addReg(IA64::r12
).addImm(-NumBytes
);
273 MBB
.insert(MBBI
, MI
);
274 } else { // we use r22 as a scratch register here
275 MI
=BuildMI(IA64::MOVLIMM64
, 1, IA64::r22
).addSImm(-NumBytes
);
276 // FIXME: MOVLSI32 expects a _u_32imm
277 MBB
.insert(MBBI
, MI
); // first load the decrement into r22
278 MI
=BuildMI(IA64::ADD
, 2, IA64::r12
).addReg(IA64::r12
).addReg(IA64::r22
);
279 MBB
.insert(MBBI
, MI
); // then add (subtract) it to r12 (stack ptr)
282 // now if we need to, save the old FP and set the new
284 MI
= BuildMI(IA64::ST8
, 2).addReg(IA64::r12
).addReg(IA64::r5
);
285 MBB
.insert(MBBI
, MI
);
286 // this must be the last instr in the prolog ? (XXX: why??)
287 MI
= BuildMI(IA64::MOV
, 1, IA64::r5
).addReg(IA64::r12
);
288 MBB
.insert(MBBI
, MI
);
293 void IA64RegisterInfo::emitEpilogue(MachineFunction
&MF
,
294 MachineBasicBlock
&MBB
) const {
295 const MachineFrameInfo
*MFI
= MF
.getFrameInfo();
296 MachineBasicBlock::iterator MBBI
= prior(MBB
.end());
298 assert(MBBI
->getOpcode() == IA64::RET
&&
299 "Can only insert epilog into returning blocks");
303 // Get the number of bytes allocated from the FrameInfo...
304 unsigned NumBytes
= MFI
->getStackSize();
306 //now if we need to, restore the old FP
309 //copy the FP into the SP (discards allocas)
310 MI
=BuildMI(IA64::MOV
, 1, IA64::r12
).addReg(IA64::r5
);
311 MBB
.insert(MBBI
, MI
);
313 MI
=BuildMI(IA64::LD8
, 1, IA64::r5
).addReg(IA64::r5
);
314 MBB
.insert(MBBI
, MI
);
319 if (NumBytes
<= 8191) {
320 MI
=BuildMI(IA64::ADDIMM22
, 2, IA64::r12
).addReg(IA64::r12
).addImm(NumBytes
);
321 MBB
.insert(MBBI
, MI
);
323 MI
=BuildMI(IA64::MOVLIMM64
, 1, IA64::r22
).addImm(NumBytes
);
324 MBB
.insert(MBBI
, MI
);
325 MI
=BuildMI(IA64::ADD
, 2, IA64::r12
).addReg(IA64::r12
).addReg(IA64::r22
);
326 MBB
.insert(MBBI
, MI
);
332 unsigned IA64RegisterInfo::getRARegister() const {
333 assert(0 && "What is the return address register");
337 unsigned IA64RegisterInfo::getFrameRegister(MachineFunction
&MF
) const {
338 return hasFP(MF
) ? IA64::r5
: IA64::r12
;
341 #include "IA64GenRegisterInfo.inc"