23using namespace TargetOpcode;
24using namespace LegalizeActions;
25using namespace LegalityPredicates;
31 bool Is64Bit = Subtarget.is64Bit();
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();
39 bool HasVLX = Subtarget.hasVLX();
40 bool HasDQI = Subtarget.
hasAVX512() && Subtarget.hasDQI();
41 bool HasBWI = Subtarget.
hasAVX512() && Subtarget.hasBWI();
42 bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();
52 const LLT sMaxScalar = Subtarget.is64Bit() ? s64 : s32;
82 return typeInSet(0, {p0, s1, s8, s16, s32, s64})(Query) ||
88 return typeInSet(0, {p0, s8, s16, s32})(Query) ||
91 .widenScalarToNextPow2(0, 8)
95 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
96 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
97 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
104 switch (Q.
Types[BigTyIdx].getSizeInBits()) {
115 switch (Q.
Types[LitTyIdx].getSizeInBits()) {
134 if (Is64Bit &&
typeInSet(0, {s64})(Query))
136 if (HasSSE2 &&
typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))
138 if (HasAVX2 &&
typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))
140 if (HasAVX512 &&
typeInSet(0, {v16s32, v8s64})(Query))
142 if (HasBWI &&
typeInSet(0, {v64s8, v32s16})(Query))
146 .clampMinNumElements(0, s8, 16)
160 return typePairInSet(0, 1, {{s8, s1}, {s16, s1}, {s32, s1}})(Query) ||
163 .widenScalarToNextPow2(0, 32)
173 if (Is64Bit &&
typeInSet(0, {s64})(Query))
175 if (HasSSE2 &&
typeInSet(0, {v8s16})(Query))
177 if (HasSSE41 &&
typeInSet(0, {v4s32})(Query))
179 if (HasAVX2 &&
typeInSet(0, {v16s16, v8s32})(Query))
181 if (HasAVX512 &&
typeInSet(0, {v16s32})(Query))
183 if (HasDQI &&
typeInSet(0, {v8s64})(Query))
185 if (HasDQI && HasVLX &&
typeInSet(0, {v2s64, v4s64})(Query))
187 if (HasBWI &&
typeInSet(0, {v32s16})(Query))
191 .clampMinNumElements(0, s16, 8)
203 return typeInSet(0, {s8, s16, s32})(Query) ||
206 .widenScalarToNextPow2(0, 32)
213 return typeInSet(0, {s8, s16, s32})(Query) ||
217 .clampScalar(0, s8, sMaxScalar);
222 return typePairInSet(0, 1, {{s8, s8}, {s16, s8}, {s32, s8}})(Query) ||
225 .clampScalar(0, s8, sMaxScalar)
233 if (Is64Bit &&
typeInSet(0, {s64})(Query))
235 if (HasSSE2 &&
typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))
237 if (HasAVX &&
typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))
239 if (HasAVX512 &&
typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query))
243 .clampMinNumElements(0, s8, 16)
256 const std::initializer_list<LLT> IntTypes32 = {s8, s16, s32, p0};
257 const std::initializer_list<LLT> IntTypes64 = {s8, s16, s32, s64, p0};
261 .clampScalar(0, s8, s8)
267 return Query.
Types[0] == s32 ||
268 (Subtarget.is64Bit() && Query.
Types[0] == s64);
270 .widenScalarToNextPow2(0, 32)
276 return Subtarget.hasPOPCNT() &&
280 .widenScalarToNextPow2(1, 16)
287 return Subtarget.hasLZCNT() &&
291 .widenScalarToNextPow2(1, 16)
298 return (Query.
Opcode == G_CTTZ_ZERO_UNDEF || Subtarget.hasBMI()) &&
302 .widenScalarToNextPow2(1, 16)
309 return typeInSet(0, {s8, s16, s32, p0})(Query) ||
310 (Is64Bit &&
typeInSet(0, {s64})(Query)) ||
311 (HasSSE1 &&
typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query)) ||
312 (HasAVX &&
typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query)) ||
314 typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query));
316 .clampMinNumElements(0, s8, 16)
321 .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))
322 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))
323 .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))
324 .widenScalarToNextPow2(0, 32)
331 const std::initializer_list<LLT> PtrTypes32 = {s1, s8, s16, s32};
332 const std::initializer_list<LLT> PtrTypes64 = {s1, s8, s16, s32, s64};
336 .maxScalar(0, sMaxScalar)
346 .widenScalarToNextPow2(1, 32)
352 for (
unsigned Op : {G_LOAD, G_STORE}) {
354 Action.legalForTypesWithMemDesc({{s8, p0, s1, 1},
363 {v4s8, p0, v4s8, 1}});
365 Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},
369 {v2s32, p0, v2s32, 1}});
371 Action.legalForTypesWithMemDesc({{v16s8, p0, v16s8, 1},
372 {v8s16, p0, v8s16, 1},
373 {v4s32, p0, v4s32, 1},
374 {v2s64, p0, v2s64, 1},
375 {v2p0, p0, v2p0, 1}});
377 Action.legalForTypesWithMemDesc({{v32s8, p0, v32s8, 1},
378 {v16s16, p0, v16s16, 1},
379 {v8s32, p0, v8s32, 1},
380 {v4s64, p0, v4s64, 1},
381 {v4p0, p0, v4p0, 1}});
383 Action.legalForTypesWithMemDesc({{v64s8, p0, v64s8, 1},
384 {v32s16, p0, v32s16, 1},
385 {v16s32, p0, v16s32, 1},
386 {v8s64, p0, v8s64, 1}});
387 Action.widenScalarToNextPow2(0, 8).clampScalar(0, s8, sMaxScalar);
390 for (
unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {
392 Action.legalForTypesWithMemDesc({{s16, p0, s8, 1},
396 Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},
405 return typeInSet(0, {s8, s16, s32})(Query) ||
406 (Query.
Opcode == G_ANYEXT && Query.
Types[0] == s128) ||
407 (Is64Bit && Query.
Types[0] == s64);
409 .widenScalarToNextPow2(0, 8)
419 return (
typeInSet(0, {s32, s64})(Query)) ||
426 return (
typeInSet(0, {s32, s64})(Query)) ||
427 (HasSSE1 &&
typeInSet(0, {v4s32})(Query)) ||
428 (HasSSE2 &&
typeInSet(0, {v2s64})(Query)) ||
429 (HasAVX &&
typeInSet(0, {v8s32, v4s64})(Query)) ||
430 (HasAVX512 &&
typeInSet(0, {v16s32, v8s64})(Query)) ||
437 return (HasSSE1 &&
typePairInSet(0, 1, {{s8, s32}})(Query)) ||
440 .clampScalar(0, s8, s8)
446 return (HasSSE2 &&
typePairInSet(0, 1, {{s64, s32}})(Query)) ||
453 return (HasSSE2 &&
typePairInSet(0, 1, {{s32, s64}})(Query)) ||
467 .clampScalar(1, s32, sMaxScalar)
481 .clampScalar(1, s32, HasSSE2 ? s64 : s32)
489 unsigned SubIdx = Query.
Opcode == G_EXTRACT ? 0 : 1;
490 unsigned FullIdx = Query.
Opcode == G_EXTRACT ? 1 : 0;
495 {v2s64, v4s64}})(Query)) ||
504 {v4s64, v8s64}})(Query));
514 {v2s64, v4s64}})(Query)) ||
523 {v4s64, v8s64}})(Query));
528 .
legalFor({{s8, s32}, {s16, s32}, {s32, s32}, {s64, s32}, {p0, s32}})
529 .widenScalarToNextPow2(0, 8)
538 G_STACKRESTORE}).lower();
547 .legalFor({s8, s16, s32, s64, p0})
548 .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...