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