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/CodeGen/MachineInstr.h"
18 #include "llvm/CodeGen/MachineMemOperand.h"
19 #include "llvm/CodeGen/TargetOpcodes.h"
20 #include "llvm/Support/Casting.h"
21 
22 namespace llvm {
23 
24 /// A base class for all GenericMachineInstrs.
25 class GenericMachineInstr : public MachineInstr {
26 public:
27   GenericMachineInstr() = delete;
28 
29   /// Access the Idx'th operand as a register and return it.
30   /// This assumes that the Idx'th operand is a Register type.
getReg(unsigned Idx)31   Register getReg(unsigned Idx) const { return getOperand(Idx).getReg(); }
32 
classof(const MachineInstr * MI)33   static bool classof(const MachineInstr *MI) {
34     return isPreISelGenericOpcode(MI->getOpcode());
35   }
36 };
37 
38 /// Represents any type of generic load or store.
39 /// G_LOAD, G_STORE, G_ZEXTLOAD, G_SEXTLOAD.
40 class GLoadStore : public GenericMachineInstr {
41 public:
42   /// Get the source register of the pointer value.
getPointerReg()43   Register getPointerReg() const { return getOperand(1).getReg(); }
44 
45   /// Get the MachineMemOperand on this instruction.
getMMO()46   MachineMemOperand &getMMO() const { return **memoperands_begin(); }
47 
48   /// Returns true if the attached MachineMemOperand  has the atomic flag set.
isAtomic()49   bool isAtomic() const { return getMMO().isAtomic(); }
50   /// Returns true if the attached MachineMemOpeand as the volatile flag set.
isVolatile()51   bool isVolatile() const { return getMMO().isVolatile(); }
52   /// Returns true if the memory operation is neither atomic or volatile.
isSimple()53   bool isSimple() const { return !isAtomic() && !isVolatile(); }
54   /// Returns true if this memory operation doesn't have any ordering
55   /// constraints other than normal aliasing. Volatile and (ordered) atomic
56   /// memory operations can't be reordered.
isUnordered()57   bool isUnordered() const { return getMMO().isUnordered(); }
58 
59   /// Returns the size in bytes of the memory access.
getMemSize()60   uint64_t getMemSize() { return getMMO().getSize();
61   } /// Returns the size in bits of the memory access.
getMemSizeInBits()62   uint64_t getMemSizeInBits() { return getMMO().getSizeInBits(); }
63 
classof(const MachineInstr * MI)64   static bool classof(const MachineInstr *MI) {
65     switch (MI->getOpcode()) {
66     case TargetOpcode::G_LOAD:
67     case TargetOpcode::G_STORE:
68     case TargetOpcode::G_ZEXTLOAD:
69     case TargetOpcode::G_SEXTLOAD:
70       return true;
71     default:
72       return false;
73     }
74   }
75 };
76 
77 /// Represents any generic load, including sign/zero extending variants.
78 class GAnyLoad : public GLoadStore {
79 public:
80   /// Get the definition register of the loaded value.
getDstReg()81   Register getDstReg() const { return getOperand(0).getReg(); }
82 
classof(const MachineInstr * MI)83   static bool classof(const MachineInstr *MI) {
84     switch (MI->getOpcode()) {
85     case TargetOpcode::G_LOAD:
86     case TargetOpcode::G_ZEXTLOAD:
87     case TargetOpcode::G_SEXTLOAD:
88       return true;
89     default:
90       return false;
91     }
92   }
93 };
94 
95 /// Represents a G_LOAD.
96 class GLoad : public GAnyLoad {
97 public:
classof(const MachineInstr * MI)98   static bool classof(const MachineInstr *MI) {
99     return MI->getOpcode() == TargetOpcode::G_LOAD;
100   }
101 };
102 
103 /// Represents either a G_SEXTLOAD or G_ZEXTLOAD.
104 class GExtLoad : public GAnyLoad {
105 public:
classof(const MachineInstr * MI)106   static bool classof(const MachineInstr *MI) {
107     return MI->getOpcode() == TargetOpcode::G_SEXTLOAD ||
108            MI->getOpcode() == TargetOpcode::G_ZEXTLOAD;
109   }
110 };
111 
112 /// Represents a G_SEXTLOAD.
113 class GSExtLoad : public GExtLoad {
114 public:
classof(const MachineInstr * MI)115   static bool classof(const MachineInstr *MI) {
116     return MI->getOpcode() == TargetOpcode::G_SEXTLOAD;
117   }
118 };
119 
120 /// Represents a G_ZEXTLOAD.
121 class GZExtLoad : public GExtLoad {
122 public:
classof(const MachineInstr * MI)123   static bool classof(const MachineInstr *MI) {
124     return MI->getOpcode() == TargetOpcode::G_ZEXTLOAD;
125   }
126 };
127 
128 /// Represents a G_STORE.
129 class GStore : public GLoadStore {
130 public:
131   /// Get the stored value register.
getValueReg()132   Register getValueReg() const { return getOperand(0).getReg(); }
133 
classof(const MachineInstr * MI)134   static bool classof(const MachineInstr *MI) {
135     return MI->getOpcode() == TargetOpcode::G_STORE;
136   }
137 };
138 
139 /// Represents a G_UNMERGE_VALUES.
140 class GUnmerge : public GenericMachineInstr {
141 public:
142   /// Returns the number of def registers.
getNumDefs()143   unsigned getNumDefs() const { return getNumOperands() - 1; }
144   /// Get the unmerge source register.
getSourceReg()145   Register getSourceReg() const { return getOperand(getNumDefs()).getReg(); }
146 
classof(const MachineInstr * MI)147   static bool classof(const MachineInstr *MI) {
148     return MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES;
149   }
150 };
151 
152 /// Represents G_BUILD_VECTOR, G_CONCAT_VECTORS or G_MERGE_VALUES.
153 /// All these have the common property of generating a single value from
154 /// multiple sources.
155 class GMergeLikeOp : public GenericMachineInstr {
156 public:
157   /// Returns the number of source registers.
getNumSources()158   unsigned getNumSources() const { return getNumOperands() - 1; }
159   /// Returns the I'th source register.
getSourceReg(unsigned I)160   Register getSourceReg(unsigned I) const { return getReg(I + 1); }
161 
classof(const MachineInstr * MI)162   static bool classof(const MachineInstr *MI) {
163     switch (MI->getOpcode()) {
164     case TargetOpcode::G_MERGE_VALUES:
165     case TargetOpcode::G_CONCAT_VECTORS:
166     case TargetOpcode::G_BUILD_VECTOR:
167       return true;
168     default:
169       return false;
170     }
171   }
172 };
173 
174 /// Represents a G_MERGE_VALUES.
175 class GMerge : public GMergeLikeOp {
176 public:
classof(const MachineInstr * MI)177   static bool classof(const MachineInstr *MI) {
178     return MI->getOpcode() == TargetOpcode::G_MERGE_VALUES;
179   }
180 };
181 
182 /// Represents a G_CONCAT_VECTORS.
183 class GConcatVectors : public GMergeLikeOp {
184 public:
classof(const MachineInstr * MI)185   static bool classof(const MachineInstr *MI) {
186     return MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS;
187   }
188 };
189 
190 /// Represents a G_BUILD_VECTOR.
191 class GBuildVector : public GMergeLikeOp {
192 public:
classof(const MachineInstr * MI)193   static bool classof(const MachineInstr *MI) {
194     return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR;
195   }
196 };
197 
198 } // namespace llvm
199 
200 #endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H