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