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