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/Target/TargetInstrInfo.h"
30 #include "llvm/Support/CommandLine.h"
31 #include "llvm/ADT/BitVector.h"
32 #include "llvm/ADT/STLExtras.h"
35 IA64RegisterInfo::IA64RegisterInfo(const TargetInstrInfo
&tii
)
36 : IA64GenRegisterInfo(IA64::ADJUSTCALLSTACKDOWN
, IA64::ADJUSTCALLSTACKUP
),
39 void IA64RegisterInfo::storeRegToStackSlot(MachineBasicBlock
&MBB
,
40 MachineBasicBlock::iterator MI
,
41 unsigned SrcReg
, int FrameIdx
,
42 const TargetRegisterClass
*RC
) const{
44 if (RC
== IA64::FPRegisterClass
) {
45 BuildMI(MBB
, MI
, TII
.get(IA64::STF_SPILL
)).addFrameIndex(FrameIdx
)
46 .addReg(SrcReg
, false, false, true);
47 } else if (RC
== IA64::GRRegisterClass
) {
48 BuildMI(MBB
, MI
, TII
.get(IA64::ST8
)).addFrameIndex(FrameIdx
)
49 .addReg(SrcReg
, false, false, true);
50 } else if (RC
== IA64::PRRegisterClass
) {
51 /* we use IA64::r2 as a temporary register for doing this hackery. */
53 BuildMI(MBB
, MI
, TII
.get(IA64::MOV
), IA64::r2
).addReg(IA64::r0
);
54 // then conditionally add 1:
55 BuildMI(MBB
, MI
, TII
.get(IA64::CADDIMM22
), IA64::r2
).addReg(IA64::r2
)
56 .addImm(1).addReg(SrcReg
, false, false, true);
57 // and then store it to the stack
58 BuildMI(MBB
, MI
, TII
.get(IA64::ST8
)).addFrameIndex(FrameIdx
).addReg(IA64::r2
);
60 "sorry, I don't know how to store this sort of reg in the stack\n");
63 void IA64RegisterInfo::loadRegFromStackSlot(MachineBasicBlock
&MBB
,
64 MachineBasicBlock::iterator MI
,
65 unsigned DestReg
, int FrameIdx
,
66 const TargetRegisterClass
*RC
)const{
68 if (RC
== IA64::FPRegisterClass
) {
69 BuildMI(MBB
, MI
, TII
.get(IA64::LDF_FILL
), DestReg
).addFrameIndex(FrameIdx
);
70 } else if (RC
== IA64::GRRegisterClass
) {
71 BuildMI(MBB
, MI
, TII
.get(IA64::LD8
), DestReg
).addFrameIndex(FrameIdx
);
72 } else if (RC
== IA64::PRRegisterClass
) {
73 // first we load a byte from the stack into r2, our 'predicate hackery'
75 BuildMI(MBB
, MI
, TII
.get(IA64::LD8
), IA64::r2
).addFrameIndex(FrameIdx
);
76 // then we compare it to zero. If it _is_ zero, compare-not-equal to
77 // r0 gives us 0, which is what we want, so that's nice.
78 BuildMI(MBB
, MI
, TII
.get(IA64::CMPNE
), DestReg
).addReg(IA64::r2
).addReg(IA64::r0
);
80 "sorry, I don't know how to load this sort of reg from the stack\n");
83 void IA64RegisterInfo::copyRegToReg(MachineBasicBlock
&MBB
,
84 MachineBasicBlock::iterator MI
,
85 unsigned DestReg
, unsigned SrcReg
,
86 const TargetRegisterClass
*DestRC
,
87 const TargetRegisterClass
*SrcRC
) const {
88 if (DestRC
!= SrcRC
) {
89 cerr
<< "Not yet supported!";
93 if(DestRC
== IA64::PRRegisterClass
) // if a bool, we use pseudocode
94 // (SrcReg) DestReg = cmp.eq.unc(r0, r0)
95 BuildMI(MBB
, MI
, TII
.get(IA64::PCMPEQUNC
), DestReg
)
96 .addReg(IA64::r0
).addReg(IA64::r0
).addReg(SrcReg
);
97 else // otherwise, MOV works (for both gen. regs and FP regs)
98 BuildMI(MBB
, MI
, TII
.get(IA64::MOV
), DestReg
).addReg(SrcReg
);
101 void IA64RegisterInfo::reMaterialize(MachineBasicBlock
&MBB
,
102 MachineBasicBlock::iterator I
,
104 const MachineInstr
*Orig
) const {
105 MachineInstr
*MI
= Orig
->clone();
106 MI
->getOperand(0).setReg(DestReg
);
110 const unsigned* IA64RegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF
)
112 static const unsigned CalleeSavedRegs
[] = {
115 return CalleeSavedRegs
;
118 const TargetRegisterClass
* const*
119 IA64RegisterInfo::getCalleeSavedRegClasses(const MachineFunction
*MF
) const {
120 static const TargetRegisterClass
* const CalleeSavedRegClasses
[] = {
123 return CalleeSavedRegClasses
;
126 BitVector
IA64RegisterInfo::getReservedRegs(const MachineFunction
&MF
) const {
127 BitVector
Reserved(getNumRegs());
128 Reserved
.set(IA64::r0
);
129 Reserved
.set(IA64::r1
);
130 Reserved
.set(IA64::r2
);
131 Reserved
.set(IA64::r5
);
132 Reserved
.set(IA64::r12
);
133 Reserved
.set(IA64::r13
);
134 Reserved
.set(IA64::r22
);
135 Reserved
.set(IA64::rp
);
139 //===----------------------------------------------------------------------===//
140 // Stack Frame Processing methods
141 //===----------------------------------------------------------------------===//
143 // hasFP - Return true if the specified function should have a dedicated frame
144 // pointer register. This is true if the function has variable sized allocas or
145 // if frame pointer elimination is disabled.
147 bool IA64RegisterInfo::hasFP(const MachineFunction
&MF
) const {
148 return NoFramePointerElim
|| MF
.getFrameInfo()->hasVarSizedObjects();
151 void IA64RegisterInfo::
152 eliminateCallFramePseudoInstr(MachineFunction
&MF
, MachineBasicBlock
&MBB
,
153 MachineBasicBlock::iterator I
) const {
155 // If we have a frame pointer, turn the adjcallstackup instruction into a
156 // 'sub SP, <amt>' and the adjcallstackdown instruction into 'add SP,
158 MachineInstr
*Old
= I
;
159 unsigned Amount
= Old
->getOperand(0).getImmedValue();
161 // We need to keep the stack aligned properly. To do this, we round the
162 // amount of space needed for the outgoing arguments up to the next
163 // alignment boundary.
164 unsigned Align
= MF
.getTarget().getFrameInfo()->getStackAlignment();
165 Amount
= (Amount
+Align
-1)/Align
*Align
;
168 if (Old
->getOpcode() == IA64::ADJUSTCALLSTACKDOWN
) {
169 New
=BuildMI(TII
.get(IA64::ADDIMM22
), IA64::r12
).addReg(IA64::r12
)
172 assert(Old
->getOpcode() == IA64::ADJUSTCALLSTACKUP
);
173 New
=BuildMI(TII
.get(IA64::ADDIMM22
), IA64::r12
).addReg(IA64::r12
)
177 // Replace the pseudo instruction with a new instruction...
185 void IA64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
186 int SPAdj
, RegScavenger
*RS
)const{
187 assert(SPAdj
== 0 && "Unexpected");
190 MachineInstr
&MI
= *II
;
191 MachineBasicBlock
&MBB
= *MI
.getParent();
192 MachineFunction
&MF
= *MBB
.getParent();
196 while (!MI
.getOperand(i
).isFrameIndex()) {
198 assert(i
< MI
.getNumOperands() && "Instr doesn't have FrameIndex operand!");
201 int FrameIndex
= MI
.getOperand(i
).getFrameIndex();
203 // choose a base register: ( hasFP? framepointer : stack pointer )
204 unsigned BaseRegister
= FP
? IA64::r5
: IA64::r12
;
205 // Add the base register
206 MI
.getOperand(i
).ChangeToRegister(BaseRegister
, false);
208 // Now add the frame object offset to the offset from r1.
209 int Offset
= MF
.getFrameInfo()->getObjectOffset(FrameIndex
);
211 // If we're not using a Frame Pointer that has been set to the value of the
212 // SP before having the stack size subtracted from it, then add the stack size
213 // to Offset to get the correct offset.
214 Offset
+= MF
.getFrameInfo()->getStackSize();
216 // XXX: we use 'r22' as another hack+slash temporary register here :(
217 if (Offset
<= 8191 && Offset
>= -8192) { // smallish offset
219 MI
.getOperand(i
).ChangeToRegister(IA64::r22
, false);
221 MachineInstr
* nMI
=BuildMI(TII
.get(IA64::ADDIMM22
), IA64::r22
)
222 .addReg(BaseRegister
).addImm(Offset
);
226 MI
.getOperand(i
).ChangeToRegister(IA64::r22
, false);
228 nMI
=BuildMI(TII
.get(IA64::MOVLIMM64
), IA64::r22
).addImm(Offset
);
230 nMI
=BuildMI(TII
.get(IA64::ADD
), IA64::r22
).addReg(BaseRegister
)
237 void IA64RegisterInfo::emitPrologue(MachineFunction
&MF
) const {
238 MachineBasicBlock
&MBB
= MF
.front(); // Prolog goes in entry BB
239 MachineBasicBlock::iterator MBBI
= MBB
.begin();
240 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
244 // first, we handle the 'alloc' instruction, that should be right up the
245 // top of any function
246 static const unsigned RegsInOrder
[96] = { // there are 96 GPRs the
248 IA64::r32
, IA64::r33
, IA64::r34
, IA64::r35
,
249 IA64::r36
, IA64::r37
, IA64::r38
, IA64::r39
, IA64::r40
, IA64::r41
,
250 IA64::r42
, IA64::r43
, IA64::r44
, IA64::r45
, IA64::r46
, IA64::r47
,
251 IA64::r48
, IA64::r49
, IA64::r50
, IA64::r51
, IA64::r52
, IA64::r53
,
252 IA64::r54
, IA64::r55
, IA64::r56
, IA64::r57
, IA64::r58
, IA64::r59
,
253 IA64::r60
, IA64::r61
, IA64::r62
, IA64::r63
, IA64::r64
, IA64::r65
,
254 IA64::r66
, IA64::r67
, IA64::r68
, IA64::r69
, IA64::r70
, IA64::r71
,
255 IA64::r72
, IA64::r73
, IA64::r74
, IA64::r75
, IA64::r76
, IA64::r77
,
256 IA64::r78
, IA64::r79
, IA64::r80
, IA64::r81
, IA64::r82
, IA64::r83
,
257 IA64::r84
, IA64::r85
, IA64::r86
, IA64::r87
, IA64::r88
, IA64::r89
,
258 IA64::r90
, IA64::r91
, IA64::r92
, IA64::r93
, IA64::r94
, IA64::r95
,
259 IA64::r96
, IA64::r97
, IA64::r98
, IA64::r99
, IA64::r100
, IA64::r101
,
260 IA64::r102
, IA64::r103
, IA64::r104
, IA64::r105
, IA64::r106
, IA64::r107
,
261 IA64::r108
, IA64::r109
, IA64::r110
, IA64::r111
, IA64::r112
, IA64::r113
,
262 IA64::r114
, IA64::r115
, IA64::r116
, IA64::r117
, IA64::r118
, IA64::r119
,
263 IA64::r120
, IA64::r121
, IA64::r122
, IA64::r123
, IA64::r124
, IA64::r125
,
264 IA64::r126
, IA64::r127
};
266 unsigned numStackedGPRsUsed
=0;
267 for(int i
=0; i
<96; i
++) {
268 if(MF
.isPhysRegUsed(RegsInOrder
[i
]))
269 numStackedGPRsUsed
=i
+1; // (i+1 and not ++ - consider fn(fp, fp, int)
272 unsigned numOutRegsUsed
=MF
.getInfo
<IA64FunctionInfo
>()->outRegsUsed
;
274 // XXX FIXME : this code should be a bit more reliable (in case there _isn't_
275 // a pseudo_alloc in the MBB)
276 unsigned dstRegOfPseudoAlloc
;
277 for(MBBI
= MBB
.begin(); /*MBBI->getOpcode() != IA64::PSEUDO_ALLOC*/; ++MBBI
) {
278 assert(MBBI
!= MBB
.end());
279 if(MBBI
->getOpcode() == IA64::PSEUDO_ALLOC
) {
280 dstRegOfPseudoAlloc
=MBBI
->getOperand(0).getReg();
285 MI
=BuildMI(TII
.get(IA64::ALLOC
)).addReg(dstRegOfPseudoAlloc
).addImm(0). \
286 addImm(numStackedGPRsUsed
).addImm(numOutRegsUsed
).addImm(0);
287 MBB
.insert(MBBI
, MI
);
289 // Get the number of bytes to allocate from the FrameInfo
290 unsigned NumBytes
= MFI
->getStackSize();
293 NumBytes
+= 8; // reserve space for the old FP
295 // Do we need to allocate space on the stack?
299 // Add 16 bytes at the bottom of the stack (scratch area)
300 // and round the size to a multiple of the alignment.
301 unsigned Align
= MF
.getTarget().getFrameInfo()->getStackAlignment();
302 unsigned Size
= 16 + (FP
? 8 : 0);
303 NumBytes
= (NumBytes
+Size
+Align
-1)/Align
*Align
;
305 // Update frame info to pretend that this is part of the stack...
306 MFI
->setStackSize(NumBytes
);
308 // adjust stack pointer: r12 -= numbytes
309 if (NumBytes
<= 8191) {
310 MI
=BuildMI(TII
.get(IA64::ADDIMM22
),IA64::r12
).addReg(IA64::r12
).
312 MBB
.insert(MBBI
, MI
);
313 } else { // we use r22 as a scratch register here
314 MI
=BuildMI(TII
.get(IA64::MOVLIMM64
), IA64::r22
).addImm(-NumBytes
);
315 // FIXME: MOVLSI32 expects a _u_32imm
316 MBB
.insert(MBBI
, MI
); // first load the decrement into r22
317 MI
=BuildMI(TII
.get(IA64::ADD
), IA64::r12
).addReg(IA64::r12
).addReg(IA64::r22
);
318 MBB
.insert(MBBI
, MI
); // then add (subtract) it to r12 (stack ptr)
321 // now if we need to, save the old FP and set the new
323 MI
= BuildMI(TII
.get(IA64::ST8
)).addReg(IA64::r12
).addReg(IA64::r5
);
324 MBB
.insert(MBBI
, MI
);
325 // this must be the last instr in the prolog ? (XXX: why??)
326 MI
= BuildMI(TII
.get(IA64::MOV
), IA64::r5
).addReg(IA64::r12
);
327 MBB
.insert(MBBI
, MI
);
332 void IA64RegisterInfo::emitEpilogue(MachineFunction
&MF
,
333 MachineBasicBlock
&MBB
) const {
334 const MachineFrameInfo
*MFI
= MF
.getFrameInfo();
335 MachineBasicBlock::iterator MBBI
= prior(MBB
.end());
337 assert(MBBI
->getOpcode() == IA64::RET
&&
338 "Can only insert epilog into returning blocks");
342 // Get the number of bytes allocated from the FrameInfo...
343 unsigned NumBytes
= MFI
->getStackSize();
345 //now if we need to, restore the old FP
348 //copy the FP into the SP (discards allocas)
349 MI
=BuildMI(TII
.get(IA64::MOV
), IA64::r12
).addReg(IA64::r5
);
350 MBB
.insert(MBBI
, MI
);
352 MI
=BuildMI(TII
.get(IA64::LD8
), IA64::r5
).addReg(IA64::r5
);
353 MBB
.insert(MBBI
, MI
);
358 if (NumBytes
<= 8191) {
359 MI
=BuildMI(TII
.get(IA64::ADDIMM22
),IA64::r12
).addReg(IA64::r12
).
361 MBB
.insert(MBBI
, MI
);
363 MI
=BuildMI(TII
.get(IA64::MOVLIMM64
), IA64::r22
).addImm(NumBytes
);
364 MBB
.insert(MBBI
, MI
);
365 MI
=BuildMI(TII
.get(IA64::ADD
), IA64::r12
).addReg(IA64::r12
).
367 MBB
.insert(MBBI
, MI
);
373 unsigned IA64RegisterInfo::getRARegister() const {
374 assert(0 && "What is the return address register");
378 unsigned IA64RegisterInfo::getFrameRegister(MachineFunction
&MF
) const {
379 return hasFP(MF
) ? IA64::r5
: IA64::r12
;
382 unsigned IA64RegisterInfo::getEHExceptionRegister() const {
383 assert(0 && "What is the exception register");
387 unsigned IA64RegisterInfo::getEHHandlerRegister() const {
388 assert(0 && "What is the exception handler register");
392 #include "IA64GenRegisterInfo.inc"