LLVM 22.0.0git
X86LegalizerInfo.cpp
Go to the documentation of this file.
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"
24#include "llvm/IR/Type.h"
25
26using namespace llvm;
27using namespace TargetOpcode;
28using namespace LegalizeActions;
29using namespace LegalityPredicates;
30
32 const X86TargetMachine &TM)
33 : Subtarget(STI) {
34
35 bool Is64Bit = Subtarget.is64Bit();
36 bool HasCMOV = Subtarget.canUseCMOV();
37 bool HasSSE1 = Subtarget.hasSSE1();
38 bool HasSSE2 = Subtarget.hasSSE2();
39 bool HasSSE41 = Subtarget.hasSSE41();
40 bool HasAVX = Subtarget.hasAVX();
41 bool HasAVX2 = Subtarget.hasAVX2();
42 bool HasAVX512 = Subtarget.hasAVX512();
43 bool HasVLX = Subtarget.hasVLX();
44 bool HasDQI = Subtarget.hasAVX512() && Subtarget.hasDQI();
45 bool HasBWI = Subtarget.hasAVX512() && Subtarget.hasBWI();
46 bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();
47 bool HasPOPCNT = Subtarget.hasPOPCNT();
48 bool HasLZCNT = Subtarget.hasLZCNT();
49 bool HasBMI = Subtarget.hasBMI();
50
51 const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
52 const LLT s1 = LLT::scalar(1);
53 const LLT s8 = LLT::scalar(8);
54 const LLT s16 = LLT::scalar(16);
55 const LLT s32 = LLT::scalar(32);
56 const LLT s64 = LLT::scalar(64);
57 const LLT s80 = LLT::scalar(80);
58 const LLT s128 = LLT::scalar(128);
59 const LLT sMaxScalar = Subtarget.is64Bit() ? s64 : s32;
60 const LLT v2s32 = LLT::fixed_vector(2, 32);
61 const LLT v4s8 = LLT::fixed_vector(4, 8);
62
63 const LLT v16s8 = LLT::fixed_vector(16, 8);
64 const LLT v8s16 = LLT::fixed_vector(8, 16);
65 const LLT v4s32 = LLT::fixed_vector(4, 32);
66 const LLT v2s64 = LLT::fixed_vector(2, 64);
67 const LLT v2p0 = LLT::fixed_vector(2, p0);
68
69 const LLT v32s8 = LLT::fixed_vector(32, 8);
70 const LLT v16s16 = LLT::fixed_vector(16, 16);
71 const LLT v8s32 = LLT::fixed_vector(8, 32);
72 const LLT v4s64 = LLT::fixed_vector(4, 64);
73 const LLT v4p0 = LLT::fixed_vector(4, p0);
74
75 const LLT v64s8 = LLT::fixed_vector(64, 8);
76 const LLT v32s16 = LLT::fixed_vector(32, 16);
77 const LLT v16s32 = LLT::fixed_vector(16, 32);
78 const LLT v8s64 = LLT::fixed_vector(8, 64);
79
80 const LLT s8MaxVector = HasAVX512 ? v64s8 : HasAVX ? v32s8 : v16s8;
81 const LLT s16MaxVector = HasAVX512 ? v32s16 : HasAVX ? v16s16 : v8s16;
82 const LLT s32MaxVector = HasAVX512 ? v16s32 : HasAVX ? v8s32 : v4s32;
83 const LLT s64MaxVector = HasAVX512 ? v8s64 : HasAVX ? v4s64 : v2s64;
84
85 // todo: AVX512 bool vector predicate types
86
87 // implicit/constants
88 // 32/64-bits needs support for s64/s128 to handle cases:
89 // s64 = EXTEND (G_IMPLICIT_DEF s32) -> s64 = G_IMPLICIT_DEF
90 // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF
91 getActionDefinitionsBuilder(G_IMPLICIT_DEF)
92 .legalFor({p0, s1, s8, s16, s32, s64})
93 .legalFor(Is64Bit, {s128});
94
96 .legalFor({p0, s8, s16, s32})
97 .legalFor(Is64Bit, {s64})
98 .widenScalarToNextPow2(0, /*Min=*/8)
99 .clampScalar(0, s8, sMaxScalar);
100
102 {G_LROUND, G_LLROUND, G_FCOS, G_FCOSH, G_FACOS, G_FSIN, G_FSINH,
103 G_FASIN, G_FTAN, G_FTANH, G_FATAN, G_FATAN2, G_FPOW, G_FEXP,
104 G_FEXP2, G_FEXP10, G_FLOG, G_FLOG2, G_FLOG10, G_FPOWI, G_FSINCOS})
105 .libcall();
106
108 .legalFor(HasSSE1 || UseX87, {s32})
109 .legalFor(HasSSE2 || UseX87, {s64})
110 .legalFor(UseX87, {s80});
111
112 getActionDefinitionsBuilder(G_GET_ROUNDING).customFor({s32});
113
114 // merge/unmerge
115 for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
116 unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;
117 unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;
119 .widenScalarToNextPow2(LitTyIdx, /*Min=*/8)
120 .widenScalarToNextPow2(BigTyIdx, /*Min=*/16)
121 .minScalar(LitTyIdx, s8)
122 .minScalar(BigTyIdx, s32)
123 .legalIf([=](const LegalityQuery &Q) {
124 switch (Q.Types[BigTyIdx].getSizeInBits()) {
125 case 16:
126 case 32:
127 case 64:
128 case 128:
129 case 256:
130 case 512:
131 break;
132 default:
133 return false;
134 }
135 switch (Q.Types[LitTyIdx].getSizeInBits()) {
136 case 8:
137 case 16:
138 case 32:
139 case 64:
140 case 128:
141 case 256:
142 return true;
143 default:
144 return false;
145 }
146 });
147 }
148
149 // integer addition/subtraction
150 getActionDefinitionsBuilder({G_ADD, G_SUB})
151 .legalFor({s8, s16, s32})
152 .legalFor(Is64Bit, {s64})
153 .legalFor(HasSSE2, {v16s8, v8s16, v4s32, v2s64})
154 .legalFor(HasAVX2, {v32s8, v16s16, v8s32, v4s64})
155 .legalFor(HasAVX512, {v16s32, v8s64})
156 .legalFor(HasBWI, {v64s8, v32s16})
157 .clampMinNumElements(0, s8, 16)
158 .clampMinNumElements(0, s16, 8)
159 .clampMinNumElements(0, s32, 4)
160 .clampMinNumElements(0, s64, 2)
161 .clampMaxNumElements(0, s8, HasBWI ? 64 : (HasAVX2 ? 32 : 16))
162 .clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8))
163 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4))
164 .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX2 ? 4 : 2))
165 .widenScalarToNextPow2(0, /*Min=*/32)
166 .clampScalar(0, s8, sMaxScalar)
167 .scalarize(0);
168
169 getActionDefinitionsBuilder({G_UADDE, G_UADDO, G_USUBE, G_USUBO})
170 .legalFor({{s8, s1}, {s16, s1}, {s32, s1}})
171 .legalFor(Is64Bit, {{s64, s1}})
172 .widenScalarToNextPow2(0, /*Min=*/32)
173 .clampScalar(0, s8, sMaxScalar)
174 .clampScalar(1, s1, s1)
175 .scalarize(0);
176
177 // integer multiply
179 .legalFor({s8, s16, s32})
180 .legalFor(Is64Bit, {s64})
181 .legalFor(HasSSE2, {v8s16})
182 .legalFor(HasSSE41, {v4s32})
183 .legalFor(HasAVX2, {v16s16, v8s32})
184 .legalFor(HasAVX512, {v16s32})
185 .legalFor(HasDQI, {v8s64})
186 .legalFor(HasDQI && HasVLX, {v2s64, v4s64})
187 .legalFor(HasBWI, {v32s16})
188 .clampMinNumElements(0, s16, 8)
189 .clampMinNumElements(0, s32, 4)
190 .clampMinNumElements(0, s64, HasVLX ? 2 : 8)
191 .clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8))
192 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4))
193 .clampMaxNumElements(0, s64, 8)
194 .widenScalarToNextPow2(0, /*Min=*/32)
195 .clampScalar(0, s8, sMaxScalar)
196 .scalarize(0);
197
198 getActionDefinitionsBuilder({G_SMULH, G_UMULH})
199 .legalFor({s8, s16, s32})
200 .legalFor(Is64Bit, {s64})
201 .widenScalarToNextPow2(0, /*Min=*/32)
202 .clampScalar(0, s8, sMaxScalar)
203 .scalarize(0);
204
205 // integer divisions
206 getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UDIV, G_UREM})
207 .legalFor({s8, s16, s32})
208 .legalFor(Is64Bit, {s64})
209 .libcallFor({s64})
210 .clampScalar(0, s8, sMaxScalar);
211
212 // integer shifts
213 getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
214 .legalFor({{s8, s8}, {s16, s8}, {s32, s8}})
215 .legalFor(Is64Bit, {{s64, s8}})
216 .clampScalar(0, s8, sMaxScalar)
217 .clampScalar(1, s8, s8);
218
219 // integer logic
220 getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
221 .legalFor({s8, s16, s32})
222 .legalFor(Is64Bit, {s64})
223 .legalFor(HasSSE2, {v16s8, v8s16, v4s32, v2s64})
224 .legalFor(HasAVX, {v32s8, v16s16, v8s32, v4s64})
225 .legalFor(HasAVX512, {v64s8, v32s16, v16s32, v8s64})
226 .clampMinNumElements(0, s8, 16)
227 .clampMinNumElements(0, s16, 8)
228 .clampMinNumElements(0, s32, 4)
229 .clampMinNumElements(0, s64, 2)
230 .clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16))
231 .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))
232 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))
233 .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))
234 .widenScalarToNextPow2(0, /*Min=*/32)
235 .clampScalar(0, s8, sMaxScalar)
236 .scalarize(0);
237
238 // integer comparison
239 const std::initializer_list<LLT> IntTypes32 = {s8, s16, s32, p0};
240 const std::initializer_list<LLT> IntTypes64 = {s8, s16, s32, s64, p0};
241
243 .legalForCartesianProduct({s8}, Is64Bit ? IntTypes64 : IntTypes32)
244 .clampScalar(0, s8, s8)
245 .clampScalar(1, s8, sMaxScalar);
246
247 // bswap
249 .legalFor({s32})
250 .legalFor(Is64Bit, {s64})
251 .widenScalarToNextPow2(0, /*Min=*/32)
252 .clampScalar(0, s32, sMaxScalar);
253
254 // popcount
256 .legalFor(HasPOPCNT, {{s16, s16}, {s32, s32}})
257 .legalFor(HasPOPCNT && Is64Bit, {{s64, s64}})
258 .widenScalarToNextPow2(1, /*Min=*/16)
259 .clampScalar(1, s16, sMaxScalar)
260 .scalarSameSizeAs(0, 1);
261
262 // count leading zeros (LZCNT)
264 .legalFor(HasLZCNT, {{s16, s16}, {s32, s32}})
265 .legalFor(HasLZCNT && Is64Bit, {{s64, s64}})
266 .widenScalarToNextPow2(1, /*Min=*/16)
267 .clampScalar(1, s16, sMaxScalar)
268 .scalarSameSizeAs(0, 1);
269
270 // count trailing zeros
271 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF)
272 .legalFor({{s16, s16}, {s32, s32}})
273 .legalFor(Is64Bit, {{s64, s64}})
274 .widenScalarToNextPow2(1, /*Min=*/16)
275 .clampScalar(1, s16, sMaxScalar)
276 .scalarSameSizeAs(0, 1);
277
279 .legalFor(HasBMI, {{s16, s16}, {s32, s32}})
280 .legalFor(HasBMI && Is64Bit, {{s64, s64}})
281 .widenScalarToNextPow2(1, /*Min=*/16)
282 .clampScalar(1, s16, sMaxScalar)
283 .scalarSameSizeAs(0, 1);
284
285 // control flow
287 .legalFor({s8, s16, s32, p0})
288 .legalFor(UseX87, {s80})
289 .legalFor(Is64Bit, {s64})
290 .legalFor(HasSSE1, {v16s8, v8s16, v4s32, v2s64})
291 .legalFor(HasAVX, {v32s8, v16s16, v8s32, v4s64})
292 .legalFor(HasAVX512, {v64s8, v32s16, v16s32, v8s64})
293 .clampMinNumElements(0, s8, 16)
294 .clampMinNumElements(0, s16, 8)
295 .clampMinNumElements(0, s32, 4)
296 .clampMinNumElements(0, s64, 2)
297 .clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16))
298 .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))
299 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))
300 .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))
301 .widenScalarToNextPow2(0, /*Min=*/32)
302 .clampScalar(0, s8, sMaxScalar)
303 .scalarize(0);
304
306
307 // pointer handling
308 const std::initializer_list<LLT> PtrTypes32 = {s1, s8, s16, s32};
309 const std::initializer_list<LLT> PtrTypes64 = {s1, s8, s16, s32, s64};
310
312 .legalForCartesianProduct(Is64Bit ? PtrTypes64 : PtrTypes32, {p0})
313 .maxScalar(0, sMaxScalar)
314 .widenScalarToNextPow2(0, /*Min*/ 8);
315
316 getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, sMaxScalar}});
317
318 getActionDefinitionsBuilder(G_CONSTANT_POOL).legalFor({p0});
319
321 .legalFor({{p0, s32}})
322 .legalFor(Is64Bit, {{p0, s64}})
323 .widenScalarToNextPow2(1, /*Min*/ 32)
324 .clampScalar(1, s32, sMaxScalar);
325
326 getActionDefinitionsBuilder({G_FRAME_INDEX, G_GLOBAL_VALUE}).legalFor({p0});
327
328 // load/store: add more corner cases
329 for (unsigned Op : {G_LOAD, G_STORE}) {
330 auto &Action = getActionDefinitionsBuilder(Op);
331 Action.legalForTypesWithMemDesc({{s8, p0, s8, 1},
332 {s16, p0, s16, 1},
333 {s32, p0, s32, 1},
334 {s80, p0, s80, 1},
335 {p0, p0, p0, 1},
336 {v4s8, p0, v4s8, 1}});
337 if (Is64Bit)
338 Action.legalForTypesWithMemDesc(
339 {{s64, p0, s64, 1}, {v2s32, p0, v2s32, 1}});
340
341 if (HasSSE1)
342 Action.legalForTypesWithMemDesc({{v4s32, p0, v4s32, 1}});
343 if (HasSSE2)
344 Action.legalForTypesWithMemDesc({{v16s8, p0, v16s8, 1},
345 {v8s16, p0, v8s16, 1},
346 {v2s64, p0, v2s64, 1},
347 {v2p0, p0, v2p0, 1}});
348 if (HasAVX)
349 Action.legalForTypesWithMemDesc({{v32s8, p0, v32s8, 1},
350 {v16s16, p0, v16s16, 1},
351 {v8s32, p0, v8s32, 1},
352 {v4s64, p0, v4s64, 1},
353 {v4p0, p0, v4p0, 1}});
354 if (HasAVX512)
355 Action.legalForTypesWithMemDesc({{v64s8, p0, v64s8, 1},
356 {v32s16, p0, v32s16, 1},
357 {v16s32, p0, v16s32, 1},
358 {v8s64, p0, v8s64, 1}});
359
360 // X86 supports extending loads but not stores for GPRs
361 if (Op == G_LOAD) {
362 Action.legalForTypesWithMemDesc({{s8, p0, s1, 1},
363 {s16, p0, s8, 1},
364 {s32, p0, s8, 1},
365 {s32, p0, s16, 1}});
366 if (Is64Bit)
367 Action.legalForTypesWithMemDesc(
368 {{s64, p0, s8, 1}, {s64, p0, s16, 1}, {s64, p0, s32, 1}});
369 } else {
370 Action.customIf([=](const LegalityQuery &Query) {
371 return Query.Types[0] != Query.MMODescrs[0].MemoryTy;
372 });
373 }
374 Action.widenScalarToNextPow2(0, /*Min=*/8)
375 .clampScalar(0, s8, sMaxScalar)
376 .scalarize(0);
377 }
378
379 for (unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {
380 auto &Action = getActionDefinitionsBuilder(Op);
381 Action.legalForTypesWithMemDesc(
382 {{s16, p0, s8, 1}, {s32, p0, s8, 1}, {s32, p0, s16, 1}});
383 if (Is64Bit)
384 Action.legalForTypesWithMemDesc(
385 {{s64, p0, s8, 1}, {s64, p0, s16, 1}, {s64, p0, s32, 1}});
386 // TODO - SSE41/AVX2/AVX512F/AVX512BW vector extensions
387 }
388
389 // sext, zext, and anyext
391 .legalFor({s8, s16, s32, s128})
392 .legalFor(Is64Bit, {s64})
393 .widenScalarToNextPow2(0, /*Min=*/8)
394 .clampScalar(0, s8, sMaxScalar)
395 .widenScalarToNextPow2(1, /*Min=*/8)
396 .clampScalar(1, s8, sMaxScalar)
397 .scalarize(0);
398
399 getActionDefinitionsBuilder({G_SEXT, G_ZEXT})
400 .legalFor({s8, s16, s32})
401 .legalFor(Is64Bit, {s64})
402 .widenScalarToNextPow2(0, /*Min=*/8)
403 .clampScalar(0, s8, sMaxScalar)
404 .widenScalarToNextPow2(1, /*Min=*/8)
405 .clampScalar(1, s8, sMaxScalar)
406 .scalarize(0);
407
408 getActionDefinitionsBuilder(G_SEXT_INREG).lower();
409
410 // fp constants
411 getActionDefinitionsBuilder(G_FCONSTANT)
412 .legalFor({s32, s64})
413 .legalFor(UseX87, {s80});
414
415 // fp arithmetic
416 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
417 .legalFor({s32, s64})
418 .legalFor(HasSSE1, {v4s32})
419 .legalFor(HasSSE2, {v2s64})
420 .legalFor(HasAVX, {v8s32, v4s64})
421 .legalFor(HasAVX512, {v16s32, v8s64})
422 .legalFor(UseX87, {s80});
423
425 .legalFor(UseX87, {s80})
426 .legalFor(UseX87 && !Is64Bit, {s64})
427 .lower();
428
429 // fp comparison
431 .legalFor(HasSSE1 || UseX87, {s8, s32})
432 .legalFor(HasSSE2 || UseX87, {s8, s64})
433 .legalFor(UseX87, {s8, s80})
434 .clampScalar(0, s8, s8)
435 .clampScalar(1, s32, HasSSE2 ? s64 : s32)
437
438 // fp conversions
440 .legalFor(HasSSE2, {{s64, s32}})
441 .legalFor(HasAVX, {{v4s64, v4s32}})
442 .legalFor(HasAVX512, {{v8s64, v8s32}});
443
445 .legalFor(HasSSE2, {{s32, s64}})
446 .legalFor(HasAVX, {{v4s32, v4s64}})
447 .legalFor(HasAVX512, {{v8s32, v8s64}});
448
450 .legalFor(HasSSE1, {{s32, s32}})
451 .legalFor(HasSSE1 && Is64Bit, {{s32, s64}})
452 .legalFor(HasSSE2, {{s64, s32}})
453 .legalFor(HasSSE2 && Is64Bit, {{s64, s64}})
454 .clampScalar(1, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar)
456 .customForCartesianProduct(UseX87, {s32, s64, s80}, {s16, s32, s64})
457 .clampScalar(0, s32, HasSSE2 ? s64 : s32)
459
461 .legalFor(HasSSE1, {{s32, s32}})
462 .legalFor(HasSSE1 && Is64Bit, {{s64, s32}})
463 .legalFor(HasSSE2, {{s32, s64}})
464 .legalFor(HasSSE2 && Is64Bit, {{s64, s64}})
465 .clampScalar(0, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar)
467 .customForCartesianProduct(UseX87, {s16, s32, s64}, {s32, s64, s80})
468 .clampScalar(1, s32, HasSSE2 ? s64 : s32)
470
471 // For G_UITOFP and G_FPTOUI without AVX512, we have to custom legalize types
472 // <= s32 manually. Otherwise, in custom handler there is no way to
473 // understand whether s32 is an original type and we need to promote it to
474 // s64 or s32 is obtained after widening and we shouldn't widen it to s64.
475 //
476 // For AVX512 we simply widen types as there is direct mapping from opcodes
477 // to asm instructions.
479 .legalFor(HasAVX512, {{s32, s32}, {s32, s64}, {s64, s32}, {s64, s64}})
480 .customIf([=](const LegalityQuery &Query) {
481 return !HasAVX512 &&
482 ((HasSSE1 && typeIs(0, s32)(Query)) ||
483 (HasSSE2 && typeIs(0, s64)(Query))) &&
484 scalarNarrowerThan(1, Is64Bit ? 64 : 32)(Query);
485 })
486 .lowerIf([=](const LegalityQuery &Query) {
487 // Lower conversions from s64
488 return !HasAVX512 &&
489 ((HasSSE1 && typeIs(0, s32)(Query)) ||
490 (HasSSE2 && typeIs(0, s64)(Query))) &&
491 (Is64Bit && typeIs(1, s64)(Query));
492 })
493 .clampScalar(0, s32, HasSSE2 ? s64 : s32)
495 .clampScalar(1, s32, sMaxScalar)
497
499 .legalFor(HasAVX512, {{s32, s32}, {s32, s64}, {s64, s32}, {s64, s64}})
500 .customIf([=](const LegalityQuery &Query) {
501 return !HasAVX512 &&
502 ((HasSSE1 && typeIs(1, s32)(Query)) ||
503 (HasSSE2 && typeIs(1, s64)(Query))) &&
504 scalarNarrowerThan(0, Is64Bit ? 64 : 32)(Query);
505 })
506 // TODO: replace with customized legalization using
507 // specifics of cvttsd2si. The selection of this node requires
508 // a vector type. Either G_SCALAR_TO_VECTOR is needed or more advanced
509 // support of G_BUILD_VECTOR/G_INSERT_VECTOR_ELT is required beforehand.
510 .lowerIf([=](const LegalityQuery &Query) {
511 return !HasAVX512 &&
512 ((HasSSE1 && typeIs(1, s32)(Query)) ||
513 (HasSSE2 && typeIs(1, s64)(Query))) &&
514 (Is64Bit && typeIs(0, s64)(Query));
515 })
516 .clampScalar(0, s32, sMaxScalar)
518 .clampScalar(1, s32, HasSSE2 ? s64 : s32)
520
521 // vector ops
522 getActionDefinitionsBuilder(G_BUILD_VECTOR)
523 .customIf([=](const LegalityQuery &Query) {
524 return (HasSSE1 && typeInSet(0, {v4s32})(Query)) ||
525 (HasSSE2 && typeInSet(0, {v2s64, v8s16, v16s8})(Query)) ||
526 (HasAVX && typeInSet(0, {v4s64, v8s32, v16s16, v32s8})(Query)) ||
527 (HasAVX512 && typeInSet(0, {v8s64, v16s32, v32s16, v64s8}));
528 })
529 .clampNumElements(0, v16s8, s8MaxVector)
530 .clampNumElements(0, v8s16, s16MaxVector)
531 .clampNumElements(0, v4s32, s32MaxVector)
532 .clampNumElements(0, v2s64, s64MaxVector)
534
535 getActionDefinitionsBuilder({G_EXTRACT, G_INSERT})
536 .legalIf([=](const LegalityQuery &Query) {
537 unsigned SubIdx = Query.Opcode == G_EXTRACT ? 0 : 1;
538 unsigned FullIdx = Query.Opcode == G_EXTRACT ? 1 : 0;
539 return (HasAVX && typePairInSet(SubIdx, FullIdx,
540 {{v16s8, v32s8},
541 {v8s16, v16s16},
542 {v4s32, v8s32},
543 {v2s64, v4s64}})(Query)) ||
544 (HasAVX512 && typePairInSet(SubIdx, FullIdx,
545 {{v16s8, v64s8},
546 {v32s8, v64s8},
547 {v8s16, v32s16},
548 {v16s16, v32s16},
549 {v4s32, v16s32},
550 {v8s32, v16s32},
551 {v2s64, v8s64},
552 {v4s64, v8s64}})(Query));
553 });
554
555 // todo: only permit dst types up to max legal vector register size?
556 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
557 .legalFor(
558 HasSSE1,
559 {{v32s8, v16s8}, {v16s16, v8s16}, {v8s32, v4s32}, {v4s64, v2s64}})
560 .legalFor(HasAVX, {{v64s8, v16s8},
561 {v64s8, v32s8},
562 {v32s16, v8s16},
563 {v32s16, v16s16},
564 {v16s32, v4s32},
565 {v16s32, v8s32},
566 {v8s64, v2s64},
567 {v8s64, v4s64}});
568
569 // todo: vectors and address spaces
571 .legalFor({{s8, s32}, {s16, s32}, {s32, s32}, {s64, s32}, {p0, s32}})
572 .widenScalarToNextPow2(0, /*Min=*/8)
573 .clampScalar(0, HasCMOV ? s16 : s8, sMaxScalar)
574 .clampScalar(1, s32, s32);
575
576 // memory intrinsics
577 getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
578
579 getActionDefinitionsBuilder({G_DYN_STACKALLOC, G_STACKSAVE, G_STACKRESTORE})
580 .lower();
581
582 // fp intrinsics
583 getActionDefinitionsBuilder(G_INTRINSIC_ROUNDEVEN)
584 .scalarize(0)
585 .minScalar(0, LLT::scalar(32))
586 .libcall();
587
588 getActionDefinitionsBuilder({G_FREEZE, G_CONSTANT_FOLD_BARRIER})
589 .legalFor({s8, s16, s32, s64, p0})
590 .widenScalarToNextPow2(0, /*Min=*/8)
591 .clampScalar(0, s8, sMaxScalar);
592
594 verify(*STI.getInstrInfo());
595}
596
598 LostDebugLocObserver &LocObserver) const {
599 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
600 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
601 switch (MI.getOpcode()) {
602 default:
603 // No idea what to do.
604 return false;
605 case TargetOpcode::G_BUILD_VECTOR:
606 return legalizeBuildVector(MI, MRI, Helper);
607 case TargetOpcode::G_FPTOUI:
608 return legalizeFPTOUI(MI, MRI, Helper);
609 case TargetOpcode::G_UITOFP:
610 return legalizeUITOFP(MI, MRI, Helper);
611 case TargetOpcode::G_STORE:
612 return legalizeNarrowingStore(MI, MRI, Helper);
613 case TargetOpcode::G_SITOFP:
614 return legalizeSITOFP(MI, MRI, Helper);
615 case TargetOpcode::G_FPTOSI:
616 return legalizeFPTOSI(MI, MRI, Helper);
617 case TargetOpcode::G_GET_ROUNDING:
618 return legalizeGETROUNDING(MI, MRI, Helper);
619 }
620 llvm_unreachable("expected switch to return");
621}
622
623bool X86LegalizerInfo::legalizeSITOFP(MachineInstr &MI,
625 LegalizerHelper &Helper) const {
626 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
627 MachineFunction &MF = *MI.getMF();
628 auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
629
630 assert((SrcTy.getSizeInBits() == 16 || SrcTy.getSizeInBits() == 32 ||
631 SrcTy.getSizeInBits() == 64) &&
632 "Unexpected source type for SITOFP in X87 mode.");
633
634 TypeSize MemSize = SrcTy.getSizeInBytes();
635 MachinePointerInfo PtrInfo;
636 Align Alignmt = Helper.getStackTemporaryAlignment(SrcTy);
637 auto SlotPointer = Helper.createStackTemporary(MemSize, Alignmt, PtrInfo);
639 PtrInfo, MachineMemOperand::MOStore, MemSize, Align(MemSize));
640
641 // Store the integer value on the FPU stack.
642 MIRBuilder.buildStore(Src, SlotPointer, *StoreMMO);
643
645 PtrInfo, MachineMemOperand::MOLoad, MemSize, Align(MemSize));
646 MIRBuilder.buildInstr(X86::G_FILD)
647 .addDef(Dst)
648 .addUse(SlotPointer.getReg(0))
649 .addMemOperand(LoadMMO);
650
651 MI.eraseFromParent();
652 return true;
653}
654
655bool X86LegalizerInfo::legalizeFPTOSI(MachineInstr &MI,
657 LegalizerHelper &Helper) const {
658 MachineFunction &MF = *MI.getMF();
659 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
660 auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
661
662 TypeSize MemSize = DstTy.getSizeInBytes();
663 MachinePointerInfo PtrInfo;
664 Align Alignmt = Helper.getStackTemporaryAlignment(DstTy);
665 auto SlotPointer = Helper.createStackTemporary(MemSize, Alignmt, PtrInfo);
667 PtrInfo, MachineMemOperand::MOStore, MemSize, Align(MemSize));
668
669 MIRBuilder.buildInstr(X86::G_FIST)
670 .addUse(Src)
671 .addUse(SlotPointer.getReg(0))
672 .addMemOperand(StoreMMO);
673
674 MIRBuilder.buildLoad(Dst, SlotPointer, PtrInfo, Align(MemSize));
675 MI.eraseFromParent();
676 return true;
677}
678
679bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI,
681 LegalizerHelper &Helper) const {
682 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
683 const auto &BuildVector = cast<GBuildVector>(MI);
684 Register Dst = BuildVector.getReg(0);
685 LLT DstTy = MRI.getType(Dst);
686 MachineFunction &MF = MIRBuilder.getMF();
687 LLVMContext &Ctx = MF.getFunction().getContext();
688 uint64_t DstTySize = DstTy.getScalarSizeInBits();
689
691 for (unsigned i = 0; i < BuildVector.getNumSources(); ++i) {
692 Register Source = BuildVector.getSourceReg(i);
693
694 auto ValueAndReg = getIConstantVRegValWithLookThrough(Source, MRI);
695 if (ValueAndReg) {
696 CstIdxs.emplace_back(ConstantInt::get(Ctx, ValueAndReg->Value));
697 continue;
698 }
699
700 auto FPValueAndReg = getFConstantVRegValWithLookThrough(Source, MRI);
701 if (FPValueAndReg) {
702 CstIdxs.emplace_back(ConstantFP::get(Ctx, FPValueAndReg->Value));
703 continue;
704 }
705
706 if (getOpcodeDef<GImplicitDef>(Source, MRI)) {
707 CstIdxs.emplace_back(UndefValue::get(Type::getIntNTy(Ctx, DstTySize)));
708 continue;
709 }
710 return false;
711 }
712
713 Constant *ConstVal = ConstantVector::get(CstIdxs);
714
715 const DataLayout &DL = MIRBuilder.getDataLayout();
716 unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace();
717 Align Alignment(DL.getABITypeAlign(ConstVal->getType()));
718 auto Addr = MIRBuilder.buildConstantPool(
719 LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace)),
720 MF.getConstantPool()->getConstantPoolIndex(ConstVal, Alignment));
721 MachineMemOperand *MMO =
723 MachineMemOperand::MOLoad, DstTy, Alignment);
724
725 MIRBuilder.buildLoad(Dst, Addr, *MMO);
726 MI.eraseFromParent();
727 return true;
728}
729
730bool X86LegalizerInfo::legalizeFPTOUI(MachineInstr &MI,
732 LegalizerHelper &Helper) const {
733 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
734 auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
735 unsigned DstSizeInBits = DstTy.getScalarSizeInBits();
736 const LLT s32 = LLT::scalar(32);
737 const LLT s64 = LLT::scalar(64);
738
739 // Simply reuse FPTOSI when it is possible to widen the type
740 if (DstSizeInBits <= 32) {
741 auto Casted = MIRBuilder.buildFPTOSI(DstTy == s32 ? s64 : s32, Src);
742 MIRBuilder.buildTrunc(Dst, Casted);
743 MI.eraseFromParent();
744 return true;
745 }
746
747 return false;
748}
749
750bool X86LegalizerInfo::legalizeUITOFP(MachineInstr &MI,
752 LegalizerHelper &Helper) const {
753 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
754 auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
755 const LLT s32 = LLT::scalar(32);
756 const LLT s64 = LLT::scalar(64);
757
758 // Simply reuse SITOFP when it is possible to widen the type
759 if (SrcTy.getSizeInBits() <= 32) {
760 auto Ext = MIRBuilder.buildZExt(SrcTy == s32 ? s64 : s32, Src);
761 MIRBuilder.buildSITOFP(Dst, Ext);
762 MI.eraseFromParent();
763 return true;
764 }
765
766 return false;
767}
768
769bool X86LegalizerInfo::legalizeNarrowingStore(MachineInstr &MI,
771 LegalizerHelper &Helper) const {
772 auto &Store = cast<GStore>(MI);
773 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
774 MachineMemOperand &MMO = **Store.memoperands_begin();
775 MachineFunction &MF = MIRBuilder.getMF();
776 LLT ValTy = MRI.getType(Store.getValueReg());
777 auto *NewMMO = MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), ValTy);
778
779 Helper.Observer.changingInstr(Store);
780 Store.setMemRefs(MF, {NewMMO});
781 Helper.Observer.changedInstr(Store);
782 return true;
783}
784
785bool X86LegalizerInfo::legalizeGETROUNDING(MachineInstr &MI,
787 LegalizerHelper &Helper) const {
788 /*
789 The rounding mode is in bits 11:10 of FPSR, and has the following
790 settings:
791 00 Round to nearest
792 01 Round to -inf
793 10 Round to +inf
794 11 Round to 0
795
796 GET_ROUNDING, on the other hand, expects the following:
797 -1 Undefined
798 0 Round to 0
799 1 Round to nearest
800 2 Round to +inf
801 3 Round to -inf
802
803 To perform the conversion, we use a packed lookup table of the four 2-bit
804 values that we can index by FPSP[11:10]
805 0x2d --> (0b00,10,11,01) --> (0,2,3,1) >> FPSR[11:10]
806
807 (0x2d >> ((FPSR >> 9) & 6)) & 3
808 */
809
810 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
811 MachineFunction &MF = MIRBuilder.getMF();
812 Register Dst = MI.getOperand(0).getReg();
813 LLT DstTy = MRI.getType(Dst);
814 const LLT s8 = LLT::scalar(8);
815 const LLT s16 = LLT::scalar(16);
816 const LLT s32 = LLT::scalar(32);
817
818 // Save FP Control Word to stack slot
819 int MemSize = 2;
820 Align Alignment = Align(2);
821 MachinePointerInfo PtrInfo;
822 auto StackTemp = Helper.createStackTemporary(TypeSize::getFixed(MemSize),
823 Alignment, PtrInfo);
824 Register StackPtr = StackTemp.getReg(0);
825
826 auto StoreMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
827 MemSize, Alignment);
828
829 // Store FP Control Word to stack slot using G_FNSTCW16
830 MIRBuilder.buildInstr(X86::G_FNSTCW16)
831 .addUse(StackPtr)
832 .addMemOperand(StoreMMO);
833
834 // Load FP Control Word from stack slot
835 auto LoadMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
836 MemSize, Alignment);
837
838 auto CWD32 =
839 MIRBuilder.buildZExt(s32, MIRBuilder.buildLoad(s16, StackPtr, *LoadMMO));
840 auto Shifted8 = MIRBuilder.buildTrunc(
841 s8, MIRBuilder.buildLShr(s32, CWD32, MIRBuilder.buildConstant(s8, 9)));
842 auto Masked32 = MIRBuilder.buildZExt(
843 s32, MIRBuilder.buildAnd(s8, Shifted8, MIRBuilder.buildConstant(s8, 6)));
844
845 // LUT is a packed lookup table (0x2d) used to map the 2-bit x87 FPU rounding
846 // mode (from bits 11:10 of the control word) to the values expected by
847 // GET_ROUNDING. The mapping is performed by shifting LUT right by the
848 // extracted rounding mode and masking the result with 3 to obtain the final
849 auto LUT = MIRBuilder.buildConstant(s32, 0x2d);
850 auto LUTShifted = MIRBuilder.buildLShr(s32, LUT, Masked32);
851 auto RetVal =
852 MIRBuilder.buildAnd(s32, LUTShifted, MIRBuilder.buildConstant(s32, 3));
853 auto RetValTrunc = MIRBuilder.buildZExtOrTrunc(DstTy, RetVal);
854
855 MIRBuilder.buildCopy(Dst, RetValTrunc);
856
857 MI.eraseFromParent();
858 return true;
859}
860
862 MachineInstr &MI) const {
863 return true;
864}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
uint64_t Addr
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
IRTranslator LLVM IR MI
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
ppc ctr loops verify
static const char LUT[]
This file declares the targeting of the Machinelegalizer class for X86.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
Definition: Constants.cpp:1423
This is an important base class in LLVM.
Definition: Constant.h:43
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:359
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
constexpr unsigned getScalarSizeInBits() const
Definition: LowLevelType.h:265
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:43
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
Definition: LowLevelType.h:58
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
Definition: LowLevelType.h:101
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
LLVM_ABI void computeTables()
Compute any ancillary tables needed to quickly decide how an operation should be handled.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & libcall()
The instruction is emitted as a library call.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & clampMinNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MinElements)
Limit the number of elements in EltTy vectors to at least MinElements.
LegalizeRuleSet & customForCartesianProduct(std::initializer_list< LLT > Types)
LegalizeRuleSet & moreElementsToNextPow2(unsigned TypeIdx)
Add more elements to the vector to reach the next power of two.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & clampNumElements(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the number of elements for the given vectors to at least MinTy's number of elements and at most...
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LLVM_ABI MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, MachinePointerInfo &PtrInfo)
Create a stack temporary based on the size in bytes and the alignment.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI Align getStackTemporaryAlignment(LLT Type, Align MinAlign=Align()) const
Return the alignment to use for a stack temporary object with the given type.
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
const LegacyLegalizerInfo & getLegacyLegalizerInfo() const
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
Helper class to build MachineInstr.
MachineInstrBuilder buildFPTOSI(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_FPTOSI Src0.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_SITOFP Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
Definition: MachineInstr.h:72
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition: TypeSize.h:346
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1866
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:256
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
X86LegalizerInfo(const X86Subtarget &STI, const X86TargetMachine &TM)
bool hasSSE1() const
Definition: X86Subtarget.h:189
bool canUseCMOV() const
Definition: X86Subtarget.h:188
const X86InstrInfo * getInstrInfo() const override
Definition: X86Subtarget.h:122
bool hasAVX512() const
Definition: X86Subtarget.h:197
bool hasSSE41() const
Definition: X86Subtarget.h:193
bool hasSSE2() const
Definition: X86Subtarget.h:190
bool hasAVX() const
Definition: X86Subtarget.h:195
bool hasAVX2() const
Definition: X86Subtarget.h:196
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1, std::initializer_list< std::pair< LLT, LLT > > TypesInit)
True iff the given types for the given pair of type indexes is one of the specified type pairs.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's narrower than the given size.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
LLVM_ABI std::optional< FPValueAndVReg > getFConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_FCONSTANT returns it...
Definition: Utils.cpp:447
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition: Utils.cpp:433
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
ArrayRef< LLT > Types
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.