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