12d1f6d67SPete Couperus //===- ARCInstrInfo.cpp - ARC Instruction Information -----------*- C++ -*-===//
22d1f6d67SPete Couperus //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62d1f6d67SPete Couperus //
72d1f6d67SPete Couperus //===----------------------------------------------------------------------===//
82d1f6d67SPete Couperus //
92d1f6d67SPete Couperus // This file contains the ARC implementation of the TargetInstrInfo class.
102d1f6d67SPete Couperus //
112d1f6d67SPete Couperus //===----------------------------------------------------------------------===//
122d1f6d67SPete Couperus
132d1f6d67SPete Couperus #include "ARCInstrInfo.h"
142d1f6d67SPete Couperus #include "ARC.h"
152d1f6d67SPete Couperus #include "ARCMachineFunctionInfo.h"
162d1f6d67SPete Couperus #include "ARCSubtarget.h"
172d1f6d67SPete Couperus #include "MCTargetDesc/ARCInfo.h"
182d1f6d67SPete Couperus #include "llvm/CodeGen/MachineFrameInfo.h"
192d1f6d67SPete Couperus #include "llvm/CodeGen/MachineInstrBuilder.h"
202d1f6d67SPete Couperus #include "llvm/CodeGen/MachineMemOperand.h"
2189b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
222d1f6d67SPete Couperus #include "llvm/Support/Debug.h"
232d1f6d67SPete Couperus
242d1f6d67SPete Couperus using namespace llvm;
252d1f6d67SPete Couperus
262d1f6d67SPete Couperus #define GET_INSTRINFO_CTOR_DTOR
272d1f6d67SPete Couperus #include "ARCGenInstrInfo.inc"
282d1f6d67SPete Couperus
292d1f6d67SPete Couperus #define DEBUG_TYPE "arc-inst-info"
309fd18488SPete Couperus
319fd18488SPete Couperus enum AddrIncType {
329fd18488SPete Couperus NoAddInc = 0,
339fd18488SPete Couperus PreInc = 1,
349fd18488SPete Couperus PostInc = 2,
359fd18488SPete Couperus Scaled = 3
369fd18488SPete Couperus };
379fd18488SPete Couperus
389fd18488SPete Couperus enum TSFlagsConstants {
399fd18488SPete Couperus TSF_AddrModeOff = 0,
409fd18488SPete Couperus TSF_AddModeMask = 3
419fd18488SPete Couperus };
429fd18488SPete Couperus
432d1f6d67SPete Couperus // Pin the vtable to this file.
anchor()442d1f6d67SPete Couperus void ARCInstrInfo::anchor() {}
452d1f6d67SPete Couperus
ARCInstrInfo(const ARCSubtarget & ST)46417f8ea4SMark Schimmel ARCInstrInfo::ARCInstrInfo(const ARCSubtarget &ST)
47*54405a49SFangrui Song : ARCGenInstrInfo(ARC::ADJCALLSTACKDOWN, ARC::ADJCALLSTACKUP), RI(ST) {}
482d1f6d67SPete Couperus
isZeroImm(const MachineOperand & Op)492d1f6d67SPete Couperus static bool isZeroImm(const MachineOperand &Op) {
502d1f6d67SPete Couperus return Op.isImm() && Op.getImm() == 0;
512d1f6d67SPete Couperus }
522d1f6d67SPete Couperus
isLoad(int Opcode)532d1f6d67SPete Couperus static bool isLoad(int Opcode) {
542d1f6d67SPete Couperus return Opcode == ARC::LD_rs9 || Opcode == ARC::LDH_rs9 ||
552d1f6d67SPete Couperus Opcode == ARC::LDB_rs9;
562d1f6d67SPete Couperus }
572d1f6d67SPete Couperus
isStore(int Opcode)582d1f6d67SPete Couperus static bool isStore(int Opcode) {
592d1f6d67SPete Couperus return Opcode == ARC::ST_rs9 || Opcode == ARC::STH_rs9 ||
602d1f6d67SPete Couperus Opcode == ARC::STB_rs9;
612d1f6d67SPete Couperus }
622d1f6d67SPete Couperus
632d1f6d67SPete Couperus /// If the specified machine instruction is a direct
642d1f6d67SPete Couperus /// load from a stack slot, return the virtual or physical register number of
652d1f6d67SPete Couperus /// the destination along with the FrameIndex of the loaded stack slot. If
662d1f6d67SPete Couperus /// not, return 0. This predicate must return 0 if the instruction has
672d1f6d67SPete Couperus /// any side effects other than loading from the stack slot.
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const682d1f6d67SPete Couperus unsigned ARCInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
692d1f6d67SPete Couperus int &FrameIndex) const {
702d1f6d67SPete Couperus int Opcode = MI.getOpcode();
712d1f6d67SPete Couperus if (isLoad(Opcode)) {
722d1f6d67SPete Couperus if ((MI.getOperand(1).isFI()) && // is a stack slot
732d1f6d67SPete Couperus (MI.getOperand(2).isImm()) && // the imm is zero
742d1f6d67SPete Couperus (isZeroImm(MI.getOperand(2)))) {
752d1f6d67SPete Couperus FrameIndex = MI.getOperand(1).getIndex();
762d1f6d67SPete Couperus return MI.getOperand(0).getReg();
772d1f6d67SPete Couperus }
782d1f6d67SPete Couperus }
792d1f6d67SPete Couperus return 0;
802d1f6d67SPete Couperus }
812d1f6d67SPete Couperus
822d1f6d67SPete Couperus /// If the specified machine instruction is a direct
832d1f6d67SPete Couperus /// store to a stack slot, return the virtual or physical register number of
842d1f6d67SPete Couperus /// the source reg along with the FrameIndex of the loaded stack slot. If
852d1f6d67SPete Couperus /// not, return 0. This predicate must return 0 if the instruction has
862d1f6d67SPete Couperus /// any side effects other than storing to the stack slot.
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const872d1f6d67SPete Couperus unsigned ARCInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
882d1f6d67SPete Couperus int &FrameIndex) const {
892d1f6d67SPete Couperus int Opcode = MI.getOpcode();
902d1f6d67SPete Couperus if (isStore(Opcode)) {
912d1f6d67SPete Couperus if ((MI.getOperand(1).isFI()) && // is a stack slot
922d1f6d67SPete Couperus (MI.getOperand(2).isImm()) && // the imm is zero
932d1f6d67SPete Couperus (isZeroImm(MI.getOperand(2)))) {
942d1f6d67SPete Couperus FrameIndex = MI.getOperand(1).getIndex();
952d1f6d67SPete Couperus return MI.getOperand(0).getReg();
962d1f6d67SPete Couperus }
972d1f6d67SPete Couperus }
982d1f6d67SPete Couperus return 0;
992d1f6d67SPete Couperus }
1002d1f6d67SPete Couperus
1012d1f6d67SPete Couperus /// Return the inverse of passed condition, i.e. turning COND_E to COND_NE.
getOppositeBranchCondition(ARCCC::CondCode CC)102417f8ea4SMark Schimmel static ARCCC::CondCode getOppositeBranchCondition(ARCCC::CondCode CC) {
1032d1f6d67SPete Couperus switch (CC) {
1042d1f6d67SPete Couperus default:
1052d1f6d67SPete Couperus llvm_unreachable("Illegal condition code!");
1062d1f6d67SPete Couperus case ARCCC::EQ:
1072d1f6d67SPete Couperus return ARCCC::NE;
1082d1f6d67SPete Couperus case ARCCC::NE:
1092d1f6d67SPete Couperus return ARCCC::EQ;
1102d1f6d67SPete Couperus case ARCCC::LO:
1112d1f6d67SPete Couperus return ARCCC::HS;
1122d1f6d67SPete Couperus case ARCCC::HS:
1132d1f6d67SPete Couperus return ARCCC::LO;
1142d1f6d67SPete Couperus case ARCCC::GT:
1152d1f6d67SPete Couperus return ARCCC::LE;
1162d1f6d67SPete Couperus case ARCCC::GE:
1172d1f6d67SPete Couperus return ARCCC::LT;
1188979eea0STatyana Krasnukha case ARCCC::VS:
1198979eea0STatyana Krasnukha return ARCCC::VC;
1208979eea0STatyana Krasnukha case ARCCC::VC:
1218979eea0STatyana Krasnukha return ARCCC::VS;
1222d1f6d67SPete Couperus case ARCCC::LT:
1232d1f6d67SPete Couperus return ARCCC::GE;
1242d1f6d67SPete Couperus case ARCCC::LE:
1252d1f6d67SPete Couperus return ARCCC::GT;
1262d1f6d67SPete Couperus case ARCCC::HI:
1272d1f6d67SPete Couperus return ARCCC::LS;
1282d1f6d67SPete Couperus case ARCCC::LS:
1292d1f6d67SPete Couperus return ARCCC::HI;
1302d1f6d67SPete Couperus case ARCCC::NZ:
1312d1f6d67SPete Couperus return ARCCC::Z;
1322d1f6d67SPete Couperus case ARCCC::Z:
1332d1f6d67SPete Couperus return ARCCC::NZ;
1342d1f6d67SPete Couperus }
1352d1f6d67SPete Couperus }
1362d1f6d67SPete Couperus
isUncondBranchOpcode(int Opc)1372d1f6d67SPete Couperus static bool isUncondBranchOpcode(int Opc) { return Opc == ARC::BR; }
1382d1f6d67SPete Couperus
isCondBranchOpcode(int Opc)1392d1f6d67SPete Couperus static bool isCondBranchOpcode(int Opc) {
1402d1f6d67SPete Couperus return Opc == ARC::BRcc_rr_p || Opc == ARC::BRcc_ru6_p;
1412d1f6d67SPete Couperus }
1422d1f6d67SPete Couperus
isJumpOpcode(int Opc)1432d1f6d67SPete Couperus static bool isJumpOpcode(int Opc) { return Opc == ARC::J; }
1442d1f6d67SPete Couperus
1452d1f6d67SPete Couperus /// Analyze the branching code at the end of MBB, returning
1462d1f6d67SPete Couperus /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
1472d1f6d67SPete Couperus /// implemented for a target). Upon success, this returns false and returns
1482d1f6d67SPete Couperus /// with the following information in various cases:
1492d1f6d67SPete Couperus ///
1502d1f6d67SPete Couperus /// 1. If this block ends with no branches (it just falls through to its succ)
1512d1f6d67SPete Couperus /// just return false, leaving TBB/FBB null.
1522d1f6d67SPete Couperus /// 2. If this block ends with only an unconditional branch, it sets TBB to be
1532d1f6d67SPete Couperus /// the destination block.
1542d1f6d67SPete Couperus /// 3. If this block ends with a conditional branch and it falls through to a
1552d1f6d67SPete Couperus /// successor block, it sets TBB to be the branch destination block and a
1562d1f6d67SPete Couperus /// list of operands that evaluate the condition. These operands can be
1572d1f6d67SPete Couperus /// passed to other TargetInstrInfo methods to create new branches.
1582d1f6d67SPete Couperus /// 4. If this block ends with a conditional branch followed by an
1592d1f6d67SPete Couperus /// unconditional branch, it returns the 'true' destination in TBB, the
1602d1f6d67SPete Couperus /// 'false' destination in FBB, and a list of operands that evaluate the
1612d1f6d67SPete Couperus /// condition. These operands can be passed to other TargetInstrInfo
1622d1f6d67SPete Couperus /// methods to create new branches.
1632d1f6d67SPete Couperus ///
164020041d9SKrzysztof Parzyszek /// Note that RemoveBranch and insertBranch must be implemented to support
1652d1f6d67SPete Couperus /// cases where this method returns success.
1662d1f6d67SPete Couperus ///
1672d1f6d67SPete Couperus /// If AllowModify is true, then this routine is allowed to modify the basic
1682d1f6d67SPete Couperus /// block (e.g. delete instructions after the unconditional branch).
1692d1f6d67SPete Couperus
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const1702d1f6d67SPete Couperus bool ARCInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
1712d1f6d67SPete Couperus MachineBasicBlock *&TBB,
1722d1f6d67SPete Couperus MachineBasicBlock *&FBB,
1732d1f6d67SPete Couperus SmallVectorImpl<MachineOperand> &Cond,
1742d1f6d67SPete Couperus bool AllowModify) const {
1752d1f6d67SPete Couperus TBB = FBB = nullptr;
1762d1f6d67SPete Couperus MachineBasicBlock::iterator I = MBB.end();
1772d1f6d67SPete Couperus if (I == MBB.begin())
1782d1f6d67SPete Couperus return false;
1792d1f6d67SPete Couperus --I;
1802d1f6d67SPete Couperus
1812d1f6d67SPete Couperus while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) {
1822d1f6d67SPete Couperus // Flag to be raised on unanalyzeable instructions. This is useful in cases
1832d1f6d67SPete Couperus // where we want to clean up on the end of the basic block before we bail
1842d1f6d67SPete Couperus // out.
1852d1f6d67SPete Couperus bool CantAnalyze = false;
1862d1f6d67SPete Couperus
1872d1f6d67SPete Couperus // Skip over DEBUG values and predicated nonterminators.
188801bf7ebSShiva Chen while (I->isDebugInstr() || !I->isTerminator()) {
1892d1f6d67SPete Couperus if (I == MBB.begin())
1902d1f6d67SPete Couperus return false;
1912d1f6d67SPete Couperus --I;
1922d1f6d67SPete Couperus }
1932d1f6d67SPete Couperus
1942d1f6d67SPete Couperus if (isJumpOpcode(I->getOpcode())) {
1952d1f6d67SPete Couperus // Indirect branches and jump tables can't be analyzed, but we still want
1962d1f6d67SPete Couperus // to clean up any instructions at the tail of the basic block.
1972d1f6d67SPete Couperus CantAnalyze = true;
1982d1f6d67SPete Couperus } else if (isUncondBranchOpcode(I->getOpcode())) {
1992d1f6d67SPete Couperus TBB = I->getOperand(0).getMBB();
2002d1f6d67SPete Couperus } else if (isCondBranchOpcode(I->getOpcode())) {
2012d1f6d67SPete Couperus // Bail out if we encounter multiple conditional branches.
2022d1f6d67SPete Couperus if (!Cond.empty())
2032d1f6d67SPete Couperus return true;
2042d1f6d67SPete Couperus
2052d1f6d67SPete Couperus assert(!FBB && "FBB should have been null.");
2062d1f6d67SPete Couperus FBB = TBB;
2072d1f6d67SPete Couperus TBB = I->getOperand(0).getMBB();
2082d1f6d67SPete Couperus Cond.push_back(I->getOperand(1));
2092d1f6d67SPete Couperus Cond.push_back(I->getOperand(2));
2102d1f6d67SPete Couperus Cond.push_back(I->getOperand(3));
2112d1f6d67SPete Couperus } else if (I->isReturn()) {
2122d1f6d67SPete Couperus // Returns can't be analyzed, but we should run cleanup.
2132d1f6d67SPete Couperus CantAnalyze = !isPredicated(*I);
2142d1f6d67SPete Couperus } else {
2152d1f6d67SPete Couperus // We encountered other unrecognized terminator. Bail out immediately.
2162d1f6d67SPete Couperus return true;
2172d1f6d67SPete Couperus }
2182d1f6d67SPete Couperus
2192d1f6d67SPete Couperus // Cleanup code - to be run for unpredicated unconditional branches and
2202d1f6d67SPete Couperus // returns.
2212d1f6d67SPete Couperus if (!isPredicated(*I) && (isUncondBranchOpcode(I->getOpcode()) ||
2222d1f6d67SPete Couperus isJumpOpcode(I->getOpcode()) || I->isReturn())) {
2232d1f6d67SPete Couperus // Forget any previous condition branch information - it no longer
2242d1f6d67SPete Couperus // applies.
2252d1f6d67SPete Couperus Cond.clear();
2262d1f6d67SPete Couperus FBB = nullptr;
2272d1f6d67SPete Couperus
2282d1f6d67SPete Couperus // If we can modify the function, delete everything below this
2292d1f6d67SPete Couperus // unconditional branch.
2302d1f6d67SPete Couperus if (AllowModify) {
2312d1f6d67SPete Couperus MachineBasicBlock::iterator DI = std::next(I);
2322d1f6d67SPete Couperus while (DI != MBB.end()) {
2332d1f6d67SPete Couperus MachineInstr &InstToDelete = *DI;
2342d1f6d67SPete Couperus ++DI;
2352d1f6d67SPete Couperus InstToDelete.eraseFromParent();
2362d1f6d67SPete Couperus }
2372d1f6d67SPete Couperus }
2382d1f6d67SPete Couperus }
2392d1f6d67SPete Couperus
2402d1f6d67SPete Couperus if (CantAnalyze)
2412d1f6d67SPete Couperus return true;
2422d1f6d67SPete Couperus
2432d1f6d67SPete Couperus if (I == MBB.begin())
2442d1f6d67SPete Couperus return false;
2452d1f6d67SPete Couperus
2462d1f6d67SPete Couperus --I;
2472d1f6d67SPete Couperus }
2482d1f6d67SPete Couperus
2492d1f6d67SPete Couperus // We made it past the terminators without bailing out - we must have
2502d1f6d67SPete Couperus // analyzed this branch successfully.
2512d1f6d67SPete Couperus return false;
2522d1f6d67SPete Couperus }
2532d1f6d67SPete Couperus
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const2542d1f6d67SPete Couperus unsigned ARCInstrInfo::removeBranch(MachineBasicBlock &MBB,
2552d1f6d67SPete Couperus int *BytesRemoved) const {
2562d1f6d67SPete Couperus assert(!BytesRemoved && "Code size not handled");
2572d1f6d67SPete Couperus MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
2582d1f6d67SPete Couperus if (I == MBB.end())
2592d1f6d67SPete Couperus return 0;
2602d1f6d67SPete Couperus
2612d1f6d67SPete Couperus if (!isUncondBranchOpcode(I->getOpcode()) &&
2622d1f6d67SPete Couperus !isCondBranchOpcode(I->getOpcode()))
2632d1f6d67SPete Couperus return 0;
2642d1f6d67SPete Couperus
2652d1f6d67SPete Couperus // Remove the branch.
2662d1f6d67SPete Couperus I->eraseFromParent();
2672d1f6d67SPete Couperus
2682d1f6d67SPete Couperus I = MBB.end();
2692d1f6d67SPete Couperus
2702d1f6d67SPete Couperus if (I == MBB.begin())
2712d1f6d67SPete Couperus return 1;
2722d1f6d67SPete Couperus --I;
2732d1f6d67SPete Couperus if (!isCondBranchOpcode(I->getOpcode()))
2742d1f6d67SPete Couperus return 1;
2752d1f6d67SPete Couperus
2762d1f6d67SPete Couperus // Remove the branch.
2772d1f6d67SPete Couperus I->eraseFromParent();
2782d1f6d67SPete Couperus return 2;
2792d1f6d67SPete Couperus }
2802d1f6d67SPete Couperus
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,MCRegister DestReg,MCRegister SrcReg,bool KillSrc) const2812d1f6d67SPete Couperus void ARCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
2822d1f6d67SPete Couperus MachineBasicBlock::iterator I,
283417f8ea4SMark Schimmel const DebugLoc &DL, MCRegister DestReg,
284e6c9a9afSMatt Arsenault MCRegister SrcReg, bool KillSrc) const {
2852d1f6d67SPete Couperus assert(ARC::GPR32RegClass.contains(SrcReg) &&
2862d1f6d67SPete Couperus "Only GPR32 src copy supported.");
2872d1f6d67SPete Couperus assert(ARC::GPR32RegClass.contains(DestReg) &&
2882d1f6d67SPete Couperus "Only GPR32 dest copy supported.");
289417f8ea4SMark Schimmel BuildMI(MBB, I, DL, get(ARC::MOV_rr), DestReg)
2902d1f6d67SPete Couperus .addReg(SrcReg, getKillRegState(KillSrc));
2912d1f6d67SPete Couperus }
2922d1f6d67SPete Couperus
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register SrcReg,bool IsKill,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const2932d1f6d67SPete Couperus void ARCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
2942d1f6d67SPete Couperus MachineBasicBlock::iterator I,
295417f8ea4SMark Schimmel Register SrcReg, bool IsKill,
2962d1f6d67SPete Couperus int FrameIndex,
2972d1f6d67SPete Couperus const TargetRegisterClass *RC,
2982d1f6d67SPete Couperus const TargetRegisterInfo *TRI) const {
299417f8ea4SMark Schimmel DebugLoc DL = MBB.findDebugLoc(I);
3002d1f6d67SPete Couperus MachineFunction &MF = *MBB.getParent();
3012d1f6d67SPete Couperus MachineFrameInfo &MFI = MF.getFrameInfo();
3022d1f6d67SPete Couperus
3032d1f6d67SPete Couperus MachineMemOperand *MMO = MF.getMachineMemOperand(
3042d1f6d67SPete Couperus MachinePointerInfo::getFixedStack(MF, FrameIndex),
305b9810988SGuillaume Chatelet MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
306b9810988SGuillaume Chatelet MFI.getObjectAlign(FrameIndex));
3072d1f6d67SPete Couperus
3082d1f6d67SPete Couperus assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
3092d1f6d67SPete Couperus assert(TRI->getSpillSize(*RC) == 4 &&
3102d1f6d67SPete Couperus "Only support 4-byte stores to stack now.");
3112d1f6d67SPete Couperus assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
3122d1f6d67SPete Couperus "Only support GPR32 stores to stack now.");
313d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Created store reg=" << printReg(SrcReg, TRI)
3142d1f6d67SPete Couperus << " to FrameIndex=" << FrameIndex << "\n");
315417f8ea4SMark Schimmel BuildMI(MBB, I, DL, get(ARC::ST_rs9))
316417f8ea4SMark Schimmel .addReg(SrcReg, getKillRegState(IsKill))
3172d1f6d67SPete Couperus .addFrameIndex(FrameIndex)
3182d1f6d67SPete Couperus .addImm(0)
3192d1f6d67SPete Couperus .addMemOperand(MMO);
3202d1f6d67SPete Couperus }
3212d1f6d67SPete Couperus
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register DestReg,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const3222d1f6d67SPete Couperus void ARCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
3232d1f6d67SPete Couperus MachineBasicBlock::iterator I,
3245c8ba508SSimon Moll Register DestReg, int FrameIndex,
3252d1f6d67SPete Couperus const TargetRegisterClass *RC,
3262d1f6d67SPete Couperus const TargetRegisterInfo *TRI) const {
327417f8ea4SMark Schimmel DebugLoc DL = MBB.findDebugLoc(I);
3282d1f6d67SPete Couperus MachineFunction &MF = *MBB.getParent();
3292d1f6d67SPete Couperus MachineFrameInfo &MFI = MF.getFrameInfo();
3302d1f6d67SPete Couperus MachineMemOperand *MMO = MF.getMachineMemOperand(
3312d1f6d67SPete Couperus MachinePointerInfo::getFixedStack(MF, FrameIndex),
332b9810988SGuillaume Chatelet MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
333b9810988SGuillaume Chatelet MFI.getObjectAlign(FrameIndex));
3342d1f6d67SPete Couperus
3352d1f6d67SPete Couperus assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
3362d1f6d67SPete Couperus assert(TRI->getSpillSize(*RC) == 4 &&
3372d1f6d67SPete Couperus "Only support 4-byte loads from stack now.");
3382d1f6d67SPete Couperus assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
3392d1f6d67SPete Couperus "Only support GPR32 stores to stack now.");
340d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Created load reg=" << printReg(DestReg, TRI)
3412d1f6d67SPete Couperus << " from FrameIndex=" << FrameIndex << "\n");
342417f8ea4SMark Schimmel BuildMI(MBB, I, DL, get(ARC::LD_rs9))
3432d1f6d67SPete Couperus .addReg(DestReg, RegState::Define)
3442d1f6d67SPete Couperus .addFrameIndex(FrameIndex)
3452d1f6d67SPete Couperus .addImm(0)
3462d1f6d67SPete Couperus .addMemOperand(MMO);
3472d1f6d67SPete Couperus }
3482d1f6d67SPete Couperus
3492d1f6d67SPete Couperus /// Return the inverse opcode of the specified Branch instruction.
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const3502d1f6d67SPete Couperus bool ARCInstrInfo::reverseBranchCondition(
3512d1f6d67SPete Couperus SmallVectorImpl<MachineOperand> &Cond) const {
3522d1f6d67SPete Couperus assert((Cond.size() == 3) && "Invalid ARC branch condition!");
353417f8ea4SMark Schimmel Cond[2].setImm(getOppositeBranchCondition((ARCCC::CondCode)Cond[2].getImm()));
3542d1f6d67SPete Couperus return false;
3552d1f6d67SPete Couperus }
3562d1f6d67SPete Couperus
3572d1f6d67SPete Couperus MachineBasicBlock::iterator
loadImmediate(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,unsigned Reg,uint64_t Value) const3582d1f6d67SPete Couperus ARCInstrInfo::loadImmediate(MachineBasicBlock &MBB,
3592d1f6d67SPete Couperus MachineBasicBlock::iterator MI, unsigned Reg,
3602d1f6d67SPete Couperus uint64_t Value) const {
361417f8ea4SMark Schimmel DebugLoc DL = MBB.findDebugLoc(MI);
3622d1f6d67SPete Couperus if (isInt<12>(Value)) {
363417f8ea4SMark Schimmel return BuildMI(MBB, MI, DL, get(ARC::MOV_rs12), Reg)
3642d1f6d67SPete Couperus .addImm(Value)
3652d1f6d67SPete Couperus .getInstr();
3662d1f6d67SPete Couperus }
3672d1f6d67SPete Couperus llvm_unreachable("Need Arc long immediate instructions.");
3682d1f6d67SPete Couperus }
3692d1f6d67SPete Couperus
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const3702d1f6d67SPete Couperus unsigned ARCInstrInfo::insertBranch(MachineBasicBlock &MBB,
3712d1f6d67SPete Couperus MachineBasicBlock *TBB,
3722d1f6d67SPete Couperus MachineBasicBlock *FBB,
3732d1f6d67SPete Couperus ArrayRef<MachineOperand> Cond,
374417f8ea4SMark Schimmel const DebugLoc &DL, int *BytesAdded) const {
3752d1f6d67SPete Couperus assert(!BytesAdded && "Code size not handled.");
3762d1f6d67SPete Couperus
3772d1f6d67SPete Couperus // Shouldn't be a fall through.
378020041d9SKrzysztof Parzyszek assert(TBB && "insertBranch must not be told to insert a fallthrough");
3792d1f6d67SPete Couperus assert((Cond.size() == 3 || Cond.size() == 0) &&
3802d1f6d67SPete Couperus "ARC branch conditions have two components!");
3812d1f6d67SPete Couperus
3822d1f6d67SPete Couperus if (Cond.empty()) {
383417f8ea4SMark Schimmel BuildMI(&MBB, DL, get(ARC::BR)).addMBB(TBB);
3842d1f6d67SPete Couperus return 1;
3852d1f6d67SPete Couperus }
3862d1f6d67SPete Couperus int BccOpc = Cond[1].isImm() ? ARC::BRcc_ru6_p : ARC::BRcc_rr_p;
387417f8ea4SMark Schimmel MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(BccOpc));
3882d1f6d67SPete Couperus MIB.addMBB(TBB);
3892d1f6d67SPete Couperus for (unsigned i = 0; i < 3; i++) {
3902d1f6d67SPete Couperus MIB.add(Cond[i]);
3912d1f6d67SPete Couperus }
3922d1f6d67SPete Couperus
3932d1f6d67SPete Couperus // One-way conditional branch.
3942d1f6d67SPete Couperus if (!FBB) {
3952d1f6d67SPete Couperus return 1;
3962d1f6d67SPete Couperus }
3972d1f6d67SPete Couperus
3982d1f6d67SPete Couperus // Two-way conditional branch.
399417f8ea4SMark Schimmel BuildMI(&MBB, DL, get(ARC::BR)).addMBB(FBB);
4002d1f6d67SPete Couperus return 2;
4012d1f6d67SPete Couperus }
4022d1f6d67SPete Couperus
getInstSizeInBytes(const MachineInstr & MI) const4032d1f6d67SPete Couperus unsigned ARCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
404c45e39b3SCraig Topper if (MI.isInlineAsm()) {
4052d1f6d67SPete Couperus const MachineFunction *MF = MI.getParent()->getParent();
4062d1f6d67SPete Couperus const char *AsmStr = MI.getOperand(0).getSymbolName();
4072d1f6d67SPete Couperus return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
4082d1f6d67SPete Couperus }
4092d1f6d67SPete Couperus return MI.getDesc().getSize();
4102d1f6d67SPete Couperus }
4119fd18488SPete Couperus
isPostIncrement(const MachineInstr & MI) const4129fd18488SPete Couperus bool ARCInstrInfo::isPostIncrement(const MachineInstr &MI) const {
4139fd18488SPete Couperus const MCInstrDesc &MID = MI.getDesc();
4149fd18488SPete Couperus const uint64_t F = MID.TSFlags;
4159fd18488SPete Couperus return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PostInc;
4169fd18488SPete Couperus }
4179fd18488SPete Couperus
isPreIncrement(const MachineInstr & MI) const4189fd18488SPete Couperus bool ARCInstrInfo::isPreIncrement(const MachineInstr &MI) const {
4199fd18488SPete Couperus const MCInstrDesc &MID = MI.getDesc();
4209fd18488SPete Couperus const uint64_t F = MID.TSFlags;
4219fd18488SPete Couperus return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PreInc;
4229fd18488SPete Couperus }
4239fd18488SPete Couperus
getBaseAndOffsetPosition(const MachineInstr & MI,unsigned & BasePos,unsigned & OffsetPos) const4249fd18488SPete Couperus bool ARCInstrInfo::getBaseAndOffsetPosition(const MachineInstr &MI,
4259fd18488SPete Couperus unsigned &BasePos,
4269fd18488SPete Couperus unsigned &OffsetPos) const {
4279fd18488SPete Couperus if (!MI.mayLoad() && !MI.mayStore())
4289fd18488SPete Couperus return false;
4299fd18488SPete Couperus
4309fd18488SPete Couperus BasePos = 1;
4319fd18488SPete Couperus OffsetPos = 2;
4329fd18488SPete Couperus
4339fd18488SPete Couperus if (isPostIncrement(MI) || isPreIncrement(MI)) {
4349fd18488SPete Couperus BasePos++;
4359fd18488SPete Couperus OffsetPos++;
4369fd18488SPete Couperus }
4379fd18488SPete Couperus
4389fd18488SPete Couperus if (!MI.getOperand(BasePos).isReg() || !MI.getOperand(OffsetPos).isImm())
4399fd18488SPete Couperus return false;
4409fd18488SPete Couperus
4419fd18488SPete Couperus return true;
4429fd18488SPete Couperus }
443