93ad7bd0d1393f7d0fac81e80c32451a33046f80
[oota-llvm.git] / lib / Target / ARM / Thumb2RegisterInfo.cpp
1 //===- Thumb2RegisterInfo.cpp - Thumb-2 Register Information -------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the Thumb-2 implementation of the TargetRegisterInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ARM.h"
15 #include "ARMAddressingModes.h"
16 #include "ARMBaseInstrInfo.h"
17 #include "ARMMachineFunctionInfo.h"
18 #include "ARMSubtarget.h"
19 #include "Thumb2InstrInfo.h"
20 #include "Thumb2RegisterInfo.h"
21 #include "llvm/Constants.h"
22 #include "llvm/DerivedTypes.h"
23 #include "llvm/Function.h"
24 #include "llvm/LLVMContext.h"
25 #include "llvm/CodeGen/MachineConstantPool.h"
26 #include "llvm/CodeGen/MachineFrameInfo.h"
27 #include "llvm/CodeGen/MachineFunction.h"
28 #include "llvm/CodeGen/MachineInstrBuilder.h"
29 #include "llvm/CodeGen/MachineLocation.h"
30 #include "llvm/CodeGen/MachineRegisterInfo.h"
31 #include "llvm/Target/TargetFrameInfo.h"
32 #include "llvm/Target/TargetMachine.h"
33 #include "llvm/ADT/BitVector.h"
34 #include "llvm/ADT/SmallVector.h"
35 #include "llvm/Support/CommandLine.h"
36 #include "llvm/Support/ErrorHandling.h"
37 using namespace llvm;
38
39 Thumb2RegisterInfo::Thumb2RegisterInfo(const ARMBaseInstrInfo &tii,
40                                        const ARMSubtarget &sti)
41   : ARMBaseRegisterInfo(tii, sti) {
42 }
43
44 /// emitLoadConstPool - Emits a load from constpool to materialize the
45 /// specified immediate.
46 void Thumb2RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
47                                            MachineBasicBlock::iterator &MBBI,
48                                            DebugLoc dl,
49                                            unsigned DestReg, unsigned SubIdx,
50                                            int Val,
51                                            ARMCC::CondCodes Pred,
52                                            unsigned PredReg) const {
53   MachineFunction &MF = *MBB.getParent();
54   MachineConstantPool *ConstantPool = MF.getConstantPool();
55   Constant *C = 
56              MF.getFunction()->getContext().getConstantInt(Type::Int32Ty, Val);
57   unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
58
59   BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci))
60     .addReg(DestReg, getDefRegState(true), SubIdx)
61     .addConstantPoolIndex(Idx).addImm((int64_t)ARMCC::AL).addReg(0);
62 }
63
64 static unsigned
65 negativeOffsetOpcode(unsigned opcode)
66 {
67   switch (opcode) {
68   case ARM::t2LDRi12:   return ARM::t2LDRi8;
69   case ARM::t2LDRHi12:  return ARM::t2LDRHi8;
70   case ARM::t2LDRBi12:  return ARM::t2LDRBi8;
71   case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
72   case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
73   case ARM::t2STRi12:   return ARM::t2STRi8;
74   case ARM::t2STRBi12:  return ARM::t2STRBi8;
75   case ARM::t2STRHi12:  return ARM::t2STRHi8;
76
77   case ARM::t2LDRi8:
78   case ARM::t2LDRHi8:
79   case ARM::t2LDRBi8:
80   case ARM::t2LDRSHi8:
81   case ARM::t2LDRSBi8:
82   case ARM::t2STRi8:
83   case ARM::t2STRBi8:
84   case ARM::t2STRHi8:
85     return opcode;
86
87   default:
88     break;
89   }
90
91   return 0;
92 }
93
94 static unsigned
95 positiveOffsetOpcode(unsigned opcode)
96 {
97   switch (opcode) {
98   case ARM::t2LDRi8:   return ARM::t2LDRi12;
99   case ARM::t2LDRHi8:  return ARM::t2LDRHi12;
100   case ARM::t2LDRBi8:  return ARM::t2LDRBi12;
101   case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;
102   case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;
103   case ARM::t2STRi8:   return ARM::t2STRi12;
104   case ARM::t2STRBi8:  return ARM::t2STRBi12;
105   case ARM::t2STRHi8:  return ARM::t2STRHi12;
106
107   case ARM::t2LDRi12:
108   case ARM::t2LDRHi12:
109   case ARM::t2LDRBi12:
110   case ARM::t2LDRSHi12:
111   case ARM::t2LDRSBi12:
112   case ARM::t2STRi12:
113   case ARM::t2STRBi12:
114   case ARM::t2STRHi12:
115     return opcode;
116
117   default:
118     break;
119   }
120
121   return 0;
122 }
123
124 static unsigned
125 immediateOffsetOpcode(unsigned opcode)
126 {
127   switch (opcode) {
128   case ARM::t2LDRs:   return ARM::t2LDRi12;
129   case ARM::t2LDRHs:  return ARM::t2LDRHi12;
130   case ARM::t2LDRBs:  return ARM::t2LDRBi12;
131   case ARM::t2LDRSHs: return ARM::t2LDRSHi12;
132   case ARM::t2LDRSBs: return ARM::t2LDRSBi12;
133   case ARM::t2STRs:   return ARM::t2STRi12;
134   case ARM::t2STRBs:  return ARM::t2STRBi12;
135   case ARM::t2STRHs:  return ARM::t2STRHi12;
136
137   case ARM::t2LDRi12:
138   case ARM::t2LDRHi12:
139   case ARM::t2LDRBi12:
140   case ARM::t2LDRSHi12:
141   case ARM::t2LDRSBi12:
142   case ARM::t2STRi12:
143   case ARM::t2STRBi12:
144   case ARM::t2STRHi12:
145   case ARM::t2LDRi8:
146   case ARM::t2LDRHi8:
147   case ARM::t2LDRBi8:
148   case ARM::t2LDRSHi8:
149   case ARM::t2LDRSBi8:
150   case ARM::t2STRi8:
151   case ARM::t2STRBi8:
152   case ARM::t2STRHi8:
153     return opcode;
154
155   default:
156     break;
157   }
158
159   return 0;
160 }
161
162 bool Thumb2RegisterInfo::
163 requiresRegisterScavenging(const MachineFunction &MF) const {
164   // FIXME
165   return false;
166 }
167
168 int Thumb2RegisterInfo::
169 rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
170                   unsigned FrameReg, int Offset) const 
171 {
172   unsigned Opcode = MI.getOpcode();
173   const TargetInstrDesc &Desc = MI.getDesc();
174   unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
175   bool isSub = false;
176
177   // Memory operands in inline assembly always use AddrModeT2_i12
178   if (Opcode == ARM::INLINEASM)
179     AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
180   
181   if (Opcode == getOpcode(ARMII::ADDri)) {
182     Offset += MI.getOperand(FrameRegIdx+1).getImm();
183     if (Offset == 0) {
184       // Turn it into a move.
185       MI.setDesc(TII.get(getOpcode(ARMII::MOVr)));
186       MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
187       MI.RemoveOperand(FrameRegIdx+1);
188       return 0;
189     } else if (Offset < 0) {
190       Offset = -Offset;
191       isSub = true;
192       MI.setDesc(TII.get(getOpcode(ARMII::SUBri)));
193     }
194
195     // Common case: small offset, fits into instruction.
196     if (ARM_AM::getT2SOImmVal(Offset) != -1) {
197       // Replace the FrameIndex with sp / fp
198       MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
199       MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
200       return 0;
201     }
202
203     // Otherwise, extract 8 adjacent bits from the immediate into this
204     // t2ADDri/t2SUBri.
205     unsigned RotAmt = CountLeadingZeros_32(Offset);
206     if (RotAmt > 24)
207       RotAmt = 24;
208     unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt);
209
210     // We will handle these bits from offset, clear them.
211     Offset &= ~ThisImmVal;
212
213     assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
214            "Bit extraction didn't work?");
215     MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
216   } else {
217     // AddrModeT2_so cannot handle any offset. If there is no offset
218     // register then we change to an immediate version.
219     if (AddrMode == ARMII::AddrModeT2_so) {
220       unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg();
221       if (OffsetReg != 0) {
222         MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
223         return Offset;
224       }
225       
226       MI.RemoveOperand(FrameRegIdx+1);
227       MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
228       Opcode = immediateOffsetOpcode(Opcode);
229       AddrMode = ARMII::AddrModeT2_i12;
230     }
231
232     // Neon and FP address modes are handled by the base ARM version...
233     if ((AddrMode != ARMII::AddrModeT2_i8) &&
234         (AddrMode != ARMII::AddrModeT2_i12)) {
235       return ARMBaseRegisterInfo::rewriteFrameIndex(MI, FrameRegIdx,
236                                                     FrameReg, Offset);
237     }
238     
239     unsigned NumBits = 0;
240     Offset += MI.getOperand(FrameRegIdx+1).getImm();
241
242     // i8 supports only negative, and i12 supports only positive, so
243     // based on Offset sign convert Opcode to the appropriate
244     // instruction
245     if (Offset < 0) {
246       Opcode = negativeOffsetOpcode(Opcode);
247       NumBits = 8;
248       isSub = true;
249       Offset = -Offset;
250     }
251     else {
252       Opcode = positiveOffsetOpcode(Opcode);
253       NumBits = 12;
254     }
255
256     if (Opcode) {
257       MI.setDesc(TII.get(Opcode));
258       MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
259
260       // Attempt to fold address computation
261       // Common case: small offset, fits into instruction.
262       unsigned Mask = (1 << NumBits) - 1;
263       if ((unsigned)Offset <= Mask) {
264         // Replace the FrameIndex with fp/sp
265         MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
266         ImmOp.ChangeToImmediate((isSub) ? -Offset : Offset);
267         return 0;
268       }
269       
270       // Otherwise, offset doesn't fit. Pull in what we can to simplify
271       unsigned ImmedOffset = Offset & Mask;
272       ImmOp.ChangeToImmediate((isSub) ? -ImmedOffset : ImmedOffset);
273       Offset &= ~Mask;
274     }
275   }
276
277   return (isSub) ? -Offset : Offset;
278 }