23using namespace TargetOpcode;
24using namespace LegalizeActions;
25using namespace LegalityPredicates;
31 bool Is64Bit = Subtarget.is64Bit();
32 bool HasSSE1 = Subtarget.
hasSSE1();
33 bool HasSSE2 = Subtarget.
hasSSE2();
34 bool HasSSE41 = Subtarget.
hasSSE41();
35 bool HasAVX = Subtarget.
hasAVX();
36 bool HasAVX2 = Subtarget.
hasAVX2();
38 bool HasVLX = Subtarget.hasVLX();
39 bool HasDQI = Subtarget.
hasAVX512() && Subtarget.hasDQI();
40 bool HasBWI = Subtarget.
hasAVX512() && Subtarget.hasBWI();
50 const LLT sMaxScalar = Subtarget.is64Bit() ? s64 : s32;
80 return typeInSet(0, {p0, s1, s8, s16, s32, s64})(Query) ||
86 return typeInSet(0, {p0, s8, s16, s32})(Query) ||
89 .widenScalarToNextPow2(0, 8)
93 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
94 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
95 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
102 switch (Q.
Types[BigTyIdx].getSizeInBits()) {
113 switch (Q.
Types[LitTyIdx].getSizeInBits()) {
132 if (Is64Bit &&
typeInSet(0, {s64})(Query))
134 if (HasSSE2 &&
typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))
136 if (HasAVX2 &&
typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))
138 if (HasAVX512 &&
typeInSet(0, {v16s32, v8s64})(Query))
140 if (HasBWI &&
typeInSet(0, {v64s8, v32s16})(Query))
144 .clampMinNumElements(0, s8, 16)
158 return typePairInSet(0, 1, {{s8, s1}, {s16, s1}, {s32, s1}})(Query) ||
161 .widenScalarToNextPow2(0, 32)
171 if (Is64Bit &&
typeInSet(0, {s64})(Query))
173 if (HasSSE2 &&
typeInSet(0, {v8s16})(Query))
175 if (HasSSE41 &&
typeInSet(0, {v4s32})(Query))
177 if (HasAVX2 &&
typeInSet(0, {v16s16, v8s32})(Query))
179 if (HasAVX512 &&
typeInSet(0, {v16s32})(Query))
181 if (HasDQI &&
typeInSet(0, {v8s64})(Query))
183 if (HasDQI && HasVLX &&
typeInSet(0, {v2s64, v4s64})(Query))
185 if (HasBWI &&
typeInSet(0, {v32s16})(Query))
189 .clampMinNumElements(0, s16, 8)
201 return typeInSet(0, {s8, s16, s32})(Query) ||
204 .widenScalarToNextPow2(0, 32)
211 return typeInSet(0, {s8, s16, s32})(Query) ||
214 .clampScalar(0, s8, sMaxScalar);
219 return typePairInSet(0, 1, {{s8, s8}, {s16, s8}, {s32, s8}})(Query) ||
222 .clampScalar(0, s8, sMaxScalar)
230 if (Is64Bit &&
typeInSet(0, {s64})(Query))
232 if (HasSSE2 &&
typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))
234 if (HasAVX &&
typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))
236 if (HasAVX512 &&
typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query))
240 .clampMinNumElements(0, s8, 16)
253 const std::initializer_list<LLT> IntTypes32 = {s8, s16, s32, p0};
254 const std::initializer_list<LLT> IntTypes64 = {s8, s16, s32, s64, p0};
258 .clampScalar(0, s8, s8);
263 return Query.
Types[0] == s32 ||
264 (Subtarget.is64Bit() && Query.
Types[0] == s64);
266 .widenScalarToNextPow2(0, 32)
272 return Subtarget.hasPOPCNT() &&
276 .widenScalarToNextPow2(1, 16)
283 return Subtarget.hasLZCNT() &&
287 .widenScalarToNextPow2(1, 16)
294 return (Query.
Opcode == G_CTTZ_ZERO_UNDEF || Subtarget.hasBMI()) &&
298 .widenScalarToNextPow2(1, 16)
305 return typeInSet(0, {s8, s16, s32, p0})(Query) ||
306 (Is64Bit &&
typeInSet(0, {s64})(Query)) ||
307 (HasSSE1 &&
typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query)) ||
308 (HasAVX &&
typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query)) ||
310 typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query));
312 .clampMinNumElements(0, s8, 16)
317 .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))
318 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))
319 .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))
320 .widenScalarToNextPow2(0, 32)
327 const std::initializer_list<LLT> PtrTypes32 = {s1, s8, s16, s32};
328 const std::initializer_list<LLT> PtrTypes64 = {s1, s8, s16, s32, s64};
332 .maxScalar(0, sMaxScalar)
342 .widenScalarToNextPow2(1, 32)
348 for (
unsigned Op : {G_LOAD, G_STORE}) {
350 Action.legalForTypesWithMemDesc({{s8, p0, s1, 1},
359 {v4s8, p0, v4s8, 1}});
361 Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},
365 {v2s32, p0, v2s32, 1}});
367 Action.legalForTypesWithMemDesc({{v16s8, p0, v16s8, 1},
368 {v8s16, p0, v8s16, 1},
369 {v4s32, p0, v4s32, 1},
370 {v2s64, p0, v2s64, 1},
371 {v2p0, p0, v2p0, 1}});
373 Action.legalForTypesWithMemDesc({{v32s8, p0, v32s8, 1},
374 {v16s16, p0, v16s16, 1},
375 {v8s32, p0, v8s32, 1},
376 {v4s64, p0, v4s64, 1},
377 {v4p0, p0, v4p0, 1}});
379 Action.legalForTypesWithMemDesc({{v64s8, p0, v64s8, 1},
380 {v32s16, p0, v32s16, 1},
381 {v16s32, p0, v16s32, 1},
382 {v8s64, p0, v8s64, 1}});
383 Action.widenScalarToNextPow2(0, 8).clampScalar(0, s8, sMaxScalar);
386 for (
unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {
388 Action.legalForTypesWithMemDesc({{s16, p0, s8, 1},
392 Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},
401 return typeInSet(0, {s8, s16, s32})(Query) ||
402 (Query.
Opcode == G_ANYEXT && Query.
Types[0] == s128) ||
403 (Is64Bit && Query.
Types[0] == s64);
405 .widenScalarToNextPow2(0, 8)
415 return (HasSSE1 &&
typeInSet(0, {s32})(Query)) ||
422 return (HasSSE1 &&
typeInSet(0, {s32, v4s32})(Query)) ||
423 (HasSSE2 &&
typeInSet(0, {s64, v2s64})(Query)) ||
424 (HasAVX &&
typeInSet(0, {v8s32, v4s64})(Query)) ||
425 (HasAVX512 &&
typeInSet(0, {v16s32, v8s64})(Query));
431 return (HasSSE1 &&
typePairInSet(0, 1, {{s8, s32}})(Query)) ||
434 .clampScalar(0, s8, s8)
440 return (HasSSE2 &&
typePairInSet(0, 1, {{s64, s32}})(Query)) ||
447 return (HasSSE2 &&
typePairInSet(0, 1, {{s32, s64}})(Query)) ||
461 .clampScalar(1, s32, sMaxScalar)
475 .clampScalar(1, s32, HasSSE2 ? s64 : s32)
483 unsigned SubIdx = Query.
Opcode == G_EXTRACT ? 0 : 1;
484 unsigned FullIdx = Query.
Opcode == G_EXTRACT ? 1 : 0;
489 {v2s64, v4s64}})(Query)) ||
498 {v4s64, v8s64}})(Query));
508 {v2s64, v4s64}})(Query)) ||
517 {v4s64, v8s64}})(Query));
522 .
legalFor({{s8, s32}, {s16, s32}, {s32, s32}, {s64, s32},
524 .widenScalarToNextPow2(0, 8)
533 G_STACKRESTORE}).lower();
542 .legalFor({s8, s16, s32, s64, p0})
543 .widenScalarToNextPow2(0, 8)
const char LLVMTargetMachineRef TM
This file declares the targeting of the Machinelegalizer class for X86.
This class represents an Operation in the Expression.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
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 & 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 & 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 & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
const LegacyLegalizerInfo & getLegacyLegalizerInfo() const
Representation of each machine instruction.
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
X86LegalizerInfo(const X86Subtarget &STI, const X86TargetMachine &TM)
const X86InstrInfo * getInstrInfo() const override
LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
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.
This is an optimization pass for GlobalISel generic memory operations.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...