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 GMergeLikeOp : 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 GMergeLikeOp { 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 GMergeLikeOp { 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 GMergeLikeOp { 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 264