#pragma once #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif //===- 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/IR/Instructions.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 GMergeLikeInstr : 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 GMergeLikeInstr { public: static bool classof(const MachineInstr *MI) { return MI->getOpcode() == TargetOpcode::G_MERGE_VALUES; } }; /// Represents a G_CONCAT_VECTORS. class GConcatVectors : public GMergeLikeInstr { public: static bool classof(const MachineInstr *MI) { return MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS; } }; /// Represents a G_BUILD_VECTOR. class GBuildVector : public GMergeLikeInstr { 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; } }; /// Represent a G_ICMP or G_FCMP. class GAnyCmp : public GenericMachineInstr { public: CmpInst::Predicate getCond() const { return static_cast(getOperand(1).getPredicate()); } Register getLHSReg() const { return getReg(2); } Register getRHSReg() const { return getReg(3); } static bool classof(const MachineInstr *MI) { return MI->getOpcode() == TargetOpcode::G_ICMP || MI->getOpcode() == TargetOpcode::G_FCMP; } }; /// Represent a G_ICMP. class GICmp : public GAnyCmp { public: static bool classof(const MachineInstr *MI) { return MI->getOpcode() == TargetOpcode::G_ICMP; } }; /// Represent a G_FCMP. class GFCmp : public GAnyCmp { public: static bool classof(const MachineInstr *MI) { return MI->getOpcode() == TargetOpcode::G_FCMP; } }; } // namespace llvm #endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H #ifdef __GNUC__ #pragma GCC diagnostic pop #endif