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/GlobalISel/LegalizerHelper.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   getActionDefinitionsBuilder(G_INTRINSIC_ROUNDEVEN)
74     .scalarize(0)
75     .minScalar(0, LLT::scalar(32))
76     .libcall();
77 
78   setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1);
79   for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR})
80     setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1);
81   for (unsigned MemOp : {G_LOAD, G_STORE})
82     setLegalizeScalarToDifferentSizeStrategy(MemOp, 0,
83        narrowToSmallerAndWidenToSmallest);
84   setLegalizeScalarToDifferentSizeStrategy(
85       G_PTR_ADD, 1, widenToLargerTypesUnsupportedOtherwise);
86   setLegalizeScalarToDifferentSizeStrategy(
87       G_CONSTANT, 0, widenToLargerTypesAndNarrowToLargest);
88 
89   getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
90 
91   computeTables();
92   verify(*STI.getInstrInfo());
93 }
94 
legalizeIntrinsic(LegalizerHelper & Helper,MachineInstr & MI) const95 bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
96                                          MachineInstr &MI) const {
97   return true;
98 }
99 
setLegalizerInfo32bit()100 void X86LegalizerInfo::setLegalizerInfo32bit() {
101 
102   const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
103   const LLT s1 = LLT::scalar(1);
104   const LLT s8 = LLT::scalar(8);
105   const LLT s16 = LLT::scalar(16);
106   const LLT s32 = LLT::scalar(32);
107   const LLT s64 = LLT::scalar(64);
108   const LLT s128 = LLT::scalar(128);
109 
110   for (auto Ty : {p0, s1, s8, s16, s32})
111     setAction({G_IMPLICIT_DEF, Ty}, Legal);
112 
113   for (auto Ty : {s8, s16, s32, p0})
114     setAction({G_PHI, Ty}, Legal);
115 
116   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
117     for (auto Ty : {s8, s16, s32})
118       setAction({BinOp, Ty}, Legal);
119 
120   for (unsigned Op : {G_UADDE}) {
121     setAction({Op, s32}, Legal);
122     setAction({Op, 1, s1}, Legal);
123   }
124 
125   for (unsigned MemOp : {G_LOAD, G_STORE}) {
126     for (auto Ty : {s8, s16, s32, p0})
127       setAction({MemOp, Ty}, Legal);
128 
129     // And everything's fine in addrspace 0.
130     setAction({MemOp, 1, p0}, Legal);
131   }
132 
133   // Pointer-handling
134   setAction({G_FRAME_INDEX, p0}, Legal);
135   setAction({G_GLOBAL_VALUE, p0}, Legal);
136 
137   setAction({G_PTR_ADD, p0}, Legal);
138   setAction({G_PTR_ADD, 1, s32}, Legal);
139 
140   if (!Subtarget.is64Bit()) {
141     getActionDefinitionsBuilder(G_PTRTOINT)
142         .legalForCartesianProduct({s1, s8, s16, s32}, {p0})
143         .maxScalar(0, s32)
144         .widenScalarToNextPow2(0, /*Min*/ 8);
145     getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}});
146 
147     // Shifts and SDIV
148     getActionDefinitionsBuilder(
149         {G_SDIV, G_SREM, G_UDIV, G_UREM})
150       .legalFor({s8, s16, s32})
151       .clampScalar(0, s8, s32);
152 
153     getActionDefinitionsBuilder(
154         {G_SHL, G_LSHR, G_ASHR})
155       .legalFor({{s8, s8}, {s16, s8}, {s32, s8}})
156       .clampScalar(0, s8, s32)
157       .clampScalar(1, s8, s8);
158 
159     // Comparison
160     getActionDefinitionsBuilder(G_ICMP)
161         .legalForCartesianProduct({s8}, {s8, s16, s32, p0})
162         .clampScalar(0, s8, s8);
163   }
164 
165   // Control-flow
166   setAction({G_BRCOND, s1}, Legal);
167 
168   // Constants
169   for (auto Ty : {s8, s16, s32, p0})
170     setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
171 
172   // Extensions
173   for (auto Ty : {s8, s16, s32}) {
174     setAction({G_ZEXT, Ty}, Legal);
175     setAction({G_SEXT, Ty}, Legal);
176     setAction({G_ANYEXT, Ty}, Legal);
177   }
178   setAction({G_ANYEXT, s128}, Legal);
179   getActionDefinitionsBuilder(G_SEXT_INREG).lower();
180 
181   // Merge/Unmerge
182   for (const auto &Ty : {s16, s32, s64}) {
183     setAction({G_MERGE_VALUES, Ty}, Legal);
184     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
185   }
186   for (const auto &Ty : {s8, s16, s32}) {
187     setAction({G_MERGE_VALUES, 1, Ty}, Legal);
188     setAction({G_UNMERGE_VALUES, Ty}, Legal);
189   }
190 }
191 
setLegalizerInfo64bit()192 void X86LegalizerInfo::setLegalizerInfo64bit() {
193 
194   if (!Subtarget.is64Bit())
195     return;
196 
197   const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
198   const LLT s1 = LLT::scalar(1);
199   const LLT s8 = LLT::scalar(8);
200   const LLT s16 = LLT::scalar(16);
201   const LLT s32 = LLT::scalar(32);
202   const LLT s64 = LLT::scalar(64);
203   const LLT s128 = LLT::scalar(128);
204 
205   setAction({G_IMPLICIT_DEF, s64}, Legal);
206   // Need to have that, as tryFoldImplicitDef will create this pattern:
207   // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF
208   setAction({G_IMPLICIT_DEF, s128}, Legal);
209 
210   setAction({G_PHI, s64}, Legal);
211 
212   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
213     setAction({BinOp, s64}, Legal);
214 
215   for (unsigned MemOp : {G_LOAD, G_STORE})
216     setAction({MemOp, s64}, Legal);
217 
218   // Pointer-handling
219   setAction({G_PTR_ADD, 1, s64}, Legal);
220   getActionDefinitionsBuilder(G_PTRTOINT)
221       .legalForCartesianProduct({s1, s8, s16, s32, s64}, {p0})
222       .maxScalar(0, s64)
223       .widenScalarToNextPow2(0, /*Min*/ 8);
224   getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s64}});
225 
226   // Constants
227   setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
228 
229   // Extensions
230   for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
231     setAction({extOp, s64}, Legal);
232   }
233 
234   getActionDefinitionsBuilder(G_SITOFP)
235     .legalForCartesianProduct({s32, s64})
236       .clampScalar(1, s32, s64)
237       .widenScalarToNextPow2(1)
238       .clampScalar(0, s32, s64)
239       .widenScalarToNextPow2(0);
240 
241   getActionDefinitionsBuilder(G_FPTOSI)
242       .legalForCartesianProduct({s32, s64})
243       .clampScalar(1, s32, s64)
244       .widenScalarToNextPow2(0)
245       .clampScalar(0, s32, s64)
246       .widenScalarToNextPow2(1);
247 
248   // Comparison
249   getActionDefinitionsBuilder(G_ICMP)
250       .legalForCartesianProduct({s8}, {s8, s16, s32, s64, p0})
251       .clampScalar(0, s8, s8);
252 
253   getActionDefinitionsBuilder(G_FCMP)
254       .legalForCartesianProduct({s8}, {s32, s64})
255       .clampScalar(0, s8, s8)
256       .clampScalar(1, s32, s64)
257       .widenScalarToNextPow2(1);
258 
259   // Divisions
260   getActionDefinitionsBuilder(
261       {G_SDIV, G_SREM, G_UDIV, G_UREM})
262       .legalFor({s8, s16, s32, s64})
263       .clampScalar(0, s8, s64);
264 
265   // Shifts
266   getActionDefinitionsBuilder(
267     {G_SHL, G_LSHR, G_ASHR})
268     .legalFor({{s8, s8}, {s16, s8}, {s32, s8}, {s64, s8}})
269     .clampScalar(0, s8, s64)
270     .clampScalar(1, s8, s8);
271 
272   // Merge/Unmerge
273   setAction({G_MERGE_VALUES, s128}, Legal);
274   setAction({G_UNMERGE_VALUES, 1, s128}, Legal);
275   setAction({G_MERGE_VALUES, 1, s128}, Legal);
276   setAction({G_UNMERGE_VALUES, s128}, Legal);
277 }
278 
setLegalizerInfoSSE1()279 void X86LegalizerInfo::setLegalizerInfoSSE1() {
280   if (!Subtarget.hasSSE1())
281     return;
282 
283   const LLT s32 = LLT::scalar(32);
284   const LLT s64 = LLT::scalar(64);
285   const LLT v4s32 = LLT::vector(4, 32);
286   const LLT v2s64 = LLT::vector(2, 64);
287 
288   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
289     for (auto Ty : {s32, v4s32})
290       setAction({BinOp, Ty}, Legal);
291 
292   for (unsigned MemOp : {G_LOAD, G_STORE})
293     for (auto Ty : {v4s32, v2s64})
294       setAction({MemOp, Ty}, Legal);
295 
296   // Constants
297   setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
298 
299   // Merge/Unmerge
300   for (const auto &Ty : {v4s32, v2s64}) {
301     setAction({G_CONCAT_VECTORS, Ty}, Legal);
302     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
303   }
304   setAction({G_MERGE_VALUES, 1, s64}, Legal);
305   setAction({G_UNMERGE_VALUES, s64}, Legal);
306 }
307 
setLegalizerInfoSSE2()308 void X86LegalizerInfo::setLegalizerInfoSSE2() {
309   if (!Subtarget.hasSSE2())
310     return;
311 
312   const LLT s32 = LLT::scalar(32);
313   const LLT s64 = LLT::scalar(64);
314   const LLT v16s8 = LLT::vector(16, 8);
315   const LLT v8s16 = LLT::vector(8, 16);
316   const LLT v4s32 = LLT::vector(4, 32);
317   const LLT v2s64 = LLT::vector(2, 64);
318 
319   const LLT v32s8 = LLT::vector(32, 8);
320   const LLT v16s16 = LLT::vector(16, 16);
321   const LLT v8s32 = LLT::vector(8, 32);
322   const LLT v4s64 = LLT::vector(4, 64);
323 
324   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
325     for (auto Ty : {s64, v2s64})
326       setAction({BinOp, Ty}, Legal);
327 
328   for (unsigned BinOp : {G_ADD, G_SUB})
329     for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
330       setAction({BinOp, Ty}, Legal);
331 
332   setAction({G_MUL, v8s16}, Legal);
333 
334   setAction({G_FPEXT, s64}, Legal);
335   setAction({G_FPEXT, 1, s32}, Legal);
336 
337   setAction({G_FPTRUNC, s32}, Legal);
338   setAction({G_FPTRUNC, 1, s64}, Legal);
339 
340   // Constants
341   setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
342 
343   // Merge/Unmerge
344   for (const auto &Ty :
345        {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
346     setAction({G_CONCAT_VECTORS, Ty}, Legal);
347     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
348   }
349   for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) {
350     setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
351     setAction({G_UNMERGE_VALUES, Ty}, Legal);
352   }
353 }
354 
setLegalizerInfoSSE41()355 void X86LegalizerInfo::setLegalizerInfoSSE41() {
356   if (!Subtarget.hasSSE41())
357     return;
358 
359   const LLT v4s32 = LLT::vector(4, 32);
360 
361   setAction({G_MUL, v4s32}, Legal);
362 }
363 
setLegalizerInfoAVX()364 void X86LegalizerInfo::setLegalizerInfoAVX() {
365   if (!Subtarget.hasAVX())
366     return;
367 
368   const LLT v16s8 = LLT::vector(16, 8);
369   const LLT v8s16 = LLT::vector(8, 16);
370   const LLT v4s32 = LLT::vector(4, 32);
371   const LLT v2s64 = LLT::vector(2, 64);
372 
373   const LLT v32s8 = LLT::vector(32, 8);
374   const LLT v64s8 = LLT::vector(64, 8);
375   const LLT v16s16 = LLT::vector(16, 16);
376   const LLT v32s16 = LLT::vector(32, 16);
377   const LLT v8s32 = LLT::vector(8, 32);
378   const LLT v16s32 = LLT::vector(16, 32);
379   const LLT v4s64 = LLT::vector(4, 64);
380   const LLT v8s64 = LLT::vector(8, 64);
381 
382   for (unsigned MemOp : {G_LOAD, G_STORE})
383     for (auto Ty : {v8s32, v4s64})
384       setAction({MemOp, Ty}, Legal);
385 
386   for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
387     setAction({G_INSERT, Ty}, Legal);
388     setAction({G_EXTRACT, 1, Ty}, Legal);
389   }
390   for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
391     setAction({G_INSERT, 1, Ty}, Legal);
392     setAction({G_EXTRACT, Ty}, Legal);
393   }
394   // Merge/Unmerge
395   for (const auto &Ty :
396        {v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) {
397     setAction({G_CONCAT_VECTORS, Ty}, Legal);
398     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
399   }
400   for (const auto &Ty :
401        {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
402     setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
403     setAction({G_UNMERGE_VALUES, Ty}, Legal);
404   }
405 }
406 
setLegalizerInfoAVX2()407 void X86LegalizerInfo::setLegalizerInfoAVX2() {
408   if (!Subtarget.hasAVX2())
409     return;
410 
411   const LLT v32s8 = LLT::vector(32, 8);
412   const LLT v16s16 = LLT::vector(16, 16);
413   const LLT v8s32 = LLT::vector(8, 32);
414   const LLT v4s64 = LLT::vector(4, 64);
415 
416   const LLT v64s8 = LLT::vector(64, 8);
417   const LLT v32s16 = LLT::vector(32, 16);
418   const LLT v16s32 = LLT::vector(16, 32);
419   const LLT v8s64 = LLT::vector(8, 64);
420 
421   for (unsigned BinOp : {G_ADD, G_SUB})
422     for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
423       setAction({BinOp, Ty}, Legal);
424 
425   for (auto Ty : {v16s16, v8s32})
426     setAction({G_MUL, Ty}, Legal);
427 
428   // Merge/Unmerge
429   for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) {
430     setAction({G_CONCAT_VECTORS, Ty}, Legal);
431     setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
432   }
433   for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) {
434     setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
435     setAction({G_UNMERGE_VALUES, Ty}, Legal);
436   }
437 }
438 
setLegalizerInfoAVX512()439 void X86LegalizerInfo::setLegalizerInfoAVX512() {
440   if (!Subtarget.hasAVX512())
441     return;
442 
443   const LLT v16s8 = LLT::vector(16, 8);
444   const LLT v8s16 = LLT::vector(8, 16);
445   const LLT v4s32 = LLT::vector(4, 32);
446   const LLT v2s64 = LLT::vector(2, 64);
447 
448   const LLT v32s8 = LLT::vector(32, 8);
449   const LLT v16s16 = LLT::vector(16, 16);
450   const LLT v8s32 = LLT::vector(8, 32);
451   const LLT v4s64 = LLT::vector(4, 64);
452 
453   const LLT v64s8 = LLT::vector(64, 8);
454   const LLT v32s16 = LLT::vector(32, 16);
455   const LLT v16s32 = LLT::vector(16, 32);
456   const LLT v8s64 = LLT::vector(8, 64);
457 
458   for (unsigned BinOp : {G_ADD, G_SUB})
459     for (auto Ty : {v16s32, v8s64})
460       setAction({BinOp, Ty}, Legal);
461 
462   setAction({G_MUL, v16s32}, Legal);
463 
464   for (unsigned MemOp : {G_LOAD, G_STORE})
465     for (auto Ty : {v16s32, v8s64})
466       setAction({MemOp, Ty}, Legal);
467 
468   for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
469     setAction({G_INSERT, Ty}, Legal);
470     setAction({G_EXTRACT, 1, Ty}, Legal);
471   }
472   for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
473     setAction({G_INSERT, 1, Ty}, Legal);
474     setAction({G_EXTRACT, Ty}, Legal);
475   }
476 
477   /************ VLX *******************/
478   if (!Subtarget.hasVLX())
479     return;
480 
481   for (auto Ty : {v4s32, v8s32})
482     setAction({G_MUL, Ty}, Legal);
483 }
484 
setLegalizerInfoAVX512DQ()485 void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
486   if (!(Subtarget.hasAVX512() && Subtarget.hasDQI()))
487     return;
488 
489   const LLT v8s64 = LLT::vector(8, 64);
490 
491   setAction({G_MUL, v8s64}, Legal);
492 
493   /************ VLX *******************/
494   if (!Subtarget.hasVLX())
495     return;
496 
497   const LLT v2s64 = LLT::vector(2, 64);
498   const LLT v4s64 = LLT::vector(4, 64);
499 
500   for (auto Ty : {v2s64, v4s64})
501     setAction({G_MUL, Ty}, Legal);
502 }
503 
setLegalizerInfoAVX512BW()504 void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
505   if (!(Subtarget.hasAVX512() && Subtarget.hasBWI()))
506     return;
507 
508   const LLT v64s8 = LLT::vector(64, 8);
509   const LLT v32s16 = LLT::vector(32, 16);
510 
511   for (unsigned BinOp : {G_ADD, G_SUB})
512     for (auto Ty : {v64s8, v32s16})
513       setAction({BinOp, Ty}, Legal);
514 
515   setAction({G_MUL, v32s16}, Legal);
516 
517   /************ VLX *******************/
518   if (!Subtarget.hasVLX())
519     return;
520 
521   const LLT v8s16 = LLT::vector(8, 16);
522   const LLT v16s16 = LLT::vector(16, 16);
523 
524   for (auto Ty : {v8s16, v16s16})
525     setAction({G_MUL, Ty}, Legal);
526 }
527