Optimize Thumb2 jumptable to use tbb / tbh when all the offsets fit in byte / halfword.
[oota-llvm.git] / lib / Target / ARM / Thumb2InstrInfo.cpp
1 //===- Thumb2InstrInfo.cpp - Thumb-2 Instruction 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 TargetInstrInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ARMInstrInfo.h"
15 #include "ARM.h"
16 #include "ARMAddressingModes.h"
17 #include "ARMGenInstrInfo.inc"
18 #include "ARMMachineFunctionInfo.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "Thumb2InstrInfo.h"
23
24 using namespace llvm;
25
26 Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget &STI)
27   : ARMBaseInstrInfo(STI), RI(*this, STI) {
28 }
29
30 unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const {
31   // FIXME
32   return 0;
33 }
34
35 bool
36 Thumb2InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
37   if (MBB.empty()) return false;
38
39   switch (MBB.back().getOpcode()) {
40   case ARM::t2LDM_RET:
41   case ARM::t2B:        // Uncond branch.
42   case ARM::t2BR_JT:    // Jumptable branch.
43   case ARM::t2TBB:      // Table branch byte.
44   case ARM::t2TBH:      // Table branch halfword.
45   case ARM::tBR_JTr:    // Jumptable branch (16-bit version).
46   case ARM::tBX_RET:
47   case ARM::tBX_RET_vararg:
48   case ARM::tPOP_RET:
49   case ARM::tB:
50     return true;
51   default:
52     break;
53   }
54
55   return false;
56 }
57
58 bool
59 Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
60                               MachineBasicBlock::iterator I,
61                               unsigned DestReg, unsigned SrcReg,
62                               const TargetRegisterClass *DestRC,
63                               const TargetRegisterClass *SrcRC) const {
64   DebugLoc DL = DebugLoc::getUnknownLoc();
65   if (I != MBB.end()) DL = I->getDebugLoc();
66
67   if (DestRC == ARM::GPRRegisterClass &&
68       SrcRC == ARM::GPRRegisterClass) {
69     AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::t2MOVr),
70                                         DestReg).addReg(SrcReg)));
71     return true;
72   } else if (DestRC == ARM::GPRRegisterClass &&
73       SrcRC == ARM::tGPRRegisterClass) {
74     BuildMI(MBB, I, DL, get(ARM::tMOVtgpr2gpr), DestReg).addReg(SrcReg);
75     return true;
76   } else if (DestRC == ARM::tGPRRegisterClass &&
77              SrcRC == ARM::GPRRegisterClass) {
78     BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg);
79     return true;
80   }
81
82   // Handle SPR, DPR, and QPR copies.
83   return ARMBaseInstrInfo::copyRegToReg(MBB, I, DestReg, SrcReg, DestRC, SrcRC);
84 }
85
86 void Thumb2InstrInfo::
87 storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
88                     unsigned SrcReg, bool isKill, int FI,
89                     const TargetRegisterClass *RC) const {
90   DebugLoc DL = DebugLoc::getUnknownLoc();
91   if (I != MBB.end()) DL = I->getDebugLoc();
92
93   if (RC == ARM::GPRRegisterClass) {
94     AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::t2STRi12))
95                    .addReg(SrcReg, getKillRegState(isKill))
96                    .addFrameIndex(FI).addImm(0));
97     return;
98   }
99
100   ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC);
101 }
102
103 void Thumb2InstrInfo::
104 loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
105                      unsigned DestReg, int FI,
106                      const TargetRegisterClass *RC) const {
107   DebugLoc DL = DebugLoc::getUnknownLoc();
108   if (I != MBB.end()) DL = I->getDebugLoc();
109
110   if (RC == ARM::GPRRegisterClass) {
111     AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::t2LDRi12), DestReg)
112                    .addFrameIndex(FI).addImm(0));
113     return;
114   }
115
116   ARMBaseInstrInfo::loadRegFromStackSlot(MBB, I, DestReg, FI, RC);
117 }
118
119
120 void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
121                                MachineBasicBlock::iterator &MBBI, DebugLoc dl,
122                                unsigned DestReg, unsigned BaseReg, int NumBytes,
123                                ARMCC::CondCodes Pred, unsigned PredReg,
124                                const ARMBaseInstrInfo &TII) {
125   bool isSub = NumBytes < 0;
126   if (isSub) NumBytes = -NumBytes;
127
128   // If profitable, use a movw or movt to materialize the offset.
129   // FIXME: Use the scavenger to grab a scratch register.
130   if (DestReg != ARM::SP && DestReg != BaseReg &&
131       NumBytes >= 4096 &&
132       ARM_AM::getT2SOImmVal(NumBytes) == -1) {
133     bool Fits = false;
134     if (NumBytes < 65536) {
135       // Use a movw to materialize the 16-bit constant.
136       BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg)
137         .addImm(NumBytes)
138         .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
139       Fits = true;
140     } else if ((NumBytes & 0xffff) == 0) {
141       // Use a movt to materialize the 32-bit constant.
142       BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg)
143         .addReg(DestReg)
144         .addImm(NumBytes >> 16)
145         .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
146       Fits = true;
147     }
148
149     if (Fits) {
150       if (isSub) {
151         BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg)
152           .addReg(BaseReg, RegState::Kill)
153           .addReg(DestReg, RegState::Kill)
154           .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
155       } else {
156         BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg)
157           .addReg(DestReg, RegState::Kill)
158           .addReg(BaseReg, RegState::Kill)
159         .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
160       }
161       return;
162     }
163   }
164
165   while (NumBytes) {
166     unsigned Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri;
167     unsigned ThisVal = NumBytes;
168     if (ARM_AM::getT2SOImmVal(NumBytes) != -1) {
169       NumBytes = 0;
170     } else if (ThisVal < 4096) {
171       Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12;
172       NumBytes = 0;
173     } else {
174       // FIXME: Move this to ARMAddressingModes.h?
175       unsigned RotAmt = CountLeadingZeros_32(ThisVal);
176       ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt);
177       NumBytes &= ~ThisVal;
178       assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 &&
179              "Bit extraction didn't work?");
180     }
181
182     // Build the new ADD / SUB.
183     BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
184       .addReg(BaseReg, RegState::Kill).addImm(ThisVal)
185       .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
186     BaseReg = DestReg;
187   }
188 }
189
190 static unsigned
191 negativeOffsetOpcode(unsigned opcode)
192 {
193   switch (opcode) {
194   case ARM::t2LDRi12:   return ARM::t2LDRi8;
195   case ARM::t2LDRHi12:  return ARM::t2LDRHi8;
196   case ARM::t2LDRBi12:  return ARM::t2LDRBi8;
197   case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
198   case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
199   case ARM::t2STRi12:   return ARM::t2STRi8;
200   case ARM::t2STRBi12:  return ARM::t2STRBi8;
201   case ARM::t2STRHi12:  return ARM::t2STRHi8;
202
203   case ARM::t2LDRi8:
204   case ARM::t2LDRHi8:
205   case ARM::t2LDRBi8:
206   case ARM::t2LDRSHi8:
207   case ARM::t2LDRSBi8:
208   case ARM::t2STRi8:
209   case ARM::t2STRBi8:
210   case ARM::t2STRHi8:
211     return opcode;
212
213   default:
214     break;
215   }
216
217   return 0;
218 }
219
220 static unsigned
221 positiveOffsetOpcode(unsigned opcode)
222 {
223   switch (opcode) {
224   case ARM::t2LDRi8:   return ARM::t2LDRi12;
225   case ARM::t2LDRHi8:  return ARM::t2LDRHi12;
226   case ARM::t2LDRBi8:  return ARM::t2LDRBi12;
227   case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;
228   case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;
229   case ARM::t2STRi8:   return ARM::t2STRi12;
230   case ARM::t2STRBi8:  return ARM::t2STRBi12;
231   case ARM::t2STRHi8:  return ARM::t2STRHi12;
232
233   case ARM::t2LDRi12:
234   case ARM::t2LDRHi12:
235   case ARM::t2LDRBi12:
236   case ARM::t2LDRSHi12:
237   case ARM::t2LDRSBi12:
238   case ARM::t2STRi12:
239   case ARM::t2STRBi12:
240   case ARM::t2STRHi12:
241     return opcode;
242
243   default:
244     break;
245   }
246
247   return 0;
248 }
249
250 static unsigned
251 immediateOffsetOpcode(unsigned opcode)
252 {
253   switch (opcode) {
254   case ARM::t2LDRs:   return ARM::t2LDRi12;
255   case ARM::t2LDRHs:  return ARM::t2LDRHi12;
256   case ARM::t2LDRBs:  return ARM::t2LDRBi12;
257   case ARM::t2LDRSHs: return ARM::t2LDRSHi12;
258   case ARM::t2LDRSBs: return ARM::t2LDRSBi12;
259   case ARM::t2STRs:   return ARM::t2STRi12;
260   case ARM::t2STRBs:  return ARM::t2STRBi12;
261   case ARM::t2STRHs:  return ARM::t2STRHi12;
262
263   case ARM::t2LDRi12:
264   case ARM::t2LDRHi12:
265   case ARM::t2LDRBi12:
266   case ARM::t2LDRSHi12:
267   case ARM::t2LDRSBi12:
268   case ARM::t2STRi12:
269   case ARM::t2STRBi12:
270   case ARM::t2STRHi12:
271   case ARM::t2LDRi8:
272   case ARM::t2LDRHi8:
273   case ARM::t2LDRBi8:
274   case ARM::t2LDRSHi8:
275   case ARM::t2LDRSBi8:
276   case ARM::t2STRi8:
277   case ARM::t2STRBi8:
278   case ARM::t2STRHi8:
279     return opcode;
280
281   default:
282     break;
283   }
284
285   return 0;
286 }
287
288 int llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
289                               unsigned FrameReg, int Offset,
290                               const ARMBaseInstrInfo &TII) {
291   unsigned Opcode = MI.getOpcode();
292   unsigned NewOpc = Opcode;
293   const TargetInstrDesc &Desc = MI.getDesc();
294   unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
295   bool isSub = false;
296
297   // Memory operands in inline assembly always use AddrModeT2_i12.
298   if (Opcode == ARM::INLINEASM)
299     AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
300   
301   if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
302     Offset += MI.getOperand(FrameRegIdx+1).getImm();
303     if (Offset == 0) {
304       // Turn it into a move.
305       MI.setDesc(TII.get(ARM::t2MOVr));
306       MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
307       MI.RemoveOperand(FrameRegIdx+1);
308       return 0;
309     }
310
311     if (Offset < 0) {
312       Offset = -Offset;
313       isSub = true;
314       MI.setDesc(TII.get(ARM::t2SUBri));
315     }
316
317     // Common case: small offset, fits into instruction.
318     if (ARM_AM::getT2SOImmVal(Offset) != -1) {
319       NewOpc = isSub ? ARM::t2SUBri : ARM::t2ADDri;
320       if (NewOpc != Opcode)
321         MI.setDesc(TII.get(NewOpc));
322       MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
323       MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
324       return 0;
325     }
326     // Another common case: imm12.
327     if (Offset < 4096) {
328       NewOpc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12;
329       if (NewOpc != Opcode)
330         MI.setDesc(TII.get(NewOpc));
331       MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
332       MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
333       return 0;
334     }
335
336     // Otherwise, extract 8 adjacent bits from the immediate into this
337     // t2ADDri/t2SUBri.
338     unsigned RotAmt = CountLeadingZeros_32(Offset);
339     unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt);
340
341     // We will handle these bits from offset, clear them.
342     Offset &= ~ThisImmVal;
343
344     assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
345            "Bit extraction didn't work?");
346     MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
347   } else {
348     // AddrModeT2_so cannot handle any offset. If there is no offset
349     // register then we change to an immediate version.
350     NewOpc = Opcode;
351     if (AddrMode == ARMII::AddrModeT2_so) {
352       unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg();
353       if (OffsetReg != 0) {
354         MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
355         return Offset;
356       }
357       
358       MI.RemoveOperand(FrameRegIdx+1);
359       MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
360       NewOpc = immediateOffsetOpcode(Opcode);
361       AddrMode = ARMII::AddrModeT2_i12;
362     }
363
364     unsigned NumBits = 0;
365     unsigned Scale = 1;
366     if (AddrMode == ARMII::AddrModeT2_i8 || AddrMode == ARMII::AddrModeT2_i12) {
367       // i8 supports only negative, and i12 supports only positive, so
368       // based on Offset sign convert Opcode to the appropriate
369       // instruction
370       Offset += MI.getOperand(FrameRegIdx+1).getImm();
371       if (Offset < 0) {
372         NewOpc = negativeOffsetOpcode(Opcode);
373         NumBits = 8;
374         isSub = true;
375         Offset = -Offset;
376       } else {
377         NewOpc = positiveOffsetOpcode(Opcode);
378         NumBits = 12;
379       }
380     } else {
381       // VFP address modes.
382       assert(AddrMode == ARMII::AddrMode5);
383       int InstrOffs=ARM_AM::getAM5Offset(MI.getOperand(FrameRegIdx+1).getImm());
384       if (ARM_AM::getAM5Op(MI.getOperand(FrameRegIdx+1).getImm()) ==ARM_AM::sub)
385         InstrOffs *= -1;
386       NumBits = 8;
387       Scale = 4;
388       Offset += InstrOffs * 4;
389       assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
390       if (Offset < 0) {
391         Offset = -Offset;
392         isSub = true;
393       }
394     }
395
396     if (NewOpc != Opcode)
397       MI.setDesc(TII.get(NewOpc));
398
399     MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
400
401     // Attempt to fold address computation
402     // Common case: small offset, fits into instruction.
403     int ImmedOffset = Offset / Scale;
404     unsigned Mask = (1 << NumBits) - 1;
405     if ((unsigned)Offset <= Mask * Scale) {
406       // Replace the FrameIndex with fp/sp
407       MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
408       if (isSub) {
409         if (AddrMode == ARMII::AddrMode5)
410           // FIXME: Not consistent.
411           ImmedOffset |= 1 << NumBits;
412         else 
413           ImmedOffset = -ImmedOffset;
414       }
415       ImmOp.ChangeToImmediate(ImmedOffset);
416       return 0;
417     }
418       
419     // Otherwise, offset doesn't fit. Pull in what we can to simplify
420     ImmedOffset = ImmedOffset & Mask;
421     if (isSub) {
422       if (AddrMode == ARMII::AddrMode5)
423         // FIXME: Not consistent.
424         ImmedOffset |= 1 << NumBits;
425       else
426         ImmedOffset = -ImmedOffset;
427     }
428     ImmOp.ChangeToImmediate(ImmedOffset);
429     Offset &= ~(Mask*Scale);
430   }
431
432   return (isSub) ? -Offset : Offset;
433 }