LLVM API Documentation
00001 //===- IA64RegisterInfo.cpp - IA64 Register Information ---------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains the IA64 implementation of the TargetRegisterInfo class. 00011 // This file is responsible for the frame pointer elimination optimization 00012 // on IA64. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #include "IA64.h" 00017 #include "IA64RegisterInfo.h" 00018 #include "IA64InstrBuilder.h" 00019 #include "IA64MachineFunctionInfo.h" 00020 #include "llvm/Constants.h" 00021 #include "llvm/Type.h" 00022 #include "llvm/CodeGen/ValueTypes.h" 00023 #include "llvm/CodeGen/MachineInstrBuilder.h" 00024 #include "llvm/CodeGen/MachineFunction.h" 00025 #include "llvm/CodeGen/MachineFrameInfo.h" 00026 #include "llvm/CodeGen/MachineLocation.h" 00027 #include "llvm/CodeGen/MachineRegisterInfo.h" 00028 #include "llvm/Target/TargetFrameInfo.h" 00029 #include "llvm/Target/TargetMachine.h" 00030 #include "llvm/Target/TargetOptions.h" 00031 #include "llvm/Target/TargetInstrInfo.h" 00032 #include "llvm/ADT/BitVector.h" 00033 #include "llvm/ADT/STLExtras.h" 00034 using namespace llvm; 00035 00036 IA64RegisterInfo::IA64RegisterInfo(const TargetInstrInfo &tii) 00037 : IA64GenRegisterInfo(IA64::ADJUSTCALLSTACKDOWN, IA64::ADJUSTCALLSTACKUP), 00038 TII(tii) {} 00039 00040 const unsigned* IA64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) 00041 const { 00042 static const unsigned CalleeSavedRegs[] = { 00043 IA64::r5, 0 00044 }; 00045 return CalleeSavedRegs; 00046 } 00047 00048 const TargetRegisterClass* const* 00049 IA64RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { 00050 static const TargetRegisterClass * const CalleeSavedRegClasses[] = { 00051 &IA64::GRRegClass, 0 00052 }; 00053 return CalleeSavedRegClasses; 00054 } 00055 00056 BitVector IA64RegisterInfo::getReservedRegs(const MachineFunction &MF) const { 00057 BitVector Reserved(getNumRegs()); 00058 Reserved.set(IA64::r0); 00059 Reserved.set(IA64::r1); 00060 Reserved.set(IA64::r2); 00061 Reserved.set(IA64::r5); 00062 Reserved.set(IA64::r12); 00063 Reserved.set(IA64::r13); 00064 Reserved.set(IA64::r22); 00065 Reserved.set(IA64::rp); 00066 return Reserved; 00067 } 00068 00069 //===----------------------------------------------------------------------===// 00070 // Stack Frame Processing methods 00071 //===----------------------------------------------------------------------===// 00072 00073 // hasFP - Return true if the specified function should have a dedicated frame 00074 // pointer register. This is true if the function has variable sized allocas or 00075 // if frame pointer elimination is disabled. 00076 // 00077 bool IA64RegisterInfo::hasFP(const MachineFunction &MF) const { 00078 const MachineFrameInfo *MFI = MF.getFrameInfo(); 00079 return NoFramePointerElim || MFI->hasVarSizedObjects(); 00080 } 00081 00082 void IA64RegisterInfo:: 00083 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 00084 MachineBasicBlock::iterator I) const { 00085 if (hasFP(MF)) { 00086 // If we have a frame pointer, turn the adjcallstackup instruction into a 00087 // 'sub SP, <amt>' and the adjcallstackdown instruction into 'add SP, 00088 // <amt>' 00089 MachineInstr *Old = I; 00090 unsigned Amount = Old->getOperand(0).getImm(); 00091 if (Amount != 0) { 00092 // We need to keep the stack aligned properly. To do this, we round the 00093 // amount of space needed for the outgoing arguments up to the next 00094 // alignment boundary. 00095 unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); 00096 Amount = (Amount+Align-1)/Align*Align; 00097 00098 // Replace the pseudo instruction with a new instruction... 00099 if (Old->getOpcode() == IA64::ADJUSTCALLSTACKDOWN) { 00100 BuildMI(MBB, I, TII.get(IA64::ADDIMM22), IA64::r12).addReg(IA64::r12) 00101 .addImm(-Amount); 00102 } else { 00103 assert(Old->getOpcode() == IA64::ADJUSTCALLSTACKUP); 00104 BuildMI(MBB, I, TII.get(IA64::ADDIMM22), IA64::r12).addReg(IA64::r12) 00105 .addImm(Amount); 00106 } 00107 } 00108 } 00109 00110 MBB.erase(I); 00111 } 00112 00113 void IA64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 00114 int SPAdj, RegScavenger *RS)const{ 00115 assert(SPAdj == 0 && "Unexpected"); 00116 00117 unsigned i = 0; 00118 MachineInstr &MI = *II; 00119 MachineBasicBlock &MBB = *MI.getParent(); 00120 MachineFunction &MF = *MBB.getParent(); 00121 00122 bool FP = hasFP(MF); 00123 00124 while (!MI.getOperand(i).isFI()) { 00125 ++i; 00126 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 00127 } 00128 00129 int FrameIndex = MI.getOperand(i).getIndex(); 00130 00131 // choose a base register: ( hasFP? framepointer : stack pointer ) 00132 unsigned BaseRegister = FP ? IA64::r5 : IA64::r12; 00133 // Add the base register 00134 MI.getOperand(i).ChangeToRegister(BaseRegister, false); 00135 00136 // Now add the frame object offset to the offset from r1. 00137 int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); 00138 00139 // If we're not using a Frame Pointer that has been set to the value of the 00140 // SP before having the stack size subtracted from it, then add the stack size 00141 // to Offset to get the correct offset. 00142 Offset += MF.getFrameInfo()->getStackSize(); 00143 00144 // XXX: we use 'r22' as another hack+slash temporary register here :( 00145 if (Offset <= 8191 && Offset >= -8192) { // smallish offset 00146 // Fix up the old: 00147 MI.getOperand(i).ChangeToRegister(IA64::r22, false); 00148 //insert the new 00149 BuildMI(MBB, II, TII.get(IA64::ADDIMM22), IA64::r22) 00150 .addReg(BaseRegister).addImm(Offset); 00151 } else { // it's big 00152 //fix up the old: 00153 MI.getOperand(i).ChangeToRegister(IA64::r22, false); 00154 BuildMI(MBB, II, TII.get(IA64::MOVLIMM64), IA64::r22).addImm(Offset); 00155 BuildMI(MBB, II, TII.get(IA64::ADD), IA64::r22).addReg(BaseRegister) 00156 .addReg(IA64::r22); 00157 } 00158 00159 } 00160 00161 void IA64RegisterInfo::emitPrologue(MachineFunction &MF) const { 00162 MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB 00163 MachineBasicBlock::iterator MBBI = MBB.begin(); 00164 MachineFrameInfo *MFI = MF.getFrameInfo(); 00165 bool FP = hasFP(MF); 00166 00167 // first, we handle the 'alloc' instruction, that should be right up the 00168 // top of any function 00169 static const unsigned RegsInOrder[96] = { // there are 96 GPRs the 00170 // RSE worries about 00171 IA64::r32, IA64::r33, IA64::r34, IA64::r35, 00172 IA64::r36, IA64::r37, IA64::r38, IA64::r39, IA64::r40, IA64::r41, 00173 IA64::r42, IA64::r43, IA64::r44, IA64::r45, IA64::r46, IA64::r47, 00174 IA64::r48, IA64::r49, IA64::r50, IA64::r51, IA64::r52, IA64::r53, 00175 IA64::r54, IA64::r55, IA64::r56, IA64::r57, IA64::r58, IA64::r59, 00176 IA64::r60, IA64::r61, IA64::r62, IA64::r63, IA64::r64, IA64::r65, 00177 IA64::r66, IA64::r67, IA64::r68, IA64::r69, IA64::r70, IA64::r71, 00178 IA64::r72, IA64::r73, IA64::r74, IA64::r75, IA64::r76, IA64::r77, 00179 IA64::r78, IA64::r79, IA64::r80, IA64::r81, IA64::r82, IA64::r83, 00180 IA64::r84, IA64::r85, IA64::r86, IA64::r87, IA64::r88, IA64::r89, 00181 IA64::r90, IA64::r91, IA64::r92, IA64::r93, IA64::r94, IA64::r95, 00182 IA64::r96, IA64::r97, IA64::r98, IA64::r99, IA64::r100, IA64::r101, 00183 IA64::r102, IA64::r103, IA64::r104, IA64::r105, IA64::r106, IA64::r107, 00184 IA64::r108, IA64::r109, IA64::r110, IA64::r111, IA64::r112, IA64::r113, 00185 IA64::r114, IA64::r115, IA64::r116, IA64::r117, IA64::r118, IA64::r119, 00186 IA64::r120, IA64::r121, IA64::r122, IA64::r123, IA64::r124, IA64::r125, 00187 IA64::r126, IA64::r127 }; 00188 00189 unsigned numStackedGPRsUsed=0; 00190 for (int i=0; i != 96; i++) { 00191 if (MF.getRegInfo().isPhysRegUsed(RegsInOrder[i])) 00192 numStackedGPRsUsed=i+1; // (i+1 and not ++ - consider fn(fp, fp, int) 00193 } 00194 00195 unsigned numOutRegsUsed=MF.getInfo<IA64FunctionInfo>()->outRegsUsed; 00196 00197 // XXX FIXME : this code should be a bit more reliable (in case there _isn't_ 00198 // a pseudo_alloc in the MBB) 00199 unsigned dstRegOfPseudoAlloc; 00200 for(MBBI = MBB.begin(); /*MBBI->getOpcode() != IA64::PSEUDO_ALLOC*/; ++MBBI) { 00201 assert(MBBI != MBB.end()); 00202 if(MBBI->getOpcode() == IA64::PSEUDO_ALLOC) { 00203 dstRegOfPseudoAlloc=MBBI->getOperand(0).getReg(); 00204 break; 00205 } 00206 } 00207 00208 BuildMI(MBB, MBBI, TII.get(IA64::ALLOC)). 00209 addReg(dstRegOfPseudoAlloc).addImm(0). 00210 addImm(numStackedGPRsUsed).addImm(numOutRegsUsed).addImm(0); 00211 00212 // Get the number of bytes to allocate from the FrameInfo 00213 unsigned NumBytes = MFI->getStackSize(); 00214 00215 if(FP) 00216 NumBytes += 8; // reserve space for the old FP 00217 00218 // Do we need to allocate space on the stack? 00219 if (NumBytes == 0) 00220 return; 00221 00222 // Add 16 bytes at the bottom of the stack (scratch area) 00223 // and round the size to a multiple of the alignment. 00224 unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); 00225 unsigned Size = 16 + (FP ? 8 : 0); 00226 NumBytes = (NumBytes+Size+Align-1)/Align*Align; 00227 00228 // Update frame info to pretend that this is part of the stack... 00229 MFI->setStackSize(NumBytes); 00230 00231 // adjust stack pointer: r12 -= numbytes 00232 if (NumBytes <= 8191) { 00233 BuildMI(MBB, MBBI, TII.get(IA64::ADDIMM22),IA64::r12).addReg(IA64::r12). 00234 addImm(-NumBytes); 00235 } else { // we use r22 as a scratch register here 00236 // first load the decrement into r22 00237 BuildMI(MBB, MBBI, TII.get(IA64::MOVLIMM64), IA64::r22).addImm(-NumBytes); 00238 // FIXME: MOVLSI32 expects a _u_32imm 00239 // then add (subtract) it to r12 (stack ptr) 00240 BuildMI(MBB, MBBI, TII.get(IA64::ADD), IA64::r12) 00241 .addReg(IA64::r12).addReg(IA64::r22); 00242 00243 } 00244 00245 // now if we need to, save the old FP and set the new 00246 if (FP) { 00247 BuildMI(MBB, MBBI, TII.get(IA64::ST8)).addReg(IA64::r12).addReg(IA64::r5); 00248 // this must be the last instr in the prolog ? (XXX: why??) 00249 BuildMI(MBB, MBBI, TII.get(IA64::MOV), IA64::r5).addReg(IA64::r12); 00250 } 00251 00252 } 00253 00254 void IA64RegisterInfo::emitEpilogue(MachineFunction &MF, 00255 MachineBasicBlock &MBB) const { 00256 const MachineFrameInfo *MFI = MF.getFrameInfo(); 00257 MachineBasicBlock::iterator MBBI = prior(MBB.end()); 00258 assert(MBBI->getOpcode() == IA64::RET && 00259 "Can only insert epilog into returning blocks"); 00260 00261 bool FP = hasFP(MF); 00262 00263 // Get the number of bytes allocated from the FrameInfo... 00264 unsigned NumBytes = MFI->getStackSize(); 00265 00266 //now if we need to, restore the old FP 00267 if (FP) 00268 { 00269 //copy the FP into the SP (discards allocas) 00270 BuildMI(MBB, MBBI, TII.get(IA64::MOV), IA64::r12).addReg(IA64::r5); 00271 //restore the FP 00272 BuildMI(MBB, MBBI, TII.get(IA64::LD8), IA64::r5).addReg(IA64::r5); 00273 } 00274 00275 if (NumBytes != 0) 00276 { 00277 if (NumBytes <= 8191) { 00278 BuildMI(MBB, MBBI, TII.get(IA64::ADDIMM22),IA64::r12).addReg(IA64::r12). 00279 addImm(NumBytes); 00280 } else { 00281 BuildMI(MBB, MBBI, TII.get(IA64::MOVLIMM64), IA64::r22). 00282 addImm(NumBytes); 00283 BuildMI(MBB, MBBI, TII.get(IA64::ADD), IA64::r12).addReg(IA64::r12). 00284 addReg(IA64::r22); 00285 } 00286 } 00287 00288 } 00289 00290 unsigned IA64RegisterInfo::getRARegister() const { 00291 assert(0 && "What is the return address register"); 00292 return 0; 00293 } 00294 00295 unsigned IA64RegisterInfo::getFrameRegister(MachineFunction &MF) const { 00296 return hasFP(MF) ? IA64::r5 : IA64::r12; 00297 } 00298 00299 unsigned IA64RegisterInfo::getEHExceptionRegister() const { 00300 assert(0 && "What is the exception register"); 00301 return 0; 00302 } 00303 00304 unsigned IA64RegisterInfo::getEHHandlerRegister() const { 00305 assert(0 && "What is the exception handler register"); 00306 return 0; 00307 } 00308 00309 int IA64RegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { 00310 assert(0 && "What is the dwarf register number"); 00311 return -1; 00312 } 00313 00314 #include "IA64GenRegisterInfo.inc" 00315