1 //===- X86LegalizerInfo.cpp --------------------------------------*- 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 /// \file
10 /// This file implements the targeting of the Machinelegalizer class for X86.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
13 
14 #include "X86LegalizerInfo.h"
15 #include "X86Subtarget.h"
16 #include "X86TargetMachine.h"
17 #include "llvm/CodeGen/ValueTypes.h"
18 #include "llvm/IR/DerivedTypes.h"
19 #include "llvm/IR/Type.h"
20 #include "llvm/Target/TargetOpcodes.h"
21 
22 using namespace llvm;
23 using namespace TargetOpcode;
24 
25 #ifndef LLVM_BUILD_GLOBAL_ISEL
26 #error "You shouldn't build this"
27 #endif
28 
29 X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
30                                    const X86TargetMachine &TM)
31     : Subtarget(STI), TM(TM) {
32 
33   setLegalizerInfo32bit();
34   setLegalizerInfo64bit();
35   setLegalizerInfoSSE1();
36   setLegalizerInfoSSE2();
37   setLegalizerInfoSSE41();
38   setLegalizerInfoAVX();
39   setLegalizerInfoAVX2();
40   setLegalizerInfoAVX512();
41   setLegalizerInfoAVX512DQ();
42   setLegalizerInfoAVX512BW();
43 
44   computeTables();
45 }
46 
47 void X86LegalizerInfo::setLegalizerInfo32bit() {
48 
49   if (Subtarget.is64Bit())
50     return;
51 
52   const LLT p0 = LLT::pointer(0, 32);
53   const LLT s1 = LLT::scalar(1);
54   const LLT s8 = LLT::scalar(8);
55   const LLT s16 = LLT::scalar(16);
56   const LLT s32 = LLT::scalar(32);
57   const LLT s64 = LLT::scalar(64);
58 
59   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
60     for (auto Ty : {s8, s16, s32})
61       setAction({BinOp, Ty}, Legal);
62 
63   for (unsigned Op : {G_UADDE}) {
64     setAction({Op, s32}, Legal);
65     setAction({Op, 1, s1}, Legal);
66   }
67 
68   for (unsigned MemOp : {G_LOAD, G_STORE}) {
69     for (auto Ty : {s8, s16, s32, p0})
70       setAction({MemOp, Ty}, Legal);
71 
72     setAction({MemOp, s1}, WidenScalar);
73     // And everything's fine in addrspace 0.
74     setAction({MemOp, 1, p0}, Legal);
75   }
76 
77   // Pointer-handling
78   setAction({G_FRAME_INDEX, p0}, Legal);
79   setAction({G_GLOBAL_VALUE, p0}, Legal);
80 
81   setAction({G_GEP, p0}, Legal);
82   setAction({G_GEP, 1, s32}, Legal);
83 
84   for (auto Ty : {s1, s8, s16})
85     setAction({G_GEP, 1, Ty}, WidenScalar);
86 
87   // Constants
88   for (auto Ty : {s8, s16, s32, p0})
89     setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
90 
91   setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar);
92   setAction({TargetOpcode::G_CONSTANT, s64}, NarrowScalar);
93 
94   // Extensions
95   for (auto Ty : {s8, s16, s32}) {
96     setAction({G_ZEXT, Ty}, Legal);
97     setAction({G_SEXT, Ty}, Legal);
98   }
99 
100   for (auto Ty : {s1, s8, s16}) {
101     setAction({G_ZEXT, 1, Ty}, Legal);
102     setAction({G_SEXT, 1, Ty}, Legal);
103   }
104 
105   // Comparison
106   setAction({G_ICMP, s1}, Legal);
107 
108   for (auto Ty : {s8, s16, s32, p0})
109     setAction({G_ICMP, 1, Ty}, Legal);
110 }
111 
112 void X86LegalizerInfo::setLegalizerInfo64bit() {
113 
114   if (!Subtarget.is64Bit())
115     return;
116 
117   const LLT p0 = LLT::pointer(0, TM.getPointerSize() * 8);
118   const LLT s1 = LLT::scalar(1);
119   const LLT s8 = LLT::scalar(8);
120   const LLT s16 = LLT::scalar(16);
121   const LLT s32 = LLT::scalar(32);
122   const LLT s64 = LLT::scalar(64);
123 
124   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
125     for (auto Ty : {s8, s16, s32, s64})
126       setAction({BinOp, Ty}, Legal);
127 
128   for (unsigned MemOp : {G_LOAD, G_STORE}) {
129     for (auto Ty : {s8, s16, s32, s64, p0})
130       setAction({MemOp, Ty}, Legal);
131 
132     setAction({MemOp, s1}, WidenScalar);
133     // And everything's fine in addrspace 0.
134     setAction({MemOp, 1, p0}, Legal);
135   }
136 
137   // Pointer-handling
138   setAction({G_FRAME_INDEX, p0}, Legal);
139   setAction({G_GLOBAL_VALUE, p0}, Legal);
140 
141   setAction({G_GEP, p0}, Legal);
142   setAction({G_GEP, 1, s32}, Legal);
143   setAction({G_GEP, 1, s64}, Legal);
144 
145   for (auto Ty : {s1, s8, s16})
146     setAction({G_GEP, 1, Ty}, WidenScalar);
147 
148   // Constants
149   for (auto Ty : {s8, s16, s32, s64, p0})
150     setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
151 
152   setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar);
153 
154   // Extensions
155   for (auto Ty : {s8, s16, s32, s64}) {
156     setAction({G_ZEXT, Ty}, Legal);
157     setAction({G_SEXT, Ty}, Legal);
158   }
159 
160   for (auto Ty : {s1, s8, s16, s32}) {
161     setAction({G_ZEXT, 1, Ty}, Legal);
162     setAction({G_SEXT, 1, Ty}, Legal);
163   }
164 
165   // Comparison
166   setAction({G_ICMP, s1}, Legal);
167 
168   for (auto Ty : {s8, s16, s32, s64, p0})
169     setAction({G_ICMP, 1, Ty}, Legal);
170 }
171 
172 void X86LegalizerInfo::setLegalizerInfoSSE1() {
173   if (!Subtarget.hasSSE1())
174     return;
175 
176   const LLT s32 = LLT::scalar(32);
177   const LLT v4s32 = LLT::vector(4, 32);
178   const LLT v2s64 = LLT::vector(2, 64);
179 
180   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
181     for (auto Ty : {s32, v4s32})
182       setAction({BinOp, Ty}, Legal);
183 
184   for (unsigned MemOp : {G_LOAD, G_STORE})
185     for (auto Ty : {v4s32, v2s64})
186       setAction({MemOp, Ty}, Legal);
187 }
188 
189 void X86LegalizerInfo::setLegalizerInfoSSE2() {
190   if (!Subtarget.hasSSE2())
191     return;
192 
193   const LLT s64 = LLT::scalar(64);
194   const LLT v16s8 = LLT::vector(16, 8);
195   const LLT v8s16 = LLT::vector(8, 16);
196   const LLT v4s32 = LLT::vector(4, 32);
197   const LLT v2s64 = LLT::vector(2, 64);
198 
199   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
200     for (auto Ty : {s64, v2s64})
201       setAction({BinOp, Ty}, Legal);
202 
203   for (unsigned BinOp : {G_ADD, G_SUB})
204     for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
205       setAction({BinOp, Ty}, Legal);
206 
207   setAction({G_MUL, v8s16}, Legal);
208 }
209 
210 void X86LegalizerInfo::setLegalizerInfoSSE41() {
211   if (!Subtarget.hasSSE41())
212     return;
213 
214   const LLT v4s32 = LLT::vector(4, 32);
215 
216   setAction({G_MUL, v4s32}, Legal);
217 }
218 
219 void X86LegalizerInfo::setLegalizerInfoAVX() {
220   if (!Subtarget.hasAVX())
221     return;
222 
223   const LLT v16s8 = LLT::vector(16, 8);
224   const LLT v8s16 = LLT::vector(8, 16);
225   const LLT v4s32 = LLT::vector(4, 32);
226   const LLT v2s64 = LLT::vector(2, 64);
227 
228   const LLT v32s8 = LLT::vector(32, 8);
229   const LLT v16s16 = LLT::vector(16, 16);
230   const LLT v8s32 = LLT::vector(8, 32);
231   const LLT v4s64 = LLT::vector(4, 64);
232 
233   for (unsigned MemOp : {G_LOAD, G_STORE})
234     for (auto Ty : {v8s32, v4s64})
235       setAction({MemOp, Ty}, Legal);
236 
237   for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
238     setAction({G_INSERT, Ty}, Legal);
239     setAction({G_EXTRACT, 1, Ty}, Legal);
240   }
241   for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
242     setAction({G_INSERT, 1, Ty}, Legal);
243     setAction({G_EXTRACT, Ty}, Legal);
244   }
245 }
246 
247 void X86LegalizerInfo::setLegalizerInfoAVX2() {
248   if (!Subtarget.hasAVX2())
249     return;
250 
251   const LLT v32s8 = LLT::vector(32, 8);
252   const LLT v16s16 = LLT::vector(16, 16);
253   const LLT v8s32 = LLT::vector(8, 32);
254   const LLT v4s64 = LLT::vector(4, 64);
255 
256   for (unsigned BinOp : {G_ADD, G_SUB})
257     for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
258       setAction({BinOp, Ty}, Legal);
259 
260   for (auto Ty : {v16s16, v8s32})
261     setAction({G_MUL, Ty}, Legal);
262 }
263 
264 void X86LegalizerInfo::setLegalizerInfoAVX512() {
265   if (!Subtarget.hasAVX512())
266     return;
267 
268   const LLT v16s8 = LLT::vector(16, 8);
269   const LLT v8s16 = LLT::vector(8, 16);
270   const LLT v4s32 = LLT::vector(4, 32);
271   const LLT v2s64 = LLT::vector(2, 64);
272 
273   const LLT v32s8 = LLT::vector(32, 8);
274   const LLT v16s16 = LLT::vector(16, 16);
275   const LLT v8s32 = LLT::vector(8, 32);
276   const LLT v4s64 = LLT::vector(4, 64);
277 
278   const LLT v64s8 = LLT::vector(64, 8);
279   const LLT v32s16 = LLT::vector(32, 16);
280   const LLT v16s32 = LLT::vector(16, 32);
281   const LLT v8s64 = LLT::vector(8, 64);
282 
283   for (unsigned BinOp : {G_ADD, G_SUB})
284     for (auto Ty : {v16s32, v8s64})
285       setAction({BinOp, Ty}, Legal);
286 
287   setAction({G_MUL, v16s32}, Legal);
288 
289   for (unsigned MemOp : {G_LOAD, G_STORE})
290     for (auto Ty : {v16s32, v8s64})
291       setAction({MemOp, Ty}, Legal);
292 
293   for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
294     setAction({G_INSERT, Ty}, Legal);
295     setAction({G_EXTRACT, 1, Ty}, Legal);
296   }
297   for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
298     setAction({G_INSERT, 1, Ty}, Legal);
299     setAction({G_EXTRACT, Ty}, Legal);
300   }
301 
302   /************ VLX *******************/
303   if (!Subtarget.hasVLX())
304     return;
305 
306   for (auto Ty : {v4s32, v8s32})
307     setAction({G_MUL, Ty}, Legal);
308 }
309 
310 void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
311   if (!(Subtarget.hasAVX512() && Subtarget.hasDQI()))
312     return;
313 
314   const LLT v8s64 = LLT::vector(8, 64);
315 
316   setAction({G_MUL, v8s64}, Legal);
317 
318   /************ VLX *******************/
319   if (!Subtarget.hasVLX())
320     return;
321 
322   const LLT v2s64 = LLT::vector(2, 64);
323   const LLT v4s64 = LLT::vector(4, 64);
324 
325   for (auto Ty : {v2s64, v4s64})
326     setAction({G_MUL, Ty}, Legal);
327 }
328 
329 void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
330   if (!(Subtarget.hasAVX512() && Subtarget.hasBWI()))
331     return;
332 
333   const LLT v64s8 = LLT::vector(64, 8);
334   const LLT v32s16 = LLT::vector(32, 16);
335 
336   for (unsigned BinOp : {G_ADD, G_SUB})
337     for (auto Ty : {v64s8, v32s16})
338       setAction({BinOp, Ty}, Legal);
339 
340   setAction({G_MUL, v32s16}, Legal);
341 
342   /************ VLX *******************/
343   if (!Subtarget.hasVLX())
344     return;
345 
346   const LLT v8s16 = LLT::vector(8, 16);
347   const LLT v16s16 = LLT::vector(16, 16);
348 
349   for (auto Ty : {v8s16, v16s16})
350     setAction({G_MUL, Ty}, Legal);
351 }
352