LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
XCoreInstrInfo.cpp
Go to the documentation of this file.
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"
17 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/Support/Debug.h"
24 
25 #define GET_INSTRINFO_CTOR_DTOR
26 #include "XCoreGenInstrInfo.inc"
27 
28 namespace llvm {
29 namespace XCore {
30 
31  // XCore Condition Codes
32  enum CondCode {
36  };
37 }
38 }
39 
40 using namespace llvm;
41 
42 
43 // Pin the vtable to this file.
44 void XCoreInstrInfo::anchor() {}
45 
47  : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
48  RI() {
49 }
50 
51 static bool isZeroImm(const MachineOperand &op) {
52  return op.isImm() && op.getImm() == 0;
53 }
54 
55 /// isLoadFromStackSlot - If the specified machine instruction is a direct
56 /// load from a stack slot, return the virtual or physical register number of
57 /// the destination along with the FrameIndex of the loaded stack slot. If
58 /// not, return 0. This predicate must return 0 if the instruction has
59 /// any side effects other than loading from the stack slot.
60 unsigned
62  int Opcode = MI->getOpcode();
63  if (Opcode == XCore::LDWFI)
64  {
65  if ((MI->getOperand(1).isFI()) && // is a stack slot
66  (MI->getOperand(2).isImm()) && // the imm is zero
67  (isZeroImm(MI->getOperand(2))))
68  {
69  FrameIndex = MI->getOperand(1).getIndex();
70  return MI->getOperand(0).getReg();
71  }
72  }
73  return 0;
74 }
75 
76  /// isStoreToStackSlot - If the specified machine instruction is a direct
77  /// store to a stack slot, return the virtual or physical register number of
78  /// the source reg along with the FrameIndex of the loaded stack slot. If
79  /// not, return 0. This predicate must return 0 if the instruction has
80  /// any side effects other than storing to the stack slot.
81 unsigned
83  int &FrameIndex) const {
84  int Opcode = MI->getOpcode();
85  if (Opcode == XCore::STWFI)
86  {
87  if ((MI->getOperand(1).isFI()) && // is a stack slot
88  (MI->getOperand(2).isImm()) && // the imm is zero
89  (isZeroImm(MI->getOperand(2))))
90  {
91  FrameIndex = MI->getOperand(1).getIndex();
92  return MI->getOperand(0).getReg();
93  }
94  }
95  return 0;
96 }
97 
98 //===----------------------------------------------------------------------===//
99 // Branch Analysis
100 //===----------------------------------------------------------------------===//
101 
102 static inline bool IsBRU(unsigned BrOpc) {
103  return BrOpc == XCore::BRFU_u6
104  || BrOpc == XCore::BRFU_lu6
105  || BrOpc == XCore::BRBU_u6
106  || BrOpc == XCore::BRBU_lu6;
107 }
108 
109 static inline bool IsBRT(unsigned BrOpc) {
110  return BrOpc == XCore::BRFT_ru6
111  || BrOpc == XCore::BRFT_lru6
112  || BrOpc == XCore::BRBT_ru6
113  || BrOpc == XCore::BRBT_lru6;
114 }
115 
116 static inline bool IsBRF(unsigned BrOpc) {
117  return BrOpc == XCore::BRFF_ru6
118  || BrOpc == XCore::BRFF_lru6
119  || BrOpc == XCore::BRBF_ru6
120  || BrOpc == XCore::BRBF_lru6;
121 }
122 
123 static inline bool IsCondBranch(unsigned BrOpc) {
124  return IsBRF(BrOpc) || IsBRT(BrOpc);
125 }
126 
127 static inline bool IsBR_JT(unsigned BrOpc) {
128  return BrOpc == XCore::BR_JT
129  || BrOpc == XCore::BR_JT32;
130 }
131 
132 /// GetCondFromBranchOpc - Return the XCore CC that matches
133 /// the correspondent Branch instruction opcode.
134 static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
135 {
136  if (IsBRT(BrOpc)) {
137  return XCore::COND_TRUE;
138  } else if (IsBRF(BrOpc)) {
139  return XCore::COND_FALSE;
140  } else {
141  return XCore::COND_INVALID;
142  }
143 }
144 
145 /// GetCondBranchFromCond - Return the Branch instruction
146 /// opcode that matches the cc.
147 static inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
148 {
149  switch (CC) {
150  default: llvm_unreachable("Illegal condition code!");
151  case XCore::COND_TRUE : return XCore::BRFT_lru6;
152  case XCore::COND_FALSE : return XCore::BRFF_lru6;
153  }
154 }
155 
156 /// GetOppositeBranchCondition - Return the inverse of the specified
157 /// condition, e.g. turning COND_E to COND_NE.
159 {
160  switch (CC) {
161  default: llvm_unreachable("Illegal condition code!");
162  case XCore::COND_TRUE : return XCore::COND_FALSE;
163  case XCore::COND_FALSE : return XCore::COND_TRUE;
164  }
165 }
166 
167 /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
168 /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
169 /// implemented for a target). Upon success, this returns false and returns
170 /// with the following information in various cases:
171 ///
172 /// 1. If this block ends with no branches (it just falls through to its succ)
173 /// just return false, leaving TBB/FBB null.
174 /// 2. If this block ends with only an unconditional branch, it sets TBB to be
175 /// the destination block.
176 /// 3. If this block ends with an conditional branch and it falls through to
177 /// an successor block, it sets TBB to be the branch destination block and a
178 /// list of operands that evaluate the condition. These
179 /// operands can be passed to other TargetInstrInfo methods to create new
180 /// branches.
181 /// 4. If this block ends with an conditional branch and an unconditional
182 /// block, it returns the 'true' destination in TBB, the 'false' destination
183 /// in FBB, and a list of operands that evaluate the condition. These
184 /// operands can be passed to other TargetInstrInfo methods to create new
185 /// branches.
186 ///
187 /// Note that RemoveBranch and InsertBranch must be implemented to support
188 /// cases where this method returns success.
189 ///
190 bool
192  MachineBasicBlock *&FBB,
194  bool AllowModify) const {
195  // If the block has no terminators, it just falls into the block after it.
197  if (I == MBB.begin())
198  return false;
199  --I;
200  while (I->isDebugValue()) {
201  if (I == MBB.begin())
202  return false;
203  --I;
204  }
205  if (!isUnpredicatedTerminator(I))
206  return false;
207 
208  // Get the last instruction in the block.
209  MachineInstr *LastInst = I;
210 
211  // If there is only one terminator instruction, process it.
212  if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
213  if (IsBRU(LastInst->getOpcode())) {
214  TBB = LastInst->getOperand(0).getMBB();
215  return false;
216  }
217 
218  XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
219  if (BranchCode == XCore::COND_INVALID)
220  return true; // Can't handle indirect branch.
221 
222  // Conditional branch
223  // Block ends with fall-through condbranch.
224 
225  TBB = LastInst->getOperand(1).getMBB();
226  Cond.push_back(MachineOperand::CreateImm(BranchCode));
227  Cond.push_back(LastInst->getOperand(0));
228  return false;
229  }
230 
231  // Get the instruction before it if it's a terminator.
232  MachineInstr *SecondLastInst = I;
233 
234  // If there are three terminators, we don't know what sort of block this is.
235  if (SecondLastInst && I != MBB.begin() &&
236  isUnpredicatedTerminator(--I))
237  return true;
238 
239  unsigned SecondLastOpc = SecondLastInst->getOpcode();
240  XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
241 
242  // If the block ends with conditional branch followed by unconditional,
243  // handle it.
244  if (BranchCode != XCore::COND_INVALID
245  && IsBRU(LastInst->getOpcode())) {
246 
247  TBB = SecondLastInst->getOperand(1).getMBB();
248  Cond.push_back(MachineOperand::CreateImm(BranchCode));
249  Cond.push_back(SecondLastInst->getOperand(0));
250 
251  FBB = LastInst->getOperand(0).getMBB();
252  return false;
253  }
254 
255  // If the block ends with two unconditional branches, handle it. The second
256  // one is not executed, so remove it.
257  if (IsBRU(SecondLastInst->getOpcode()) &&
258  IsBRU(LastInst->getOpcode())) {
259  TBB = SecondLastInst->getOperand(0).getMBB();
260  I = LastInst;
261  if (AllowModify)
262  I->eraseFromParent();
263  return false;
264  }
265 
266  // Likewise if it ends with a branch table followed by an unconditional branch.
267  if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
268  I = LastInst;
269  if (AllowModify)
270  I->eraseFromParent();
271  return true;
272  }
273 
274  // Otherwise, can't handle this.
275  return true;
276 }
277 
278 unsigned
280  MachineBasicBlock *FBB,
282  DebugLoc DL)const{
283  // Shouldn't be a fall through.
284  assert(TBB && "InsertBranch must not be told to insert a fallthrough");
285  assert((Cond.size() == 2 || Cond.size() == 0) &&
286  "Unexpected number of components!");
287 
288  if (FBB == 0) { // One way branch.
289  if (Cond.empty()) {
290  // Unconditional branch
291  BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
292  } else {
293  // Conditional branch.
294  unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
295  BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
296  .addMBB(TBB);
297  }
298  return 1;
299  }
300 
301  // Two-way Conditional branch.
302  assert(Cond.size() == 2 && "Unexpected number of components!");
303  unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
304  BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
305  .addMBB(TBB);
306  BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
307  return 2;
308 }
309 
310 unsigned
313  if (I == MBB.begin()) return 0;
314  --I;
315  while (I->isDebugValue()) {
316  if (I == MBB.begin())
317  return 0;
318  --I;
319  }
320  if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
321  return 0;
322 
323  // Remove the branch.
324  I->eraseFromParent();
325 
326  I = MBB.end();
327 
328  if (I == MBB.begin()) return 1;
329  --I;
330  if (!IsCondBranch(I->getOpcode()))
331  return 1;
332 
333  // Remove the branch.
334  I->eraseFromParent();
335  return 2;
336 }
337 
340  unsigned DestReg, unsigned SrcReg,
341  bool KillSrc) const {
342  bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
343  bool GRSrc = XCore::GRRegsRegClass.contains(SrcReg);
344 
345  if (GRDest && GRSrc) {
346  BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
347  .addReg(SrcReg, getKillRegState(KillSrc))
348  .addImm(0);
349  return;
350  }
351 
352  if (GRDest && SrcReg == XCore::SP) {
353  BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
354  return;
355  }
356 
357  if (DestReg == XCore::SP && GRSrc) {
358  BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
359  .addReg(SrcReg, getKillRegState(KillSrc));
360  return;
361  }
362  llvm_unreachable("Impossible reg-to-reg copy");
363 }
364 
367  unsigned SrcReg, bool isKill,
368  int FrameIndex,
369  const TargetRegisterClass *RC,
370  const TargetRegisterInfo *TRI) const
371 {
372  DebugLoc DL;
373  if (I != MBB.end()) DL = I->getDebugLoc();
374  BuildMI(MBB, I, DL, get(XCore::STWFI))
375  .addReg(SrcReg, getKillRegState(isKill))
376  .addFrameIndex(FrameIndex)
377  .addImm(0);
378 }
379 
382  unsigned DestReg, int FrameIndex,
383  const TargetRegisterClass *RC,
384  const TargetRegisterInfo *TRI) const
385 {
386  DebugLoc DL;
387  if (I != MBB.end()) DL = I->getDebugLoc();
388  BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
389  .addFrameIndex(FrameIndex)
390  .addImm(0);
391 }
392 
393 /// ReverseBranchCondition - Return the inverse opcode of the
394 /// specified Branch instruction.
395 bool XCoreInstrInfo::
397  assert((Cond.size() == 2) &&
398  "Invalid XCore branch condition!");
399  Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
400  return false;
401 }
static bool IsBRT(unsigned BrOpc)
MachineBasicBlock * getMBB() const
static XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
static bool IsBRF(unsigned BrOpc)
const MachineInstrBuilder & addImm(int64_t Val) const
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
Definition: SmallVector.h:56
int getOpcode() const
Definition: MachineInstr.h:261
int64_t getImm() const
static bool IsBRU(unsigned BrOpc)
unsigned getKillRegState(bool B)
bundle_iterator< MachineInstr, instr_iterator > iterator
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:267
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
static unsigned GetCondBranchFromCond(XCore::CondCode CC)
virtual bool ReverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
virtual void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const
static bool IsCondBranch(unsigned BrOpc)
virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const
static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl< MachineOperand > &Cond, DebugLoc DL) const
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static MachineOperand CreateImm(int64_t Val)
#define I(x, y, z)
Definition: MD5.cpp:54
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
unsigned getReg() const
getReg - Returns the register number.
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const
virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
virtual unsigned isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
static bool IsBR_JT(unsigned BrOpc)
static bool isZeroImm(const MachineOperand &op)