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