1234353Sdim//===-- XCoreInstrInfo.cpp - XCore Instruction Information ----------------===//
2193323Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193323Sed//
7193323Sed//===----------------------------------------------------------------------===//
8193323Sed//
9193323Sed// This file contains the XCore implementation of the TargetInstrInfo class.
10193323Sed//
11193323Sed//===----------------------------------------------------------------------===//
12193323Sed
13234353Sdim#include "XCoreInstrInfo.h"
14249423Sdim#include "XCore.h"
15193323Sed#include "XCoreMachineFunctionInfo.h"
16249423Sdim#include "llvm/ADT/STLExtras.h"
17276479Sdim#include "llvm/CodeGen/MachineConstantPool.h"
18249423Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
19249423Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
20276479Sdim#include "llvm/CodeGen/MachineMemOperand.h"
21276479Sdim#include "llvm/IR/Constants.h"
22276479Sdim#include "llvm/IR/Function.h"
23206274Srdivacky#include "llvm/MC/MCContext.h"
24193323Sed#include "llvm/Support/Debug.h"
25198090Srdivacky#include "llvm/Support/ErrorHandling.h"
26226633Sdim#include "llvm/Support/TargetRegistry.h"
27193323Sed
28276479Sdimusing namespace llvm;
29276479Sdim
30261991Sdim#define GET_INSTRINFO_CTOR_DTOR
31224145Sdim#include "XCoreGenInstrInfo.inc"
32224145Sdim
33193323Sednamespace llvm {
34193323Sednamespace XCore {
35193323Sed
36193323Sed  // XCore Condition Codes
37193323Sed  enum CondCode {
38193323Sed    COND_TRUE,
39193323Sed    COND_FALSE,
40193323Sed    COND_INVALID
41193323Sed  };
42193323Sed}
43193323Sed}
44193323Sed
45261991Sdim// Pin the vtable to this file.
46261991Sdimvoid XCoreInstrInfo::anchor() {}
47261991Sdim
48198090SrdivackyXCoreInstrInfo::XCoreInstrInfo()
49224145Sdim  : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
50261991Sdim    RI() {
51193323Sed}
52193323Sed
53193323Sedstatic bool isZeroImm(const MachineOperand &op) {
54193323Sed  return op.isImm() && op.getImm() == 0;
55193323Sed}
56193323Sed
57193323Sed/// isLoadFromStackSlot - If the specified machine instruction is a direct
58193323Sed/// load from a stack slot, return the virtual or physical register number of
59193323Sed/// the destination along with the FrameIndex of the loaded stack slot.  If
60193323Sed/// not, return 0.  This predicate must return 0 if the instruction has
61193323Sed/// any side effects other than loading from the stack slot.
62309124Sdimunsigned XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
63309124Sdim                                             int &FrameIndex) const {
64309124Sdim  int Opcode = MI.getOpcode();
65341825Sdim  if (Opcode == XCore::LDWFI)
66193323Sed  {
67309124Sdim    if ((MI.getOperand(1).isFI()) &&  // is a stack slot
68309124Sdim        (MI.getOperand(2).isImm()) && // the imm is zero
69309124Sdim        (isZeroImm(MI.getOperand(2)))) {
70309124Sdim      FrameIndex = MI.getOperand(1).getIndex();
71309124Sdim      return MI.getOperand(0).getReg();
72193323Sed    }
73193323Sed  }
74193323Sed  return 0;
75193323Sed}
76341825Sdim
77193323Sed  /// isStoreToStackSlot - If the specified machine instruction is a direct
78193323Sed  /// store to a stack slot, return the virtual or physical register number of
79193323Sed  /// the source reg along with the FrameIndex of the loaded stack slot.  If
80193323Sed  /// not, return 0.  This predicate must return 0 if the instruction has
81193323Sed  /// any side effects other than storing to the stack slot.
82309124Sdimunsigned XCoreInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
83309124Sdim                                            int &FrameIndex) const {
84309124Sdim  int Opcode = MI.getOpcode();
85193323Sed  if (Opcode == XCore::STWFI)
86193323Sed  {
87309124Sdim    if ((MI.getOperand(1).isFI()) &&  // is a stack slot
88309124Sdim        (MI.getOperand(2).isImm()) && // the imm is zero
89309124Sdim        (isZeroImm(MI.getOperand(2)))) {
90309124Sdim      FrameIndex = MI.getOperand(1).getIndex();
91309124Sdim      return MI.getOperand(0).getReg();
92193323Sed    }
93193323Sed  }
94193323Sed  return 0;
95193323Sed}
96193323Sed
97193323Sed//===----------------------------------------------------------------------===//
98193323Sed// Branch Analysis
99193323Sed//===----------------------------------------------------------------------===//
100193323Sed
101193323Sedstatic inline bool IsBRU(unsigned BrOpc) {
102193323Sed  return BrOpc == XCore::BRFU_u6
103193323Sed      || BrOpc == XCore::BRFU_lu6
104193323Sed      || BrOpc == XCore::BRBU_u6
105193323Sed      || BrOpc == XCore::BRBU_lu6;
106193323Sed}
107193323Sed
108193323Sedstatic inline bool IsBRT(unsigned BrOpc) {
109193323Sed  return BrOpc == XCore::BRFT_ru6
110193323Sed      || BrOpc == XCore::BRFT_lru6
111193323Sed      || BrOpc == XCore::BRBT_ru6
112193323Sed      || BrOpc == XCore::BRBT_lru6;
113193323Sed}
114193323Sed
115193323Sedstatic inline bool IsBRF(unsigned BrOpc) {
116193323Sed  return BrOpc == XCore::BRFF_ru6
117193323Sed      || BrOpc == XCore::BRFF_lru6
118193323Sed      || BrOpc == XCore::BRBF_ru6
119193323Sed      || BrOpc == XCore::BRBF_lru6;
120193323Sed}
121193323Sed
122193323Sedstatic inline bool IsCondBranch(unsigned BrOpc) {
123193323Sed  return IsBRF(BrOpc) || IsBRT(BrOpc);
124193323Sed}
125193323Sed
126204642Srdivackystatic inline bool IsBR_JT(unsigned BrOpc) {
127204642Srdivacky  return BrOpc == XCore::BR_JT
128204642Srdivacky      || BrOpc == XCore::BR_JT32;
129204642Srdivacky}
130204642Srdivacky
131341825Sdim/// GetCondFromBranchOpc - Return the XCore CC that matches
132193323Sed/// the correspondent Branch instruction opcode.
133341825Sdimstatic XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
134193323Sed{
135193323Sed  if (IsBRT(BrOpc)) {
136193323Sed    return XCore::COND_TRUE;
137193323Sed  } else if (IsBRF(BrOpc)) {
138193323Sed    return XCore::COND_FALSE;
139193323Sed  } else {
140193323Sed    return XCore::COND_INVALID;
141193323Sed  }
142193323Sed}
143193323Sed
144193323Sed/// GetCondBranchFromCond - Return the Branch instruction
145193323Sed/// opcode that matches the cc.
146341825Sdimstatic inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
147193323Sed{
148193323Sed  switch (CC) {
149198090Srdivacky  default: llvm_unreachable("Illegal condition code!");
150193323Sed  case XCore::COND_TRUE   : return XCore::BRFT_lru6;
151193323Sed  case XCore::COND_FALSE  : return XCore::BRFF_lru6;
152193323Sed  }
153193323Sed}
154193323Sed
155341825Sdim/// GetOppositeBranchCondition - Return the inverse of the specified
156193323Sed/// condition, e.g. turning COND_E to COND_NE.
157193323Sedstatic inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
158193323Sed{
159193323Sed  switch (CC) {
160198090Srdivacky  default: llvm_unreachable("Illegal condition code!");
161193323Sed  case XCore::COND_TRUE   : return XCore::COND_FALSE;
162193323Sed  case XCore::COND_FALSE  : return XCore::COND_TRUE;
163193323Sed  }
164193323Sed}
165193323Sed
166193323Sed/// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
167193323Sed/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
168193323Sed/// implemented for a target).  Upon success, this returns false and returns
169193323Sed/// with the following information in various cases:
170193323Sed///
171193323Sed/// 1. If this block ends with no branches (it just falls through to its succ)
172193323Sed///    just return false, leaving TBB/FBB null.
173193323Sed/// 2. If this block ends with only an unconditional branch, it sets TBB to be
174193323Sed///    the destination block.
175193323Sed/// 3. If this block ends with an conditional branch and it falls through to
176193323Sed///    an successor block, it sets TBB to be the branch destination block and a
177193323Sed///    list of operands that evaluate the condition. These
178193323Sed///    operands can be passed to other TargetInstrInfo methods to create new
179193323Sed///    branches.
180193323Sed/// 4. If this block ends with an conditional branch and an unconditional
181193323Sed///    block, it returns the 'true' destination in TBB, the 'false' destination
182193323Sed///    in FBB, and a list of operands that evaluate the condition. These
183193323Sed///    operands can be passed to other TargetInstrInfo methods to create new
184193323Sed///    branches.
185193323Sed///
186314564Sdim/// Note that removeBranch and insertBranch must be implemented to support
187193323Sed/// cases where this method returns success.
188193323Sed///
189309124Sdimbool XCoreInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
190309124Sdim                                   MachineBasicBlock *&TBB,
191309124Sdim                                   MachineBasicBlock *&FBB,
192309124Sdim                                   SmallVectorImpl<MachineOperand> &Cond,
193309124Sdim                                   bool AllowModify) const {
194193323Sed  // If the block has no terminators, it just falls into the block after it.
195288943Sdim  MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
196288943Sdim  if (I == MBB.end())
197193323Sed    return false;
198288943Sdim
199309124Sdim  if (!isUnpredicatedTerminator(*I))
200206083Srdivacky    return false;
201193323Sed
202193323Sed  // Get the last instruction in the block.
203314564Sdim  MachineInstr *LastInst = &*I;
204314564Sdim
205193323Sed  // If there is only one terminator instruction, process it.
206309124Sdim  if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
207193323Sed    if (IsBRU(LastInst->getOpcode())) {
208193323Sed      TBB = LastInst->getOperand(0).getMBB();
209193323Sed      return false;
210193323Sed    }
211341825Sdim
212193323Sed    XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
213193323Sed    if (BranchCode == XCore::COND_INVALID)
214193323Sed      return true;  // Can't handle indirect branch.
215341825Sdim
216193323Sed    // Conditional branch
217193323Sed    // Block ends with fall-through condbranch.
218193323Sed
219193323Sed    TBB = LastInst->getOperand(1).getMBB();
220193323Sed    Cond.push_back(MachineOperand::CreateImm(BranchCode));
221193323Sed    Cond.push_back(LastInst->getOperand(0));
222193323Sed    return false;
223193323Sed  }
224341825Sdim
225193323Sed  // Get the instruction before it if it's a terminator.
226314564Sdim  MachineInstr *SecondLastInst = &*I;
227193323Sed
228193323Sed  // If there are three terminators, we don't know what sort of block this is.
229309124Sdim  if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
230193323Sed    return true;
231341825Sdim
232193323Sed  unsigned SecondLastOpc    = SecondLastInst->getOpcode();
233193323Sed  XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
234341825Sdim
235193323Sed  // If the block ends with conditional branch followed by unconditional,
236193323Sed  // handle it.
237193323Sed  if (BranchCode != XCore::COND_INVALID
238193323Sed    && IsBRU(LastInst->getOpcode())) {
239193323Sed
240193323Sed    TBB = SecondLastInst->getOperand(1).getMBB();
241193323Sed    Cond.push_back(MachineOperand::CreateImm(BranchCode));
242193323Sed    Cond.push_back(SecondLastInst->getOperand(0));
243193323Sed
244193323Sed    FBB = LastInst->getOperand(0).getMBB();
245193323Sed    return false;
246193323Sed  }
247341825Sdim
248193323Sed  // If the block ends with two unconditional branches, handle it.  The second
249193323Sed  // one is not executed, so remove it.
250341825Sdim  if (IsBRU(SecondLastInst->getOpcode()) &&
251193323Sed      IsBRU(LastInst->getOpcode())) {
252193323Sed    TBB = SecondLastInst->getOperand(0).getMBB();
253193323Sed    I = LastInst;
254193323Sed    if (AllowModify)
255193323Sed      I->eraseFromParent();
256193323Sed    return false;
257193323Sed  }
258193323Sed
259204642Srdivacky  // Likewise if it ends with a branch table followed by an unconditional branch.
260204642Srdivacky  if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
261204642Srdivacky    I = LastInst;
262204642Srdivacky    if (AllowModify)
263204642Srdivacky      I->eraseFromParent();
264204642Srdivacky    return true;
265204642Srdivacky  }
266204642Srdivacky
267193323Sed  // Otherwise, can't handle this.
268193323Sed  return true;
269193323Sed}
270193323Sed
271314564Sdimunsigned XCoreInstrInfo::insertBranch(MachineBasicBlock &MBB,
272309124Sdim                                      MachineBasicBlock *TBB,
273309124Sdim                                      MachineBasicBlock *FBB,
274309124Sdim                                      ArrayRef<MachineOperand> Cond,
275314564Sdim                                      const DebugLoc &DL,
276314564Sdim                                      int *BytesAdded) const {
277193323Sed  // Shouldn't be a fall through.
278314564Sdim  assert(TBB && "insertBranch must not be told to insert a fallthrough");
279193323Sed  assert((Cond.size() == 2 || Cond.size() == 0) &&
280193323Sed         "Unexpected number of components!");
281314564Sdim  assert(!BytesAdded && "code size not handled");
282314564Sdim
283276479Sdim  if (!FBB) { // One way branch.
284193323Sed    if (Cond.empty()) {
285193323Sed      // Unconditional branch
286210299Sed      BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
287193323Sed    } else {
288193323Sed      // Conditional branch.
289193323Sed      unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
290210299Sed      BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
291193323Sed                             .addMBB(TBB);
292193323Sed    }
293193323Sed    return 1;
294193323Sed  }
295341825Sdim
296193323Sed  // Two-way Conditional branch.
297193323Sed  assert(Cond.size() == 2 && "Unexpected number of components!");
298193323Sed  unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
299210299Sed  BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
300193323Sed                         .addMBB(TBB);
301210299Sed  BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
302193323Sed  return 2;
303193323Sed}
304193323Sed
305193323Sedunsigned
306314564SdimXCoreInstrInfo::removeBranch(MachineBasicBlock &MBB, int *BytesRemoved) const {
307314564Sdim  assert(!BytesRemoved && "code size not handled");
308314564Sdim
309288943Sdim  MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
310288943Sdim  if (I == MBB.end())
311288943Sdim    return 0;
312288943Sdim
313193323Sed  if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
314193323Sed    return 0;
315341825Sdim
316193323Sed  // Remove the branch.
317193323Sed  I->eraseFromParent();
318341825Sdim
319193323Sed  I = MBB.end();
320193323Sed
321193323Sed  if (I == MBB.begin()) return 1;
322193323Sed  --I;
323193323Sed  if (!IsCondBranch(I->getOpcode()))
324193323Sed    return 1;
325341825Sdim
326193323Sed  // Remove the branch.
327193323Sed  I->eraseFromParent();
328193323Sed  return 2;
329193323Sed}
330193323Sed
331210299Sedvoid XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
332309124Sdim                                 MachineBasicBlock::iterator I,
333360784Sdim                                 const DebugLoc &DL, MCRegister DestReg,
334360784Sdim                                 MCRegister SrcReg, bool KillSrc) const {
335210299Sed  bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
336210299Sed  bool GRSrc  = XCore::GRRegsRegClass.contains(SrcReg);
337193323Sed
338210299Sed  if (GRDest && GRSrc) {
339210299Sed    BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
340210299Sed      .addReg(SrcReg, getKillRegState(KillSrc))
341210299Sed      .addImm(0);
342210299Sed    return;
343193323Sed  }
344341825Sdim
345210299Sed  if (GRDest && SrcReg == XCore::SP) {
346210299Sed    BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
347210299Sed    return;
348193323Sed  }
349210299Sed
350210299Sed  if (DestReg == XCore::SP && GRSrc) {
351193323Sed    BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
352210299Sed      .addReg(SrcReg, getKillRegState(KillSrc));
353210299Sed    return;
354193323Sed  }
355210299Sed  llvm_unreachable("Impossible reg-to-reg copy");
356193323Sed}
357193323Sed
358193323Sedvoid XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
359193323Sed                                         MachineBasicBlock::iterator I,
360193323Sed                                         unsigned SrcReg, bool isKill,
361193323Sed                                         int FrameIndex,
362208599Srdivacky                                         const TargetRegisterClass *RC,
363208599Srdivacky                                         const TargetRegisterInfo *TRI) const
364193323Sed{
365206124Srdivacky  DebugLoc DL;
366341825Sdim  if (I != MBB.end() && !I->isDebugInstr())
367276479Sdim    DL = I->getDebugLoc();
368276479Sdim  MachineFunction *MF = MBB.getParent();
369314564Sdim  const MachineFrameInfo &MFI = MF->getFrameInfo();
370296417Sdim  MachineMemOperand *MMO = MF->getMachineMemOperand(
371296417Sdim      MachinePointerInfo::getFixedStack(*MF, FrameIndex),
372296417Sdim      MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
373296417Sdim      MFI.getObjectAlignment(FrameIndex));
374193323Sed  BuildMI(MBB, I, DL, get(XCore::STWFI))
375193323Sed    .addReg(SrcReg, getKillRegState(isKill))
376193323Sed    .addFrameIndex(FrameIndex)
377276479Sdim    .addImm(0)
378276479Sdim    .addMemOperand(MMO);
379193323Sed}
380193323Sed
381193323Sedvoid XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
382193323Sed                                          MachineBasicBlock::iterator I,
383193323Sed                                          unsigned DestReg, int FrameIndex,
384208599Srdivacky                                          const TargetRegisterClass *RC,
385208599Srdivacky                                          const TargetRegisterInfo *TRI) const
386193323Sed{
387206124Srdivacky  DebugLoc DL;
388341825Sdim  if (I != MBB.end() && !I->isDebugInstr())
389276479Sdim    DL = I->getDebugLoc();
390276479Sdim  MachineFunction *MF = MBB.getParent();
391314564Sdim  const MachineFrameInfo &MFI = MF->getFrameInfo();
392296417Sdim  MachineMemOperand *MMO = MF->getMachineMemOperand(
393296417Sdim      MachinePointerInfo::getFixedStack(*MF, FrameIndex),
394296417Sdim      MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
395296417Sdim      MFI.getObjectAlignment(FrameIndex));
396193323Sed  BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
397193323Sed    .addFrameIndex(FrameIndex)
398276479Sdim    .addImm(0)
399276479Sdim    .addMemOperand(MMO);
400193323Sed}
401193323Sed
402193323Sedbool XCoreInstrInfo::
403314564SdimreverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
404314564Sdim  assert((Cond.size() == 2) &&
405193323Sed          "Invalid XCore branch condition!");
406193323Sed  Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
407193323Sed  return false;
408193323Sed}
409276479Sdim
410276479Sdimstatic inline bool isImmU6(unsigned val) {
411276479Sdim  return val < (1 << 6);
412276479Sdim}
413276479Sdim
414276479Sdimstatic inline bool isImmU16(unsigned val) {
415276479Sdim  return val < (1 << 16);
416276479Sdim}
417276479Sdim
418276479Sdimstatic bool isImmMskBitp(unsigned val) {
419276479Sdim  if (!isMask_32(val)) {
420276479Sdim    return false;
421276479Sdim  }
422276479Sdim  int N = Log2_32(val) + 1;
423276479Sdim  return (N >= 1 && N <= 8) || N == 16 || N == 24 || N == 32;
424276479Sdim}
425276479Sdim
426276479SdimMachineBasicBlock::iterator XCoreInstrInfo::loadImmediate(
427276479Sdim                                              MachineBasicBlock &MBB,
428276479Sdim                                              MachineBasicBlock::iterator MI,
429276479Sdim                                              unsigned Reg, uint64_t Value) const {
430276479Sdim  DebugLoc dl;
431341825Sdim  if (MI != MBB.end() && !MI->isDebugInstr())
432276479Sdim    dl = MI->getDebugLoc();
433276479Sdim  if (isImmMskBitp(Value)) {
434276479Sdim    int N = Log2_32(Value) + 1;
435280031Sdim    return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg)
436280031Sdim        .addImm(N)
437280031Sdim        .getInstr();
438276479Sdim  }
439276479Sdim  if (isImmU16(Value)) {
440276479Sdim    int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
441280031Sdim    return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value).getInstr();
442276479Sdim  }
443276479Sdim  MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool();
444276479Sdim  const Constant *C = ConstantInt::get(
445327952Sdim        Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Value);
446276479Sdim  unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
447276479Sdim  return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg)
448280031Sdim      .addConstantPoolIndex(Idx)
449280031Sdim      .getInstr();
450276479Sdim}
451