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