10b57cec5SDimitry Andric //===- MipsInstrInfo.h - Mips 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 Mips implementation of the TargetInstrInfo class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // FIXME: We need to override TargetInstrInfo::getInlineAsmLength method in 120b57cec5SDimitry Andric // order for MipsLongBranch pass to work correctly when the code has inline 130b57cec5SDimitry Andric // assembly. The returned value doesn't have to be the asm instruction's exact 140b57cec5SDimitry Andric // size in bytes; MipsLongBranch only expects it to be the correct upper bound. 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H 180b57cec5SDimitry Andric #define LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h" 210b57cec5SDimitry Andric #include "Mips.h" 220b57cec5SDimitry Andric #include "MipsRegisterInfo.h" 230b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 280b57cec5SDimitry Andric #include <cstdint> 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric #define GET_INSTRINFO_HEADER 310b57cec5SDimitry Andric #include "MipsGenInstrInfo.inc" 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace llvm { 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric class MachineInstr; 360b57cec5SDimitry Andric class MachineOperand; 370b57cec5SDimitry Andric class MipsSubtarget; 380b57cec5SDimitry Andric class TargetRegisterClass; 390b57cec5SDimitry Andric class TargetRegisterInfo; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric class MipsInstrInfo : public MipsGenInstrInfo { 420b57cec5SDimitry Andric virtual void anchor(); 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric protected: 450b57cec5SDimitry Andric const MipsSubtarget &Subtarget; 460b57cec5SDimitry Andric unsigned UncondBrOpc; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric public: 490b57cec5SDimitry Andric enum BranchType { 500b57cec5SDimitry Andric BT_None, // Couldn't analyze branch. 510b57cec5SDimitry Andric BT_NoBranch, // No branches found. 520b57cec5SDimitry Andric BT_Uncond, // One unconditional branch. 530b57cec5SDimitry Andric BT_Cond, // One conditional branch. 540b57cec5SDimitry Andric BT_CondUncond, // A conditional branch followed by an unconditional branch. 550b57cec5SDimitry Andric BT_Indirect // One indirct branch. 560b57cec5SDimitry Andric }; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric explicit MipsInstrInfo(const MipsSubtarget &STI, unsigned UncondBrOpc); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric static const MipsInstrInfo *create(MipsSubtarget &STI); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// Branch Analysis 630b57cec5SDimitry Andric bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 640b57cec5SDimitry Andric MachineBasicBlock *&FBB, 650b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 660b57cec5SDimitry Andric bool AllowModify) const override; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric unsigned removeBranch(MachineBasicBlock &MBB, 690b57cec5SDimitry Andric int *BytesRemoved = nullptr) const override; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 720b57cec5SDimitry Andric MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, 730b57cec5SDimitry Andric const DebugLoc &DL, 740b57cec5SDimitry Andric int *BytesAdded = nullptr) const override; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric bool 770b57cec5SDimitry Andric reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric BranchType analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 800b57cec5SDimitry Andric MachineBasicBlock *&FBB, 810b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 820b57cec5SDimitry Andric bool AllowModify, 830b57cec5SDimitry Andric SmallVectorImpl<MachineInstr *> &BranchInstrs) const; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric /// Determine the opcode of a non-delay slot form for a branch if one exists. 860b57cec5SDimitry Andric unsigned getEquivalentCompactForm(const MachineBasicBlock::iterator I) const; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric /// Determine if the branch target is in range. 890b57cec5SDimitry Andric bool isBranchOffsetInRange(unsigned BranchOpc, 900b57cec5SDimitry Andric int64_t BrOffset) const override; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /// Predicate to determine if an instruction can go in a forbidden slot. 930b57cec5SDimitry Andric bool SafeInForbiddenSlot(const MachineInstr &MI) const; 940b57cec5SDimitry Andric 950eae32dcSDimitry Andric /// Predicate to determine if an instruction can go in an FPU delay slot. 960eae32dcSDimitry Andric bool SafeInFPUDelaySlot(const MachineInstr &MIInSlot, 970eae32dcSDimitry Andric const MachineInstr &FPUMI) const; 980eae32dcSDimitry Andric 9981ad6265SDimitry Andric /// Predicate to determine if an instruction can go in a load delay slot. 10081ad6265SDimitry Andric bool SafeInLoadDelaySlot(const MachineInstr &MIInSlot, 10181ad6265SDimitry Andric const MachineInstr &LoadMI) const; 10281ad6265SDimitry Andric 1030b57cec5SDimitry Andric /// Predicate to determine if an instruction has a forbidden slot. 1040b57cec5SDimitry Andric bool HasForbiddenSlot(const MachineInstr &MI) const; 1050b57cec5SDimitry Andric 1060eae32dcSDimitry Andric /// Predicate to determine if an instruction has an FPU delay slot. 1070eae32dcSDimitry Andric bool HasFPUDelaySlot(const MachineInstr &MI) const; 1080eae32dcSDimitry Andric 10981ad6265SDimitry Andric /// Predicate to determine if an instruction has a load delay slot. 11081ad6265SDimitry Andric bool HasLoadDelaySlot(const MachineInstr &MI) const; 11181ad6265SDimitry Andric 1120b57cec5SDimitry Andric /// Insert nop instruction when hazard condition is found 1130b57cec5SDimitry Andric void insertNoop(MachineBasicBlock &MBB, 1140b57cec5SDimitry Andric MachineBasicBlock::iterator MI) const override; 1150b57cec5SDimitry Andric 11681ad6265SDimitry Andric /// Insert an ISA appropriate `nop`. 11781ad6265SDimitry Andric // FIXME: Add support for MIPS16e. 11881ad6265SDimitry Andric MachineInstrBuilder insertNop(MachineBasicBlock &MBB, 11981ad6265SDimitry Andric MachineBasicBlock::iterator MI, 12081ad6265SDimitry Andric DebugLoc DL) const; 12181ad6265SDimitry Andric 1220b57cec5SDimitry Andric /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As 1230b57cec5SDimitry Andric /// such, whenever a client has an instance of instruction info, it should 1240b57cec5SDimitry Andric /// always be able to get register info as well (through this method). 1250b57cec5SDimitry Andric virtual const MipsRegisterInfo &getRegisterInfo() const = 0; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric virtual unsigned getOppositeBranchOpc(unsigned Opc) const = 0; 1280b57cec5SDimitry Andric isBranchWithImm(unsigned Opc)1295ffd83dbSDimitry Andric virtual bool isBranchWithImm(unsigned Opc) const { 1305ffd83dbSDimitry Andric return false; 1315ffd83dbSDimitry Andric } 1325ffd83dbSDimitry Andric 1330b57cec5SDimitry Andric /// Return the number of bytes of code the specified instruction may be. 1340b57cec5SDimitry Andric unsigned getInstSizeInBytes(const MachineInstr &MI) const override; 1350b57cec5SDimitry Andric storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,Register SrcReg,bool isKill,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg)1360b57cec5SDimitry Andric void storeRegToStackSlot(MachineBasicBlock &MBB, 137*bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI, Register SrcReg, 138*bdd1243dSDimitry Andric bool isKill, int FrameIndex, 1390b57cec5SDimitry Andric const TargetRegisterClass *RC, 140*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 141*bdd1243dSDimitry Andric Register VReg) const override { 1420b57cec5SDimitry Andric storeRegToStack(MBB, MBBI, SrcReg, isKill, FrameIndex, RC, TRI, 0); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,Register DestReg,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg)1450b57cec5SDimitry Andric void loadRegFromStackSlot(MachineBasicBlock &MBB, 146*bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI, Register DestReg, 147*bdd1243dSDimitry Andric int FrameIndex, const TargetRegisterClass *RC, 148*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 149*bdd1243dSDimitry Andric Register VReg) const override { 1500b57cec5SDimitry Andric loadRegFromStack(MBB, MBBI, DestReg, FrameIndex, RC, TRI, 0); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric virtual void storeRegToStack(MachineBasicBlock &MBB, 1540b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 1555ffd83dbSDimitry Andric Register SrcReg, bool isKill, int FrameIndex, 1560b57cec5SDimitry Andric const TargetRegisterClass *RC, 1570b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 1580b57cec5SDimitry Andric int64_t Offset) const = 0; 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric virtual void loadRegFromStack(MachineBasicBlock &MBB, 1610b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 1625ffd83dbSDimitry Andric Register DestReg, int FrameIndex, 1630b57cec5SDimitry Andric const TargetRegisterClass *RC, 1640b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 1650b57cec5SDimitry Andric int64_t Offset) const = 0; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric virtual void adjustStackPtr(unsigned SP, int64_t Amount, 1680b57cec5SDimitry Andric MachineBasicBlock &MBB, 1690b57cec5SDimitry Andric MachineBasicBlock::iterator I) const = 0; 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric /// Create an instruction which has the same operands and memory operands 1720b57cec5SDimitry Andric /// as MI but has a new opcode. 1730b57cec5SDimitry Andric MachineInstrBuilder genInstrWithNewOpc(unsigned NewOpc, 1740b57cec5SDimitry Andric MachineBasicBlock::iterator I) const; 1750b57cec5SDimitry Andric 1768bcb0991SDimitry Andric bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, 1770b57cec5SDimitry Andric unsigned &SrcOpIdx2) const override; 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric /// Perform target specific instruction verification. 1800b57cec5SDimitry Andric bool verifyInstruction(const MachineInstr &MI, 1810b57cec5SDimitry Andric StringRef &ErrInfo) const override; 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric std::pair<unsigned, unsigned> 1840b57cec5SDimitry Andric decomposeMachineOperandsTargetFlags(unsigned TF) const override; 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric ArrayRef<std::pair<unsigned, const char *>> 1870b57cec5SDimitry Andric getSerializableDirectMachineOperandTargetFlags() const override; 1880b57cec5SDimitry Andric 189*bdd1243dSDimitry Andric std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI, 1905ffd83dbSDimitry Andric Register Reg) const override; 1915ffd83dbSDimitry Andric 192*bdd1243dSDimitry Andric std::optional<ParamLoadedValue> 193*bdd1243dSDimitry Andric describeLoadedValue(const MachineInstr &MI, Register Reg) const override; 1945ffd83dbSDimitry Andric 1950b57cec5SDimitry Andric protected: 1960b57cec5SDimitry Andric bool isZeroImm(const MachineOperand &op) const; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric MachineMemOperand *GetMemOperand(MachineBasicBlock &MBB, int FI, 1990b57cec5SDimitry Andric MachineMemOperand::Flags Flags) const; 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric private: 2020b57cec5SDimitry Andric virtual unsigned getAnalyzableBrOpc(unsigned Opc) const = 0; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric void AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, 2050b57cec5SDimitry Andric MachineBasicBlock *&BB, 2060b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond) const; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric void BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 2090b57cec5SDimitry Andric const DebugLoc &DL, ArrayRef<MachineOperand> Cond) const; 2100b57cec5SDimitry Andric }; 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric /// Create MipsInstrInfo objects. 2130b57cec5SDimitry Andric const MipsInstrInfo *createMips16InstrInfo(const MipsSubtarget &STI); 2140b57cec5SDimitry Andric const MipsInstrInfo *createMipsSEInstrInfo(const MipsSubtarget &STI); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric } // end namespace llvm 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H 219