1235633Sdim//===-- XCoreInstrInfo.cpp - XCore Instruction Information ----------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file contains the XCore implementation of the TargetInstrInfo class.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14235633Sdim#include "XCoreInstrInfo.h"
15252723Sdim#include "XCore.h"
16193323Sed#include "XCoreMachineFunctionInfo.h"
17252723Sdim#include "llvm/ADT/STLExtras.h"
18252723Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
19252723Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
20206274Srdivacky#include "llvm/MC/MCContext.h"
21193323Sed#include "llvm/Support/Debug.h"
22198090Srdivacky#include "llvm/Support/ErrorHandling.h"
23226890Sdim#include "llvm/Support/TargetRegistry.h"
24193323Sed
25263509Sdim#define GET_INSTRINFO_CTOR_DTOR
26224145Sdim#include "XCoreGenInstrInfo.inc"
27224145Sdim
28193323Sednamespace llvm {
29193323Sednamespace XCore {
30193323Sed
31193323Sed  // XCore Condition Codes
32193323Sed  enum CondCode {
33193323Sed    COND_TRUE,
34193323Sed    COND_FALSE,
35193323Sed    COND_INVALID
36193323Sed  };
37193323Sed}
38193323Sed}
39193323Sed
40193323Sedusing namespace llvm;
41193323Sed
42263509Sdim
43263509Sdim// Pin the vtable to this file.
44263509Sdimvoid XCoreInstrInfo::anchor() {}
45263509Sdim
46198090SrdivackyXCoreInstrInfo::XCoreInstrInfo()
47224145Sdim  : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
48263509Sdim    RI() {
49193323Sed}
50193323Sed
51193323Sedstatic bool isZeroImm(const MachineOperand &op) {
52193323Sed  return op.isImm() && op.getImm() == 0;
53193323Sed}
54193323Sed
55193323Sed/// isLoadFromStackSlot - If the specified machine instruction is a direct
56193323Sed/// load from a stack slot, return the virtual or physical register number of
57193323Sed/// the destination along with the FrameIndex of the loaded stack slot.  If
58193323Sed/// not, return 0.  This predicate must return 0 if the instruction has
59193323Sed/// any side effects other than loading from the stack slot.
60193323Sedunsigned
61193323SedXCoreInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const{
62193323Sed  int Opcode = MI->getOpcode();
63193323Sed  if (Opcode == XCore::LDWFI)
64193323Sed  {
65193323Sed    if ((MI->getOperand(1).isFI()) && // is a stack slot
66193323Sed        (MI->getOperand(2).isImm()) &&  // the imm is zero
67193323Sed        (isZeroImm(MI->getOperand(2))))
68193323Sed    {
69193323Sed      FrameIndex = MI->getOperand(1).getIndex();
70193323Sed      return MI->getOperand(0).getReg();
71193323Sed    }
72193323Sed  }
73193323Sed  return 0;
74193323Sed}
75193323Sed
76193323Sed  /// isStoreToStackSlot - If the specified machine instruction is a direct
77193323Sed  /// store to a stack slot, return the virtual or physical register number of
78193323Sed  /// the source reg along with the FrameIndex of the loaded stack slot.  If
79193323Sed  /// not, return 0.  This predicate must return 0 if the instruction has
80193323Sed  /// any side effects other than storing to the stack slot.
81193323Sedunsigned
82193323SedXCoreInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
83193323Sed                                   int &FrameIndex) const {
84193323Sed  int Opcode = MI->getOpcode();
85193323Sed  if (Opcode == XCore::STWFI)
86193323Sed  {
87193323Sed    if ((MI->getOperand(1).isFI()) && // is a stack slot
88193323Sed        (MI->getOperand(2).isImm()) &&  // the imm is zero
89193323Sed        (isZeroImm(MI->getOperand(2))))
90193323Sed    {
91193323Sed      FrameIndex = MI->getOperand(1).getIndex();
92193323Sed      return MI->getOperand(0).getReg();
93193323Sed    }
94193323Sed  }
95193323Sed  return 0;
96193323Sed}
97193323Sed
98193323Sed//===----------------------------------------------------------------------===//
99193323Sed// Branch Analysis
100193323Sed//===----------------------------------------------------------------------===//
101193323Sed
102193323Sedstatic inline bool IsBRU(unsigned BrOpc) {
103193323Sed  return BrOpc == XCore::BRFU_u6
104193323Sed      || BrOpc == XCore::BRFU_lu6
105193323Sed      || BrOpc == XCore::BRBU_u6
106193323Sed      || BrOpc == XCore::BRBU_lu6;
107193323Sed}
108193323Sed
109193323Sedstatic inline bool IsBRT(unsigned BrOpc) {
110193323Sed  return BrOpc == XCore::BRFT_ru6
111193323Sed      || BrOpc == XCore::BRFT_lru6
112193323Sed      || BrOpc == XCore::BRBT_ru6
113193323Sed      || BrOpc == XCore::BRBT_lru6;
114193323Sed}
115193323Sed
116193323Sedstatic inline bool IsBRF(unsigned BrOpc) {
117193323Sed  return BrOpc == XCore::BRFF_ru6
118193323Sed      || BrOpc == XCore::BRFF_lru6
119193323Sed      || BrOpc == XCore::BRBF_ru6
120193323Sed      || BrOpc == XCore::BRBF_lru6;
121193323Sed}
122193323Sed
123193323Sedstatic inline bool IsCondBranch(unsigned BrOpc) {
124193323Sed  return IsBRF(BrOpc) || IsBRT(BrOpc);
125193323Sed}
126193323Sed
127204642Srdivackystatic inline bool IsBR_JT(unsigned BrOpc) {
128204642Srdivacky  return BrOpc == XCore::BR_JT
129204642Srdivacky      || BrOpc == XCore::BR_JT32;
130204642Srdivacky}
131204642Srdivacky
132193323Sed/// GetCondFromBranchOpc - Return the XCore CC that matches
133193323Sed/// the correspondent Branch instruction opcode.
134193323Sedstatic XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
135193323Sed{
136193323Sed  if (IsBRT(BrOpc)) {
137193323Sed    return XCore::COND_TRUE;
138193323Sed  } else if (IsBRF(BrOpc)) {
139193323Sed    return XCore::COND_FALSE;
140193323Sed  } else {
141193323Sed    return XCore::COND_INVALID;
142193323Sed  }
143193323Sed}
144193323Sed
145193323Sed/// GetCondBranchFromCond - Return the Branch instruction
146193323Sed/// opcode that matches the cc.
147193323Sedstatic inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
148193323Sed{
149193323Sed  switch (CC) {
150198090Srdivacky  default: llvm_unreachable("Illegal condition code!");
151193323Sed  case XCore::COND_TRUE   : return XCore::BRFT_lru6;
152193323Sed  case XCore::COND_FALSE  : return XCore::BRFF_lru6;
153193323Sed  }
154193323Sed}
155193323Sed
156193323Sed/// GetOppositeBranchCondition - Return the inverse of the specified
157193323Sed/// condition, e.g. turning COND_E to COND_NE.
158193323Sedstatic inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
159193323Sed{
160193323Sed  switch (CC) {
161198090Srdivacky  default: llvm_unreachable("Illegal condition code!");
162193323Sed  case XCore::COND_TRUE   : return XCore::COND_FALSE;
163193323Sed  case XCore::COND_FALSE  : return XCore::COND_TRUE;
164193323Sed  }
165193323Sed}
166193323Sed
167193323Sed/// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
168193323Sed/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
169193323Sed/// implemented for a target).  Upon success, this returns false and returns
170193323Sed/// with the following information in various cases:
171193323Sed///
172193323Sed/// 1. If this block ends with no branches (it just falls through to its succ)
173193323Sed///    just return false, leaving TBB/FBB null.
174193323Sed/// 2. If this block ends with only an unconditional branch, it sets TBB to be
175193323Sed///    the destination block.
176193323Sed/// 3. If this block ends with an conditional branch and it falls through to
177193323Sed///    an successor block, it sets TBB to be the branch destination block and a
178193323Sed///    list of operands that evaluate the condition. These
179193323Sed///    operands can be passed to other TargetInstrInfo methods to create new
180193323Sed///    branches.
181193323Sed/// 4. If this block ends with an conditional branch and an unconditional
182193323Sed///    block, it returns the 'true' destination in TBB, the 'false' destination
183193323Sed///    in FBB, and a list of operands that evaluate the condition. These
184193323Sed///    operands can be passed to other TargetInstrInfo methods to create new
185193323Sed///    branches.
186193323Sed///
187193323Sed/// Note that RemoveBranch and InsertBranch must be implemented to support
188193323Sed/// cases where this method returns success.
189193323Sed///
190193323Sedbool
191193323SedXCoreInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
192193323Sed                              MachineBasicBlock *&FBB,
193193323Sed                              SmallVectorImpl<MachineOperand> &Cond,
194193323Sed                              bool AllowModify) const {
195193323Sed  // If the block has no terminators, it just falls into the block after it.
196193323Sed  MachineBasicBlock::iterator I = MBB.end();
197206083Srdivacky  if (I == MBB.begin())
198193323Sed    return false;
199206083Srdivacky  --I;
200206083Srdivacky  while (I->isDebugValue()) {
201206083Srdivacky    if (I == MBB.begin())
202206083Srdivacky      return false;
203206083Srdivacky    --I;
204206083Srdivacky  }
205206083Srdivacky  if (!isUnpredicatedTerminator(I))
206206083Srdivacky    return false;
207193323Sed
208193323Sed  // Get the last instruction in the block.
209193323Sed  MachineInstr *LastInst = I;
210193323Sed
211193323Sed  // If there is only one terminator instruction, process it.
212193323Sed  if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
213193323Sed    if (IsBRU(LastInst->getOpcode())) {
214193323Sed      TBB = LastInst->getOperand(0).getMBB();
215193323Sed      return false;
216193323Sed    }
217193323Sed
218193323Sed    XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
219193323Sed    if (BranchCode == XCore::COND_INVALID)
220193323Sed      return true;  // Can't handle indirect branch.
221193323Sed
222193323Sed    // Conditional branch
223193323Sed    // Block ends with fall-through condbranch.
224193323Sed
225193323Sed    TBB = LastInst->getOperand(1).getMBB();
226193323Sed    Cond.push_back(MachineOperand::CreateImm(BranchCode));
227193323Sed    Cond.push_back(LastInst->getOperand(0));
228193323Sed    return false;
229193323Sed  }
230193323Sed
231193323Sed  // Get the instruction before it if it's a terminator.
232193323Sed  MachineInstr *SecondLastInst = I;
233193323Sed
234193323Sed  // If there are three terminators, we don't know what sort of block this is.
235193323Sed  if (SecondLastInst && I != MBB.begin() &&
236193323Sed      isUnpredicatedTerminator(--I))
237193323Sed    return true;
238193323Sed
239193323Sed  unsigned SecondLastOpc    = SecondLastInst->getOpcode();
240193323Sed  XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
241193323Sed
242193323Sed  // If the block ends with conditional branch followed by unconditional,
243193323Sed  // handle it.
244193323Sed  if (BranchCode != XCore::COND_INVALID
245193323Sed    && IsBRU(LastInst->getOpcode())) {
246193323Sed
247193323Sed    TBB = SecondLastInst->getOperand(1).getMBB();
248193323Sed    Cond.push_back(MachineOperand::CreateImm(BranchCode));
249193323Sed    Cond.push_back(SecondLastInst->getOperand(0));
250193323Sed
251193323Sed    FBB = LastInst->getOperand(0).getMBB();
252193323Sed    return false;
253193323Sed  }
254193323Sed
255193323Sed  // If the block ends with two unconditional branches, handle it.  The second
256193323Sed  // one is not executed, so remove it.
257193323Sed  if (IsBRU(SecondLastInst->getOpcode()) &&
258193323Sed      IsBRU(LastInst->getOpcode())) {
259193323Sed    TBB = SecondLastInst->getOperand(0).getMBB();
260193323Sed    I = LastInst;
261193323Sed    if (AllowModify)
262193323Sed      I->eraseFromParent();
263193323Sed    return false;
264193323Sed  }
265193323Sed
266204642Srdivacky  // Likewise if it ends with a branch table followed by an unconditional branch.
267204642Srdivacky  if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
268204642Srdivacky    I = LastInst;
269204642Srdivacky    if (AllowModify)
270204642Srdivacky      I->eraseFromParent();
271204642Srdivacky    return true;
272204642Srdivacky  }
273204642Srdivacky
274193323Sed  // Otherwise, can't handle this.
275193323Sed  return true;
276193323Sed}
277193323Sed
278193323Sedunsigned
279193323SedXCoreInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
280193323Sed                             MachineBasicBlock *FBB,
281210299Sed                             const SmallVectorImpl<MachineOperand> &Cond,
282210299Sed                             DebugLoc DL)const{
283193323Sed  // Shouldn't be a fall through.
284193323Sed  assert(TBB && "InsertBranch must not be told to insert a fallthrough");
285193323Sed  assert((Cond.size() == 2 || Cond.size() == 0) &&
286193323Sed         "Unexpected number of components!");
287193323Sed
288193323Sed  if (FBB == 0) { // One way branch.
289193323Sed    if (Cond.empty()) {
290193323Sed      // Unconditional branch
291210299Sed      BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
292193323Sed    } else {
293193323Sed      // Conditional branch.
294193323Sed      unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
295210299Sed      BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
296193323Sed                             .addMBB(TBB);
297193323Sed    }
298193323Sed    return 1;
299193323Sed  }
300193323Sed
301193323Sed  // Two-way Conditional branch.
302193323Sed  assert(Cond.size() == 2 && "Unexpected number of components!");
303193323Sed  unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
304210299Sed  BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
305193323Sed                         .addMBB(TBB);
306210299Sed  BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
307193323Sed  return 2;
308193323Sed}
309193323Sed
310193323Sedunsigned
311193323SedXCoreInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
312193323Sed  MachineBasicBlock::iterator I = MBB.end();
313193323Sed  if (I == MBB.begin()) return 0;
314193323Sed  --I;
315206083Srdivacky  while (I->isDebugValue()) {
316206083Srdivacky    if (I == MBB.begin())
317206083Srdivacky      return 0;
318206083Srdivacky    --I;
319206083Srdivacky  }
320193323Sed  if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
321193323Sed    return 0;
322193323Sed
323193323Sed  // Remove the branch.
324193323Sed  I->eraseFromParent();
325193323Sed
326193323Sed  I = MBB.end();
327193323Sed
328193323Sed  if (I == MBB.begin()) return 1;
329193323Sed  --I;
330193323Sed  if (!IsCondBranch(I->getOpcode()))
331193323Sed    return 1;
332193323Sed
333193323Sed  // Remove the branch.
334193323Sed  I->eraseFromParent();
335193323Sed  return 2;
336193323Sed}
337193323Sed
338210299Sedvoid XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
339210299Sed                                 MachineBasicBlock::iterator I, DebugLoc DL,
340210299Sed                                 unsigned DestReg, unsigned SrcReg,
341210299Sed                                 bool KillSrc) const {
342210299Sed  bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
343210299Sed  bool GRSrc  = XCore::GRRegsRegClass.contains(SrcReg);
344193323Sed
345210299Sed  if (GRDest && GRSrc) {
346210299Sed    BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
347210299Sed      .addReg(SrcReg, getKillRegState(KillSrc))
348210299Sed      .addImm(0);
349210299Sed    return;
350193323Sed  }
351193323Sed
352210299Sed  if (GRDest && SrcReg == XCore::SP) {
353210299Sed    BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
354210299Sed    return;
355193323Sed  }
356210299Sed
357210299Sed  if (DestReg == XCore::SP && GRSrc) {
358193323Sed    BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
359210299Sed      .addReg(SrcReg, getKillRegState(KillSrc));
360210299Sed    return;
361193323Sed  }
362210299Sed  llvm_unreachable("Impossible reg-to-reg copy");
363193323Sed}
364193323Sed
365193323Sedvoid XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
366193323Sed                                         MachineBasicBlock::iterator I,
367193323Sed                                         unsigned SrcReg, bool isKill,
368193323Sed                                         int FrameIndex,
369208599Srdivacky                                         const TargetRegisterClass *RC,
370208599Srdivacky                                         const TargetRegisterInfo *TRI) const
371193323Sed{
372206124Srdivacky  DebugLoc DL;
373193323Sed  if (I != MBB.end()) DL = I->getDebugLoc();
374193323Sed  BuildMI(MBB, I, DL, get(XCore::STWFI))
375193323Sed    .addReg(SrcReg, getKillRegState(isKill))
376193323Sed    .addFrameIndex(FrameIndex)
377193323Sed    .addImm(0);
378193323Sed}
379193323Sed
380193323Sedvoid XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
381193323Sed                                          MachineBasicBlock::iterator I,
382193323Sed                                          unsigned DestReg, int FrameIndex,
383208599Srdivacky                                          const TargetRegisterClass *RC,
384208599Srdivacky                                          const TargetRegisterInfo *TRI) const
385193323Sed{
386206124Srdivacky  DebugLoc DL;
387193323Sed  if (I != MBB.end()) DL = I->getDebugLoc();
388193323Sed  BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
389193323Sed    .addFrameIndex(FrameIndex)
390193323Sed    .addImm(0);
391193323Sed}
392193323Sed
393193323Sed/// ReverseBranchCondition - Return the inverse opcode of the
394193323Sed/// specified Branch instruction.
395193323Sedbool XCoreInstrInfo::
396218893SdimReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
397193323Sed  assert((Cond.size() == 2) &&
398193323Sed          "Invalid XCore branch condition!");
399193323Sed  Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
400193323Sed  return false;
401193323Sed}
402