1 //===-- X86InstrFMA3Info.cpp - 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 #include "X86InstrFMA3Info.h"
16 #include "X86InstrInfo.h"
17 #include "llvm/Support/ManagedStatic.h"
18 #include "llvm/Support/Threading.h"
19 #include <cassert>
20 #include <cstdint>
21 
22 using namespace llvm;
23 
24 #define FMA3BASE(X132, X213, X231, Attrs)                                      \
25   { { X132, X213, X231 }, Attrs },
26 
27 #define FMA3RA(R132, R213, R231, Attrs)                                        \
28   FMA3BASE(X86::R132, X86::R213, X86::R231, Attrs)
29 
30 #define FMA3R(R132, R213, R231)                                                \
31   FMA3RA(R132, R213, R231, 0)
32 
33 #define FMA3MA(M132, M213, M231, Attrs)                                        \
34   FMA3BASE(X86::M132, X86::M213, X86::M231, Attrs)
35 
36 #define FMA3M(M132, M213, M231)                                                \
37   FMA3MA(M132, M213, M231, 0)
38 
39 #define FMA3RMA(R132, R213, R231, M132, M213, M231, Attrs)                     \
40   FMA3RA(R132, R213, R231, Attrs)                                              \
41   FMA3MA(M132, M213, M231, Attrs)
42 
43 #define FMA3RM(R132, R213, R231, M132, M213, M231)                             \
44   FMA3RMA(R132, R213, R231, M132, M213, M231, 0)
45 
46 #define FMA3_AVX2_VECTOR_GROUP(Name)                                           \
47   FMA3RM(Name##132PSr, Name##213PSr, Name##231PSr,                             \
48          Name##132PSm, Name##213PSm, Name##231PSm)                             \
49   FMA3RM(Name##132PDr, Name##213PDr, Name##231PDr,                             \
50          Name##132PDm, Name##213PDm, Name##231PDm)                             \
51   FMA3RM(Name##132PSYr, Name##213PSYr, Name##231PSYr,                          \
52          Name##132PSYm, Name##213PSYm, Name##231PSYm)                          \
53   FMA3RM(Name##132PDYr, Name##213PDYr, Name##231PDYr,                          \
54          Name##132PDYm, Name##213PDYm, Name##231PDYm)
55 
56 #define FMA3_AVX2_SCALAR_GROUP(Name)                                           \
57   FMA3RM(Name##132SSr, Name##213SSr, Name##231SSr,                             \
58          Name##132SSm, Name##213SSm, Name##231SSm)                             \
59   FMA3RM(Name##132SDr, Name##213SDr, Name##231SDr,                             \
60          Name##132SDm, Name##213SDm, Name##231SDm)                             \
61   FMA3RMA(Name##132SSr_Int, Name##213SSr_Int, Name##231SSr_Int,                \
62           Name##132SSm_Int, Name##213SSm_Int, Name##231SSm_Int,                \
63           X86InstrFMA3Group::X86FMA3Intrinsic)                                 \
64   FMA3RMA(Name##132SDr_Int, Name##213SDr_Int, Name##231SDr_Int,                \
65           Name##132SDm_Int, Name##213SDm_Int, Name##231SDm_Int,                \
66           X86InstrFMA3Group::X86FMA3Intrinsic)
67 
68 #define FMA3_AVX2_FULL_GROUP(Name)                                             \
69   FMA3_AVX2_VECTOR_GROUP(Name)                                                 \
70   FMA3_AVX2_SCALAR_GROUP(Name)
71 
72 #define FMA3_AVX512_VECTOR_GROUP(Name)                                         \
73   FMA3RM(Name##132PSZ128r, Name##213PSZ128r, Name##231PSZ128r,                 \
74          Name##132PSZ128m, Name##213PSZ128m, Name##231PSZ128m)                 \
75   FMA3RM(Name##132PDZ128r, Name##213PDZ128r, Name##231PDZ128r,                 \
76          Name##132PDZ128m, Name##213PDZ128m, Name##231PDZ128m)                 \
77   FMA3RM(Name##132PSZ256r, Name##213PSZ256r, Name##231PSZ256r,                 \
78          Name##132PSZ256m, Name##213PSZ256m, Name##231PSZ256m)                 \
79   FMA3RM(Name##132PDZ256r, Name##213PDZ256r, Name##231PDZ256r,                 \
80          Name##132PDZ256m, Name##213PDZ256m, Name##231PDZ256m)                 \
81   FMA3RM(Name##132PSZr,    Name##213PSZr,    Name##231PSZr,                    \
82          Name##132PSZm,    Name##213PSZm,    Name##231PSZm)                    \
83   FMA3RM(Name##132PDZr,    Name##213PDZr,    Name##231PDZr,                    \
84          Name##132PDZm,    Name##213PDZm,    Name##231PDZm)                    \
85   FMA3RMA(Name##132PSZ128rk, Name##213PSZ128rk, Name##231PSZ128rk,             \
86           Name##132PSZ128mk, Name##213PSZ128mk, Name##231PSZ128mk,             \
87           X86InstrFMA3Group::X86FMA3KMergeMasked)                              \
88   FMA3RMA(Name##132PDZ128rk, Name##213PDZ128rk, Name##231PDZ128rk,             \
89           Name##132PDZ128mk, Name##213PDZ128mk, Name##231PDZ128mk,             \
90           X86InstrFMA3Group::X86FMA3KMergeMasked)                              \
91   FMA3RMA(Name##132PSZ256rk, Name##213PSZ256rk, Name##231PSZ256rk,             \
92           Name##132PSZ256mk, Name##213PSZ256mk, Name##231PSZ256mk,             \
93           X86InstrFMA3Group::X86FMA3KMergeMasked)                              \
94   FMA3RMA(Name##132PDZ256rk, Name##213PDZ256rk, Name##231PDZ256rk,             \
95           Name##132PDZ256mk, Name##213PDZ256mk, Name##231PDZ256mk,             \
96           X86InstrFMA3Group::X86FMA3KMergeMasked)                              \
97   FMA3RMA(Name##132PSZrk,    Name##213PSZrk,    Name##231PSZrk,                \
98           Name##132PSZmk,    Name##213PSZmk,    Name##231PSZmk,                \
99           X86InstrFMA3Group::X86FMA3KMergeMasked)                              \
100   FMA3RMA(Name##132PDZrk,    Name##213PDZrk,    Name##231PDZrk,                \
101           Name##132PDZmk,    Name##213PDZmk,    Name##231PDZmk,                \
102           X86InstrFMA3Group::X86FMA3KMergeMasked)                              \
103   FMA3RMA(Name##132PSZ128rkz, Name##213PSZ128rkz, Name##231PSZ128rkz,          \
104           Name##132PSZ128mkz, Name##213PSZ128mkz, Name##231PSZ128mkz,          \
105           X86InstrFMA3Group::X86FMA3KZeroMasked)                               \
106   FMA3RMA(Name##132PDZ128rkz, Name##213PDZ128rkz, Name##231PDZ128rkz,          \
107           Name##132PDZ128mkz, Name##213PDZ128mkz, Name##231PDZ128mkz,          \
108           X86InstrFMA3Group::X86FMA3KZeroMasked)                               \
109   FMA3RMA(Name##132PSZ256rkz, Name##213PSZ256rkz, Name##231PSZ256rkz,          \
110           Name##132PSZ256mkz, Name##213PSZ256mkz, Name##231PSZ256mkz,          \
111           X86InstrFMA3Group::X86FMA3KZeroMasked)                               \
112   FMA3RMA(Name##132PDZ256rkz, Name##213PDZ256rkz, Name##231PDZ256rkz,          \
113           Name##132PDZ256mkz, Name##213PDZ256mkz, Name##231PDZ256mkz,          \
114           X86InstrFMA3Group::X86FMA3KZeroMasked)                               \
115   FMA3RMA(Name##132PSZrkz,    Name##213PSZrkz,    Name##231PSZrkz,             \
116           Name##132PSZmkz,    Name##213PSZmkz,    Name##231PSZmkz,             \
117           X86InstrFMA3Group::X86FMA3KZeroMasked)                               \
118   FMA3RMA(Name##132PDZrkz,    Name##213PDZrkz,    Name##231PDZrkz,             \
119           Name##132PDZmkz,    Name##213PDZmkz,    Name##231PDZmkz,             \
120           X86InstrFMA3Group::X86FMA3KZeroMasked)                               \
121   FMA3R(Name##132PSZrb, Name##213PSZrb, Name##231PSZrb)                        \
122   FMA3R(Name##132PDZrb, Name##213PDZrb, Name##231PDZrb)                        \
123   FMA3RA(Name##132PSZrbk, Name##213PSZrbk, Name##231PSZrbk,                    \
124          X86InstrFMA3Group::X86FMA3KMergeMasked)                               \
125   FMA3RA(Name##132PDZrbk, Name##213PDZrbk, Name##231PDZrbk,                    \
126          X86InstrFMA3Group::X86FMA3KMergeMasked)                               \
127   FMA3RA(Name##132PSZrbkz, Name##213PSZrbkz, Name##231PSZrbkz,                 \
128          X86InstrFMA3Group::X86FMA3KZeroMasked)                                \
129   FMA3RA(Name##132PDZrbkz, Name##213PDZrbkz, Name##231PDZrbkz,                 \
130          X86InstrFMA3Group::X86FMA3KZeroMasked)                                \
131   FMA3M(Name##132PSZ128mb, Name##213PSZ128mb, Name##231PSZ128mb)               \
132   FMA3M(Name##132PDZ128mb, Name##213PDZ128mb, Name##231PDZ128mb)               \
133   FMA3M(Name##132PSZ256mb, Name##213PSZ256mb, Name##231PSZ256mb)               \
134   FMA3M(Name##132PDZ256mb, Name##213PDZ256mb, Name##231PDZ256mb)               \
135   FMA3M(Name##132PSZmb, Name##213PSZmb, Name##231PSZmb)                        \
136   FMA3M(Name##132PDZmb, Name##213PDZmb, Name##231PDZmb)                        \
137   FMA3MA(Name##132PSZ128mbk, Name##213PSZ128mbk, Name##231PSZ128mbk,           \
138          X86InstrFMA3Group::X86FMA3KMergeMasked)                               \
139   FMA3MA(Name##132PDZ128mbk, Name##213PDZ128mbk, Name##231PDZ128mbk,           \
140          X86InstrFMA3Group::X86FMA3KMergeMasked)                               \
141   FMA3MA(Name##132PSZ256mbk, Name##213PSZ256mbk, Name##231PSZ256mbk,           \
142          X86InstrFMA3Group::X86FMA3KMergeMasked)                               \
143   FMA3MA(Name##132PDZ256mbk, Name##213PDZ256mbk, Name##231PDZ256mbk,           \
144          X86InstrFMA3Group::X86FMA3KMergeMasked)                               \
145   FMA3MA(Name##132PSZmbk,    Name##213PSZmbk,    Name##231PSZmbk,              \
146          X86InstrFMA3Group::X86FMA3KMergeMasked)                               \
147   FMA3MA(Name##132PDZmbk,    Name##213PDZmbk,    Name##231PDZmbk,              \
148          X86InstrFMA3Group::X86FMA3KMergeMasked)                               \
149   FMA3MA(Name##132PSZ128mbkz, Name##213PSZ128mbkz, Name##231PSZ128mbkz,        \
150          X86InstrFMA3Group::X86FMA3KZeroMasked)                                \
151   FMA3MA(Name##132PDZ128mbkz, Name##213PDZ128mbkz, Name##231PDZ128mbkz,        \
152          X86InstrFMA3Group::X86FMA3KZeroMasked)                                \
153   FMA3MA(Name##132PSZ256mbkz, Name##213PSZ256mbkz, Name##231PSZ256mbkz,        \
154          X86InstrFMA3Group::X86FMA3KZeroMasked)                                \
155   FMA3MA(Name##132PDZ256mbkz, Name##213PDZ256mbkz, Name##231PDZ256mbkz,        \
156          X86InstrFMA3Group::X86FMA3KZeroMasked)                                \
157   FMA3MA(Name##132PSZmbkz, Name##213PSZmbkz, Name##231PSZmbkz,                 \
158          X86InstrFMA3Group::X86FMA3KZeroMasked)                                \
159   FMA3MA(Name##132PDZmbkz, Name##213PDZmbkz, Name##231PDZmbkz,                 \
160          X86InstrFMA3Group::X86FMA3KZeroMasked)
161 
162 #define FMA3_AVX512_SCALAR_GROUP(Name)                                         \
163   FMA3RM(Name##132SSZr,      Name##213SSZr,     Name##231SSZr,                 \
164          Name##132SSZm,      Name##213SSZm,     Name##231SSZm)                 \
165   FMA3RM(Name##132SDZr,      Name##213SDZr,     Name##231SDZr,                 \
166          Name##132SDZm,      Name##213SDZm,     Name##231SDZm)                 \
167   FMA3RMA(Name##132SSZr_Int, Name##213SSZr_Int, Name##231SSZr_Int,             \
168           Name##132SSZm_Int, Name##213SSZm_Int, Name##231SSZm_Int,             \
169           X86InstrFMA3Group::X86FMA3Intrinsic)                                 \
170   FMA3RMA(Name##132SDZr_Int, Name##213SDZr_Int, Name##231SDZr_Int,             \
171           Name##132SDZm_Int, Name##213SDZm_Int, Name##231SDZm_Int,             \
172           X86InstrFMA3Group::X86FMA3Intrinsic)                                 \
173   FMA3RMA(Name##132SSZr_Intk, Name##213SSZr_Intk, Name##231SSZr_Intk,          \
174           Name##132SSZm_Intk, Name##213SSZm_Intk, Name##231SSZm_Intk,          \
175           X86InstrFMA3Group::X86FMA3Intrinsic |                                \
176               X86InstrFMA3Group::X86FMA3KMergeMasked)                          \
177   FMA3RMA(Name##132SDZr_Intk, Name##213SDZr_Intk, Name##231SDZr_Intk,          \
178           Name##132SDZm_Intk, Name##213SDZm_Intk, Name##231SDZm_Intk,          \
179           X86InstrFMA3Group::X86FMA3Intrinsic |                                \
180               X86InstrFMA3Group::X86FMA3KMergeMasked)                          \
181   FMA3RMA(Name##132SSZr_Intkz, Name##213SSZr_Intkz, Name##231SSZr_Intkz,       \
182           Name##132SSZm_Intkz, Name##213SSZm_Intkz, Name##231SSZm_Intkz,       \
183           X86InstrFMA3Group::X86FMA3Intrinsic |                                \
184               X86InstrFMA3Group::X86FMA3KZeroMasked)                           \
185   FMA3RMA(Name##132SDZr_Intkz, Name##213SDZr_Intkz, Name##231SDZr_Intkz,       \
186           Name##132SDZm_Intkz, Name##213SDZm_Intkz, Name##231SDZm_Intkz,       \
187           X86InstrFMA3Group::X86FMA3Intrinsic |                                \
188               X86InstrFMA3Group::X86FMA3KZeroMasked)                           \
189   FMA3RA(Name##132SSZrb_Int, Name##213SSZrb_Int, Name##231SSZrb_Int,           \
190          X86InstrFMA3Group::X86FMA3Intrinsic)                                  \
191   FMA3RA(Name##132SDZrb_Int, Name##213SDZrb_Int, Name##231SDZrb_Int,           \
192          X86InstrFMA3Group::X86FMA3Intrinsic)                                  \
193   FMA3RA(Name##132SSZrb_Intk, Name##213SSZrb_Intk, Name##231SSZrb_Intk,        \
194          X86InstrFMA3Group::X86FMA3Intrinsic |                                 \
195              X86InstrFMA3Group::X86FMA3KMergeMasked)                           \
196   FMA3RA(Name##132SDZrb_Intk, Name##213SDZrb_Intk, Name##231SDZrb_Intk,        \
197          X86InstrFMA3Group::X86FMA3Intrinsic |                                 \
198              X86InstrFMA3Group::X86FMA3KMergeMasked)                           \
199   FMA3RA(Name##132SSZrb_Intkz, Name##213SSZrb_Intkz, Name##231SSZrb_Intkz,     \
200          X86InstrFMA3Group::X86FMA3Intrinsic |                                 \
201              X86InstrFMA3Group::X86FMA3KZeroMasked)                            \
202   FMA3RA(Name##132SDZrb_Intkz, Name##213SDZrb_Intkz, Name##231SDZrb_Intkz,     \
203          X86InstrFMA3Group::X86FMA3Intrinsic |                                 \
204              X86InstrFMA3Group::X86FMA3KZeroMasked)
205 
206 #define FMA3_AVX512_FULL_GROUP(Name)                                           \
207   FMA3_AVX512_VECTOR_GROUP(Name)                                               \
208   FMA3_AVX512_SCALAR_GROUP(Name)
209 
210 static const X86InstrFMA3Group Groups[] = {
211   FMA3_AVX2_FULL_GROUP(VFMADD)
212   FMA3_AVX2_FULL_GROUP(VFMSUB)
213   FMA3_AVX2_FULL_GROUP(VFNMADD)
214   FMA3_AVX2_FULL_GROUP(VFNMSUB)
215 
216   FMA3_AVX2_VECTOR_GROUP(VFMADDSUB)
217   FMA3_AVX2_VECTOR_GROUP(VFMSUBADD)
218 
219   FMA3_AVX512_FULL_GROUP(VFMADD)
220   FMA3_AVX512_FULL_GROUP(VFMSUB)
221   FMA3_AVX512_FULL_GROUP(VFNMADD)
222   FMA3_AVX512_FULL_GROUP(VFNMSUB)
223 
224   FMA3_AVX512_VECTOR_GROUP(VFMADDSUB)
225   FMA3_AVX512_VECTOR_GROUP(VFMSUBADD)
226 };
227 
228 namespace {
229 
230 struct X86InstrFMA3Info {
231   /// A map that is used to find the group of FMA opcodes using any FMA opcode
232   /// from the group.
233   DenseMap<unsigned, const X86InstrFMA3Group *> OpcodeToGroup;
234 
235   /// Constructor. Just creates an object of the class.
236   X86InstrFMA3Info() {
237     for (const X86InstrFMA3Group &G : Groups) {
238       OpcodeToGroup[G.Opcodes[0]] = &G;
239       OpcodeToGroup[G.Opcodes[1]] = &G;
240       OpcodeToGroup[G.Opcodes[2]] = &G;
241     }
242   }
243 };
244 
245 }
246 
247 static ManagedStatic<X86InstrFMA3Info> X86FMA3InfoObj;
248 
249 /// Returns a reference to a group of FMA3 opcodes to where the given
250 /// \p Opcode is included. If the given \p Opcode is not recognized as FMA3
251 /// and not included into any FMA3 group, then nullptr is returned.
252 const X86InstrFMA3Group *llvm::getFMA3Group(unsigned Opcode) {
253   auto &Map = X86FMA3InfoObj->OpcodeToGroup;
254   auto I = Map.find(Opcode);
255   if (I != Map.end())
256     return I->second;
257 
258   return nullptr;
259 }
260