]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Target/X86/X86InstrFMA3Info.h
Vendor import of llvm trunk r291274:
[FreeBSD/FreeBSD.git] / lib / Target / X86 / X86InstrFMA3Info.h
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.
28 class X86InstrFMA3Group {
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 ///
166 class X86InstrFMA3Info {
167 private:
168   /// A map that is used to find the group of FMA opcodes using any FMA opcode
169   /// from the group.
170   DenseMap<unsigned, const X86InstrFMA3Group *> OpcodeToGroup;
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.
201   static X86InstrFMA3Info *getX86InstrFMA3Info();
202
203   /// Constructor. Just creates an object of the class.
204   X86InstrFMA3Info() {}
205
206   /// Destructor. Deallocates the memory used for FMA3 Groups.
207   ~X86InstrFMA3Info() {
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.
248     DenseMap<unsigned, const X86InstrFMA3Group *>::const_iterator I;
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.
255     rm_iterator(DenseMap<unsigned, const X86InstrFMA3Group *>::const_iterator I)
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.
278     rm_iterator &operator++() {
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.
292   static rm_iterator rm_begin() {
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