Thumb2InstrInfo.cpp revision 1b2b3e209303c078ada99f0a74bad71defe1cf7e
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)
27  : ARMBaseInstrInfo(STI), RI(*this, STI) {
28}
29
30unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const {
31  // FIXME
32  return 0;
33}
34
35bool
36Thumb2InstrInfo::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
58bool
59Thumb2InstrInfo::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
86void Thumb2InstrInfo::
87storeRegToStackSlot(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
103void Thumb2InstrInfo::
104loadRegFromStackSlot(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
120void 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
190static unsigned
191negativeOffsetOpcode(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
220static unsigned
221positiveOffsetOpcode(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
250static unsigned
251immediateOffsetOpcode(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
288int 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}
434