LLVM  4.0.0
X86InstrFMA3Info.h
Go to the documentation of this file.
1 //===-- X86InstrFMA3Info.h - X86 FMA3 Instruction Information -------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the implementation of the classes providing information
11 // about existing X86 FMA3 opcodes, classifying and grouping them.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_LIB_TARGET_X86_UTILS_X86INSTRFMA3INFO_H
16 #define LLVM_LIB_TARGET_X86_UTILS_X86INSTRFMA3INFO_H
17 
18 #include "X86.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include <cassert>
21 #include <set>
22 
23 namespace llvm {
24 /// This class is used to group {132, 213, 231} forms of FMA opcodes together.
25 /// Each of the groups has either 3 register opcodes, 3 memory opcodes,
26 /// or 6 register and memory opcodes. Also, each group has an attrubutes field
27 /// describing it.
29 private:
30  /// Reference to an array holding 3 forms of register FMA opcodes.
31  /// It may be set to nullptr if the group of FMA opcodes does not have
32  /// any register form opcodes.
33  const uint16_t *RegOpcodes;
34 
35  /// Reference to an array holding 3 forms of memory FMA opcodes.
36  /// It may be set to nullptr if the group of FMA opcodes does not have
37  /// any register form opcodes.
38  const uint16_t *MemOpcodes;
39 
40  /// This bitfield specifies the attributes associated with the created
41  /// FMA groups of opcodes.
42  unsigned Attributes;
43 
44  static const unsigned Form132 = 0;
45  static const unsigned Form213 = 1;
46  static const unsigned Form231 = 2;
47 
48 public:
49  /// This bit must be set in the 'Attributes' field of FMA group if such
50  /// group of FMA opcodes consists of FMA intrinsic opcodes.
51  static const unsigned X86FMA3Intrinsic = 0x1;
52 
53  /// This bit must be set in the 'Attributes' field of FMA group if such
54  /// group of FMA opcodes consists of AVX512 opcodes accepting a k-mask and
55  /// passing the elements from the 1st operand to the result of the operation
56  /// when the correpondings bits in the k-mask are unset.
57  static const unsigned X86FMA3KMergeMasked = 0x2;
58 
59  /// This bit must be set in the 'Attributes' field of FMA group if such
60  /// group of FMA opcodes consists of AVX512 opcodes accepting a k-zeromask.
61  static const unsigned X86FMA3KZeroMasked = 0x4;
62 
63  /// Constructor. Creates a new group of FMA opcodes with three register form
64  /// FMA opcodes \p RegOpcodes and three memory form FMA opcodes \p MemOpcodes.
65  /// The parameters \p RegOpcodes and \p MemOpcodes may be set to nullptr,
66  /// which means that the created group of FMA opcodes does not have the
67  /// corresponding (register or memory) opcodes.
68  /// The parameter \p Attr specifies the attributes describing the created
69  /// group.
70  X86InstrFMA3Group(const uint16_t *RegOpcodes, const uint16_t *MemOpcodes,
71  unsigned Attr)
72  : RegOpcodes(RegOpcodes), MemOpcodes(MemOpcodes), Attributes(Attr) {
73  assert((RegOpcodes || MemOpcodes) &&
74  "Cannot create a group not having any opcodes.");
75  }
76 
77  /// Returns a memory form opcode that is the equivalent of the given register
78  /// form opcode \p RegOpcode. 0 is returned if the group does not have
79  /// either register of memory opcodes.
80  unsigned getMemOpcode(unsigned RegOpcode) const {
81  if (!RegOpcodes || !MemOpcodes)
82  return 0;
83  for (unsigned Form = 0; Form < 3; Form++)
84  if (RegOpcodes[Form] == RegOpcode)
85  return MemOpcodes[Form];
86  return 0;
87  }
88 
89  /// Returns the 132 form of FMA register opcode.
90  unsigned getReg132Opcode() const {
91  assert(RegOpcodes && "The group does not have register opcodes.");
92  return RegOpcodes[Form132];
93  }
94 
95  /// Returns the 213 form of FMA register opcode.
96  unsigned getReg213Opcode() const {
97  assert(RegOpcodes && "The group does not have register opcodes.");
98  return RegOpcodes[Form213];
99  }
100 
101  /// Returns the 231 form of FMA register opcode.
102  unsigned getReg231Opcode() const {
103  assert(RegOpcodes && "The group does not have register opcodes.");
104  return RegOpcodes[Form231];
105  }
106 
107  /// Returns the 132 form of FMA memory opcode.
108  unsigned getMem132Opcode() const {
109  assert(MemOpcodes && "The group does not have memory opcodes.");
110  return MemOpcodes[Form132];
111  }
112 
113  /// Returns the 213 form of FMA memory opcode.
114  unsigned getMem213Opcode() const {
115  assert(MemOpcodes && "The group does not have memory opcodes.");
116  return MemOpcodes[Form213];
117  }
118 
119  /// Returns the 231 form of FMA memory opcode.
120  unsigned getMem231Opcode() const {
121  assert(MemOpcodes && "The group does not have memory opcodes.");
122  return MemOpcodes[Form231];
123  }
124 
125  /// Returns true iff the group of FMA opcodes holds intrinsic opcodes.
126  bool isIntrinsic() const { return (Attributes & X86FMA3Intrinsic) != 0; }
127 
128  /// Returns true iff the group of FMA opcodes holds k-merge-masked opcodes.
129  bool isKMergeMasked() const {
130  return (Attributes & X86FMA3KMergeMasked) != 0;
131  }
132 
133  /// Returns true iff the group of FMA opcodes holds k-zero-masked opcodes.
134  bool isKZeroMasked() const { return (Attributes & X86FMA3KZeroMasked) != 0; }
135 
136  /// Returns true iff the group of FMA opcodes holds any of k-masked opcodes.
137  bool isKMasked() const {
138  return (Attributes & (X86FMA3KMergeMasked | X86FMA3KZeroMasked)) != 0;
139  }
140 
141  /// Returns true iff the given \p Opcode is a register opcode from the
142  /// groups of FMA opcodes.
143  bool isRegOpcodeFromGroup(unsigned Opcode) const {
144  if (!RegOpcodes)
145  return false;
146  for (unsigned Form = 0; Form < 3; Form++)
147  if (Opcode == RegOpcodes[Form])
148  return true;
149  return false;
150  }
151 
152  /// Returns true iff the given \p Opcode is a memory opcode from the
153  /// groups of FMA opcodes.
154  bool isMemOpcodeFromGroup(unsigned Opcode) const {
155  if (!MemOpcodes)
156  return false;
157  for (unsigned Form = 0; Form < 3; Form++)
158  if (Opcode == MemOpcodes[Form])
159  return true;
160  return false;
161  }
162 };
163 
164 /// This class provides information about all existing FMA3 opcodes
165 ///
167 private:
168  /// A map that is used to find the group of FMA opcodes using any FMA opcode
169  /// from the group.
171 
172  /// Creates groups of FMA opcodes and initializes Opcode-to-Group map.
173  /// This method can be called many times, but the actual initialization is
174  /// called only once.
175  static void initGroupsOnce();
176 
177  /// Creates groups of FMA opcodes and initializes Opcode-to-Group map.
178  /// This method must be called ONLY from initGroupsOnce(). Otherwise, such
179  /// call is not thread safe.
180  void initGroupsOnceImpl();
181 
182  /// Creates one group of FMA opcodes having the register opcodes
183  /// \p RegOpcodes and memory opcodes \p MemOpcodes. The parameter \p Attr
184  /// specifies the attributes describing the created group.
185  void initRMGroup(const uint16_t *RegOpcodes,
186  const uint16_t *MemOpcodes, unsigned Attr = 0);
187 
188  /// Creates one group of FMA opcodes having only the register opcodes
189  /// \p RegOpcodes. The parameter \p Attr specifies the attributes describing
190  /// the created group.
191  void initRGroup(const uint16_t *RegOpcodes, unsigned Attr = 0);
192 
193  /// Creates one group of FMA opcodes having only the memory opcodes
194  /// \p MemOpcodes. The parameter \p Attr specifies the attributes describing
195  /// the created group.
196  void initMGroup(const uint16_t *MemOpcodes, unsigned Attr = 0);
197 
198 public:
199  /// Returns the reference to an object of this class. It is assumed that
200  /// only one object may exist.
202 
203  /// Constructor. Just creates an object of the class.
205 
206  /// Destructor. Deallocates the memory used for FMA3 Groups.
208  std::set<const X86InstrFMA3Group *> DeletedGroups;
209  auto E = OpcodeToGroup.end();
210  for (auto I = OpcodeToGroup.begin(); I != E; I++) {
211  const X86InstrFMA3Group *G = I->second;
212  if (DeletedGroups.find(G) == DeletedGroups.end()) {
213  DeletedGroups.insert(G);
214  delete G;
215  }
216  }
217  }
218 
219  /// Returns a reference to a group of FMA3 opcodes to where the given
220  /// \p Opcode is included. If the given \p Opcode is not recognized as FMA3
221  /// and not included into any FMA3 group, then nullptr is returned.
222  static const X86InstrFMA3Group *getFMA3Group(unsigned Opcode) {
223  // Ensure that the groups of opcodes are initialized.
224  initGroupsOnce();
225 
226  // Find the group including the given opcode.
227  const X86InstrFMA3Info *FMA3Info = getX86InstrFMA3Info();
228  auto I = FMA3Info->OpcodeToGroup.find(Opcode);
229  if (I == FMA3Info->OpcodeToGroup.end())
230  return nullptr;
231 
232  return I->second;
233  }
234 
235  /// Returns true iff the given \p Opcode is recognized as FMA3 by this class.
236  static bool isFMA3(unsigned Opcode) {
237  return getFMA3Group(Opcode) != nullptr;
238  }
239 
240  /// Iterator that is used to walk on FMA register opcodes having memory
241  /// form equivalents.
242  class rm_iterator {
243  private:
244  /// Iterator associated with the OpcodeToGroup map. It must always be
245  /// initialized with an entry from OpcodeToGroup for which I->first
246  /// points to a register FMA opcode and I->second points to a group of
247  /// FMA opcodes having memory form equivalent of I->first.
249 
250  public:
251  /// Constructor. Creates rm_iterator. The parameter \p I must be an
252  /// iterator to OpcodeToGroup map entry having I->first pointing to
253  /// register form FMA opcode and I->second pointing to a group of FMA
254  /// opcodes holding memory form equivalent for I->fist.
256  : I(I) {}
257 
258  /// Returns the register form FMA opcode.
259  unsigned getRegOpcode() const { return I->first; };
260 
261  /// Returns the memory form equivalent opcode for FMA register opcode
262  /// referenced by I->first.
263  unsigned getMemOpcode() const {
264  unsigned Opcode = I->first;
265  const X86InstrFMA3Group *Group = I->second;
266  return Group->getMemOpcode(Opcode);
267  }
268 
269  /// Returns a reference to a group of FMA opcodes.
270  const X86InstrFMA3Group *getGroup() const { return I->second; }
271 
272  bool operator==(const rm_iterator &OtherIt) const { return I == OtherIt.I; }
273  bool operator!=(const rm_iterator &OtherIt) const { return I != OtherIt.I; }
274 
275  /// Increment. Advances the 'I' iterator to the next OpcodeToGroup entry
276  /// having I->first pointing to register form FMA and I->second pointing
277  /// to a group of FMA opcodes holding memory form equivalen for I->first.
279  auto E = getX86InstrFMA3Info()->OpcodeToGroup.end();
280  for (++I; I != E; ++I) {
281  unsigned RegOpcode = I->first;
282  const X86InstrFMA3Group *Group = I->second;
283  if (Group->getMemOpcode(RegOpcode) != 0)
284  break;
285  }
286  return *this;
287  }
288  };
289 
290  /// Returns rm_iterator pointing to the first entry of OpcodeToGroup map
291  /// with a register FMA opcode having memory form opcode equivalent.
293  initGroupsOnce();
294  const X86InstrFMA3Info *FMA3Info = getX86InstrFMA3Info();
295  auto I = FMA3Info->OpcodeToGroup.begin();
296  auto E = FMA3Info->OpcodeToGroup.end();
297  while (I != E) {
298  unsigned Opcode = I->first;
299  const X86InstrFMA3Group *G = I->second;
300  if (G->getMemOpcode(Opcode) != 0)
301  break;
302  I++;
303  }
304  return rm_iterator(I);
305  }
306 
307  /// Returns the last rm_iterator.
308  static rm_iterator rm_end() {
309  initGroupsOnce();
310  return rm_iterator(getX86InstrFMA3Info()->OpcodeToGroup.end());
311  }
312 };
313 } // namespace llvm
314 
315 #endif
bool isKMasked() const
Returns true iff the group of FMA opcodes holds any of k-masked opcodes.
static const unsigned X86FMA3KZeroMasked
This bit must be set in the 'Attributes' field of FMA group if such group of FMA opcodes consists of ...
This class provides information about all existing FMA3 opcodes.
static bool isFMA3(unsigned Opcode)
Returns true iff the given Opcode is recognized as FMA3 by this class.
bool operator==(const rm_iterator &OtherIt) const
const X86InstrFMA3Group * getGroup() const
Returns a reference to a group of FMA opcodes.
static const X86InstrFMA3Group * getFMA3Group(unsigned Opcode)
Returns a reference to a group of FMA3 opcodes to where the given Opcode is included.
rm_iterator & operator++()
Increment.
unsigned getReg132Opcode() const
Returns the 132 form of FMA register opcode.
~X86InstrFMA3Info()
Destructor. Deallocates the memory used for FMA3 Groups.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
unsigned getMem132Opcode() const
Returns the 132 form of FMA memory opcode.
unsigned getReg213Opcode() const
Returns the 213 form of FMA register opcode.
unsigned getMem231Opcode() const
Returns the 231 form of FMA memory opcode.
unsigned getRegOpcode() const
Returns the register form FMA opcode.
unsigned getReg231Opcode() const
Returns the 231 form of FMA register opcode.
This class is used to group {132, 213, 231} forms of FMA opcodes together.
unsigned getMemOpcode(unsigned RegOpcode) const
Returns a memory form opcode that is the equivalent of the given register form opcode RegOpcode...
bool isKMergeMasked() const
Returns true iff the group of FMA opcodes holds k-merge-masked opcodes.
bool isKZeroMasked() const
Returns true iff the group of FMA opcodes holds k-zero-masked opcodes.
const DataFlowGraph & G
Definition: RDFGraph.cpp:206
bool isIntrinsic() const
Returns true iff the group of FMA opcodes holds intrinsic opcodes.
bool operator!=(const rm_iterator &OtherIt) const
X86InstrFMA3Group(const uint16_t *RegOpcodes, const uint16_t *MemOpcodes, unsigned Attr)
Constructor.
unsigned getMemOpcode() const
Returns the memory form equivalent opcode for FMA register opcode referenced by I->first.
static rm_iterator rm_end()
Returns the last rm_iterator.
bool isRegOpcodeFromGroup(unsigned Opcode) const
Returns true iff the given Opcode is a register opcode from the groups of FMA opcodes.
unsigned getMem213Opcode() const
Returns the 213 form of FMA memory opcode.
static const unsigned X86FMA3Intrinsic
This bit must be set in the 'Attributes' field of FMA group if such group of FMA opcodes consists of ...
#define I(x, y, z)
Definition: MD5.cpp:54
bool isMemOpcodeFromGroup(unsigned Opcode) const
Returns true iff the given Opcode is a memory opcode from the groups of FMA opcodes.
static rm_iterator rm_begin()
Returns rm_iterator pointing to the first entry of OpcodeToGroup map with a register FMA opcode havin...
Iterator that is used to walk on FMA register opcodes having memory form equivalents.
static X86InstrFMA3Info * getX86InstrFMA3Info()
Returns the reference to an object of this class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const unsigned X86FMA3KMergeMasked
This bit must be set in the 'Attributes' field of FMA group if such group of FMA opcodes consists of ...
rm_iterator(DenseMap< unsigned, const X86InstrFMA3Group * >::const_iterator I)
Constructor.
X86InstrFMA3Info()
Constructor. Just creates an object of the class.