ARMRegisterInfo.cpp revision 3ef39ca6a119caced345e35204e170ee3ad9aa29
1//===- ARMRegisterInfo.cpp - ARM Register Information -----------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the "Instituto Nokia de Tecnologia" and 6// is distributed under the University of Illinois Open Source 7// License. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10// 11// This file contains the ARM implementation of the MRegisterInfo class. 12// 13//===----------------------------------------------------------------------===// 14 15#include "ARM.h" 16#include "ARMRegisterInfo.h" 17#include "llvm/CodeGen/MachineInstrBuilder.h" 18#include "llvm/CodeGen/MachineFunction.h" 19#include "llvm/CodeGen/MachineFrameInfo.h" 20#include "llvm/CodeGen/MachineLocation.h" 21#include "llvm/Type.h" 22#include "llvm/Target/TargetFrameInfo.h" 23#include "llvm/Target/TargetMachine.h" 24#include "llvm/Target/TargetOptions.h" 25#include "llvm/Target/TargetInstrInfo.h" 26#include "llvm/ADT/STLExtras.h" 27using namespace llvm; 28 29// hasFP - Return true if the specified function should have a dedicated frame 30// pointer register. This is true if the function has variable sized allocas or 31// if frame pointer elimination is disabled. 32// 33static bool hasFP(const MachineFunction &MF) { 34 const MachineFrameInfo *MFI = MF.getFrameInfo(); 35 return NoFramePointerElim || MFI->hasVarSizedObjects(); 36} 37 38static inline unsigned rotateL(unsigned x, unsigned n){ 39 return ((x << n) | (x >> (32 - n))); 40} 41 42static inline unsigned rotateR(unsigned x, unsigned n){ 43 return ((x >> n) | (x << (32 - n))); 44} 45 46// finds the end position of largest sequence of zeros in binary representation 47// of 'immediate'. 48static int findLargestZeroSequence(unsigned immediate){ 49 int max_zero_pos; 50 int max_zero_length = 0; 51 int zero_pos; 52 int zero_length; 53 int pos = 0; 54 int end_pos; 55 56 while ((immediate & 0x3) == 0) { 57 immediate = rotateR(immediate, 2); 58 pos+=2; 59 } 60 end_pos = pos+32; 61 62 while (pos<end_pos){ 63 while ((immediate & 0x3) != 0) { 64 immediate = rotateR(immediate, 2); 65 pos+=2; 66 } 67 zero_pos = pos; 68 while ((immediate & 0x3) == 0) { 69 immediate = rotateR(immediate, 2); 70 pos+=2; 71 } 72 zero_length = pos - zero_pos; 73 if (zero_length > max_zero_length){ 74 max_zero_length = zero_length; 75 max_zero_pos = zero_pos % 32; 76 } 77 78 } 79 80 return (max_zero_pos + max_zero_length) % 32; 81} 82 83static void splitInstructionWithImmediate(MachineBasicBlock &BB, 84 MachineBasicBlock::iterator I, 85 const TargetInstrDescriptor &TID, 86 unsigned DestReg, 87 unsigned OrigReg, 88 unsigned immediate){ 89 90 if (immediate == 0){ 91 BuildMI(BB, I, TID, DestReg).addReg(OrigReg).addImm(0) 92 .addImm(0).addImm(ARMShift::LSL); 93 return; 94 } 95 96 int start_pos = findLargestZeroSequence(immediate); 97 unsigned immediate_tmp = rotateR(immediate, start_pos); 98 99 int pos = 0; 100 while (pos < 32){ 101 while(((immediate_tmp&0x3) == 0)&&(pos<32)){ 102 immediate_tmp = rotateR(immediate_tmp,2); 103 pos+=2; 104 } 105 if (pos < 32){ 106 BuildMI(BB, I, TID, DestReg).addReg(OrigReg) 107 .addImm(rotateL(immediate_tmp&0xFF, (start_pos + pos) % 32 )) 108 .addImm(0).addImm(ARMShift::LSL); 109 immediate_tmp = rotateR(immediate_tmp,8); 110 pos+=8; 111 } 112 } 113 114} 115 116ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii) 117 : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), 118 TII(tii) { 119} 120 121void ARMRegisterInfo:: 122storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 123 unsigned SrcReg, int FI, 124 const TargetRegisterClass *RC) const { 125 assert (RC == ARM::IntRegsRegisterClass); 126 BuildMI(MBB, I, TII.get(ARM::STR)).addReg(SrcReg).addFrameIndex(FI).addImm(0); 127} 128 129void ARMRegisterInfo:: 130loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 131 unsigned DestReg, int FI, 132 const TargetRegisterClass *RC) const { 133 assert (RC == ARM::IntRegsRegisterClass); 134 BuildMI(MBB, I, TII.get(ARM::LDR), DestReg).addFrameIndex(FI).addImm(0); 135} 136 137void ARMRegisterInfo::copyRegToReg(MachineBasicBlock &MBB, 138 MachineBasicBlock::iterator I, 139 unsigned DestReg, unsigned SrcReg, 140 const TargetRegisterClass *RC) const { 141 assert(RC == ARM::IntRegsRegisterClass || 142 RC == ARM::FPRegsRegisterClass || 143 RC == ARM::DFPRegsRegisterClass); 144 145 if (RC == ARM::IntRegsRegisterClass) 146 BuildMI(MBB, I, TII.get(ARM::MOV), DestReg).addReg(SrcReg).addImm(0) 147 .addImm(ARMShift::LSL); 148 else if (RC == ARM::FPRegsRegisterClass) 149 BuildMI(MBB, I, TII.get(ARM::FCPYS), DestReg).addReg(SrcReg); 150 else 151 BuildMI(MBB, I, TII.get(ARM::FCPYD), DestReg).addReg(SrcReg); 152} 153 154MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr* MI, 155 unsigned OpNum, 156 int FI) const { 157 return NULL; 158} 159 160const unsigned* ARMRegisterInfo::getCalleeSaveRegs() const { 161 static const unsigned CalleeSaveRegs[] = { 162 ARM::R4, ARM::R5, ARM::R6, ARM::R7, 163 ARM::R8, ARM::R9, ARM::R10, ARM::R11, 164 ARM::R14, 0 165 }; 166 return CalleeSaveRegs; 167} 168 169const TargetRegisterClass* const * 170ARMRegisterInfo::getCalleeSaveRegClasses() const { 171 static const TargetRegisterClass * const CalleeSaveRegClasses[] = { 172 &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, 173 &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, 174 &ARM::IntRegsRegClass, 0 175 }; 176 return CalleeSaveRegClasses; 177} 178 179void ARMRegisterInfo:: 180eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 181 MachineBasicBlock::iterator I) const { 182 if (hasFP(MF)) { 183 MachineInstr *Old = I; 184 unsigned Amount = Old->getOperand(0).getImmedValue(); 185 if (Amount != 0) { 186 unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); 187 Amount = (Amount+Align-1)/Align*Align; 188 189 if (Old->getOpcode() == ARM::ADJCALLSTACKDOWN) { 190 // sub sp, sp, amount 191 splitInstructionWithImmediate(MBB, I, TII.get(ARM::SUB), ARM::R13, 192 ARM::R13, Amount); 193 } else { 194 // add sp, sp, amount 195 assert(Old->getOpcode() == ARM::ADJCALLSTACKUP); 196 splitInstructionWithImmediate(MBB, I, TII.get(ARM::ADD), ARM::R13, 197 ARM::R13, Amount); 198 } 199 } 200 } 201 MBB.erase(I); 202} 203 204void 205ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const { 206 MachineInstr &MI = *II; 207 MachineBasicBlock &MBB = *MI.getParent(); 208 MachineFunction &MF = *MBB.getParent(); 209 210 assert (MI.getOpcode() == ARM::LDR || 211 MI.getOpcode() == ARM::STR || 212 MI.getOpcode() == ARM::ADD); 213 214 unsigned FrameIdx = 1; 215 unsigned OffIdx = 2; 216 217 int FrameIndex = MI.getOperand(FrameIdx).getFrameIndex(); 218 219 int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + 220 MI.getOperand(OffIdx).getImmedValue(); 221 222 unsigned StackSize = MF.getFrameInfo()->getStackSize(); 223 224 Offset += StackSize; 225 226 assert (Offset >= 0); 227 unsigned BaseRegister = hasFP(MF) ? ARM::R11 : ARM::R13; 228 if (Offset < 4096) { 229 // Replace the FrameIndex with r13 230 MI.getOperand(FrameIdx).ChangeToRegister(BaseRegister, false); 231 // Replace the ldr offset with Offset 232 MI.getOperand(OffIdx).ChangeToImmediate(Offset); 233 } else { 234 // Insert a set of r12 with the full address 235 // r12 = r13 + offset 236 MachineBasicBlock *MBB2 = MI.getParent(); 237 splitInstructionWithImmediate(*MBB2, II, TII.get(ARM::ADD), ARM::R12, 238 BaseRegister, Offset); 239 240 // Replace the FrameIndex with r12 241 MI.getOperand(FrameIdx).ChangeToRegister(ARM::R12, false); 242 } 243} 244 245void ARMRegisterInfo:: 246processFunctionBeforeFrameFinalized(MachineFunction &MF) const {} 247 248void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const { 249 MachineBasicBlock &MBB = MF.front(); 250 MachineBasicBlock::iterator MBBI = MBB.begin(); 251 MachineFrameInfo *MFI = MF.getFrameInfo(); 252 int NumBytes = (int) MFI->getStackSize(); 253 254 bool HasFP = hasFP(MF); 255 256 if (MFI->hasCalls()) { 257 // We reserve argument space for call sites in the function immediately on 258 // entry to the current function. This eliminates the need for add/sub 259 // brackets around call sites. 260 NumBytes += MFI->getMaxCallFrameSize(); 261 } 262 263 if (HasFP) 264 // Add space for storing the FP 265 NumBytes += 4; 266 267 // Align to 8 bytes 268 NumBytes = ((NumBytes + 7) / 8) * 8; 269 270 MFI->setStackSize(NumBytes); 271 272 //sub sp, sp, #NumBytes 273 splitInstructionWithImmediate(MBB, MBBI, TII.get(ARM::SUB), ARM::R13, 274 ARM::R13, NumBytes); 275 276 277 if (HasFP) { 278 BuildMI(MBB, MBBI, TII.get(ARM::STR)) 279 .addReg(ARM::R11).addReg(ARM::R13).addImm(0); 280 BuildMI(MBB, MBBI, TII.get(ARM::MOV), ARM::R11).addReg(ARM::R13).addImm(0). 281 addImm(ARMShift::LSL); 282 } 283} 284 285void ARMRegisterInfo::emitEpilogue(MachineFunction &MF, 286 MachineBasicBlock &MBB) const { 287 MachineBasicBlock::iterator MBBI = prior(MBB.end()); 288 assert(MBBI->getOpcode() == ARM::bx && 289 "Can only insert epilog into returning blocks"); 290 291 MachineFrameInfo *MFI = MF.getFrameInfo(); 292 int NumBytes = (int) MFI->getStackSize(); 293 294 if (hasFP(MF)) { 295 BuildMI(MBB, MBBI, TII.get(ARM::MOV), ARM::R13).addReg(ARM::R11).addImm(0). 296 addImm(ARMShift::LSL); 297 BuildMI(MBB, MBBI, TII.get(ARM::LDR), ARM::R11).addReg(ARM::R13).addImm(0); 298 } 299 300 //add sp, sp, #NumBytes 301 splitInstructionWithImmediate(MBB, MBBI, TII.get(ARM::ADD), ARM::R13, 302 ARM::R13, NumBytes); 303 304} 305 306unsigned ARMRegisterInfo::getRARegister() const { 307 return ARM::R14; 308} 309 310unsigned ARMRegisterInfo::getFrameRegister(MachineFunction &MF) const { 311 return hasFP(MF) ? ARM::R11 : ARM::R13; 312} 313 314#include "ARMGenRegisterInfo.inc" 315 316