LLVM  10.0.0svn
XCoreInstrInfo.cpp
Go to the documentation of this file.
1 //===-- XCoreInstrInfo.cpp - XCore Instruction Information ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the XCore implementation of the TargetInstrInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "XCoreInstrInfo.h"
14 #include "XCore.h"
16 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/Support/Debug.h"
27 
28 using namespace llvm;
29 
30 #define GET_INSTRINFO_CTOR_DTOR
31 #include "XCoreGenInstrInfo.inc"
32 
33 namespace llvm {
34 namespace XCore {
35 
36  // XCore Condition Codes
37  enum CondCode {
41  };
42 }
43 }
44 
45 // Pin the vtable to this file.
46 void XCoreInstrInfo::anchor() {}
47 
49  : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
50  RI() {
51 }
52 
53 static bool isZeroImm(const MachineOperand &op) {
54  return op.isImm() && op.getImm() == 0;
55 }
56 
57 /// isLoadFromStackSlot - If the specified machine instruction is a direct
58 /// load from a stack slot, return the virtual or physical register number of
59 /// the destination along with the FrameIndex of the loaded stack slot. If
60 /// not, return 0. This predicate must return 0 if the instruction has
61 /// any side effects other than loading from the stack slot.
63  int &FrameIndex) const {
64  int Opcode = MI.getOpcode();
65  if (Opcode == XCore::LDWFI)
66  {
67  if ((MI.getOperand(1).isFI()) && // is a stack slot
68  (MI.getOperand(2).isImm()) && // the imm is zero
69  (isZeroImm(MI.getOperand(2)))) {
70  FrameIndex = MI.getOperand(1).getIndex();
71  return MI.getOperand(0).getReg();
72  }
73  }
74  return 0;
75 }
76 
77  /// isStoreToStackSlot - If the specified machine instruction is a direct
78  /// store to a stack slot, return the virtual or physical register number of
79  /// the source reg along with the FrameIndex of the loaded stack slot. If
80  /// not, return 0. This predicate must return 0 if the instruction has
81  /// any side effects other than storing to the stack slot.
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  FrameIndex = MI.getOperand(1).getIndex();
91  return MI.getOperand(0).getReg();
92  }
93  }
94  return 0;
95 }
96 
97 //===----------------------------------------------------------------------===//
98 // Branch Analysis
99 //===----------------------------------------------------------------------===//
100 
101 static inline bool IsBRU(unsigned BrOpc) {
102  return BrOpc == XCore::BRFU_u6
103  || BrOpc == XCore::BRFU_lu6
104  || BrOpc == XCore::BRBU_u6
105  || BrOpc == XCore::BRBU_lu6;
106 }
107 
108 static inline bool IsBRT(unsigned BrOpc) {
109  return BrOpc == XCore::BRFT_ru6
110  || BrOpc == XCore::BRFT_lru6
111  || BrOpc == XCore::BRBT_ru6
112  || BrOpc == XCore::BRBT_lru6;
113 }
114 
115 static inline bool IsBRF(unsigned BrOpc) {
116  return BrOpc == XCore::BRFF_ru6
117  || BrOpc == XCore::BRFF_lru6
118  || BrOpc == XCore::BRBF_ru6
119  || BrOpc == XCore::BRBF_lru6;
120 }
121 
122 static inline bool IsCondBranch(unsigned BrOpc) {
123  return IsBRF(BrOpc) || IsBRT(BrOpc);
124 }
125 
126 static inline bool IsBR_JT(unsigned BrOpc) {
127  return BrOpc == XCore::BR_JT
128  || BrOpc == XCore::BR_JT32;
129 }
130 
131 /// GetCondFromBranchOpc - Return the XCore CC that matches
132 /// the correspondent Branch instruction opcode.
133 static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
134 {
135  if (IsBRT(BrOpc)) {
136  return XCore::COND_TRUE;
137  } else if (IsBRF(BrOpc)) {
138  return XCore::COND_FALSE;
139  } else {
140  return XCore::COND_INVALID;
141  }
142 }
143 
144 /// GetCondBranchFromCond - Return the Branch instruction
145 /// opcode that matches the cc.
146 static inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
147 {
148  switch (CC) {
149  default: llvm_unreachable("Illegal condition code!");
150  case XCore::COND_TRUE : return XCore::BRFT_lru6;
151  case XCore::COND_FALSE : return XCore::BRFF_lru6;
152  }
153 }
154 
155 /// GetOppositeBranchCondition - Return the inverse of the specified
156 /// condition, e.g. turning COND_E to COND_NE.
158 {
159  switch (CC) {
160  default: llvm_unreachable("Illegal condition code!");
161  case XCore::COND_TRUE : return XCore::COND_FALSE;
162  case XCore::COND_FALSE : return XCore::COND_TRUE;
163  }
164 }
165 
166 /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
167 /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
168 /// implemented for a target). Upon success, this returns false and returns
169 /// with the following information in various cases:
170 ///
171 /// 1. If this block ends with no branches (it just falls through to its succ)
172 /// just return false, leaving TBB/FBB null.
173 /// 2. If this block ends with only an unconditional branch, it sets TBB to be
174 /// the destination block.
175 /// 3. If this block ends with an conditional branch and it falls through to
176 /// an successor block, it sets TBB to be the branch destination block and a
177 /// list of operands that evaluate the condition. These
178 /// operands can be passed to other TargetInstrInfo methods to create new
179 /// branches.
180 /// 4. If this block ends with an conditional branch and an unconditional
181 /// block, it returns the 'true' destination in TBB, the 'false' destination
182 /// in FBB, and a list of operands that evaluate the condition. These
183 /// operands can be passed to other TargetInstrInfo methods to create new
184 /// branches.
185 ///
186 /// Note that removeBranch and insertBranch must be implemented to support
187 /// cases where this method returns success.
188 ///
190  MachineBasicBlock *&TBB,
191  MachineBasicBlock *&FBB,
193  bool AllowModify) const {
194  // If the block has no terminators, it just falls into the block after it.
196  if (I == MBB.end())
197  return false;
198 
199  if (!isUnpredicatedTerminator(*I))
200  return false;
201 
202  // Get the last instruction in the block.
203  MachineInstr *LastInst = &*I;
204 
205  // If there is only one terminator instruction, process it.
206  if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
207  if (IsBRU(LastInst->getOpcode())) {
208  TBB = LastInst->getOperand(0).getMBB();
209  return false;
210  }
211 
212  XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
213  if (BranchCode == XCore::COND_INVALID)
214  return true; // Can't handle indirect branch.
215 
216  // Conditional branch
217  // Block ends with fall-through condbranch.
218 
219  TBB = LastInst->getOperand(1).getMBB();
220  Cond.push_back(MachineOperand::CreateImm(BranchCode));
221  Cond.push_back(LastInst->getOperand(0));
222  return false;
223  }
224 
225  // Get the instruction before it if it's a terminator.
226  MachineInstr *SecondLastInst = &*I;
227 
228  // If there are three terminators, we don't know what sort of block this is.
229  if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
230  return true;
231 
232  unsigned SecondLastOpc = SecondLastInst->getOpcode();
233  XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
234 
235  // If the block ends with conditional branch followed by unconditional,
236  // handle it.
237  if (BranchCode != XCore::COND_INVALID
238  && IsBRU(LastInst->getOpcode())) {
239 
240  TBB = SecondLastInst->getOperand(1).getMBB();
241  Cond.push_back(MachineOperand::CreateImm(BranchCode));
242  Cond.push_back(SecondLastInst->getOperand(0));
243 
244  FBB = LastInst->getOperand(0).getMBB();
245  return false;
246  }
247 
248  // If the block ends with two unconditional branches, handle it. The second
249  // one is not executed, so remove it.
250  if (IsBRU(SecondLastInst->getOpcode()) &&
251  IsBRU(LastInst->getOpcode())) {
252  TBB = SecondLastInst->getOperand(0).getMBB();
253  I = LastInst;
254  if (AllowModify)
255  I->eraseFromParent();
256  return false;
257  }
258 
259  // Likewise if it ends with a branch table followed by an unconditional branch.
260  if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
261  I = LastInst;
262  if (AllowModify)
263  I->eraseFromParent();
264  return true;
265  }
266 
267  // Otherwise, can't handle this.
268  return true;
269 }
270 
272  MachineBasicBlock *TBB,
273  MachineBasicBlock *FBB,
275  const DebugLoc &DL,
276  int *BytesAdded) const {
277  // Shouldn't be a fall through.
278  assert(TBB && "insertBranch must not be told to insert a fallthrough");
279  assert((Cond.size() == 2 || Cond.size() == 0) &&
280  "Unexpected number of components!");
281  assert(!BytesAdded && "code size not handled");
282 
283  if (!FBB) { // One way branch.
284  if (Cond.empty()) {
285  // Unconditional branch
286  BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
287  } else {
288  // Conditional branch.
289  unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
290  BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
291  .addMBB(TBB);
292  }
293  return 1;
294  }
295 
296  // Two-way Conditional branch.
297  assert(Cond.size() == 2 && "Unexpected number of components!");
298  unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
299  BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
300  .addMBB(TBB);
301  BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
302  return 2;
303 }
304 
305 unsigned
306 XCoreInstrInfo::removeBranch(MachineBasicBlock &MBB, int *BytesRemoved) const {
307  assert(!BytesRemoved && "code size not handled");
308 
310  if (I == MBB.end())
311  return 0;
312 
313  if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
314  return 0;
315 
316  // Remove the branch.
317  I->eraseFromParent();
318 
319  I = MBB.end();
320 
321  if (I == MBB.begin()) return 1;
322  --I;
323  if (!IsCondBranch(I->getOpcode()))
324  return 1;
325 
326  // Remove the branch.
327  I->eraseFromParent();
328  return 2;
329 }
330 
333  const DebugLoc &DL, unsigned DestReg,
334  unsigned SrcReg, bool KillSrc) const {
335  bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
336  bool GRSrc = XCore::GRRegsRegClass.contains(SrcReg);
337 
338  if (GRDest && GRSrc) {
339  BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
340  .addReg(SrcReg, getKillRegState(KillSrc))
341  .addImm(0);
342  return;
343  }
344 
345  if (GRDest && SrcReg == XCore::SP) {
346  BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
347  return;
348  }
349 
350  if (DestReg == XCore::SP && GRSrc) {
351  BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
352  .addReg(SrcReg, getKillRegState(KillSrc));
353  return;
354  }
355  llvm_unreachable("Impossible reg-to-reg copy");
356 }
357 
360  unsigned SrcReg, bool isKill,
361  int FrameIndex,
362  const TargetRegisterClass *RC,
363  const TargetRegisterInfo *TRI) const
364 {
365  DebugLoc DL;
366  if (I != MBB.end() && !I->isDebugInstr())
367  DL = I->getDebugLoc();
368  MachineFunction *MF = MBB.getParent();
369  const MachineFrameInfo &MFI = MF->getFrameInfo();
371  MachinePointerInfo::getFixedStack(*MF, FrameIndex),
372  MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
373  MFI.getObjectAlignment(FrameIndex));
374  BuildMI(MBB, I, DL, get(XCore::STWFI))
375  .addReg(SrcReg, getKillRegState(isKill))
376  .addFrameIndex(FrameIndex)
377  .addImm(0)
378  .addMemOperand(MMO);
379 }
380 
383  unsigned DestReg, int FrameIndex,
384  const TargetRegisterClass *RC,
385  const TargetRegisterInfo *TRI) const
386 {
387  DebugLoc DL;
388  if (I != MBB.end() && !I->isDebugInstr())
389  DL = I->getDebugLoc();
390  MachineFunction *MF = MBB.getParent();
391  const MachineFrameInfo &MFI = MF->getFrameInfo();
393  MachinePointerInfo::getFixedStack(*MF, FrameIndex),
394  MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
395  MFI.getObjectAlignment(FrameIndex));
396  BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
397  .addFrameIndex(FrameIndex)
398  .addImm(0)
399  .addMemOperand(MMO);
400 }
401 
402 bool XCoreInstrInfo::
404  assert((Cond.size() == 2) &&
405  "Invalid XCore branch condition!");
406  Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
407  return false;
408 }
409 
410 static inline bool isImmU6(unsigned val) {
411  return val < (1 << 6);
412 }
413 
414 static inline bool isImmU16(unsigned val) {
415  return val < (1 << 16);
416 }
417 
418 static bool isImmMskBitp(unsigned val) {
419  if (!isMask_32(val)) {
420  return false;
421  }
422  int N = Log2_32(val) + 1;
423  return (N >= 1 && N <= 8) || N == 16 || N == 24 || N == 32;
424 }
425 
427  MachineBasicBlock &MBB,
429  unsigned Reg, uint64_t Value) const {
430  DebugLoc dl;
431  if (MI != MBB.end() && !MI->isDebugInstr())
432  dl = MI->getDebugLoc();
433  if (isImmMskBitp(Value)) {
434  int N = Log2_32(Value) + 1;
435  return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg)
436  .addImm(N)
437  .getInstr();
438  }
439  if (isImmU16(Value)) {
440  int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
441  return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value).getInstr();
442  }
444  const Constant *C = ConstantInt::get(
445  Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Value);
446  unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
447  return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg)
449  .getInstr();
450 }
uint64_t CallInst * C
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
static bool IsBRT(unsigned BrOpc)
MachineBasicBlock * getMBB() const
unsigned isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
isLoadFromStackSlot - If the specified machine instruction is a direct load from a stack slot...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static bool isImmMskBitp(unsigned val)
unsigned Reg
unsigned const TargetRegisterInfo * TRI
A debug info location.
Definition: DebugLoc.h:33
static XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
GetOppositeBranchCondition - Return the inverse of the specified condition, e.g.
#define op(i)
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
Definition: MathExtras.h:404
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
A description of a memory reference used in the backend.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static bool IsBRF(unsigned BrOpc)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:41
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:411
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, unsigned base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
iterator getLastNonDebugInstr()
Returns an iterator to the last non-debug instruction in the basic block, or end().
static bool IsBRU(unsigned BrOpc)
static bool isImmU16(unsigned val)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
unsigned getKillRegState(bool B)
MachineBasicBlock::iterator loadImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Reg, uint64_t Value) const
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned getObjectAlignment(int ObjectIdx) const
Return the alignment of the specified stack object.
static bool isImmU6(unsigned val)
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
This is an important base class in LLVM.
Definition: Constant.h:41
This file contains the declarations for the subclasses of Constant, which represent the different fla...
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineInstrBuilder & addFrameIndex(int Idx) const
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:205
static unsigned GetCondBranchFromCond(XCore::CondCode CC)
GetCondBranchFromCond - Return the Branch instruction opcode that matches the cc. ...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
size_t size() const
Definition: SmallVector.h:52
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
The memory access writes data.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
MachineOperand class - Representation of each machine instruction operand.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
AnalyzeBranch - Analyze the branching code at the end of MBB, returning true if it cannot be understo...
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:653
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly. ...
unsigned isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
isStoreToStackSlot - If the specified machine instruction is a direct store to a stack slot...
int64_t getImm() const
const Function & getFunction() const
Return the LLVM function that this machine code represents.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:538
static bool IsCondBranch(unsigned BrOpc)
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
The memory access reads data.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
BR_JT - Jumptable branch.
Definition: ISDOpcodes.h:666
Representation of each machine instruction.
Definition: MachineInstr.h:64
static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
GetCondFromBranchOpc - Return the XCore CC that matches the correspondent Branch instruction opcode...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:175
static MachineOperand CreateImm(int64_t Val)
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
IRTranslator LLVM IR MI
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:416
static bool IsBR_JT(unsigned BrOpc)
static bool isZeroImm(const MachineOperand &op)
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
unsigned getConstantPoolIndex(const Constant *C, unsigned Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one...
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:143