[llvm-shlib] Fix the version naming style of libLLVM for Windows (#85710)
[llvm-project.git] / llvm / lib / Target / X86 / GISel / X86LegalizerInfo.cpp
blob27381dff338e2d52bfbd9bea7269ac8a0c61ad99
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 //===----------------------------------------------------------------------===//
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"
22 using namespace llvm;
23 using namespace TargetOpcode;
24 using namespace LegalizeActions;
25 using namespace LegalityPredicates;
27 X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
28 const X86TargetMachine &TM)
29 : Subtarget(STI) {
31 bool Is64Bit = Subtarget.is64Bit();
32 bool HasCMOV = Subtarget.canUseCMOV();
33 bool HasSSE1 = Subtarget.hasSSE1();
34 bool HasSSE2 = Subtarget.hasSSE2();
35 bool HasSSE41 = Subtarget.hasSSE41();
36 bool HasAVX = Subtarget.hasAVX();
37 bool HasAVX2 = Subtarget.hasAVX2();
38 bool HasAVX512 = Subtarget.hasAVX512();
39 bool HasVLX = Subtarget.hasVLX();
40 bool HasDQI = Subtarget.hasAVX512() && Subtarget.hasDQI();
41 bool HasBWI = Subtarget.hasAVX512() && Subtarget.hasBWI();
43 const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
44 const LLT s1 = LLT::scalar(1);
45 const LLT s8 = LLT::scalar(8);
46 const LLT s16 = LLT::scalar(16);
47 const LLT s32 = LLT::scalar(32);
48 const LLT s64 = LLT::scalar(64);
49 const LLT s80 = LLT::scalar(80);
50 const LLT s128 = LLT::scalar(128);
51 const LLT sMaxScalar = Subtarget.is64Bit() ? s64 : s32;
52 const LLT v2s32 = LLT::fixed_vector(2, 32);
53 const LLT v4s8 = LLT::fixed_vector(4, 8);
56 const LLT v16s8 = LLT::fixed_vector(16, 8);
57 const LLT v8s16 = LLT::fixed_vector(8, 16);
58 const LLT v4s32 = LLT::fixed_vector(4, 32);
59 const LLT v2s64 = LLT::fixed_vector(2, 64);
60 const LLT v2p0 = LLT::fixed_vector(2, p0);
62 const LLT v32s8 = LLT::fixed_vector(32, 8);
63 const LLT v16s16 = LLT::fixed_vector(16, 16);
64 const LLT v8s32 = LLT::fixed_vector(8, 32);
65 const LLT v4s64 = LLT::fixed_vector(4, 64);
66 const LLT v4p0 = LLT::fixed_vector(4, p0);
68 const LLT v64s8 = LLT::fixed_vector(64, 8);
69 const LLT v32s16 = LLT::fixed_vector(32, 16);
70 const LLT v16s32 = LLT::fixed_vector(16, 32);
71 const LLT v8s64 = LLT::fixed_vector(8, 64);
73 // todo: AVX512 bool vector predicate types
75 // implicit/constants
76 getActionDefinitionsBuilder(G_IMPLICIT_DEF)
77 .legalIf([=](const LegalityQuery &Query) -> bool {
78 // 32/64-bits needs support for s64/s128 to handle cases:
79 // s64 = EXTEND (G_IMPLICIT_DEF s32) -> s64 = G_IMPLICIT_DEF
80 // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF
81 return typeInSet(0, {p0, s1, s8, s16, s32, s64})(Query) ||
82 (Is64Bit && typeInSet(0, {s128})(Query));
83 });
85 getActionDefinitionsBuilder(G_CONSTANT)
86 .legalIf([=](const LegalityQuery &Query) -> bool {
87 return typeInSet(0, {p0, s8, s16, s32})(Query) ||
88 (Is64Bit && typeInSet(0, {s64})(Query));
90 .widenScalarToNextPow2(0, /*Min=*/8)
91 .clampScalar(0, s8, sMaxScalar);
93 // merge/unmerge
94 for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
95 unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;
96 unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;
97 getActionDefinitionsBuilder(Op)
98 .widenScalarToNextPow2(LitTyIdx, /*Min=*/8)
99 .widenScalarToNextPow2(BigTyIdx, /*Min=*/16)
100 .minScalar(LitTyIdx, s8)
101 .minScalar(BigTyIdx, s32)
102 .legalIf([=](const LegalityQuery &Q) {
103 switch (Q.Types[BigTyIdx].getSizeInBits()) {
104 case 16:
105 case 32:
106 case 64:
107 case 128:
108 case 256:
109 case 512:
110 break;
111 default:
112 return false;
114 switch (Q.Types[LitTyIdx].getSizeInBits()) {
115 case 8:
116 case 16:
117 case 32:
118 case 64:
119 case 128:
120 case 256:
121 return true;
122 default:
123 return false;
128 // integer addition/subtraction
129 getActionDefinitionsBuilder({G_ADD, G_SUB})
130 .legalIf([=](const LegalityQuery &Query) -> bool {
131 if (typeInSet(0, {s8, s16, s32})(Query))
132 return true;
133 if (Is64Bit && typeInSet(0, {s64})(Query))
134 return true;
135 if (HasSSE2 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))
136 return true;
137 if (HasAVX2 && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))
138 return true;
139 if (HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query))
140 return true;
141 if (HasBWI && typeInSet(0, {v64s8, v32s16})(Query))
142 return true;
143 return false;
145 .clampMinNumElements(0, s8, 16)
146 .clampMinNumElements(0, s16, 8)
147 .clampMinNumElements(0, s32, 4)
148 .clampMinNumElements(0, s64, 2)
149 .clampMaxNumElements(0, s8, HasBWI ? 64 : (HasAVX2 ? 32 : 16))
150 .clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8))
151 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4))
152 .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX2 ? 4 : 2))
153 .widenScalarToNextPow2(0, /*Min=*/32)
154 .clampScalar(0, s8, sMaxScalar)
155 .scalarize(0);
157 getActionDefinitionsBuilder({G_UADDE, G_UADDO, G_USUBE, G_USUBO})
158 .legalIf([=](const LegalityQuery &Query) -> bool {
159 return typePairInSet(0, 1, {{s8, s1}, {s16, s1}, {s32, s1}})(Query) ||
160 (Is64Bit && typePairInSet(0, 1, {{s64, s1}})(Query));
162 .widenScalarToNextPow2(0, /*Min=*/32)
163 .clampScalar(0, s8, sMaxScalar)
164 .clampScalar(1, s1, s1)
165 .scalarize(0);
167 // integer multiply
168 getActionDefinitionsBuilder(G_MUL)
169 .legalIf([=](const LegalityQuery &Query) -> bool {
170 if (typeInSet(0, {s8, s16, s32})(Query))
171 return true;
172 if (Is64Bit && typeInSet(0, {s64})(Query))
173 return true;
174 if (HasSSE2 && typeInSet(0, {v8s16})(Query))
175 return true;
176 if (HasSSE41 && typeInSet(0, {v4s32})(Query))
177 return true;
178 if (HasAVX2 && typeInSet(0, {v16s16, v8s32})(Query))
179 return true;
180 if (HasAVX512 && typeInSet(0, {v16s32})(Query))
181 return true;
182 if (HasDQI && typeInSet(0, {v8s64})(Query))
183 return true;
184 if (HasDQI && HasVLX && typeInSet(0, {v2s64, v4s64})(Query))
185 return true;
186 if (HasBWI && typeInSet(0, {v32s16})(Query))
187 return true;
188 return false;
190 .clampMinNumElements(0, s16, 8)
191 .clampMinNumElements(0, s32, 4)
192 .clampMinNumElements(0, s64, HasVLX ? 2 : 8)
193 .clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8))
194 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4))
195 .clampMaxNumElements(0, s64, 8)
196 .widenScalarToNextPow2(0, /*Min=*/32)
197 .clampScalar(0, s8, sMaxScalar)
198 .scalarize(0);
200 getActionDefinitionsBuilder({G_SMULH, G_UMULH})
201 .legalIf([=](const LegalityQuery &Query) -> bool {
202 return typeInSet(0, {s8, s16, s32})(Query) ||
203 (Is64Bit && typeInSet(0, {s64})(Query));
205 .widenScalarToNextPow2(0, /*Min=*/32)
206 .clampScalar(0, s8, sMaxScalar)
207 .scalarize(0);
209 // integer divisions
210 getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UDIV, G_UREM})
211 .legalIf([=](const LegalityQuery &Query) -> bool {
212 return typeInSet(0, {s8, s16, s32})(Query) ||
213 (Is64Bit && typeInSet(0, {s64})(Query));
215 .clampScalar(0, s8, sMaxScalar);
217 // integer shifts
218 getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
219 .legalIf([=](const LegalityQuery &Query) -> bool {
220 return typePairInSet(0, 1, {{s8, s8}, {s16, s8}, {s32, s8}})(Query) ||
221 (Is64Bit && typePairInSet(0, 1, {{s64, s8}})(Query));
223 .clampScalar(0, s8, sMaxScalar)
224 .clampScalar(1, s8, s8);
226 // integer logic
227 getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
228 .legalIf([=](const LegalityQuery &Query) -> bool {
229 if (typeInSet(0, {s8, s16, s32})(Query))
230 return true;
231 if (Is64Bit && typeInSet(0, {s64})(Query))
232 return true;
233 if (HasSSE2 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))
234 return true;
235 if (HasAVX && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))
236 return true;
237 if (HasAVX512 && typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query))
238 return true;
239 return false;
241 .clampMinNumElements(0, s8, 16)
242 .clampMinNumElements(0, s16, 8)
243 .clampMinNumElements(0, s32, 4)
244 .clampMinNumElements(0, s64, 2)
245 .clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16))
246 .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))
247 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))
248 .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))
249 .widenScalarToNextPow2(0, /*Min=*/32)
250 .clampScalar(0, s8, sMaxScalar)
251 .scalarize(0);
253 // integer comparison
254 const std::initializer_list<LLT> IntTypes32 = {s8, s16, s32, p0};
255 const std::initializer_list<LLT> IntTypes64 = {s8, s16, s32, s64, p0};
257 getActionDefinitionsBuilder(G_ICMP)
258 .legalForCartesianProduct({s8}, Is64Bit ? IntTypes64 : IntTypes32)
259 .clampScalar(0, s8, s8)
260 .clampScalar(1, s8, sMaxScalar)
261 .scalarSameSizeAs(2, 1);
263 // bswap
264 getActionDefinitionsBuilder(G_BSWAP)
265 .legalIf([=](const LegalityQuery &Query) {
266 return Query.Types[0] == s32 ||
267 (Subtarget.is64Bit() && Query.Types[0] == s64);
269 .widenScalarToNextPow2(0, /*Min=*/32)
270 .clampScalar(0, s32, sMaxScalar);
272 // popcount
273 getActionDefinitionsBuilder(G_CTPOP)
274 .legalIf([=](const LegalityQuery &Query) -> bool {
275 return Subtarget.hasPOPCNT() &&
276 (typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) ||
277 (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)));
279 .widenScalarToNextPow2(1, /*Min=*/16)
280 .clampScalar(1, s16, sMaxScalar)
281 .scalarSameSizeAs(0, 1);
283 // count leading zeros (LZCNT)
284 getActionDefinitionsBuilder(G_CTLZ)
285 .legalIf([=](const LegalityQuery &Query) -> bool {
286 return Subtarget.hasLZCNT() &&
287 (typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) ||
288 (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)));
290 .widenScalarToNextPow2(1, /*Min=*/16)
291 .clampScalar(1, s16, sMaxScalar)
292 .scalarSameSizeAs(0, 1);
294 // count trailing zeros
295 getActionDefinitionsBuilder({G_CTTZ_ZERO_UNDEF, G_CTTZ})
296 .legalIf([=](const LegalityQuery &Query) -> bool {
297 return (Query.Opcode == G_CTTZ_ZERO_UNDEF || Subtarget.hasBMI()) &&
298 (typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) ||
299 (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)));
301 .widenScalarToNextPow2(1, /*Min=*/16)
302 .clampScalar(1, s16, sMaxScalar)
303 .scalarSameSizeAs(0, 1);
305 // control flow
306 getActionDefinitionsBuilder(G_PHI)
307 .legalIf([=](const LegalityQuery &Query) -> bool {
308 return typeInSet(0, {s8, s16, s32, p0})(Query) ||
309 (Is64Bit && typeInSet(0, {s64})(Query)) ||
310 (HasSSE1 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query)) ||
311 (HasAVX && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query)) ||
312 (HasAVX512 &&
313 typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query));
315 .clampMinNumElements(0, s8, 16)
316 .clampMinNumElements(0, s16, 8)
317 .clampMinNumElements(0, s32, 4)
318 .clampMinNumElements(0, s64, 2)
319 .clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16))
320 .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))
321 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))
322 .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))
323 .widenScalarToNextPow2(0, /*Min=*/32)
324 .clampScalar(0, s8, sMaxScalar)
325 .scalarize(0);
327 getActionDefinitionsBuilder(G_BRCOND).legalFor({s1});
329 // pointer handling
330 const std::initializer_list<LLT> PtrTypes32 = {s1, s8, s16, s32};
331 const std::initializer_list<LLT> PtrTypes64 = {s1, s8, s16, s32, s64};
333 getActionDefinitionsBuilder(G_PTRTOINT)
334 .legalForCartesianProduct(Is64Bit ? PtrTypes64 : PtrTypes32, {p0})
335 .maxScalar(0, sMaxScalar)
336 .widenScalarToNextPow2(0, /*Min*/ 8);
338 getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, sMaxScalar}});
340 getActionDefinitionsBuilder(G_PTR_ADD)
341 .legalIf([=](const LegalityQuery &Query) -> bool {
342 return typePairInSet(0, 1, {{p0, s32}})(Query) ||
343 (Is64Bit && typePairInSet(0, 1, {{p0, s64}})(Query));
345 .widenScalarToNextPow2(1, /*Min*/ 32)
346 .clampScalar(1, s32, sMaxScalar);
348 getActionDefinitionsBuilder({G_FRAME_INDEX, G_GLOBAL_VALUE}).legalFor({p0});
350 // load/store: add more corner cases
351 for (unsigned Op : {G_LOAD, G_STORE}) {
352 auto &Action = getActionDefinitionsBuilder(Op);
353 Action.legalForTypesWithMemDesc({{s8, p0, s1, 1},
354 {s8, p0, s8, 1},
355 {s16, p0, s8, 1},
356 {s16, p0, s16, 1},
357 {s32, p0, s8, 1},
358 {s32, p0, s16, 1},
359 {s32, p0, s32, 1},
360 {s80, p0, s80, 1},
361 {p0, p0, p0, 1},
362 {v4s8, p0, v4s8, 1}});
363 if (Is64Bit)
364 Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},
365 {s64, p0, s16, 1},
366 {s64, p0, s32, 1},
367 {s64, p0, s64, 1},
368 {v2s32, p0, v2s32, 1}});
369 if (HasSSE1)
370 Action.legalForTypesWithMemDesc({{v16s8, p0, v16s8, 1},
371 {v8s16, p0, v8s16, 1},
372 {v4s32, p0, v4s32, 1},
373 {v2s64, p0, v2s64, 1},
374 {v2p0, p0, v2p0, 1}});
375 if (HasAVX)
376 Action.legalForTypesWithMemDesc({{v32s8, p0, v32s8, 1},
377 {v16s16, p0, v16s16, 1},
378 {v8s32, p0, v8s32, 1},
379 {v4s64, p0, v4s64, 1},
380 {v4p0, p0, v4p0, 1}});
381 if (HasAVX512)
382 Action.legalForTypesWithMemDesc({{v64s8, p0, v64s8, 1},
383 {v32s16, p0, v32s16, 1},
384 {v16s32, p0, v16s32, 1},
385 {v8s64, p0, v8s64, 1}});
386 Action.widenScalarToNextPow2(0, /*Min=*/8).clampScalar(0, s8, sMaxScalar);
389 for (unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {
390 auto &Action = getActionDefinitionsBuilder(Op);
391 Action.legalForTypesWithMemDesc({{s16, p0, s8, 1},
392 {s32, p0, s8, 1},
393 {s32, p0, s16, 1}});
394 if (Is64Bit)
395 Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},
396 {s64, p0, s16, 1},
397 {s64, p0, s32, 1}});
398 // TODO - SSE41/AVX2/AVX512F/AVX512BW vector extensions
401 // sext, zext, and anyext
402 getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT})
403 .legalIf([=](const LegalityQuery &Query) {
404 return typeInSet(0, {s8, s16, s32})(Query) ||
405 (Query.Opcode == G_ANYEXT && Query.Types[0] == s128) ||
406 (Is64Bit && Query.Types[0] == s64);
408 .widenScalarToNextPow2(0, /*Min=*/8)
409 .clampScalar(0, s8, sMaxScalar)
410 .widenScalarToNextPow2(1, /*Min=*/8)
411 .clampScalar(1, s8, sMaxScalar);
413 getActionDefinitionsBuilder(G_SEXT_INREG).lower();
415 // fp constants
416 getActionDefinitionsBuilder(G_FCONSTANT)
417 .legalIf([=](const LegalityQuery &Query) -> bool {
418 return (HasSSE1 && typeInSet(0, {s32})(Query)) ||
419 (HasSSE2 && typeInSet(0, {s64})(Query));
422 // fp arithmetic
423 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
424 .legalIf([=](const LegalityQuery &Query) {
425 return (HasSSE1 && typeInSet(0, {s32, v4s32})(Query)) ||
426 (HasSSE2 && typeInSet(0, {s64, v2s64})(Query)) ||
427 (HasAVX && typeInSet(0, {v8s32, v4s64})(Query)) ||
428 (HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query));
431 // fp comparison
432 getActionDefinitionsBuilder(G_FCMP)
433 .legalIf([=](const LegalityQuery &Query) {
434 return (HasSSE1 && typePairInSet(0, 1, {{s8, s32}})(Query)) ||
435 (HasSSE2 && typePairInSet(0, 1, {{s8, s64}})(Query));
437 .clampScalar(0, s8, s8)
438 .clampScalar(1, s32, HasSSE2 ? s64 : s32)
439 .widenScalarToNextPow2(1);
441 // fp conversions
442 getActionDefinitionsBuilder(G_FPEXT).legalIf([=](const LegalityQuery &Query) {
443 return (HasSSE2 && typePairInSet(0, 1, {{s64, s32}})(Query)) ||
444 (HasAVX && typePairInSet(0, 1, {{v4s64, v4s32}})(Query)) ||
445 (HasAVX512 && typePairInSet(0, 1, {{v8s64, v8s32}})(Query));
448 getActionDefinitionsBuilder(G_FPTRUNC).legalIf(
449 [=](const LegalityQuery &Query) {
450 return (HasSSE2 && typePairInSet(0, 1, {{s32, s64}})(Query)) ||
451 (HasAVX && typePairInSet(0, 1, {{v4s32, v4s64}})(Query)) ||
452 (HasAVX512 && typePairInSet(0, 1, {{v8s32, v8s64}})(Query));
455 getActionDefinitionsBuilder(G_SITOFP)
456 .legalIf([=](const LegalityQuery &Query) {
457 return (HasSSE1 &&
458 (typePairInSet(0, 1, {{s32, s32}})(Query) ||
459 (Is64Bit && typePairInSet(0, 1, {{s32, s64}})(Query)))) ||
460 (HasSSE2 &&
461 (typePairInSet(0, 1, {{s64, s32}})(Query) ||
462 (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));
464 .clampScalar(1, s32, sMaxScalar)
465 .widenScalarToNextPow2(1)
466 .clampScalar(0, s32, HasSSE2 ? s64 : s32)
467 .widenScalarToNextPow2(0);
469 getActionDefinitionsBuilder(G_FPTOSI)
470 .legalIf([=](const LegalityQuery &Query) {
471 return (HasSSE1 &&
472 (typePairInSet(0, 1, {{s32, s32}})(Query) ||
473 (Is64Bit && typePairInSet(0, 1, {{s64, s32}})(Query)))) ||
474 (HasSSE2 &&
475 (typePairInSet(0, 1, {{s32, s64}})(Query) ||
476 (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));
478 .clampScalar(1, s32, HasSSE2 ? s64 : s32)
479 .widenScalarToNextPow2(0)
480 .clampScalar(0, s32, sMaxScalar)
481 .widenScalarToNextPow2(1);
483 // vector ops
484 getActionDefinitionsBuilder({G_EXTRACT, G_INSERT})
485 .legalIf([=](const LegalityQuery &Query) {
486 unsigned SubIdx = Query.Opcode == G_EXTRACT ? 0 : 1;
487 unsigned FullIdx = Query.Opcode == G_EXTRACT ? 1 : 0;
488 return (HasAVX && typePairInSet(SubIdx, FullIdx,
489 {{v16s8, v32s8},
490 {v8s16, v16s16},
491 {v4s32, v8s32},
492 {v2s64, v4s64}})(Query)) ||
493 (HasAVX512 && typePairInSet(SubIdx, FullIdx,
494 {{v16s8, v64s8},
495 {v32s8, v64s8},
496 {v8s16, v32s16},
497 {v16s16, v32s16},
498 {v4s32, v16s32},
499 {v8s32, v16s32},
500 {v2s64, v8s64},
501 {v4s64, v8s64}})(Query));
504 // todo: only permit dst types up to max legal vector register size?
505 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
506 .legalIf([=](const LegalityQuery &Query) {
507 return (HasSSE1 && typePairInSet(1, 0,
508 {{v16s8, v32s8},
509 {v8s16, v16s16},
510 {v4s32, v8s32},
511 {v2s64, v4s64}})(Query)) ||
512 (HasAVX && typePairInSet(1, 0,
513 {{v16s8, v64s8},
514 {v32s8, v64s8},
515 {v8s16, v32s16},
516 {v16s16, v32s16},
517 {v4s32, v16s32},
518 {v8s32, v16s32},
519 {v2s64, v8s64},
520 {v4s64, v8s64}})(Query));
523 // todo: vectors and address spaces
524 getActionDefinitionsBuilder(G_SELECT)
525 .legalFor({{s8, s32}, {s16, s32}, {s32, s32}, {s64, s32}, {p0, s32}})
526 .widenScalarToNextPow2(0, /*Min=*/8)
527 .clampScalar(0, HasCMOV ? s16 : s8, sMaxScalar)
528 .clampScalar(1, s32, s32);
530 // memory intrinsics
531 getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
533 getActionDefinitionsBuilder({G_DYN_STACKALLOC,
534 G_STACKSAVE,
535 G_STACKRESTORE}).lower();
537 // fp intrinsics
538 getActionDefinitionsBuilder(G_INTRINSIC_ROUNDEVEN)
539 .scalarize(0)
540 .minScalar(0, LLT::scalar(32))
541 .libcall();
543 getActionDefinitionsBuilder({G_FREEZE, G_CONSTANT_FOLD_BARRIER})
544 .legalFor({s8, s16, s32, s64, p0})
545 .widenScalarToNextPow2(0, /*Min=*/8)
546 .clampScalar(0, s8, sMaxScalar);
548 getLegacyLegalizerInfo().computeTables();
549 verify(*STI.getInstrInfo());
552 bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
553 MachineInstr &MI) const {
554 return true;