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