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