| //===- llvm/CodeGen/GlobalISel/GenericMachineInstrs.h -----------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// \file |
| /// Declares convenience wrapper classes for interpreting MachineInstr instances |
| /// as specific generic operations. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H |
| #define LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H |
| |
| #include "llvm/CodeGen/MachineInstr.h" |
| #include "llvm/CodeGen/MachineMemOperand.h" |
| #include "llvm/CodeGen/TargetOpcodes.h" |
| #include "llvm/Support/Casting.h" |
| |
| namespace llvm { |
| |
| /// A base class for all GenericMachineInstrs. |
| class GenericMachineInstr : public MachineInstr { |
| public: |
| GenericMachineInstr() = delete; |
| |
| /// Access the Idx'th operand as a register and return it. |
| /// This assumes that the Idx'th operand is a Register type. |
| Register getReg(unsigned Idx) const { return getOperand(Idx).getReg(); } |
| |
| static bool classof(const MachineInstr *MI) { |
| return isPreISelGenericOpcode(MI->getOpcode()); |
| } |
| }; |
| |
| /// Represents any type of generic load or store. |
| /// G_LOAD, G_STORE, G_ZEXTLOAD, G_SEXTLOAD. |
| class GLoadStore : public GenericMachineInstr { |
| public: |
| /// Get the source register of the pointer value. |
| Register getPointerReg() const { return getOperand(1).getReg(); } |
| |
| /// Get the MachineMemOperand on this instruction. |
| MachineMemOperand &getMMO() const { return **memoperands_begin(); } |
| |
| /// Returns true if the attached MachineMemOperand has the atomic flag set. |
| bool isAtomic() const { return getMMO().isAtomic(); } |
| /// Returns true if the attached MachineMemOpeand as the volatile flag set. |
| bool isVolatile() const { return getMMO().isVolatile(); } |
| /// Returns true if the memory operation is neither atomic or volatile. |
| bool isSimple() const { return !isAtomic() && !isVolatile(); } |
| /// Returns true if this memory operation doesn't have any ordering |
| /// constraints other than normal aliasing. Volatile and (ordered) atomic |
| /// memory operations can't be reordered. |
| bool isUnordered() const { return getMMO().isUnordered(); } |
| |
| /// Returns the size in bytes of the memory access. |
| uint64_t getMemSize() const { return getMMO().getSize(); |
| } /// Returns the size in bits of the memory access. |
| uint64_t getMemSizeInBits() const { return getMMO().getSizeInBits(); } |
| |
| static bool classof(const MachineInstr *MI) { |
| switch (MI->getOpcode()) { |
| case TargetOpcode::G_LOAD: |
| case TargetOpcode::G_STORE: |
| case TargetOpcode::G_ZEXTLOAD: |
| case TargetOpcode::G_SEXTLOAD: |
| return true; |
| default: |
| return false; |
| } |
| } |
| }; |
| |
| /// Represents any generic load, including sign/zero extending variants. |
| class GAnyLoad : public GLoadStore { |
| public: |
| /// Get the definition register of the loaded value. |
| Register getDstReg() const { return getOperand(0).getReg(); } |
| |
| static bool classof(const MachineInstr *MI) { |
| switch (MI->getOpcode()) { |
| case TargetOpcode::G_LOAD: |
| case TargetOpcode::G_ZEXTLOAD: |
| case TargetOpcode::G_SEXTLOAD: |
| return true; |
| default: |
| return false; |
| } |
| } |
| }; |
| |
| /// Represents a G_LOAD. |
| class GLoad : public GAnyLoad { |
| public: |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_LOAD; |
| } |
| }; |
| |
| /// Represents either a G_SEXTLOAD or G_ZEXTLOAD. |
| class GExtLoad : public GAnyLoad { |
| public: |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_SEXTLOAD || |
| MI->getOpcode() == TargetOpcode::G_ZEXTLOAD; |
| } |
| }; |
| |
| /// Represents a G_SEXTLOAD. |
| class GSExtLoad : public GExtLoad { |
| public: |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_SEXTLOAD; |
| } |
| }; |
| |
| /// Represents a G_ZEXTLOAD. |
| class GZExtLoad : public GExtLoad { |
| public: |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_ZEXTLOAD; |
| } |
| }; |
| |
| /// Represents a G_STORE. |
| class GStore : public GLoadStore { |
| public: |
| /// Get the stored value register. |
| Register getValueReg() const { return getOperand(0).getReg(); } |
| |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_STORE; |
| } |
| }; |
| |
| /// Represents a G_UNMERGE_VALUES. |
| class GUnmerge : public GenericMachineInstr { |
| public: |
| /// Returns the number of def registers. |
| unsigned getNumDefs() const { return getNumOperands() - 1; } |
| /// Get the unmerge source register. |
| Register getSourceReg() const { return getOperand(getNumDefs()).getReg(); } |
| |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES; |
| } |
| }; |
| |
| /// Represents G_BUILD_VECTOR, G_CONCAT_VECTORS or G_MERGE_VALUES. |
| /// All these have the common property of generating a single value from |
| /// multiple sources. |
| class GMergeLikeOp : public GenericMachineInstr { |
| public: |
| /// Returns the number of source registers. |
| unsigned getNumSources() const { return getNumOperands() - 1; } |
| /// Returns the I'th source register. |
| Register getSourceReg(unsigned I) const { return getReg(I + 1); } |
| |
| static bool classof(const MachineInstr *MI) { |
| switch (MI->getOpcode()) { |
| case TargetOpcode::G_MERGE_VALUES: |
| case TargetOpcode::G_CONCAT_VECTORS: |
| case TargetOpcode::G_BUILD_VECTOR: |
| return true; |
| default: |
| return false; |
| } |
| } |
| }; |
| |
| /// Represents a G_MERGE_VALUES. |
| class GMerge : public GMergeLikeOp { |
| public: |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_MERGE_VALUES; |
| } |
| }; |
| |
| /// Represents a G_CONCAT_VECTORS. |
| class GConcatVectors : public GMergeLikeOp { |
| public: |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS; |
| } |
| }; |
| |
| /// Represents a G_BUILD_VECTOR. |
| class GBuildVector : public GMergeLikeOp { |
| public: |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR; |
| } |
| }; |
| |
| /// Represents a G_PTR_ADD. |
| class GPtrAdd : public GenericMachineInstr { |
| public: |
| Register getBaseReg() const { return getReg(1); } |
| Register getOffsetReg() const { return getReg(2); } |
| |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_PTR_ADD; |
| } |
| }; |
| |
| /// Represents a G_IMPLICIT_DEF. |
| class GImplicitDef : public GenericMachineInstr { |
| public: |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF; |
| } |
| }; |
| |
| /// Represents a G_SELECT. |
| class GSelect : public GenericMachineInstr { |
| public: |
| Register getCondReg() const { return getReg(1); } |
| Register getTrueReg() const { return getReg(2); } |
| Register getFalseReg() const { return getReg(3); } |
| |
| static bool classof(const MachineInstr *MI) { |
| return MI->getOpcode() == TargetOpcode::G_SELECT; |
| } |
| }; |
| |
| } // namespace llvm |
| |
| #endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H |