xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsInstrInfo.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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