f2351e25de18a7c76bf2e5eefd16fe35f3391871
[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   return true;
165 }
166
167 int Thumb2RegisterInfo::
168 rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
169                   unsigned FrameReg, int Offset) const 
170 {
171   unsigned Opcode = MI.getOpcode();
172   const TargetInstrDesc &Desc = MI.getDesc();
173   unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
174   bool isSub = false;
175
176   // Memory operands in inline assembly always use AddrModeT2_i12
177   if (Opcode == ARM::INLINEASM)
178     AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
179   
180   if (Opcode == getOpcode(ARMII::ADDri)) {
181     Offset += MI.getOperand(FrameRegIdx+1).getImm();
182     if (Offset == 0) {
183       // Turn it into a move.
184       MI.setDesc(TII.get(getOpcode(ARMII::MOVr)));
185       MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
186       MI.RemoveOperand(FrameRegIdx+1);
187       return 0;
188     } else if (Offset < 0) {
189       Offset = -Offset;
190       isSub = true;
191       MI.setDesc(TII.get(getOpcode(ARMII::SUBri)));
192     }
193
194     // Common case: small offset, fits into instruction.
195     if (ARM_AM::getT2SOImmVal(Offset) != -1) {
196       // Replace the FrameIndex with sp / fp
197       MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
198       MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
199       return 0;
200     }
201
202     // Otherwise, extract 8 adjacent bits from the immediate into this
203     // t2ADDri/t2SUBri.
204     unsigned RotAmt = CountLeadingZeros_32(Offset);
205     if (RotAmt > 24)
206       RotAmt = 24;
207     unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt);
208
209     // We will handle these bits from offset, clear them.
210     Offset &= ~ThisImmVal;
211
212     assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
213            "Bit extraction didn't work?");
214     MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
215   } else {
216     // AddrModeT2_so cannot handle any offset. If there is no offset
217     // register then we change to an immediate version.
218     if (AddrMode == ARMII::AddrModeT2_so) {
219       unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg();
220       if (OffsetReg != 0) {
221         MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
222         return Offset;
223       }
224       
225       MI.RemoveOperand(FrameRegIdx+1);
226       MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
227       Opcode = immediateOffsetOpcode(Opcode);
228       AddrMode = ARMII::AddrModeT2_i12;
229     }
230
231     // Neon and FP address modes are handled by the base ARM version...
232     if ((AddrMode != ARMII::AddrModeT2_i8) &&
233         (AddrMode != ARMII::AddrModeT2_i12)) {
234       return ARMBaseRegisterInfo::rewriteFrameIndex(MI, FrameRegIdx,
235                                                     FrameReg, Offset);
236     }
237     
238     unsigned NumBits = 0;
239     Offset += MI.getOperand(FrameRegIdx+1).getImm();
240
241     // i8 supports only negative, and i12 supports only positive, so
242     // based on Offset sign convert Opcode to the appropriate
243     // instruction
244     if (Offset < 0) {
245       Opcode = negativeOffsetOpcode(Opcode);
246       NumBits = 8;
247       isSub = true;
248       Offset = -Offset;
249     }
250     else {
251       Opcode = positiveOffsetOpcode(Opcode);
252       NumBits = 12;
253     }
254
255     if (Opcode) {
256       MI.setDesc(TII.get(Opcode));
257       MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
258
259       // Attempt to fold address computation
260       // Common case: small offset, fits into instruction.
261       unsigned Mask = (1 << NumBits) - 1;
262       if ((unsigned)Offset <= Mask) {
263         // Replace the FrameIndex with fp/sp
264         MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
265         ImmOp.ChangeToImmediate((isSub) ? -Offset : Offset);
266         return 0;
267       }
268       
269       // Otherwise, offset doesn't fit. Pull in what we can to simplify
270       unsigned ImmedOffset = Offset & Mask;
271       ImmOp.ChangeToImmediate((isSub) ? -ImmedOffset : ImmedOffset);
272       Offset &= ~Mask;
273     }
274   }
275
276   return (isSub) ? -Offset : Offset;
277 }