XCoreInstrInfo.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- XCoreInstrInfo.cpp - XCore Instruction Information ----------------===//
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 XCore implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "XCoreInstrInfo.h"
15#include "XCore.h"
16#include "XCoreMachineFunctionInfo.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/CodeGen/MachineConstantPool.h"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
21#include "llvm/CodeGen/MachineMemOperand.h"
22#include "llvm/IR/Constants.h"
23#include "llvm/IR/Function.h"
24#include "llvm/MC/MCContext.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/ErrorHandling.h"
27#include "llvm/Support/TargetRegistry.h"
28
29#define GET_INSTRINFO_CTOR_DTOR
30#include "XCoreGenInstrInfo.inc"
31
32namespace llvm {
33namespace XCore {
34
35  // XCore Condition Codes
36  enum CondCode {
37    COND_TRUE,
38    COND_FALSE,
39    COND_INVALID
40  };
41}
42}
43
44using namespace llvm;
45
46
47// Pin the vtable to this file.
48void XCoreInstrInfo::anchor() {}
49
50XCoreInstrInfo::XCoreInstrInfo()
51  : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
52    RI() {
53}
54
55static bool isZeroImm(const MachineOperand &op) {
56  return op.isImm() && op.getImm() == 0;
57}
58
59/// isLoadFromStackSlot - If the specified machine instruction is a direct
60/// load from a stack slot, return the virtual or physical register number of
61/// the destination along with the FrameIndex of the loaded stack slot.  If
62/// not, return 0.  This predicate must return 0 if the instruction has
63/// any side effects other than loading from the stack slot.
64unsigned
65XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const{
66  int Opcode = MI->getOpcode();
67  if (Opcode == XCore::LDWFI)
68  {
69    if ((MI->getOperand(1).isFI()) && // is a stack slot
70        (MI->getOperand(2).isImm()) &&  // the imm is zero
71        (isZeroImm(MI->getOperand(2))))
72    {
73      FrameIndex = MI->getOperand(1).getIndex();
74      return MI->getOperand(0).getReg();
75    }
76  }
77  return 0;
78}
79
80  /// isStoreToStackSlot - If the specified machine instruction is a direct
81  /// store to a stack slot, return the virtual or physical register number of
82  /// the source reg along with the FrameIndex of the loaded stack slot.  If
83  /// not, return 0.  This predicate must return 0 if the instruction has
84  /// any side effects other than storing to the stack slot.
85unsigned
86XCoreInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
87                                   int &FrameIndex) const {
88  int Opcode = MI->getOpcode();
89  if (Opcode == XCore::STWFI)
90  {
91    if ((MI->getOperand(1).isFI()) && // is a stack slot
92        (MI->getOperand(2).isImm()) &&  // the imm is zero
93        (isZeroImm(MI->getOperand(2))))
94    {
95      FrameIndex = MI->getOperand(1).getIndex();
96      return MI->getOperand(0).getReg();
97    }
98  }
99  return 0;
100}
101
102//===----------------------------------------------------------------------===//
103// Branch Analysis
104//===----------------------------------------------------------------------===//
105
106static inline bool IsBRU(unsigned BrOpc) {
107  return BrOpc == XCore::BRFU_u6
108      || BrOpc == XCore::BRFU_lu6
109      || BrOpc == XCore::BRBU_u6
110      || BrOpc == XCore::BRBU_lu6;
111}
112
113static inline bool IsBRT(unsigned BrOpc) {
114  return BrOpc == XCore::BRFT_ru6
115      || BrOpc == XCore::BRFT_lru6
116      || BrOpc == XCore::BRBT_ru6
117      || BrOpc == XCore::BRBT_lru6;
118}
119
120static inline bool IsBRF(unsigned BrOpc) {
121  return BrOpc == XCore::BRFF_ru6
122      || BrOpc == XCore::BRFF_lru6
123      || BrOpc == XCore::BRBF_ru6
124      || BrOpc == XCore::BRBF_lru6;
125}
126
127static inline bool IsCondBranch(unsigned BrOpc) {
128  return IsBRF(BrOpc) || IsBRT(BrOpc);
129}
130
131static inline bool IsBR_JT(unsigned BrOpc) {
132  return BrOpc == XCore::BR_JT
133      || BrOpc == XCore::BR_JT32;
134}
135
136/// GetCondFromBranchOpc - Return the XCore CC that matches
137/// the correspondent Branch instruction opcode.
138static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
139{
140  if (IsBRT(BrOpc)) {
141    return XCore::COND_TRUE;
142  } else if (IsBRF(BrOpc)) {
143    return XCore::COND_FALSE;
144  } else {
145    return XCore::COND_INVALID;
146  }
147}
148
149/// GetCondBranchFromCond - Return the Branch instruction
150/// opcode that matches the cc.
151static inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
152{
153  switch (CC) {
154  default: llvm_unreachable("Illegal condition code!");
155  case XCore::COND_TRUE   : return XCore::BRFT_lru6;
156  case XCore::COND_FALSE  : return XCore::BRFF_lru6;
157  }
158}
159
160/// GetOppositeBranchCondition - Return the inverse of the specified
161/// condition, e.g. turning COND_E to COND_NE.
162static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
163{
164  switch (CC) {
165  default: llvm_unreachable("Illegal condition code!");
166  case XCore::COND_TRUE   : return XCore::COND_FALSE;
167  case XCore::COND_FALSE  : return XCore::COND_TRUE;
168  }
169}
170
171/// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
172/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
173/// implemented for a target).  Upon success, this returns false and returns
174/// with the following information in various cases:
175///
176/// 1. If this block ends with no branches (it just falls through to its succ)
177///    just return false, leaving TBB/FBB null.
178/// 2. If this block ends with only an unconditional branch, it sets TBB to be
179///    the destination block.
180/// 3. If this block ends with an conditional branch and it falls through to
181///    an successor block, it sets TBB to be the branch destination block and a
182///    list of operands that evaluate the condition. These
183///    operands can be passed to other TargetInstrInfo methods to create new
184///    branches.
185/// 4. If this block ends with an conditional branch and an unconditional
186///    block, it returns the 'true' destination in TBB, the 'false' destination
187///    in FBB, and a list of operands that evaluate the condition. These
188///    operands can be passed to other TargetInstrInfo methods to create new
189///    branches.
190///
191/// Note that RemoveBranch and InsertBranch must be implemented to support
192/// cases where this method returns success.
193///
194bool
195XCoreInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
196                              MachineBasicBlock *&FBB,
197                              SmallVectorImpl<MachineOperand> &Cond,
198                              bool AllowModify) const {
199  // If the block has no terminators, it just falls into the block after it.
200  MachineBasicBlock::iterator I = MBB.end();
201  if (I == MBB.begin())
202    return false;
203  --I;
204  while (I->isDebugValue()) {
205    if (I == MBB.begin())
206      return false;
207    --I;
208  }
209  if (!isUnpredicatedTerminator(I))
210    return false;
211
212  // Get the last instruction in the block.
213  MachineInstr *LastInst = I;
214
215  // If there is only one terminator instruction, process it.
216  if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
217    if (IsBRU(LastInst->getOpcode())) {
218      TBB = LastInst->getOperand(0).getMBB();
219      return false;
220    }
221
222    XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
223    if (BranchCode == XCore::COND_INVALID)
224      return true;  // Can't handle indirect branch.
225
226    // Conditional branch
227    // Block ends with fall-through condbranch.
228
229    TBB = LastInst->getOperand(1).getMBB();
230    Cond.push_back(MachineOperand::CreateImm(BranchCode));
231    Cond.push_back(LastInst->getOperand(0));
232    return false;
233  }
234
235  // Get the instruction before it if it's a terminator.
236  MachineInstr *SecondLastInst = I;
237
238  // If there are three terminators, we don't know what sort of block this is.
239  if (SecondLastInst && I != MBB.begin() &&
240      isUnpredicatedTerminator(--I))
241    return true;
242
243  unsigned SecondLastOpc    = SecondLastInst->getOpcode();
244  XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
245
246  // If the block ends with conditional branch followed by unconditional,
247  // handle it.
248  if (BranchCode != XCore::COND_INVALID
249    && IsBRU(LastInst->getOpcode())) {
250
251    TBB = SecondLastInst->getOperand(1).getMBB();
252    Cond.push_back(MachineOperand::CreateImm(BranchCode));
253    Cond.push_back(SecondLastInst->getOperand(0));
254
255    FBB = LastInst->getOperand(0).getMBB();
256    return false;
257  }
258
259  // If the block ends with two unconditional branches, handle it.  The second
260  // one is not executed, so remove it.
261  if (IsBRU(SecondLastInst->getOpcode()) &&
262      IsBRU(LastInst->getOpcode())) {
263    TBB = SecondLastInst->getOperand(0).getMBB();
264    I = LastInst;
265    if (AllowModify)
266      I->eraseFromParent();
267    return false;
268  }
269
270  // Likewise if it ends with a branch table followed by an unconditional branch.
271  if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
272    I = LastInst;
273    if (AllowModify)
274      I->eraseFromParent();
275    return true;
276  }
277
278  // Otherwise, can't handle this.
279  return true;
280}
281
282unsigned
283XCoreInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
284                             MachineBasicBlock *FBB,
285                             const SmallVectorImpl<MachineOperand> &Cond,
286                             DebugLoc DL)const{
287  // Shouldn't be a fall through.
288  assert(TBB && "InsertBranch must not be told to insert a fallthrough");
289  assert((Cond.size() == 2 || Cond.size() == 0) &&
290         "Unexpected number of components!");
291
292  if (FBB == 0) { // One way branch.
293    if (Cond.empty()) {
294      // Unconditional branch
295      BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
296    } else {
297      // Conditional branch.
298      unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
299      BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
300                             .addMBB(TBB);
301    }
302    return 1;
303  }
304
305  // Two-way Conditional branch.
306  assert(Cond.size() == 2 && "Unexpected number of components!");
307  unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
308  BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
309                         .addMBB(TBB);
310  BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
311  return 2;
312}
313
314unsigned
315XCoreInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
316  MachineBasicBlock::iterator I = MBB.end();
317  if (I == MBB.begin()) return 0;
318  --I;
319  while (I->isDebugValue()) {
320    if (I == MBB.begin())
321      return 0;
322    --I;
323  }
324  if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
325    return 0;
326
327  // Remove the branch.
328  I->eraseFromParent();
329
330  I = MBB.end();
331
332  if (I == MBB.begin()) return 1;
333  --I;
334  if (!IsCondBranch(I->getOpcode()))
335    return 1;
336
337  // Remove the branch.
338  I->eraseFromParent();
339  return 2;
340}
341
342void XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
343                                 MachineBasicBlock::iterator I, DebugLoc DL,
344                                 unsigned DestReg, unsigned SrcReg,
345                                 bool KillSrc) const {
346  bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
347  bool GRSrc  = XCore::GRRegsRegClass.contains(SrcReg);
348
349  if (GRDest && GRSrc) {
350    BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
351      .addReg(SrcReg, getKillRegState(KillSrc))
352      .addImm(0);
353    return;
354  }
355
356  if (GRDest && SrcReg == XCore::SP) {
357    BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
358    return;
359  }
360
361  if (DestReg == XCore::SP && GRSrc) {
362    BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
363      .addReg(SrcReg, getKillRegState(KillSrc));
364    return;
365  }
366  llvm_unreachable("Impossible reg-to-reg copy");
367}
368
369void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
370                                         MachineBasicBlock::iterator I,
371                                         unsigned SrcReg, bool isKill,
372                                         int FrameIndex,
373                                         const TargetRegisterClass *RC,
374                                         const TargetRegisterInfo *TRI) const
375{
376  DebugLoc DL;
377  if (I != MBB.end()) DL = I->getDebugLoc();
378  MachineFunction *MF = MBB.getParent();
379  const MachineFrameInfo &MFI = *MF->getFrameInfo();
380  MachineMemOperand *MMO =
381    MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIndex),
382                             MachineMemOperand::MOStore,
383                             MFI.getObjectSize(FrameIndex),
384                             MFI.getObjectAlignment(FrameIndex));
385  BuildMI(MBB, I, DL, get(XCore::STWFI))
386    .addReg(SrcReg, getKillRegState(isKill))
387    .addFrameIndex(FrameIndex)
388    .addImm(0)
389    .addMemOperand(MMO);
390}
391
392void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
393                                          MachineBasicBlock::iterator I,
394                                          unsigned DestReg, int FrameIndex,
395                                          const TargetRegisterClass *RC,
396                                          const TargetRegisterInfo *TRI) const
397{
398  DebugLoc DL;
399  if (I != MBB.end()) DL = I->getDebugLoc();
400  MachineFunction *MF = MBB.getParent();
401  const MachineFrameInfo &MFI = *MF->getFrameInfo();
402  MachineMemOperand *MMO =
403    MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIndex),
404                             MachineMemOperand::MOLoad,
405                             MFI.getObjectSize(FrameIndex),
406                             MFI.getObjectAlignment(FrameIndex));
407  BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
408    .addFrameIndex(FrameIndex)
409    .addImm(0)
410    .addMemOperand(MMO);
411}
412
413/// ReverseBranchCondition - Return the inverse opcode of the
414/// specified Branch instruction.
415bool XCoreInstrInfo::
416ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
417  assert((Cond.size() == 2) &&
418          "Invalid XCore branch condition!");
419  Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
420  return false;
421}
422
423static inline bool isImmU6(unsigned val) {
424  return val < (1 << 6);
425}
426
427static inline bool isImmU16(unsigned val) {
428  return val < (1 << 16);
429}
430
431MachineBasicBlock::iterator XCoreInstrInfo::loadImmediate(
432                                              MachineBasicBlock &MBB,
433                                              MachineBasicBlock::iterator MI,
434                                              unsigned Reg, uint64_t Value) const {
435  DebugLoc dl;
436  if (MI != MBB.end()) dl = MI->getDebugLoc();
437  if (isMask_32(Value)) {
438    int N = Log2_32(Value) + 1;
439    return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg).addImm(N);
440  }
441  if (isImmU16(Value)) {
442    int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
443    return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value);
444  }
445  MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool();
446  const Constant *C = ConstantInt::get(
447        Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Value);
448  unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
449  return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg)
450            .addConstantPoolIndex(Idx);
451}
452