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