Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 1 | //===- llvm/CodeGen/GlobalISel/GenericMachineInstrs.h -----------*- C++ -*-===// |
| 2 | // |
||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
| 6 | // |
||
| 7 | //===----------------------------------------------------------------------===// |
||
| 8 | /// \file |
||
| 9 | /// Declares convenience wrapper classes for interpreting MachineInstr instances |
||
| 10 | /// as specific generic operations. |
||
| 11 | /// |
||
| 12 | //===----------------------------------------------------------------------===// |
||
| 13 | |||
| 14 | #ifndef LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H |
||
| 15 | #define LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H |
||
| 16 | |||
| 17 | #include "llvm/IR/Instructions.h" |
||
| 18 | #include "llvm/CodeGen/MachineInstr.h" |
||
| 19 | #include "llvm/CodeGen/MachineMemOperand.h" |
||
| 20 | #include "llvm/CodeGen/TargetOpcodes.h" |
||
| 21 | #include "llvm/Support/Casting.h" |
||
| 22 | |||
| 23 | namespace llvm { |
||
| 24 | |||
| 25 | /// A base class for all GenericMachineInstrs. |
||
| 26 | class GenericMachineInstr : public MachineInstr { |
||
| 27 | public: |
||
| 28 | GenericMachineInstr() = delete; |
||
| 29 | |||
| 30 | /// Access the Idx'th operand as a register and return it. |
||
| 31 | /// This assumes that the Idx'th operand is a Register type. |
||
| 32 | Register getReg(unsigned Idx) const { return getOperand(Idx).getReg(); } |
||
| 33 | |||
| 34 | static bool classof(const MachineInstr *MI) { |
||
| 35 | return isPreISelGenericOpcode(MI->getOpcode()); |
||
| 36 | } |
||
| 37 | }; |
||
| 38 | |||
| 39 | /// Represents any type of generic load or store. |
||
| 40 | /// G_LOAD, G_STORE, G_ZEXTLOAD, G_SEXTLOAD. |
||
| 41 | class GLoadStore : public GenericMachineInstr { |
||
| 42 | public: |
||
| 43 | /// Get the source register of the pointer value. |
||
| 44 | Register getPointerReg() const { return getOperand(1).getReg(); } |
||
| 45 | |||
| 46 | /// Get the MachineMemOperand on this instruction. |
||
| 47 | MachineMemOperand &getMMO() const { return **memoperands_begin(); } |
||
| 48 | |||
| 49 | /// Returns true if the attached MachineMemOperand has the atomic flag set. |
||
| 50 | bool isAtomic() const { return getMMO().isAtomic(); } |
||
| 51 | /// Returns true if the attached MachineMemOpeand as the volatile flag set. |
||
| 52 | bool isVolatile() const { return getMMO().isVolatile(); } |
||
| 53 | /// Returns true if the memory operation is neither atomic or volatile. |
||
| 54 | bool isSimple() const { return !isAtomic() && !isVolatile(); } |
||
| 55 | /// Returns true if this memory operation doesn't have any ordering |
||
| 56 | /// constraints other than normal aliasing. Volatile and (ordered) atomic |
||
| 57 | /// memory operations can't be reordered. |
||
| 58 | bool isUnordered() const { return getMMO().isUnordered(); } |
||
| 59 | |||
| 60 | /// Returns the size in bytes of the memory access. |
||
| 61 | uint64_t getMemSize() const { return getMMO().getSize(); |
||
| 62 | } /// Returns the size in bits of the memory access. |
||
| 63 | uint64_t getMemSizeInBits() const { return getMMO().getSizeInBits(); } |
||
| 64 | |||
| 65 | static bool classof(const MachineInstr *MI) { |
||
| 66 | switch (MI->getOpcode()) { |
||
| 67 | case TargetOpcode::G_LOAD: |
||
| 68 | case TargetOpcode::G_STORE: |
||
| 69 | case TargetOpcode::G_ZEXTLOAD: |
||
| 70 | case TargetOpcode::G_SEXTLOAD: |
||
| 71 | return true; |
||
| 72 | default: |
||
| 73 | return false; |
||
| 74 | } |
||
| 75 | } |
||
| 76 | }; |
||
| 77 | |||
| 78 | /// Represents any generic load, including sign/zero extending variants. |
||
| 79 | class GAnyLoad : public GLoadStore { |
||
| 80 | public: |
||
| 81 | /// Get the definition register of the loaded value. |
||
| 82 | Register getDstReg() const { return getOperand(0).getReg(); } |
||
| 83 | |||
| 84 | static bool classof(const MachineInstr *MI) { |
||
| 85 | switch (MI->getOpcode()) { |
||
| 86 | case TargetOpcode::G_LOAD: |
||
| 87 | case TargetOpcode::G_ZEXTLOAD: |
||
| 88 | case TargetOpcode::G_SEXTLOAD: |
||
| 89 | return true; |
||
| 90 | default: |
||
| 91 | return false; |
||
| 92 | } |
||
| 93 | } |
||
| 94 | }; |
||
| 95 | |||
| 96 | /// Represents a G_LOAD. |
||
| 97 | class GLoad : public GAnyLoad { |
||
| 98 | public: |
||
| 99 | static bool classof(const MachineInstr *MI) { |
||
| 100 | return MI->getOpcode() == TargetOpcode::G_LOAD; |
||
| 101 | } |
||
| 102 | }; |
||
| 103 | |||
| 104 | /// Represents either a G_SEXTLOAD or G_ZEXTLOAD. |
||
| 105 | class GExtLoad : public GAnyLoad { |
||
| 106 | public: |
||
| 107 | static bool classof(const MachineInstr *MI) { |
||
| 108 | return MI->getOpcode() == TargetOpcode::G_SEXTLOAD || |
||
| 109 | MI->getOpcode() == TargetOpcode::G_ZEXTLOAD; |
||
| 110 | } |
||
| 111 | }; |
||
| 112 | |||
| 113 | /// Represents a G_SEXTLOAD. |
||
| 114 | class GSExtLoad : public GExtLoad { |
||
| 115 | public: |
||
| 116 | static bool classof(const MachineInstr *MI) { |
||
| 117 | return MI->getOpcode() == TargetOpcode::G_SEXTLOAD; |
||
| 118 | } |
||
| 119 | }; |
||
| 120 | |||
| 121 | /// Represents a G_ZEXTLOAD. |
||
| 122 | class GZExtLoad : public GExtLoad { |
||
| 123 | public: |
||
| 124 | static bool classof(const MachineInstr *MI) { |
||
| 125 | return MI->getOpcode() == TargetOpcode::G_ZEXTLOAD; |
||
| 126 | } |
||
| 127 | }; |
||
| 128 | |||
| 129 | /// Represents a G_STORE. |
||
| 130 | class GStore : public GLoadStore { |
||
| 131 | public: |
||
| 132 | /// Get the stored value register. |
||
| 133 | Register getValueReg() const { return getOperand(0).getReg(); } |
||
| 134 | |||
| 135 | static bool classof(const MachineInstr *MI) { |
||
| 136 | return MI->getOpcode() == TargetOpcode::G_STORE; |
||
| 137 | } |
||
| 138 | }; |
||
| 139 | |||
| 140 | /// Represents a G_UNMERGE_VALUES. |
||
| 141 | class GUnmerge : public GenericMachineInstr { |
||
| 142 | public: |
||
| 143 | /// Returns the number of def registers. |
||
| 144 | unsigned getNumDefs() const { return getNumOperands() - 1; } |
||
| 145 | /// Get the unmerge source register. |
||
| 146 | Register getSourceReg() const { return getOperand(getNumDefs()).getReg(); } |
||
| 147 | |||
| 148 | static bool classof(const MachineInstr *MI) { |
||
| 149 | return MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES; |
||
| 150 | } |
||
| 151 | }; |
||
| 152 | |||
| 153 | /// Represents G_BUILD_VECTOR, G_CONCAT_VECTORS or G_MERGE_VALUES. |
||
| 154 | /// All these have the common property of generating a single value from |
||
| 155 | /// multiple sources. |
||
| 156 | class GMergeLikeInstr : public GenericMachineInstr { |
||
| 157 | public: |
||
| 158 | /// Returns the number of source registers. |
||
| 159 | unsigned getNumSources() const { return getNumOperands() - 1; } |
||
| 160 | /// Returns the I'th source register. |
||
| 161 | Register getSourceReg(unsigned I) const { return getReg(I + 1); } |
||
| 162 | |||
| 163 | static bool classof(const MachineInstr *MI) { |
||
| 164 | switch (MI->getOpcode()) { |
||
| 165 | case TargetOpcode::G_MERGE_VALUES: |
||
| 166 | case TargetOpcode::G_CONCAT_VECTORS: |
||
| 167 | case TargetOpcode::G_BUILD_VECTOR: |
||
| 168 | return true; |
||
| 169 | default: |
||
| 170 | return false; |
||
| 171 | } |
||
| 172 | } |
||
| 173 | }; |
||
| 174 | |||
| 175 | /// Represents a G_MERGE_VALUES. |
||
| 176 | class GMerge : public GMergeLikeInstr { |
||
| 177 | public: |
||
| 178 | static bool classof(const MachineInstr *MI) { |
||
| 179 | return MI->getOpcode() == TargetOpcode::G_MERGE_VALUES; |
||
| 180 | } |
||
| 181 | }; |
||
| 182 | |||
| 183 | /// Represents a G_CONCAT_VECTORS. |
||
| 184 | class GConcatVectors : public GMergeLikeInstr { |
||
| 185 | public: |
||
| 186 | static bool classof(const MachineInstr *MI) { |
||
| 187 | return MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS; |
||
| 188 | } |
||
| 189 | }; |
||
| 190 | |||
| 191 | /// Represents a G_BUILD_VECTOR. |
||
| 192 | class GBuildVector : public GMergeLikeInstr { |
||
| 193 | public: |
||
| 194 | static bool classof(const MachineInstr *MI) { |
||
| 195 | return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR; |
||
| 196 | } |
||
| 197 | }; |
||
| 198 | |||
| 199 | /// Represents a G_PTR_ADD. |
||
| 200 | class GPtrAdd : public GenericMachineInstr { |
||
| 201 | public: |
||
| 202 | Register getBaseReg() const { return getReg(1); } |
||
| 203 | Register getOffsetReg() const { return getReg(2); } |
||
| 204 | |||
| 205 | static bool classof(const MachineInstr *MI) { |
||
| 206 | return MI->getOpcode() == TargetOpcode::G_PTR_ADD; |
||
| 207 | } |
||
| 208 | }; |
||
| 209 | |||
| 210 | /// Represents a G_IMPLICIT_DEF. |
||
| 211 | class GImplicitDef : public GenericMachineInstr { |
||
| 212 | public: |
||
| 213 | static bool classof(const MachineInstr *MI) { |
||
| 214 | return MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF; |
||
| 215 | } |
||
| 216 | }; |
||
| 217 | |||
| 218 | /// Represents a G_SELECT. |
||
| 219 | class GSelect : public GenericMachineInstr { |
||
| 220 | public: |
||
| 221 | Register getCondReg() const { return getReg(1); } |
||
| 222 | Register getTrueReg() const { return getReg(2); } |
||
| 223 | Register getFalseReg() const { return getReg(3); } |
||
| 224 | |||
| 225 | static bool classof(const MachineInstr *MI) { |
||
| 226 | return MI->getOpcode() == TargetOpcode::G_SELECT; |
||
| 227 | } |
||
| 228 | }; |
||
| 229 | |||
| 230 | /// Represent a G_ICMP or G_FCMP. |
||
| 231 | class GAnyCmp : public GenericMachineInstr { |
||
| 232 | public: |
||
| 233 | CmpInst::Predicate getCond() const { |
||
| 234 | return static_cast<CmpInst::Predicate>(getOperand(1).getPredicate()); |
||
| 235 | } |
||
| 236 | Register getLHSReg() const { return getReg(2); } |
||
| 237 | Register getRHSReg() const { return getReg(3); } |
||
| 238 | |||
| 239 | static bool classof(const MachineInstr *MI) { |
||
| 240 | return MI->getOpcode() == TargetOpcode::G_ICMP || |
||
| 241 | MI->getOpcode() == TargetOpcode::G_FCMP; |
||
| 242 | } |
||
| 243 | }; |
||
| 244 | |||
| 245 | /// Represent a G_ICMP. |
||
| 246 | class GICmp : public GAnyCmp { |
||
| 247 | public: |
||
| 248 | static bool classof(const MachineInstr *MI) { |
||
| 249 | return MI->getOpcode() == TargetOpcode::G_ICMP; |
||
| 250 | } |
||
| 251 | }; |
||
| 252 | |||
| 253 | /// Represent a G_FCMP. |
||
| 254 | class GFCmp : public GAnyCmp { |
||
| 255 | public: |
||
| 256 | static bool classof(const MachineInstr *MI) { |
||
| 257 | return MI->getOpcode() == TargetOpcode::G_FCMP; |
||
| 258 | } |
||
| 259 | }; |
||
| 260 | |||
| 261 | } // namespace llvm |
||
| 262 | |||
| 263 | #endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H |