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/TargetOpcodes.h"
18 #include "llvm/CodeGen/ValueTypes.h"
19 #include "llvm/IR/DerivedTypes.h"
20 #include "llvm/IR/Type.h"
21 
22 using namespace llvm;
23 using namespace TargetOpcode;
24 
25 /// FIXME: The following static functions are SizeChangeStrategy functions
26 /// that are meant to temporarily mimic the behaviour of the old legalization
27 /// based on doubling/halving non-legal types as closely as possible. This is
28 /// not entirly possible as only legalizing the types that are exactly a power
29 /// of 2 times the size of the legal types would require specifying all those
30 /// sizes explicitly.
31 /// In practice, not specifying those isn't a problem, and the below functions
32 /// should disappear quickly as we add support for legalizing non-power-of-2
33 /// sized types further.
34 static void
35 addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result,
36                                 const LegalizerInfo::SizeAndActionsVec &v) {
37   for (unsigned i = 0; i < v.size(); ++i) {
38     result.push_back(v[i]);
39     if (i + 1 < v[i].first && i + 1 < v.size() &&
40         v[i + 1].first != v[i].first + 1)
41       result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});
42   }
43 }
44 
45 static LegalizerInfo::SizeAndActionsVec
46 widen_1(const LegalizerInfo::SizeAndActionsVec &v) {
47   assert(v.size() >= 1);
48   assert(v[0].first > 1);
49   LegalizerInfo::SizeAndActionsVec result = {{1, LegalizerInfo::WidenScalar},
50                                              {2, LegalizerInfo::Unsupported}};
51   addAndInterleaveWithUnsupported(result, v);
52   auto Largest = result.back().first;
53   result.push_back({Largest + 1, LegalizerInfo::Unsupported});
54   return result;
55 }
56 
57 X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
58                                    const X86TargetMachine &TM)
59     : Subtarget(STI), TM(TM) {
60 
61   setLegalizerInfo32bit();
62   setLegalizerInfo64bit();
63   setLegalizerInfoSSE1();
64   setLegalizerInfoSSE2();
65   setLegalizerInfoSSE41();
66   setLegalizerInfoAVX();
67   setLegalizerInfoAVX2();
68   setLegalizerInfoAVX512();
69   setLegalizerInfoAVX512DQ();
70   setLegalizerInfoAVX512BW();
71 
72   setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1);
73   for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR})
74     setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1);
75   for (unsigned MemOp : {G_LOAD, G_STORE})
76     setLegalizeScalarToDifferentSizeStrategy(MemOp, 0,
77        narrowToSmallerAndWidenToSmallest);
78   setLegalizeScalarToDifferentSizeStrategy(
79       G_GEP, 1, widenToLargerTypesUnsupportedOtherwise);
80   setLegalizeScalarToDifferentSizeStrategy(
81       G_CONSTANT, 0, widenToLargerTypesAndNarrowToLargest);
82 
83   computeTables();
84 }
85 
86 void X86LegalizerInfo::setLegalizerInfo32bit() {
87 
88   const LLT p0 = LLT::pointer(0, TM.getPointerSize() * 8);
89   const LLT s1 = LLT::scalar(1);
90   const LLT s8 = LLT::scalar(8);
91   const LLT s16 = LLT::scalar(16);
92   const LLT s32 = LLT::scalar(32);
93   const LLT s64 = LLT::scalar(64);
94 
95   for (auto Ty : {p0, s1, s8, s16, s32})
96     setAction({G_IMPLICIT_DEF, Ty}, Legal);
97 
98   for (auto Ty : {s8, s16, s32, p0})
99     setAction({G_PHI, Ty}, Legal);
100 
101   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
102     for (auto Ty : {s8, s16, s32})
103       setAction({BinOp, Ty}, Legal);
104 
105   for (unsigned Op : {G_UADDE}) {
106     setAction({Op, s32}, Legal);
107     setAction({Op, 1, s1}, Legal);
108   }
109 
110   for (unsigned MemOp : {G_LOAD, G_STORE}) {
111     for (auto Ty : {s8, s16, s32, p0})
112       setAction({MemOp, Ty}, Legal);
113 
114     // And everything's fine in addrspace 0.
115     setAction({MemOp, 1, p0}, Legal);
116   }
117 
118   // Pointer-handling
119   setAction({G_FRAME_INDEX, p0}, Legal);
120   setAction({G_GLOBAL_VALUE, p0}, Legal);
121 
122   setAction({G_GEP, p0}, Legal);
123   setAction({G_GEP, 1, s32}, Legal);
124 
125   // Control-flow
126   setAction({G_BRCOND, s1}, Legal);
127 
128   // Constants
129   for (auto Ty : {s8, s16, s32, p0})
130     setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
131 
132   // Extensions
133   for (auto Ty : {s8, s16, s32}) {
134     setAction({G_ZEXT, Ty}, Legal);
135     setAction({G_SEXT, Ty}, Legal);
136     setAction({G_ANYEXT, Ty}, Legal);
137   }
138 
139   // Comparison
140   setAction({G_ICMP, s1}, Legal);
141 
142   for (auto Ty : {s8, s16, s32, p0})
143     setAction({G_ICMP, 1, Ty}, Legal);
144 
145   // Merge/Unmerge
146   for (const auto &Ty : {s16, s32, s64}) {
147     setAction({G_MERGE_VALUES, Ty}, Legal);
148     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
149   }
150   for (const auto &Ty : {s8, s16, s32}) {
151     setAction({G_MERGE_VALUES, 1, Ty}, Legal);
152     setAction({G_UNMERGE_VALUES, Ty}, Legal);
153   }
154 }
155 
156 void X86LegalizerInfo::setLegalizerInfo64bit() {
157 
158   if (!Subtarget.is64Bit())
159     return;
160 
161   const LLT s64 = LLT::scalar(64);
162   const LLT s128 = LLT::scalar(128);
163 
164   setAction({G_IMPLICIT_DEF, s64}, Legal);
165 
166   setAction({G_PHI, s64}, Legal);
167 
168   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
169     setAction({BinOp, s64}, Legal);
170 
171   for (unsigned MemOp : {G_LOAD, G_STORE})
172     setAction({MemOp, s64}, Legal);
173 
174   // Pointer-handling
175   setAction({G_GEP, 1, s64}, Legal);
176 
177   // Constants
178   setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
179 
180   // Extensions
181   for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
182     setAction({extOp, s64}, Legal);
183   }
184 
185   // Comparison
186   setAction({G_ICMP, 1, s64}, Legal);
187 
188   // Merge/Unmerge
189   setAction({G_MERGE_VALUES, s128}, Legal);
190   setAction({G_UNMERGE_VALUES, 1, s128}, Legal);
191   setAction({G_MERGE_VALUES, 1, s128}, Legal);
192   setAction({G_UNMERGE_VALUES, s128}, Legal);
193 }
194 
195 void X86LegalizerInfo::setLegalizerInfoSSE1() {
196   if (!Subtarget.hasSSE1())
197     return;
198 
199   const LLT s32 = LLT::scalar(32);
200   const LLT s64 = LLT::scalar(64);
201   const LLT v4s32 = LLT::vector(4, 32);
202   const LLT v2s64 = LLT::vector(2, 64);
203 
204   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
205     for (auto Ty : {s32, v4s32})
206       setAction({BinOp, Ty}, Legal);
207 
208   for (unsigned MemOp : {G_LOAD, G_STORE})
209     for (auto Ty : {v4s32, v2s64})
210       setAction({MemOp, Ty}, Legal);
211 
212   // Constants
213   setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
214 
215   // Merge/Unmerge
216   for (const auto &Ty : {v4s32, v2s64}) {
217     setAction({G_MERGE_VALUES, Ty}, Legal);
218     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
219   }
220   setAction({G_MERGE_VALUES, 1, s64}, Legal);
221   setAction({G_UNMERGE_VALUES, s64}, Legal);
222 }
223 
224 void X86LegalizerInfo::setLegalizerInfoSSE2() {
225   if (!Subtarget.hasSSE2())
226     return;
227 
228   const LLT s32 = LLT::scalar(32);
229   const LLT s64 = LLT::scalar(64);
230   const LLT v16s8 = LLT::vector(16, 8);
231   const LLT v8s16 = LLT::vector(8, 16);
232   const LLT v4s32 = LLT::vector(4, 32);
233   const LLT v2s64 = LLT::vector(2, 64);
234 
235   const LLT v32s8 = LLT::vector(32, 8);
236   const LLT v16s16 = LLT::vector(16, 16);
237   const LLT v8s32 = LLT::vector(8, 32);
238   const LLT v4s64 = LLT::vector(4, 64);
239 
240   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
241     for (auto Ty : {s64, v2s64})
242       setAction({BinOp, Ty}, Legal);
243 
244   for (unsigned BinOp : {G_ADD, G_SUB})
245     for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
246       setAction({BinOp, Ty}, Legal);
247 
248   setAction({G_MUL, v8s16}, Legal);
249 
250   setAction({G_FPEXT, s64}, Legal);
251   setAction({G_FPEXT, 1, s32}, Legal);
252 
253   // Constants
254   setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
255 
256   // Merge/Unmerge
257   for (const auto &Ty :
258        {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
259     setAction({G_MERGE_VALUES, Ty}, Legal);
260     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
261   }
262   for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) {
263     setAction({G_MERGE_VALUES, 1, Ty}, Legal);
264     setAction({G_UNMERGE_VALUES, Ty}, Legal);
265   }
266 }
267 
268 void X86LegalizerInfo::setLegalizerInfoSSE41() {
269   if (!Subtarget.hasSSE41())
270     return;
271 
272   const LLT v4s32 = LLT::vector(4, 32);
273 
274   setAction({G_MUL, v4s32}, Legal);
275 }
276 
277 void X86LegalizerInfo::setLegalizerInfoAVX() {
278   if (!Subtarget.hasAVX())
279     return;
280 
281   const LLT v16s8 = LLT::vector(16, 8);
282   const LLT v8s16 = LLT::vector(8, 16);
283   const LLT v4s32 = LLT::vector(4, 32);
284   const LLT v2s64 = LLT::vector(2, 64);
285 
286   const LLT v32s8 = LLT::vector(32, 8);
287   const LLT v64s8 = LLT::vector(64, 8);
288   const LLT v16s16 = LLT::vector(16, 16);
289   const LLT v32s16 = LLT::vector(32, 16);
290   const LLT v8s32 = LLT::vector(8, 32);
291   const LLT v16s32 = LLT::vector(16, 32);
292   const LLT v4s64 = LLT::vector(4, 64);
293   const LLT v8s64 = LLT::vector(8, 64);
294 
295   for (unsigned MemOp : {G_LOAD, G_STORE})
296     for (auto Ty : {v8s32, v4s64})
297       setAction({MemOp, Ty}, Legal);
298 
299   for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
300     setAction({G_INSERT, Ty}, Legal);
301     setAction({G_EXTRACT, 1, Ty}, Legal);
302   }
303   for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
304     setAction({G_INSERT, 1, Ty}, Legal);
305     setAction({G_EXTRACT, Ty}, Legal);
306   }
307   // Merge/Unmerge
308   for (const auto &Ty :
309        {v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) {
310     setAction({G_MERGE_VALUES, Ty}, Legal);
311     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
312   }
313   for (const auto &Ty :
314        {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
315     setAction({G_MERGE_VALUES, 1, Ty}, Legal);
316     setAction({G_UNMERGE_VALUES, Ty}, Legal);
317   }
318 }
319 
320 void X86LegalizerInfo::setLegalizerInfoAVX2() {
321   if (!Subtarget.hasAVX2())
322     return;
323 
324   const LLT v32s8 = LLT::vector(32, 8);
325   const LLT v16s16 = LLT::vector(16, 16);
326   const LLT v8s32 = LLT::vector(8, 32);
327   const LLT v4s64 = LLT::vector(4, 64);
328 
329   const LLT v64s8 = LLT::vector(64, 8);
330   const LLT v32s16 = LLT::vector(32, 16);
331   const LLT v16s32 = LLT::vector(16, 32);
332   const LLT v8s64 = LLT::vector(8, 64);
333 
334   for (unsigned BinOp : {G_ADD, G_SUB})
335     for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
336       setAction({BinOp, Ty}, Legal);
337 
338   for (auto Ty : {v16s16, v8s32})
339     setAction({G_MUL, Ty}, Legal);
340 
341   // Merge/Unmerge
342   for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) {
343     setAction({G_MERGE_VALUES, Ty}, Legal);
344     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
345   }
346   for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) {
347     setAction({G_MERGE_VALUES, 1, Ty}, Legal);
348     setAction({G_UNMERGE_VALUES, Ty}, Legal);
349   }
350 }
351 
352 void X86LegalizerInfo::setLegalizerInfoAVX512() {
353   if (!Subtarget.hasAVX512())
354     return;
355 
356   const LLT v16s8 = LLT::vector(16, 8);
357   const LLT v8s16 = LLT::vector(8, 16);
358   const LLT v4s32 = LLT::vector(4, 32);
359   const LLT v2s64 = LLT::vector(2, 64);
360 
361   const LLT v32s8 = LLT::vector(32, 8);
362   const LLT v16s16 = LLT::vector(16, 16);
363   const LLT v8s32 = LLT::vector(8, 32);
364   const LLT v4s64 = LLT::vector(4, 64);
365 
366   const LLT v64s8 = LLT::vector(64, 8);
367   const LLT v32s16 = LLT::vector(32, 16);
368   const LLT v16s32 = LLT::vector(16, 32);
369   const LLT v8s64 = LLT::vector(8, 64);
370 
371   for (unsigned BinOp : {G_ADD, G_SUB})
372     for (auto Ty : {v16s32, v8s64})
373       setAction({BinOp, Ty}, Legal);
374 
375   setAction({G_MUL, v16s32}, Legal);
376 
377   for (unsigned MemOp : {G_LOAD, G_STORE})
378     for (auto Ty : {v16s32, v8s64})
379       setAction({MemOp, Ty}, Legal);
380 
381   for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
382     setAction({G_INSERT, Ty}, Legal);
383     setAction({G_EXTRACT, 1, Ty}, Legal);
384   }
385   for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
386     setAction({G_INSERT, 1, Ty}, Legal);
387     setAction({G_EXTRACT, Ty}, Legal);
388   }
389 
390   /************ VLX *******************/
391   if (!Subtarget.hasVLX())
392     return;
393 
394   for (auto Ty : {v4s32, v8s32})
395     setAction({G_MUL, Ty}, Legal);
396 }
397 
398 void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
399   if (!(Subtarget.hasAVX512() && Subtarget.hasDQI()))
400     return;
401 
402   const LLT v8s64 = LLT::vector(8, 64);
403 
404   setAction({G_MUL, v8s64}, Legal);
405 
406   /************ VLX *******************/
407   if (!Subtarget.hasVLX())
408     return;
409 
410   const LLT v2s64 = LLT::vector(2, 64);
411   const LLT v4s64 = LLT::vector(4, 64);
412 
413   for (auto Ty : {v2s64, v4s64})
414     setAction({G_MUL, Ty}, Legal);
415 }
416 
417 void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
418   if (!(Subtarget.hasAVX512() && Subtarget.hasBWI()))
419     return;
420 
421   const LLT v64s8 = LLT::vector(64, 8);
422   const LLT v32s16 = LLT::vector(32, 16);
423 
424   for (unsigned BinOp : {G_ADD, G_SUB})
425     for (auto Ty : {v64s8, v32s16})
426       setAction({BinOp, Ty}, Legal);
427 
428   setAction({G_MUL, v32s16}, Legal);
429 
430   /************ VLX *******************/
431   if (!Subtarget.hasVLX())
432     return;
433 
434   const LLT v8s16 = LLT::vector(8, 16);
435   const LLT v16s16 = LLT::vector(16, 16);
436 
437   for (auto Ty : {v8s16, v16s16})
438     setAction({G_MUL, Ty}, Legal);
439 }
440