Refactor. Get rid of a few more getOpcode() calls.
[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 = ConstantInt::get(Type::Int32Ty, Val);
56   unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
57
58   BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci))
59     .addReg(DestReg, getDefRegState(true), SubIdx)
60     .addConstantPoolIndex(Idx).addImm((int64_t)ARMCC::AL).addReg(0);
61 }
62
63 static unsigned
64 negativeOffsetOpcode(unsigned opcode)
65 {
66   switch (opcode) {
67   case ARM::t2LDRi12:   return ARM::t2LDRi8;
68   case ARM::t2LDRHi12:  return ARM::t2LDRHi8;
69   case ARM::t2LDRBi12:  return ARM::t2LDRBi8;
70   case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
71   case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
72   case ARM::t2STRi12:   return ARM::t2STRi8;
73   case ARM::t2STRBi12:  return ARM::t2STRBi8;
74   case ARM::t2STRHi12:  return ARM::t2STRHi8;
75
76   case ARM::t2LDRi8:
77   case ARM::t2LDRHi8:
78   case ARM::t2LDRBi8:
79   case ARM::t2LDRSHi8:
80   case ARM::t2LDRSBi8:
81   case ARM::t2STRi8:
82   case ARM::t2STRBi8:
83   case ARM::t2STRHi8:
84     return opcode;
85
86   default:
87     break;
88   }
89
90   return 0;
91 }
92
93 static unsigned
94 positiveOffsetOpcode(unsigned opcode)
95 {
96   switch (opcode) {
97   case ARM::t2LDRi8:   return ARM::t2LDRi12;
98   case ARM::t2LDRHi8:  return ARM::t2LDRHi12;
99   case ARM::t2LDRBi8:  return ARM::t2LDRBi12;
100   case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;
101   case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;
102   case ARM::t2STRi8:   return ARM::t2STRi12;
103   case ARM::t2STRBi8:  return ARM::t2STRBi12;
104   case ARM::t2STRHi8:  return ARM::t2STRHi12;
105
106   case ARM::t2LDRi12:
107   case ARM::t2LDRHi12:
108   case ARM::t2LDRBi12:
109   case ARM::t2LDRSHi12:
110   case ARM::t2LDRSBi12:
111   case ARM::t2STRi12:
112   case ARM::t2STRBi12:
113   case ARM::t2STRHi12:
114     return opcode;
115
116   default:
117     break;
118   }
119
120   return 0;
121 }
122
123 static unsigned
124 immediateOffsetOpcode(unsigned opcode)
125 {
126   switch (opcode) {
127   case ARM::t2LDRs:   return ARM::t2LDRi12;
128   case ARM::t2LDRHs:  return ARM::t2LDRHi12;
129   case ARM::t2LDRBs:  return ARM::t2LDRBi12;
130   case ARM::t2LDRSHs: return ARM::t2LDRSHi12;
131   case ARM::t2LDRSBs: return ARM::t2LDRSBi12;
132   case ARM::t2STRs:   return ARM::t2STRi12;
133   case ARM::t2STRBs:  return ARM::t2STRBi12;
134   case ARM::t2STRHs:  return ARM::t2STRHi12;
135
136   case ARM::t2LDRi12:
137   case ARM::t2LDRHi12:
138   case ARM::t2LDRBi12:
139   case ARM::t2LDRSHi12:
140   case ARM::t2LDRSBi12:
141   case ARM::t2STRi12:
142   case ARM::t2STRBi12:
143   case ARM::t2STRHi12:
144   case ARM::t2LDRi8:
145   case ARM::t2LDRHi8:
146   case ARM::t2LDRBi8:
147   case ARM::t2LDRSHi8:
148   case ARM::t2LDRSBi8:
149   case ARM::t2STRi8:
150   case ARM::t2STRBi8:
151   case ARM::t2STRHi8:
152     return opcode;
153
154   default:
155     break;
156   }
157
158   return 0;
159 }
160
161 bool Thumb2RegisterInfo::
162 requiresRegisterScavenging(const MachineFunction &MF) const {
163   return true;
164 }
165
166 int Thumb2RegisterInfo::
167 rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
168                   unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc,
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 == ADDriOpc) {
181     Offset += MI.getOperand(FrameRegIdx+1).getImm();
182     if (Offset == 0) {
183       // Turn it into a move.
184       MI.setDesc(TII.get(MOVOpc));
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(SUBriOpc));
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                      ARM::t2MOVr, ARM::t2ADDri, ARM::t2SUBri, 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 }