xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/ARC/ARCInstrInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- ARCInstrInfo.cpp - ARC Instruction Information -----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the ARC implementation of the TargetInstrInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "ARCInstrInfo.h"
140b57cec5SDimitry Andric #include "ARC.h"
150b57cec5SDimitry Andric #include "ARCMachineFunctionInfo.h"
160b57cec5SDimitry Andric #include "ARCSubtarget.h"
170b57cec5SDimitry Andric #include "MCTargetDesc/ARCInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
21349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
220b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
270b57cec5SDimitry Andric #include "ARCGenInstrInfo.inc"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #define DEBUG_TYPE "arc-inst-info"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric enum AddrIncType {
320b57cec5SDimitry Andric     NoAddInc = 0,
330b57cec5SDimitry Andric     PreInc   = 1,
340b57cec5SDimitry Andric     PostInc  = 2,
350b57cec5SDimitry Andric     Scaled   = 3
360b57cec5SDimitry Andric };
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric enum TSFlagsConstants {
390b57cec5SDimitry Andric     TSF_AddrModeOff = 0,
400b57cec5SDimitry Andric     TSF_AddModeMask = 3
410b57cec5SDimitry Andric };
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric // Pin the vtable to this file.
440b57cec5SDimitry Andric void ARCInstrInfo::anchor() {}
450b57cec5SDimitry Andric 
46349cc55cSDimitry Andric ARCInstrInfo::ARCInstrInfo(const ARCSubtarget &ST)
47349cc55cSDimitry Andric     : ARCGenInstrInfo(ARC::ADJCALLSTACKDOWN, ARC::ADJCALLSTACKUP), RI(ST) {}
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric static bool isZeroImm(const MachineOperand &Op) {
500b57cec5SDimitry Andric   return Op.isImm() && Op.getImm() == 0;
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric static bool isLoad(int Opcode) {
540b57cec5SDimitry Andric   return Opcode == ARC::LD_rs9 || Opcode == ARC::LDH_rs9 ||
550b57cec5SDimitry Andric          Opcode == ARC::LDB_rs9;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric static bool isStore(int Opcode) {
590b57cec5SDimitry Andric   return Opcode == ARC::ST_rs9 || Opcode == ARC::STH_rs9 ||
600b57cec5SDimitry Andric          Opcode == ARC::STB_rs9;
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric /// If the specified machine instruction is a direct
640b57cec5SDimitry Andric /// load from a stack slot, return the virtual or physical register number of
650b57cec5SDimitry Andric /// the destination along with the FrameIndex of the loaded stack slot.  If
660b57cec5SDimitry Andric /// not, return 0.  This predicate must return 0 if the instruction has
670b57cec5SDimitry Andric /// any side effects other than loading from the stack slot.
68*0fca6ea1SDimitry Andric Register ARCInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
690b57cec5SDimitry Andric                                            int &FrameIndex) const {
700b57cec5SDimitry Andric   int Opcode = MI.getOpcode();
710b57cec5SDimitry Andric   if (isLoad(Opcode)) {
720b57cec5SDimitry Andric     if ((MI.getOperand(1).isFI()) &&  // is a stack slot
730b57cec5SDimitry Andric         (MI.getOperand(2).isImm()) && // the imm is zero
740b57cec5SDimitry Andric         (isZeroImm(MI.getOperand(2)))) {
750b57cec5SDimitry Andric       FrameIndex = MI.getOperand(1).getIndex();
760b57cec5SDimitry Andric       return MI.getOperand(0).getReg();
770b57cec5SDimitry Andric     }
780b57cec5SDimitry Andric   }
790b57cec5SDimitry Andric   return 0;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric /// If the specified machine instruction is a direct
830b57cec5SDimitry Andric /// store to a stack slot, return the virtual or physical register number of
840b57cec5SDimitry Andric /// the source reg along with the FrameIndex of the loaded stack slot.  If
850b57cec5SDimitry Andric /// not, return 0.  This predicate must return 0 if the instruction has
860b57cec5SDimitry Andric /// any side effects other than storing to the stack slot.
87*0fca6ea1SDimitry Andric Register ARCInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
880b57cec5SDimitry Andric                                           int &FrameIndex) const {
890b57cec5SDimitry Andric   int Opcode = MI.getOpcode();
900b57cec5SDimitry Andric   if (isStore(Opcode)) {
910b57cec5SDimitry Andric     if ((MI.getOperand(1).isFI()) &&  // is a stack slot
920b57cec5SDimitry Andric         (MI.getOperand(2).isImm()) && // the imm is zero
930b57cec5SDimitry Andric         (isZeroImm(MI.getOperand(2)))) {
940b57cec5SDimitry Andric       FrameIndex = MI.getOperand(1).getIndex();
950b57cec5SDimitry Andric       return MI.getOperand(0).getReg();
960b57cec5SDimitry Andric     }
970b57cec5SDimitry Andric   }
980b57cec5SDimitry Andric   return 0;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric /// Return the inverse of passed condition, i.e. turning COND_E to COND_NE.
102349cc55cSDimitry Andric static ARCCC::CondCode getOppositeBranchCondition(ARCCC::CondCode CC) {
1030b57cec5SDimitry Andric   switch (CC) {
1040b57cec5SDimitry Andric   default:
1050b57cec5SDimitry Andric     llvm_unreachable("Illegal condition code!");
1060b57cec5SDimitry Andric   case ARCCC::EQ:
1070b57cec5SDimitry Andric     return ARCCC::NE;
1080b57cec5SDimitry Andric   case ARCCC::NE:
1090b57cec5SDimitry Andric     return ARCCC::EQ;
1100b57cec5SDimitry Andric   case ARCCC::LO:
1110b57cec5SDimitry Andric     return ARCCC::HS;
1120b57cec5SDimitry Andric   case ARCCC::HS:
1130b57cec5SDimitry Andric     return ARCCC::LO;
1140b57cec5SDimitry Andric   case ARCCC::GT:
1150b57cec5SDimitry Andric     return ARCCC::LE;
1160b57cec5SDimitry Andric   case ARCCC::GE:
1170b57cec5SDimitry Andric     return ARCCC::LT;
1180b57cec5SDimitry Andric   case ARCCC::VS:
1190b57cec5SDimitry Andric     return ARCCC::VC;
1200b57cec5SDimitry Andric   case ARCCC::VC:
1210b57cec5SDimitry Andric     return ARCCC::VS;
1220b57cec5SDimitry Andric   case ARCCC::LT:
1230b57cec5SDimitry Andric     return ARCCC::GE;
1240b57cec5SDimitry Andric   case ARCCC::LE:
1250b57cec5SDimitry Andric     return ARCCC::GT;
1260b57cec5SDimitry Andric   case ARCCC::HI:
1270b57cec5SDimitry Andric     return ARCCC::LS;
1280b57cec5SDimitry Andric   case ARCCC::LS:
1290b57cec5SDimitry Andric     return ARCCC::HI;
1300b57cec5SDimitry Andric   case ARCCC::NZ:
1310b57cec5SDimitry Andric     return ARCCC::Z;
1320b57cec5SDimitry Andric   case ARCCC::Z:
1330b57cec5SDimitry Andric     return ARCCC::NZ;
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric static bool isUncondBranchOpcode(int Opc) { return Opc == ARC::BR; }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric static bool isCondBranchOpcode(int Opc) {
1400b57cec5SDimitry Andric   return Opc == ARC::BRcc_rr_p || Opc == ARC::BRcc_ru6_p;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric static bool isJumpOpcode(int Opc) { return Opc == ARC::J; }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric /// Analyze the branching code at the end of MBB, returning
1460b57cec5SDimitry Andric /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
1470b57cec5SDimitry Andric /// implemented for a target).  Upon success, this returns false and returns
1480b57cec5SDimitry Andric /// with the following information in various cases:
1490b57cec5SDimitry Andric ///
1500b57cec5SDimitry Andric /// 1. If this block ends with no branches (it just falls through to its succ)
1510b57cec5SDimitry Andric ///    just return false, leaving TBB/FBB null.
1520b57cec5SDimitry Andric /// 2. If this block ends with only an unconditional branch, it sets TBB to be
1530b57cec5SDimitry Andric ///    the destination block.
1540b57cec5SDimitry Andric /// 3. If this block ends with a conditional branch and it falls through to a
1550b57cec5SDimitry Andric ///    successor block, it sets TBB to be the branch destination block and a
1560b57cec5SDimitry Andric ///    list of operands that evaluate the condition. These operands can be
1570b57cec5SDimitry Andric ///    passed to other TargetInstrInfo methods to create new branches.
1580b57cec5SDimitry Andric /// 4. If this block ends with a conditional branch followed by an
1590b57cec5SDimitry Andric ///    unconditional branch, it returns the 'true' destination in TBB, the
1600b57cec5SDimitry Andric ///    'false' destination in FBB, and a list of operands that evaluate the
1610b57cec5SDimitry Andric ///    condition.  These operands can be passed to other TargetInstrInfo
1620b57cec5SDimitry Andric ///    methods to create new branches.
1630b57cec5SDimitry Andric ///
1645ffd83dbSDimitry Andric /// Note that RemoveBranch and insertBranch must be implemented to support
1650b57cec5SDimitry Andric /// cases where this method returns success.
1660b57cec5SDimitry Andric ///
1670b57cec5SDimitry Andric /// If AllowModify is true, then this routine is allowed to modify the basic
1680b57cec5SDimitry Andric /// block (e.g. delete instructions after the unconditional branch).
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric bool ARCInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
1710b57cec5SDimitry Andric                                  MachineBasicBlock *&TBB,
1720b57cec5SDimitry Andric                                  MachineBasicBlock *&FBB,
1730b57cec5SDimitry Andric                                  SmallVectorImpl<MachineOperand> &Cond,
1740b57cec5SDimitry Andric                                  bool AllowModify) const {
1750b57cec5SDimitry Andric   TBB = FBB = nullptr;
1760b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
1770b57cec5SDimitry Andric   if (I == MBB.begin())
1780b57cec5SDimitry Andric     return false;
1790b57cec5SDimitry Andric   --I;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) {
1820b57cec5SDimitry Andric     // Flag to be raised on unanalyzeable instructions. This is useful in cases
1830b57cec5SDimitry Andric     // where we want to clean up on the end of the basic block before we bail
1840b57cec5SDimitry Andric     // out.
1850b57cec5SDimitry Andric     bool CantAnalyze = false;
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric     // Skip over DEBUG values and predicated nonterminators.
1880b57cec5SDimitry Andric     while (I->isDebugInstr() || !I->isTerminator()) {
1890b57cec5SDimitry Andric       if (I == MBB.begin())
1900b57cec5SDimitry Andric         return false;
1910b57cec5SDimitry Andric       --I;
1920b57cec5SDimitry Andric     }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric     if (isJumpOpcode(I->getOpcode())) {
1950b57cec5SDimitry Andric       // Indirect branches and jump tables can't be analyzed, but we still want
1960b57cec5SDimitry Andric       // to clean up any instructions at the tail of the basic block.
1970b57cec5SDimitry Andric       CantAnalyze = true;
1980b57cec5SDimitry Andric     } else if (isUncondBranchOpcode(I->getOpcode())) {
1990b57cec5SDimitry Andric       TBB = I->getOperand(0).getMBB();
2000b57cec5SDimitry Andric     } else if (isCondBranchOpcode(I->getOpcode())) {
2010b57cec5SDimitry Andric       // Bail out if we encounter multiple conditional branches.
2020b57cec5SDimitry Andric       if (!Cond.empty())
2030b57cec5SDimitry Andric         return true;
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric       assert(!FBB && "FBB should have been null.");
2060b57cec5SDimitry Andric       FBB = TBB;
2070b57cec5SDimitry Andric       TBB = I->getOperand(0).getMBB();
2080b57cec5SDimitry Andric       Cond.push_back(I->getOperand(1));
2090b57cec5SDimitry Andric       Cond.push_back(I->getOperand(2));
2100b57cec5SDimitry Andric       Cond.push_back(I->getOperand(3));
2110b57cec5SDimitry Andric     } else if (I->isReturn()) {
2120b57cec5SDimitry Andric       // Returns can't be analyzed, but we should run cleanup.
2130b57cec5SDimitry Andric       CantAnalyze = !isPredicated(*I);
2140b57cec5SDimitry Andric     } else {
2150b57cec5SDimitry Andric       // We encountered other unrecognized terminator. Bail out immediately.
2160b57cec5SDimitry Andric       return true;
2170b57cec5SDimitry Andric     }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric     // Cleanup code - to be run for unpredicated unconditional branches and
2200b57cec5SDimitry Andric     //                returns.
2210b57cec5SDimitry Andric     if (!isPredicated(*I) && (isUncondBranchOpcode(I->getOpcode()) ||
2220b57cec5SDimitry Andric                               isJumpOpcode(I->getOpcode()) || I->isReturn())) {
2230b57cec5SDimitry Andric       // Forget any previous condition branch information - it no longer
2240b57cec5SDimitry Andric       // applies.
2250b57cec5SDimitry Andric       Cond.clear();
2260b57cec5SDimitry Andric       FBB = nullptr;
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric       // If we can modify the function, delete everything below this
2290b57cec5SDimitry Andric       // unconditional branch.
2300b57cec5SDimitry Andric       if (AllowModify) {
2310b57cec5SDimitry Andric         MachineBasicBlock::iterator DI = std::next(I);
2320b57cec5SDimitry Andric         while (DI != MBB.end()) {
2330b57cec5SDimitry Andric           MachineInstr &InstToDelete = *DI;
2340b57cec5SDimitry Andric           ++DI;
2350b57cec5SDimitry Andric           InstToDelete.eraseFromParent();
2360b57cec5SDimitry Andric         }
2370b57cec5SDimitry Andric       }
2380b57cec5SDimitry Andric     }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric     if (CantAnalyze)
2410b57cec5SDimitry Andric       return true;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric     if (I == MBB.begin())
2440b57cec5SDimitry Andric       return false;
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric     --I;
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   // We made it past the terminators without bailing out - we must have
2500b57cec5SDimitry Andric   // analyzed this branch successfully.
2510b57cec5SDimitry Andric   return false;
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric unsigned ARCInstrInfo::removeBranch(MachineBasicBlock &MBB,
2550b57cec5SDimitry Andric                                     int *BytesRemoved) const {
2560b57cec5SDimitry Andric   assert(!BytesRemoved && "Code size not handled");
2570b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
2580b57cec5SDimitry Andric   if (I == MBB.end())
2590b57cec5SDimitry Andric     return 0;
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   if (!isUncondBranchOpcode(I->getOpcode()) &&
2620b57cec5SDimitry Andric       !isCondBranchOpcode(I->getOpcode()))
2630b57cec5SDimitry Andric     return 0;
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   // Remove the branch.
2660b57cec5SDimitry Andric   I->eraseFromParent();
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   I = MBB.end();
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   if (I == MBB.begin())
2710b57cec5SDimitry Andric     return 1;
2720b57cec5SDimitry Andric   --I;
2730b57cec5SDimitry Andric   if (!isCondBranchOpcode(I->getOpcode()))
2740b57cec5SDimitry Andric     return 1;
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   // Remove the branch.
2770b57cec5SDimitry Andric   I->eraseFromParent();
2780b57cec5SDimitry Andric   return 2;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric void ARCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
2820b57cec5SDimitry Andric                                MachineBasicBlock::iterator I,
283349cc55cSDimitry Andric                                const DebugLoc &DL, MCRegister DestReg,
284480093f4SDimitry Andric                                MCRegister SrcReg, bool KillSrc) const {
2850b57cec5SDimitry Andric   assert(ARC::GPR32RegClass.contains(SrcReg) &&
2860b57cec5SDimitry Andric          "Only GPR32 src copy supported.");
2870b57cec5SDimitry Andric   assert(ARC::GPR32RegClass.contains(DestReg) &&
2880b57cec5SDimitry Andric          "Only GPR32 dest copy supported.");
289349cc55cSDimitry Andric   BuildMI(MBB, I, DL, get(ARC::MOV_rr), DestReg)
2900b57cec5SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc));
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric 
293bdd1243dSDimitry Andric void ARCInstrInfo::storeRegToStackSlot(
294bdd1243dSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register SrcReg,
295bdd1243dSDimitry Andric     bool IsKill, int FrameIndex, const TargetRegisterClass *RC,
296bdd1243dSDimitry Andric     const TargetRegisterInfo *TRI, Register VReg) const {
297349cc55cSDimitry Andric   DebugLoc DL = MBB.findDebugLoc(I);
2980b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
2990b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   MachineMemOperand *MMO = MF.getMachineMemOperand(
3020b57cec5SDimitry Andric       MachinePointerInfo::getFixedStack(MF, FrameIndex),
3035ffd83dbSDimitry Andric       MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
3045ffd83dbSDimitry Andric       MFI.getObjectAlign(FrameIndex));
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
3070b57cec5SDimitry Andric   assert(TRI->getSpillSize(*RC) == 4 &&
3080b57cec5SDimitry Andric          "Only support 4-byte stores to stack now.");
3090b57cec5SDimitry Andric   assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
3100b57cec5SDimitry Andric          "Only support GPR32 stores to stack now.");
3110b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Created store reg=" << printReg(SrcReg, TRI)
3120b57cec5SDimitry Andric                     << " to FrameIndex=" << FrameIndex << "\n");
313349cc55cSDimitry Andric   BuildMI(MBB, I, DL, get(ARC::ST_rs9))
314349cc55cSDimitry Andric       .addReg(SrcReg, getKillRegState(IsKill))
3150b57cec5SDimitry Andric       .addFrameIndex(FrameIndex)
3160b57cec5SDimitry Andric       .addImm(0)
3170b57cec5SDimitry Andric       .addMemOperand(MMO);
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric void ARCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
3210b57cec5SDimitry Andric                                         MachineBasicBlock::iterator I,
3225ffd83dbSDimitry Andric                                         Register DestReg, int FrameIndex,
3230b57cec5SDimitry Andric                                         const TargetRegisterClass *RC,
324bdd1243dSDimitry Andric                                         const TargetRegisterInfo *TRI,
325bdd1243dSDimitry Andric                                         Register VReg) const {
326349cc55cSDimitry Andric   DebugLoc DL = MBB.findDebugLoc(I);
3270b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
3280b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
3290b57cec5SDimitry Andric   MachineMemOperand *MMO = MF.getMachineMemOperand(
3300b57cec5SDimitry Andric       MachinePointerInfo::getFixedStack(MF, FrameIndex),
3315ffd83dbSDimitry Andric       MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
3325ffd83dbSDimitry Andric       MFI.getObjectAlign(FrameIndex));
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric   assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
3350b57cec5SDimitry Andric   assert(TRI->getSpillSize(*RC) == 4 &&
3360b57cec5SDimitry Andric          "Only support 4-byte loads from stack now.");
3370b57cec5SDimitry Andric   assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
3380b57cec5SDimitry Andric          "Only support GPR32 stores to stack now.");
3390b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Created load reg=" << printReg(DestReg, TRI)
3400b57cec5SDimitry Andric                     << " from FrameIndex=" << FrameIndex << "\n");
341349cc55cSDimitry Andric   BuildMI(MBB, I, DL, get(ARC::LD_rs9))
3420b57cec5SDimitry Andric       .addReg(DestReg, RegState::Define)
3430b57cec5SDimitry Andric       .addFrameIndex(FrameIndex)
3440b57cec5SDimitry Andric       .addImm(0)
3450b57cec5SDimitry Andric       .addMemOperand(MMO);
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric /// Return the inverse opcode of the specified Branch instruction.
3490b57cec5SDimitry Andric bool ARCInstrInfo::reverseBranchCondition(
3500b57cec5SDimitry Andric     SmallVectorImpl<MachineOperand> &Cond) const {
3510b57cec5SDimitry Andric   assert((Cond.size() == 3) && "Invalid ARC branch condition!");
352349cc55cSDimitry Andric   Cond[2].setImm(getOppositeBranchCondition((ARCCC::CondCode)Cond[2].getImm()));
3530b57cec5SDimitry Andric   return false;
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric MachineBasicBlock::iterator
3570b57cec5SDimitry Andric ARCInstrInfo::loadImmediate(MachineBasicBlock &MBB,
3580b57cec5SDimitry Andric                             MachineBasicBlock::iterator MI, unsigned Reg,
3590b57cec5SDimitry Andric                             uint64_t Value) const {
360349cc55cSDimitry Andric   DebugLoc DL = MBB.findDebugLoc(MI);
3610b57cec5SDimitry Andric   if (isInt<12>(Value)) {
362349cc55cSDimitry Andric     return BuildMI(MBB, MI, DL, get(ARC::MOV_rs12), Reg)
3630b57cec5SDimitry Andric         .addImm(Value)
3640b57cec5SDimitry Andric         .getInstr();
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric   llvm_unreachable("Need Arc long immediate instructions.");
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric unsigned ARCInstrInfo::insertBranch(MachineBasicBlock &MBB,
3700b57cec5SDimitry Andric                                     MachineBasicBlock *TBB,
3710b57cec5SDimitry Andric                                     MachineBasicBlock *FBB,
3720b57cec5SDimitry Andric                                     ArrayRef<MachineOperand> Cond,
373349cc55cSDimitry Andric                                     const DebugLoc &DL, int *BytesAdded) const {
3740b57cec5SDimitry Andric   assert(!BytesAdded && "Code size not handled.");
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   // Shouldn't be a fall through.
3775ffd83dbSDimitry Andric   assert(TBB && "insertBranch must not be told to insert a fallthrough");
3780b57cec5SDimitry Andric   assert((Cond.size() == 3 || Cond.size() == 0) &&
3790b57cec5SDimitry Andric          "ARC branch conditions have two components!");
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   if (Cond.empty()) {
382349cc55cSDimitry Andric     BuildMI(&MBB, DL, get(ARC::BR)).addMBB(TBB);
3830b57cec5SDimitry Andric     return 1;
3840b57cec5SDimitry Andric   }
3850b57cec5SDimitry Andric   int BccOpc = Cond[1].isImm() ? ARC::BRcc_ru6_p : ARC::BRcc_rr_p;
386349cc55cSDimitry Andric   MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(BccOpc));
3870b57cec5SDimitry Andric   MIB.addMBB(TBB);
3880b57cec5SDimitry Andric   for (unsigned i = 0; i < 3; i++) {
3890b57cec5SDimitry Andric     MIB.add(Cond[i]);
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   // One-way conditional branch.
3930b57cec5SDimitry Andric   if (!FBB) {
3940b57cec5SDimitry Andric     return 1;
3950b57cec5SDimitry Andric   }
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   // Two-way conditional branch.
398349cc55cSDimitry Andric   BuildMI(&MBB, DL, get(ARC::BR)).addMBB(FBB);
3990b57cec5SDimitry Andric   return 2;
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric unsigned ARCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
4030b57cec5SDimitry Andric   if (MI.isInlineAsm()) {
4040b57cec5SDimitry Andric     const MachineFunction *MF = MI.getParent()->getParent();
4050b57cec5SDimitry Andric     const char *AsmStr = MI.getOperand(0).getSymbolName();
4060b57cec5SDimitry Andric     return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
4070b57cec5SDimitry Andric   }
4080b57cec5SDimitry Andric   return MI.getDesc().getSize();
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric bool ARCInstrInfo::isPostIncrement(const MachineInstr &MI) const {
4120b57cec5SDimitry Andric   const MCInstrDesc &MID = MI.getDesc();
4130b57cec5SDimitry Andric   const uint64_t F = MID.TSFlags;
4140b57cec5SDimitry Andric   return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PostInc;
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric bool ARCInstrInfo::isPreIncrement(const MachineInstr &MI) const {
4180b57cec5SDimitry Andric   const MCInstrDesc &MID = MI.getDesc();
4190b57cec5SDimitry Andric   const uint64_t F = MID.TSFlags;
4200b57cec5SDimitry Andric   return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PreInc;
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric bool ARCInstrInfo::getBaseAndOffsetPosition(const MachineInstr &MI,
4240b57cec5SDimitry Andric                                         unsigned &BasePos,
4250b57cec5SDimitry Andric                                         unsigned &OffsetPos) const {
4260b57cec5SDimitry Andric   if (!MI.mayLoad() && !MI.mayStore())
4270b57cec5SDimitry Andric     return false;
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   BasePos = 1;
4300b57cec5SDimitry Andric   OffsetPos = 2;
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   if (isPostIncrement(MI) || isPreIncrement(MI)) {
4330b57cec5SDimitry Andric     BasePos++;
4340b57cec5SDimitry Andric     OffsetPos++;
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   if (!MI.getOperand(BasePos).isReg() || !MI.getOperand(OffsetPos).isImm())
4380b57cec5SDimitry Andric     return false;
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   return true;
4410b57cec5SDimitry Andric }
442