1 //===- X86LegalizerInfo.cpp --------------------------------------*- C++ -*-==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements the targeting of the Machinelegalizer class for X86.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
12 
13 #include "X86LegalizerInfo.h"
14 #include "X86Subtarget.h"
15 #include "X86TargetMachine.h"
16 #include "llvm/CodeGen/TargetOpcodes.h"
17 #include "llvm/CodeGen/ValueTypes.h"
18 #include "llvm/IR/DerivedTypes.h"
19 #include "llvm/IR/Type.h"
20 
21 using namespace llvm;
22 using namespace TargetOpcode;
23 using namespace LegalizeActions;
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
addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec & result,const LegalizerInfo::SizeAndActionsVec & v)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, Unsupported});
42   }
43 }
44 
45 static LegalizerInfo::SizeAndActionsVec
widen_1(const LegalizerInfo::SizeAndActionsVec & v)46 widen_1(const LegalizerInfo::SizeAndActionsVec &v) {
47   assert(v.size() >= 1);
48   assert(v[0].first > 1);
49   LegalizerInfo::SizeAndActionsVec result = {{1, WidenScalar},
50                                              {2, Unsupported}};
51   addAndInterleaveWithUnsupported(result, v);
52   auto Largest = result.back().first;
53   result.push_back({Largest + 1, Unsupported});
54   return result;
55 }
56 
X86LegalizerInfo(const X86Subtarget & STI,const X86TargetMachine & TM)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   verify(*STI.getInstrInfo());
85 }
86 
setLegalizerInfo32bit()87 void X86LegalizerInfo::setLegalizerInfo32bit() {
88 
89   const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
90   const LLT s1 = LLT::scalar(1);
91   const LLT s8 = LLT::scalar(8);
92   const LLT s16 = LLT::scalar(16);
93   const LLT s32 = LLT::scalar(32);
94   const LLT s64 = LLT::scalar(64);
95   const LLT s128 = LLT::scalar(128);
96 
97   for (auto Ty : {p0, s1, s8, s16, s32})
98     setAction({G_IMPLICIT_DEF, Ty}, Legal);
99 
100   for (auto Ty : {s8, s16, s32, p0})
101     setAction({G_PHI, Ty}, Legal);
102 
103   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
104     for (auto Ty : {s8, s16, s32})
105       setAction({BinOp, Ty}, Legal);
106 
107   for (unsigned Op : {G_UADDE}) {
108     setAction({Op, s32}, Legal);
109     setAction({Op, 1, s1}, Legal);
110   }
111 
112   for (unsigned MemOp : {G_LOAD, G_STORE}) {
113     for (auto Ty : {s8, s16, s32, p0})
114       setAction({MemOp, Ty}, Legal);
115 
116     // And everything's fine in addrspace 0.
117     setAction({MemOp, 1, p0}, Legal);
118   }
119 
120   // Pointer-handling
121   setAction({G_FRAME_INDEX, p0}, Legal);
122   setAction({G_GLOBAL_VALUE, p0}, Legal);
123 
124   setAction({G_GEP, p0}, Legal);
125   setAction({G_GEP, 1, s32}, Legal);
126 
127   if (!Subtarget.is64Bit()) {
128     getActionDefinitionsBuilder(G_PTRTOINT)
129         .legalForCartesianProduct({s1, s8, s16, s32}, {p0})
130         .maxScalar(0, s32)
131         .widenScalarToNextPow2(0, /*Min*/ 8);
132     getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}});
133 
134     // Shifts and SDIV
135     getActionDefinitionsBuilder(
136         {G_SDIV, G_SREM, G_UDIV, G_UREM})
137       .legalFor({s8, s16, s32})
138       .clampScalar(0, s8, s32);
139 
140     getActionDefinitionsBuilder(
141         {G_SHL, G_LSHR, G_ASHR})
142       .legalFor({{s8, s8}, {s16, s8}, {s32, s8}})
143       .clampScalar(0, s8, s32)
144       .clampScalar(1, s8, s8);
145   }
146 
147   // Control-flow
148   setAction({G_BRCOND, s1}, Legal);
149 
150   // Constants
151   for (auto Ty : {s8, s16, s32, p0})
152     setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
153 
154   // Extensions
155   for (auto Ty : {s8, s16, s32}) {
156     setAction({G_ZEXT, Ty}, Legal);
157     setAction({G_SEXT, Ty}, Legal);
158     setAction({G_ANYEXT, Ty}, Legal);
159   }
160   setAction({G_ANYEXT, s128}, Legal);
161 
162   // Comparison
163   setAction({G_ICMP, s1}, Legal);
164 
165   for (auto Ty : {s8, s16, s32, p0})
166     setAction({G_ICMP, 1, Ty}, Legal);
167 
168   // Merge/Unmerge
169   for (const auto &Ty : {s16, s32, s64}) {
170     setAction({G_MERGE_VALUES, Ty}, Legal);
171     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
172   }
173   for (const auto &Ty : {s8, s16, s32}) {
174     setAction({G_MERGE_VALUES, 1, Ty}, Legal);
175     setAction({G_UNMERGE_VALUES, Ty}, Legal);
176   }
177 }
178 
setLegalizerInfo64bit()179 void X86LegalizerInfo::setLegalizerInfo64bit() {
180 
181   if (!Subtarget.is64Bit())
182     return;
183 
184   const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
185   const LLT s1 = LLT::scalar(1);
186   const LLT s8 = LLT::scalar(8);
187   const LLT s16 = LLT::scalar(16);
188   const LLT s32 = LLT::scalar(32);
189   const LLT s64 = LLT::scalar(64);
190   const LLT s128 = LLT::scalar(128);
191 
192   setAction({G_IMPLICIT_DEF, s64}, Legal);
193   // Need to have that, as tryFoldImplicitDef will create this pattern:
194   // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF
195   setAction({G_IMPLICIT_DEF, s128}, Legal);
196 
197   setAction({G_PHI, s64}, Legal);
198 
199   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
200     setAction({BinOp, s64}, Legal);
201 
202   for (unsigned MemOp : {G_LOAD, G_STORE})
203     setAction({MemOp, s64}, Legal);
204 
205   // Pointer-handling
206   setAction({G_GEP, 1, s64}, Legal);
207   getActionDefinitionsBuilder(G_PTRTOINT)
208       .legalForCartesianProduct({s1, s8, s16, s32, s64}, {p0})
209       .maxScalar(0, s64)
210       .widenScalarToNextPow2(0, /*Min*/ 8);
211   getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s64}});
212 
213   // Constants
214   setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
215 
216   // Extensions
217   for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
218     setAction({extOp, s64}, Legal);
219   }
220 
221   getActionDefinitionsBuilder(G_SITOFP)
222     .legalForCartesianProduct({s32, s64})
223       .clampScalar(1, s32, s64)
224       .widenScalarToNextPow2(1)
225       .clampScalar(0, s32, s64)
226       .widenScalarToNextPow2(0);
227 
228   getActionDefinitionsBuilder(G_FPTOSI)
229       .legalForCartesianProduct({s32, s64})
230       .clampScalar(1, s32, s64)
231       .widenScalarToNextPow2(0)
232       .clampScalar(0, s32, s64)
233       .widenScalarToNextPow2(1);
234 
235   // Comparison
236   setAction({G_ICMP, 1, s64}, Legal);
237 
238   getActionDefinitionsBuilder(G_FCMP)
239       .legalForCartesianProduct({s8}, {s32, s64})
240       .clampScalar(0, s8, s8)
241       .clampScalar(1, s32, s64)
242       .widenScalarToNextPow2(1);
243 
244   // Divisions
245   getActionDefinitionsBuilder(
246       {G_SDIV, G_SREM, G_UDIV, G_UREM})
247       .legalFor({s8, s16, s32, s64})
248       .clampScalar(0, s8, s64);
249 
250   // Shifts
251   getActionDefinitionsBuilder(
252     {G_SHL, G_LSHR, G_ASHR})
253     .legalFor({{s8, s8}, {s16, s8}, {s32, s8}, {s64, s8}})
254     .clampScalar(0, s8, s64)
255     .clampScalar(1, s8, s8);
256 
257   // Merge/Unmerge
258   setAction({G_MERGE_VALUES, s128}, Legal);
259   setAction({G_UNMERGE_VALUES, 1, s128}, Legal);
260   setAction({G_MERGE_VALUES, 1, s128}, Legal);
261   setAction({G_UNMERGE_VALUES, s128}, Legal);
262 }
263 
setLegalizerInfoSSE1()264 void X86LegalizerInfo::setLegalizerInfoSSE1() {
265   if (!Subtarget.hasSSE1())
266     return;
267 
268   const LLT s32 = LLT::scalar(32);
269   const LLT s64 = LLT::scalar(64);
270   const LLT v4s32 = LLT::vector(4, 32);
271   const LLT v2s64 = LLT::vector(2, 64);
272 
273   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
274     for (auto Ty : {s32, v4s32})
275       setAction({BinOp, Ty}, Legal);
276 
277   for (unsigned MemOp : {G_LOAD, G_STORE})
278     for (auto Ty : {v4s32, v2s64})
279       setAction({MemOp, Ty}, Legal);
280 
281   // Constants
282   setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
283 
284   // Merge/Unmerge
285   for (const auto &Ty : {v4s32, v2s64}) {
286     setAction({G_CONCAT_VECTORS, Ty}, Legal);
287     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
288   }
289   setAction({G_MERGE_VALUES, 1, s64}, Legal);
290   setAction({G_UNMERGE_VALUES, s64}, Legal);
291 }
292 
setLegalizerInfoSSE2()293 void X86LegalizerInfo::setLegalizerInfoSSE2() {
294   if (!Subtarget.hasSSE2())
295     return;
296 
297   const LLT s32 = LLT::scalar(32);
298   const LLT s64 = LLT::scalar(64);
299   const LLT v16s8 = LLT::vector(16, 8);
300   const LLT v8s16 = LLT::vector(8, 16);
301   const LLT v4s32 = LLT::vector(4, 32);
302   const LLT v2s64 = LLT::vector(2, 64);
303 
304   const LLT v32s8 = LLT::vector(32, 8);
305   const LLT v16s16 = LLT::vector(16, 16);
306   const LLT v8s32 = LLT::vector(8, 32);
307   const LLT v4s64 = LLT::vector(4, 64);
308 
309   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
310     for (auto Ty : {s64, v2s64})
311       setAction({BinOp, Ty}, Legal);
312 
313   for (unsigned BinOp : {G_ADD, G_SUB})
314     for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
315       setAction({BinOp, Ty}, Legal);
316 
317   setAction({G_MUL, v8s16}, Legal);
318 
319   setAction({G_FPEXT, s64}, Legal);
320   setAction({G_FPEXT, 1, s32}, Legal);
321 
322   setAction({G_FPTRUNC, s32}, Legal);
323   setAction({G_FPTRUNC, 1, s64}, Legal);
324 
325   // Constants
326   setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
327 
328   // Merge/Unmerge
329   for (const auto &Ty :
330        {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
331     setAction({G_CONCAT_VECTORS, Ty}, Legal);
332     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
333   }
334   for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) {
335     setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
336     setAction({G_UNMERGE_VALUES, Ty}, Legal);
337   }
338 }
339 
setLegalizerInfoSSE41()340 void X86LegalizerInfo::setLegalizerInfoSSE41() {
341   if (!Subtarget.hasSSE41())
342     return;
343 
344   const LLT v4s32 = LLT::vector(4, 32);
345 
346   setAction({G_MUL, v4s32}, Legal);
347 }
348 
setLegalizerInfoAVX()349 void X86LegalizerInfo::setLegalizerInfoAVX() {
350   if (!Subtarget.hasAVX())
351     return;
352 
353   const LLT v16s8 = LLT::vector(16, 8);
354   const LLT v8s16 = LLT::vector(8, 16);
355   const LLT v4s32 = LLT::vector(4, 32);
356   const LLT v2s64 = LLT::vector(2, 64);
357 
358   const LLT v32s8 = LLT::vector(32, 8);
359   const LLT v64s8 = LLT::vector(64, 8);
360   const LLT v16s16 = LLT::vector(16, 16);
361   const LLT v32s16 = LLT::vector(32, 16);
362   const LLT v8s32 = LLT::vector(8, 32);
363   const LLT v16s32 = LLT::vector(16, 32);
364   const LLT v4s64 = LLT::vector(4, 64);
365   const LLT v8s64 = LLT::vector(8, 64);
366 
367   for (unsigned MemOp : {G_LOAD, G_STORE})
368     for (auto Ty : {v8s32, v4s64})
369       setAction({MemOp, Ty}, Legal);
370 
371   for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
372     setAction({G_INSERT, Ty}, Legal);
373     setAction({G_EXTRACT, 1, Ty}, Legal);
374   }
375   for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
376     setAction({G_INSERT, 1, Ty}, Legal);
377     setAction({G_EXTRACT, Ty}, Legal);
378   }
379   // Merge/Unmerge
380   for (const auto &Ty :
381        {v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) {
382     setAction({G_CONCAT_VECTORS, Ty}, Legal);
383     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
384   }
385   for (const auto &Ty :
386        {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
387     setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
388     setAction({G_UNMERGE_VALUES, Ty}, Legal);
389   }
390 }
391 
setLegalizerInfoAVX2()392 void X86LegalizerInfo::setLegalizerInfoAVX2() {
393   if (!Subtarget.hasAVX2())
394     return;
395 
396   const LLT v32s8 = LLT::vector(32, 8);
397   const LLT v16s16 = LLT::vector(16, 16);
398   const LLT v8s32 = LLT::vector(8, 32);
399   const LLT v4s64 = LLT::vector(4, 64);
400 
401   const LLT v64s8 = LLT::vector(64, 8);
402   const LLT v32s16 = LLT::vector(32, 16);
403   const LLT v16s32 = LLT::vector(16, 32);
404   const LLT v8s64 = LLT::vector(8, 64);
405 
406   for (unsigned BinOp : {G_ADD, G_SUB})
407     for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
408       setAction({BinOp, Ty}, Legal);
409 
410   for (auto Ty : {v16s16, v8s32})
411     setAction({G_MUL, Ty}, Legal);
412 
413   // Merge/Unmerge
414   for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) {
415     setAction({G_CONCAT_VECTORS, Ty}, Legal);
416     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
417   }
418   for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) {
419     setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
420     setAction({G_UNMERGE_VALUES, Ty}, Legal);
421   }
422 }
423 
setLegalizerInfoAVX512()424 void X86LegalizerInfo::setLegalizerInfoAVX512() {
425   if (!Subtarget.hasAVX512())
426     return;
427 
428   const LLT v16s8 = LLT::vector(16, 8);
429   const LLT v8s16 = LLT::vector(8, 16);
430   const LLT v4s32 = LLT::vector(4, 32);
431   const LLT v2s64 = LLT::vector(2, 64);
432 
433   const LLT v32s8 = LLT::vector(32, 8);
434   const LLT v16s16 = LLT::vector(16, 16);
435   const LLT v8s32 = LLT::vector(8, 32);
436   const LLT v4s64 = LLT::vector(4, 64);
437 
438   const LLT v64s8 = LLT::vector(64, 8);
439   const LLT v32s16 = LLT::vector(32, 16);
440   const LLT v16s32 = LLT::vector(16, 32);
441   const LLT v8s64 = LLT::vector(8, 64);
442 
443   for (unsigned BinOp : {G_ADD, G_SUB})
444     for (auto Ty : {v16s32, v8s64})
445       setAction({BinOp, Ty}, Legal);
446 
447   setAction({G_MUL, v16s32}, Legal);
448 
449   for (unsigned MemOp : {G_LOAD, G_STORE})
450     for (auto Ty : {v16s32, v8s64})
451       setAction({MemOp, Ty}, Legal);
452 
453   for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
454     setAction({G_INSERT, Ty}, Legal);
455     setAction({G_EXTRACT, 1, Ty}, Legal);
456   }
457   for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
458     setAction({G_INSERT, 1, Ty}, Legal);
459     setAction({G_EXTRACT, Ty}, Legal);
460   }
461 
462   /************ VLX *******************/
463   if (!Subtarget.hasVLX())
464     return;
465 
466   for (auto Ty : {v4s32, v8s32})
467     setAction({G_MUL, Ty}, Legal);
468 }
469 
setLegalizerInfoAVX512DQ()470 void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
471   if (!(Subtarget.hasAVX512() && Subtarget.hasDQI()))
472     return;
473 
474   const LLT v8s64 = LLT::vector(8, 64);
475 
476   setAction({G_MUL, v8s64}, Legal);
477 
478   /************ VLX *******************/
479   if (!Subtarget.hasVLX())
480     return;
481 
482   const LLT v2s64 = LLT::vector(2, 64);
483   const LLT v4s64 = LLT::vector(4, 64);
484 
485   for (auto Ty : {v2s64, v4s64})
486     setAction({G_MUL, Ty}, Legal);
487 }
488 
setLegalizerInfoAVX512BW()489 void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
490   if (!(Subtarget.hasAVX512() && Subtarget.hasBWI()))
491     return;
492 
493   const LLT v64s8 = LLT::vector(64, 8);
494   const LLT v32s16 = LLT::vector(32, 16);
495 
496   for (unsigned BinOp : {G_ADD, G_SUB})
497     for (auto Ty : {v64s8, v32s16})
498       setAction({BinOp, Ty}, Legal);
499 
500   setAction({G_MUL, v32s16}, Legal);
501 
502   /************ VLX *******************/
503   if (!Subtarget.hasVLX())
504     return;
505 
506   const LLT v8s16 = LLT::vector(8, 16);
507   const LLT v16s16 = LLT::vector(16, 16);
508 
509   for (auto Ty : {v8s16, v16s16})
510     setAction({G_MUL, Ty}, Legal);
511 }
512