xref: /llvm-project/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp (revision e9cb44090ff7b3feda386ca1ee1252ab47c0617e)
11c3f7f17SFangrui Song //===- X86LegalizerInfo.cpp --------------------------------------*- C++ -*-==//
21c3f7f17SFangrui Song //
31c3f7f17SFangrui Song // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41c3f7f17SFangrui Song // See https://llvm.org/LICENSE.txt for license information.
51c3f7f17SFangrui Song // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61c3f7f17SFangrui Song //
71c3f7f17SFangrui Song //===----------------------------------------------------------------------===//
81c3f7f17SFangrui Song /// \file
91c3f7f17SFangrui Song /// This file implements the targeting of the Machinelegalizer class for X86.
101c3f7f17SFangrui Song /// \todo This should be generated by TableGen.
111c3f7f17SFangrui Song //===----------------------------------------------------------------------===//
121c3f7f17SFangrui Song 
131c3f7f17SFangrui Song #include "X86LegalizerInfo.h"
141c3f7f17SFangrui Song #include "X86Subtarget.h"
151c3f7f17SFangrui Song #include "X86TargetMachine.h"
1611d7203cSEvgenii Kudriashov #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
171c3f7f17SFangrui Song #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
1811d7203cSEvgenii Kudriashov #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
1911d7203cSEvgenii Kudriashov #include "llvm/CodeGen/MachineConstantPool.h"
201c3f7f17SFangrui Song #include "llvm/CodeGen/TargetOpcodes.h"
211c3f7f17SFangrui Song #include "llvm/CodeGen/ValueTypes.h"
221c3f7f17SFangrui Song #include "llvm/IR/DerivedTypes.h"
231c3f7f17SFangrui Song #include "llvm/IR/Type.h"
241c3f7f17SFangrui Song 
251c3f7f17SFangrui Song using namespace llvm;
261c3f7f17SFangrui Song using namespace TargetOpcode;
271c3f7f17SFangrui Song using namespace LegalizeActions;
281c3f7f17SFangrui Song using namespace LegalityPredicates;
291c3f7f17SFangrui Song 
301c3f7f17SFangrui Song X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
311c3f7f17SFangrui Song                                    const X86TargetMachine &TM)
321c3f7f17SFangrui Song     : Subtarget(STI) {
331c3f7f17SFangrui Song 
341c3f7f17SFangrui Song   bool Is64Bit = Subtarget.is64Bit();
35ef35da82SEvgenii Kudriashov   bool HasCMOV = Subtarget.canUseCMOV();
361c3f7f17SFangrui Song   bool HasSSE1 = Subtarget.hasSSE1();
371c3f7f17SFangrui Song   bool HasSSE2 = Subtarget.hasSSE2();
381c3f7f17SFangrui Song   bool HasSSE41 = Subtarget.hasSSE41();
391c3f7f17SFangrui Song   bool HasAVX = Subtarget.hasAVX();
401c3f7f17SFangrui Song   bool HasAVX2 = Subtarget.hasAVX2();
411c3f7f17SFangrui Song   bool HasAVX512 = Subtarget.hasAVX512();
421c3f7f17SFangrui Song   bool HasVLX = Subtarget.hasVLX();
431c3f7f17SFangrui Song   bool HasDQI = Subtarget.hasAVX512() && Subtarget.hasDQI();
441c3f7f17SFangrui Song   bool HasBWI = Subtarget.hasAVX512() && Subtarget.hasBWI();
45564b81dbSMalaySanghiIntel   bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();
461c3f7f17SFangrui Song 
471c3f7f17SFangrui Song   const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
481c3f7f17SFangrui Song   const LLT s1 = LLT::scalar(1);
491c3f7f17SFangrui Song   const LLT s8 = LLT::scalar(8);
501c3f7f17SFangrui Song   const LLT s16 = LLT::scalar(16);
511c3f7f17SFangrui Song   const LLT s32 = LLT::scalar(32);
521c3f7f17SFangrui Song   const LLT s64 = LLT::scalar(64);
531c3f7f17SFangrui Song   const LLT s80 = LLT::scalar(80);
541c3f7f17SFangrui Song   const LLT s128 = LLT::scalar(128);
551c3f7f17SFangrui Song   const LLT sMaxScalar = Subtarget.is64Bit() ? s64 : s32;
561c3f7f17SFangrui Song   const LLT v2s32 = LLT::fixed_vector(2, 32);
571c3f7f17SFangrui Song   const LLT v4s8 = LLT::fixed_vector(4, 8);
581c3f7f17SFangrui Song 
591c3f7f17SFangrui Song 
601c3f7f17SFangrui Song   const LLT v16s8 = LLT::fixed_vector(16, 8);
611c3f7f17SFangrui Song   const LLT v8s16 = LLT::fixed_vector(8, 16);
621c3f7f17SFangrui Song   const LLT v4s32 = LLT::fixed_vector(4, 32);
631c3f7f17SFangrui Song   const LLT v2s64 = LLT::fixed_vector(2, 64);
641c3f7f17SFangrui Song   const LLT v2p0 = LLT::fixed_vector(2, p0);
651c3f7f17SFangrui Song 
661c3f7f17SFangrui Song   const LLT v32s8 = LLT::fixed_vector(32, 8);
671c3f7f17SFangrui Song   const LLT v16s16 = LLT::fixed_vector(16, 16);
681c3f7f17SFangrui Song   const LLT v8s32 = LLT::fixed_vector(8, 32);
691c3f7f17SFangrui Song   const LLT v4s64 = LLT::fixed_vector(4, 64);
701c3f7f17SFangrui Song   const LLT v4p0 = LLT::fixed_vector(4, p0);
711c3f7f17SFangrui Song 
721c3f7f17SFangrui Song   const LLT v64s8 = LLT::fixed_vector(64, 8);
731c3f7f17SFangrui Song   const LLT v32s16 = LLT::fixed_vector(32, 16);
741c3f7f17SFangrui Song   const LLT v16s32 = LLT::fixed_vector(16, 32);
751c3f7f17SFangrui Song   const LLT v8s64 = LLT::fixed_vector(8, 64);
761c3f7f17SFangrui Song 
7711d7203cSEvgenii Kudriashov   const LLT s8MaxVector = HasAVX512 ? v64s8 : HasAVX ? v32s8 : v16s8;
7811d7203cSEvgenii Kudriashov   const LLT s16MaxVector = HasAVX512 ? v32s16 : HasAVX ? v16s16 : v8s16;
7911d7203cSEvgenii Kudriashov   const LLT s32MaxVector = HasAVX512 ? v16s32 : HasAVX ? v8s32 : v4s32;
8011d7203cSEvgenii Kudriashov   const LLT s64MaxVector = HasAVX512 ? v8s64 : HasAVX ? v4s64 : v2s64;
8111d7203cSEvgenii Kudriashov 
821c3f7f17SFangrui Song   // todo: AVX512 bool vector predicate types
831c3f7f17SFangrui Song 
841c3f7f17SFangrui Song   // implicit/constants
851c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_IMPLICIT_DEF)
861c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
871c3f7f17SFangrui Song         // 32/64-bits needs support for s64/s128 to handle cases:
881c3f7f17SFangrui Song         // s64 = EXTEND (G_IMPLICIT_DEF s32) -> s64 = G_IMPLICIT_DEF
891c3f7f17SFangrui Song         // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF
901c3f7f17SFangrui Song         return typeInSet(0, {p0, s1, s8, s16, s32, s64})(Query) ||
911c3f7f17SFangrui Song                (Is64Bit && typeInSet(0, {s128})(Query));
921c3f7f17SFangrui Song       });
931c3f7f17SFangrui Song 
941c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_CONSTANT)
951c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
961c3f7f17SFangrui Song         return typeInSet(0, {p0, s8, s16, s32})(Query) ||
971c3f7f17SFangrui Song                (Is64Bit && typeInSet(0, {s64})(Query));
981c3f7f17SFangrui Song       })
991c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/8)
1001c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar);
1011c3f7f17SFangrui Song 
1021c3f7f17SFangrui Song   // merge/unmerge
1031c3f7f17SFangrui Song   for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
1041c3f7f17SFangrui Song     unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;
1051c3f7f17SFangrui Song     unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;
1061c3f7f17SFangrui Song     getActionDefinitionsBuilder(Op)
1071c3f7f17SFangrui Song         .widenScalarToNextPow2(LitTyIdx, /*Min=*/8)
1081c3f7f17SFangrui Song         .widenScalarToNextPow2(BigTyIdx, /*Min=*/16)
1091c3f7f17SFangrui Song         .minScalar(LitTyIdx, s8)
1101c3f7f17SFangrui Song         .minScalar(BigTyIdx, s32)
1111c3f7f17SFangrui Song         .legalIf([=](const LegalityQuery &Q) {
1121c3f7f17SFangrui Song           switch (Q.Types[BigTyIdx].getSizeInBits()) {
1131c3f7f17SFangrui Song           case 16:
1141c3f7f17SFangrui Song           case 32:
1151c3f7f17SFangrui Song           case 64:
1161c3f7f17SFangrui Song           case 128:
1171c3f7f17SFangrui Song           case 256:
1181c3f7f17SFangrui Song           case 512:
1191c3f7f17SFangrui Song             break;
1201c3f7f17SFangrui Song           default:
1211c3f7f17SFangrui Song             return false;
1221c3f7f17SFangrui Song           }
1231c3f7f17SFangrui Song           switch (Q.Types[LitTyIdx].getSizeInBits()) {
1241c3f7f17SFangrui Song           case 8:
1251c3f7f17SFangrui Song           case 16:
1261c3f7f17SFangrui Song           case 32:
1271c3f7f17SFangrui Song           case 64:
1281c3f7f17SFangrui Song           case 128:
1291c3f7f17SFangrui Song           case 256:
1301c3f7f17SFangrui Song             return true;
1311c3f7f17SFangrui Song           default:
1321c3f7f17SFangrui Song             return false;
1331c3f7f17SFangrui Song           }
1341c3f7f17SFangrui Song         });
1351c3f7f17SFangrui Song   }
1361c3f7f17SFangrui Song 
1371c3f7f17SFangrui Song   // integer addition/subtraction
1381c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_ADD, G_SUB})
1391c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
1401c3f7f17SFangrui Song         if (typeInSet(0, {s8, s16, s32})(Query))
1411c3f7f17SFangrui Song           return true;
1421c3f7f17SFangrui Song         if (Is64Bit && typeInSet(0, {s64})(Query))
1431c3f7f17SFangrui Song           return true;
1441c3f7f17SFangrui Song         if (HasSSE2 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))
1451c3f7f17SFangrui Song           return true;
1461c3f7f17SFangrui Song         if (HasAVX2 && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))
1471c3f7f17SFangrui Song           return true;
1481c3f7f17SFangrui Song         if (HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query))
1491c3f7f17SFangrui Song           return true;
1501c3f7f17SFangrui Song         if (HasBWI && typeInSet(0, {v64s8, v32s16})(Query))
1511c3f7f17SFangrui Song           return true;
1521c3f7f17SFangrui Song         return false;
1531c3f7f17SFangrui Song       })
1541c3f7f17SFangrui Song       .clampMinNumElements(0, s8, 16)
1551c3f7f17SFangrui Song       .clampMinNumElements(0, s16, 8)
1561c3f7f17SFangrui Song       .clampMinNumElements(0, s32, 4)
1571c3f7f17SFangrui Song       .clampMinNumElements(0, s64, 2)
1581c3f7f17SFangrui Song       .clampMaxNumElements(0, s8, HasBWI ? 64 : (HasAVX2 ? 32 : 16))
1591c3f7f17SFangrui Song       .clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8))
1601c3f7f17SFangrui Song       .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4))
1611c3f7f17SFangrui Song       .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX2 ? 4 : 2))
1621c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/32)
1631c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar)
1641c3f7f17SFangrui Song       .scalarize(0);
1651c3f7f17SFangrui Song 
1661c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_UADDE, G_UADDO, G_USUBE, G_USUBO})
1671c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
1681c3f7f17SFangrui Song         return typePairInSet(0, 1, {{s8, s1}, {s16, s1}, {s32, s1}})(Query) ||
1691c3f7f17SFangrui Song                (Is64Bit && typePairInSet(0, 1, {{s64, s1}})(Query));
1701c3f7f17SFangrui Song       })
1711c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/32)
1721c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar)
1731c3f7f17SFangrui Song       .clampScalar(1, s1, s1)
1741c3f7f17SFangrui Song       .scalarize(0);
1751c3f7f17SFangrui Song 
1761c3f7f17SFangrui Song   // integer multiply
1771c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_MUL)
1781c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
1791c3f7f17SFangrui Song         if (typeInSet(0, {s8, s16, s32})(Query))
1801c3f7f17SFangrui Song           return true;
1811c3f7f17SFangrui Song         if (Is64Bit && typeInSet(0, {s64})(Query))
1821c3f7f17SFangrui Song           return true;
1831c3f7f17SFangrui Song         if (HasSSE2 && typeInSet(0, {v8s16})(Query))
1841c3f7f17SFangrui Song           return true;
1851c3f7f17SFangrui Song         if (HasSSE41 && typeInSet(0, {v4s32})(Query))
1861c3f7f17SFangrui Song           return true;
1871c3f7f17SFangrui Song         if (HasAVX2 && typeInSet(0, {v16s16, v8s32})(Query))
1881c3f7f17SFangrui Song           return true;
1891c3f7f17SFangrui Song         if (HasAVX512 && typeInSet(0, {v16s32})(Query))
1901c3f7f17SFangrui Song           return true;
1911c3f7f17SFangrui Song         if (HasDQI && typeInSet(0, {v8s64})(Query))
1921c3f7f17SFangrui Song           return true;
1931c3f7f17SFangrui Song         if (HasDQI && HasVLX && typeInSet(0, {v2s64, v4s64})(Query))
1941c3f7f17SFangrui Song           return true;
1951c3f7f17SFangrui Song         if (HasBWI && typeInSet(0, {v32s16})(Query))
1961c3f7f17SFangrui Song           return true;
1971c3f7f17SFangrui Song         return false;
1981c3f7f17SFangrui Song       })
1991c3f7f17SFangrui Song       .clampMinNumElements(0, s16, 8)
2001c3f7f17SFangrui Song       .clampMinNumElements(0, s32, 4)
2011c3f7f17SFangrui Song       .clampMinNumElements(0, s64, HasVLX ? 2 : 8)
2021c3f7f17SFangrui Song       .clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8))
2031c3f7f17SFangrui Song       .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4))
2041c3f7f17SFangrui Song       .clampMaxNumElements(0, s64, 8)
2051c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/32)
2061c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar)
2071c3f7f17SFangrui Song       .scalarize(0);
2081c3f7f17SFangrui Song 
2091c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_SMULH, G_UMULH})
2101c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
2111c3f7f17SFangrui Song         return typeInSet(0, {s8, s16, s32})(Query) ||
2121c3f7f17SFangrui Song                (Is64Bit && typeInSet(0, {s64})(Query));
2131c3f7f17SFangrui Song       })
2141c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/32)
2151c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar)
2161c3f7f17SFangrui Song       .scalarize(0);
2171c3f7f17SFangrui Song 
2181c3f7f17SFangrui Song   // integer divisions
2191c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UDIV, G_UREM})
2201c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
2211c3f7f17SFangrui Song         return typeInSet(0, {s8, s16, s32})(Query) ||
2221c3f7f17SFangrui Song                (Is64Bit && typeInSet(0, {s64})(Query));
2231c3f7f17SFangrui Song       })
22410edabbcSEvgenii Kudriashov       .libcallFor({s64})
2251c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar);
2261c3f7f17SFangrui Song 
2271c3f7f17SFangrui Song   // integer shifts
2281c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
2291c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
2301c3f7f17SFangrui Song         return typePairInSet(0, 1, {{s8, s8}, {s16, s8}, {s32, s8}})(Query) ||
2311c3f7f17SFangrui Song                (Is64Bit && typePairInSet(0, 1, {{s64, s8}})(Query));
2321c3f7f17SFangrui Song       })
2331c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar)
2341c3f7f17SFangrui Song       .clampScalar(1, s8, s8);
2351c3f7f17SFangrui Song 
2361c3f7f17SFangrui Song   // integer logic
2371c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
2381c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
2391c3f7f17SFangrui Song         if (typeInSet(0, {s8, s16, s32})(Query))
2401c3f7f17SFangrui Song           return true;
2411c3f7f17SFangrui Song         if (Is64Bit && typeInSet(0, {s64})(Query))
2421c3f7f17SFangrui Song           return true;
2431c3f7f17SFangrui Song         if (HasSSE2 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))
2441c3f7f17SFangrui Song           return true;
2451c3f7f17SFangrui Song         if (HasAVX && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))
2461c3f7f17SFangrui Song           return true;
2471c3f7f17SFangrui Song         if (HasAVX512 && typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query))
2481c3f7f17SFangrui Song           return true;
2491c3f7f17SFangrui Song         return false;
2501c3f7f17SFangrui Song       })
2511c3f7f17SFangrui Song       .clampMinNumElements(0, s8, 16)
2521c3f7f17SFangrui Song       .clampMinNumElements(0, s16, 8)
2531c3f7f17SFangrui Song       .clampMinNumElements(0, s32, 4)
2541c3f7f17SFangrui Song       .clampMinNumElements(0, s64, 2)
2551c3f7f17SFangrui Song       .clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16))
2561c3f7f17SFangrui Song       .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))
2571c3f7f17SFangrui Song       .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))
2581c3f7f17SFangrui Song       .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))
2591c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/32)
2601c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar)
2611c3f7f17SFangrui Song       .scalarize(0);
2621c3f7f17SFangrui Song 
2631c3f7f17SFangrui Song   // integer comparison
2641c3f7f17SFangrui Song   const std::initializer_list<LLT> IntTypes32 = {s8, s16, s32, p0};
2651c3f7f17SFangrui Song   const std::initializer_list<LLT> IntTypes64 = {s8, s16, s32, s64, p0};
2661c3f7f17SFangrui Song 
2671c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_ICMP)
2681c3f7f17SFangrui Song       .legalForCartesianProduct({s8}, Is64Bit ? IntTypes64 : IntTypes32)
2690a8f54c3SEvgenii Kudriashov       .clampScalar(0, s8, s8)
270fb394562SEvgenii Kudriashov       .clampScalar(1, s8, sMaxScalar);
2711c3f7f17SFangrui Song 
2721c3f7f17SFangrui Song   // bswap
2731c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_BSWAP)
2741c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) {
2751c3f7f17SFangrui Song         return Query.Types[0] == s32 ||
2761c3f7f17SFangrui Song                (Subtarget.is64Bit() && Query.Types[0] == s64);
2771c3f7f17SFangrui Song       })
2781c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/32)
2791c3f7f17SFangrui Song       .clampScalar(0, s32, sMaxScalar);
2801c3f7f17SFangrui Song 
2811c3f7f17SFangrui Song   // popcount
2821c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_CTPOP)
2831c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
2841c3f7f17SFangrui Song         return Subtarget.hasPOPCNT() &&
2851c3f7f17SFangrui Song                (typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) ||
2861c3f7f17SFangrui Song                 (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)));
2871c3f7f17SFangrui Song       })
2881c3f7f17SFangrui Song       .widenScalarToNextPow2(1, /*Min=*/16)
2891c3f7f17SFangrui Song       .clampScalar(1, s16, sMaxScalar)
2901c3f7f17SFangrui Song       .scalarSameSizeAs(0, 1);
2911c3f7f17SFangrui Song 
2921c3f7f17SFangrui Song   // count leading zeros (LZCNT)
2931c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_CTLZ)
2941c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
2951c3f7f17SFangrui Song         return Subtarget.hasLZCNT() &&
2961c3f7f17SFangrui Song                (typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) ||
2971c3f7f17SFangrui Song                 (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)));
2981c3f7f17SFangrui Song       })
2991c3f7f17SFangrui Song       .widenScalarToNextPow2(1, /*Min=*/16)
3001c3f7f17SFangrui Song       .clampScalar(1, s16, sMaxScalar)
3011c3f7f17SFangrui Song       .scalarSameSizeAs(0, 1);
3021c3f7f17SFangrui Song 
3031c3f7f17SFangrui Song   // count trailing zeros
3041c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_CTTZ_ZERO_UNDEF, G_CTTZ})
3051c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
3061c3f7f17SFangrui Song         return (Query.Opcode == G_CTTZ_ZERO_UNDEF || Subtarget.hasBMI()) &&
3071c3f7f17SFangrui Song                (typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) ||
3081c3f7f17SFangrui Song                 (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)));
3091c3f7f17SFangrui Song       })
3101c3f7f17SFangrui Song       .widenScalarToNextPow2(1, /*Min=*/16)
3111c3f7f17SFangrui Song       .clampScalar(1, s16, sMaxScalar)
3121c3f7f17SFangrui Song       .scalarSameSizeAs(0, 1);
3131c3f7f17SFangrui Song 
3141c3f7f17SFangrui Song   // control flow
3151c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_PHI)
3161c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
3171c3f7f17SFangrui Song         return typeInSet(0, {s8, s16, s32, p0})(Query) ||
318c5abcb05SEvgenii Kudriashov                (UseX87 && typeIs(0, s80)(Query)) ||
319c5abcb05SEvgenii Kudriashov                (Is64Bit && typeIs(0, s64)(Query)) ||
3201c3f7f17SFangrui Song                (HasSSE1 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query)) ||
3211c3f7f17SFangrui Song                (HasAVX && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query)) ||
3221c3f7f17SFangrui Song                (HasAVX512 &&
3231c3f7f17SFangrui Song                 typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query));
3241c3f7f17SFangrui Song       })
3251c3f7f17SFangrui Song       .clampMinNumElements(0, s8, 16)
3261c3f7f17SFangrui Song       .clampMinNumElements(0, s16, 8)
3271c3f7f17SFangrui Song       .clampMinNumElements(0, s32, 4)
3281c3f7f17SFangrui Song       .clampMinNumElements(0, s64, 2)
3291c3f7f17SFangrui Song       .clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16))
3301c3f7f17SFangrui Song       .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))
3311c3f7f17SFangrui Song       .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))
3321c3f7f17SFangrui Song       .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))
3331c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/32)
3341c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar)
3351c3f7f17SFangrui Song       .scalarize(0);
3361c3f7f17SFangrui Song 
3371c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_BRCOND).legalFor({s1});
3381c3f7f17SFangrui Song 
3391c3f7f17SFangrui Song   // pointer handling
3401c3f7f17SFangrui Song   const std::initializer_list<LLT> PtrTypes32 = {s1, s8, s16, s32};
3411c3f7f17SFangrui Song   const std::initializer_list<LLT> PtrTypes64 = {s1, s8, s16, s32, s64};
3421c3f7f17SFangrui Song 
3431c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_PTRTOINT)
3441c3f7f17SFangrui Song       .legalForCartesianProduct(Is64Bit ? PtrTypes64 : PtrTypes32, {p0})
3451c3f7f17SFangrui Song       .maxScalar(0, sMaxScalar)
3461c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min*/ 8);
3471c3f7f17SFangrui Song 
3481c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, sMaxScalar}});
3491c3f7f17SFangrui Song 
35011d7203cSEvgenii Kudriashov   getActionDefinitionsBuilder(G_CONSTANT_POOL).legalFor({p0});
35111d7203cSEvgenii Kudriashov 
3521c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_PTR_ADD)
3531c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
3541c3f7f17SFangrui Song         return typePairInSet(0, 1, {{p0, s32}})(Query) ||
3551c3f7f17SFangrui Song                (Is64Bit && typePairInSet(0, 1, {{p0, s64}})(Query));
3561c3f7f17SFangrui Song       })
3571c3f7f17SFangrui Song       .widenScalarToNextPow2(1, /*Min*/ 32)
3581c3f7f17SFangrui Song       .clampScalar(1, s32, sMaxScalar);
3591c3f7f17SFangrui Song 
3601c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_FRAME_INDEX, G_GLOBAL_VALUE}).legalFor({p0});
3611c3f7f17SFangrui Song 
3621c3f7f17SFangrui Song   // load/store: add more corner cases
3631c3f7f17SFangrui Song   for (unsigned Op : {G_LOAD, G_STORE}) {
3641c3f7f17SFangrui Song     auto &Action = getActionDefinitionsBuilder(Op);
3651c3f7f17SFangrui Song     Action.legalForTypesWithMemDesc({{s8, p0, s1, 1},
3661c3f7f17SFangrui Song                                      {s8, p0, s8, 1},
3671c3f7f17SFangrui Song                                      {s16, p0, s8, 1},
3681c3f7f17SFangrui Song                                      {s16, p0, s16, 1},
3691c3f7f17SFangrui Song                                      {s32, p0, s8, 1},
3701c3f7f17SFangrui Song                                      {s32, p0, s16, 1},
3711c3f7f17SFangrui Song                                      {s32, p0, s32, 1},
3721c3f7f17SFangrui Song                                      {s80, p0, s80, 1},
3731c3f7f17SFangrui Song                                      {p0, p0, p0, 1},
3741c3f7f17SFangrui Song                                      {v4s8, p0, v4s8, 1}});
3751c3f7f17SFangrui Song     if (Is64Bit)
3761c3f7f17SFangrui Song       Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},
3771c3f7f17SFangrui Song                                        {s64, p0, s16, 1},
3781c3f7f17SFangrui Song                                        {s64, p0, s32, 1},
3791c3f7f17SFangrui Song                                        {s64, p0, s64, 1},
3801c3f7f17SFangrui Song                                        {v2s32, p0, v2s32, 1}});
3811c3f7f17SFangrui Song     if (HasSSE1)
38211d7203cSEvgenii Kudriashov       Action.legalForTypesWithMemDesc({{v4s32, p0, v4s32, 1}});
38311d7203cSEvgenii Kudriashov     if (HasSSE2)
3841c3f7f17SFangrui Song       Action.legalForTypesWithMemDesc({{v16s8, p0, v16s8, 1},
3851c3f7f17SFangrui Song                                        {v8s16, p0, v8s16, 1},
3861c3f7f17SFangrui Song                                        {v2s64, p0, v2s64, 1},
3871c3f7f17SFangrui Song                                        {v2p0, p0, v2p0, 1}});
3881c3f7f17SFangrui Song     if (HasAVX)
3891c3f7f17SFangrui Song       Action.legalForTypesWithMemDesc({{v32s8, p0, v32s8, 1},
3901c3f7f17SFangrui Song                                        {v16s16, p0, v16s16, 1},
3911c3f7f17SFangrui Song                                        {v8s32, p0, v8s32, 1},
3921c3f7f17SFangrui Song                                        {v4s64, p0, v4s64, 1},
3931c3f7f17SFangrui Song                                        {v4p0, p0, v4p0, 1}});
3941c3f7f17SFangrui Song     if (HasAVX512)
3951c3f7f17SFangrui Song       Action.legalForTypesWithMemDesc({{v64s8, p0, v64s8, 1},
3961c3f7f17SFangrui Song                                        {v32s16, p0, v32s16, 1},
3971c3f7f17SFangrui Song                                        {v16s32, p0, v16s32, 1},
3981c3f7f17SFangrui Song                                        {v8s64, p0, v8s64, 1}});
39911d7203cSEvgenii Kudriashov     Action.widenScalarToNextPow2(0, /*Min=*/8)
40011d7203cSEvgenii Kudriashov         .clampScalar(0, s8, sMaxScalar)
40111d7203cSEvgenii Kudriashov         .scalarize(0);
4021c3f7f17SFangrui Song   }
4031c3f7f17SFangrui Song 
4041c3f7f17SFangrui Song   for (unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {
4051c3f7f17SFangrui Song     auto &Action = getActionDefinitionsBuilder(Op);
4061c3f7f17SFangrui Song     Action.legalForTypesWithMemDesc({{s16, p0, s8, 1},
4071c3f7f17SFangrui Song                                      {s32, p0, s8, 1},
4081c3f7f17SFangrui Song                                      {s32, p0, s16, 1}});
4091c3f7f17SFangrui Song     if (Is64Bit)
4101c3f7f17SFangrui Song       Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},
4111c3f7f17SFangrui Song                                        {s64, p0, s16, 1},
4121c3f7f17SFangrui Song                                        {s64, p0, s32, 1}});
4131c3f7f17SFangrui Song     // TODO - SSE41/AVX2/AVX512F/AVX512BW vector extensions
4141c3f7f17SFangrui Song   }
4151c3f7f17SFangrui Song 
4161c3f7f17SFangrui Song   // sext, zext, and anyext
4171c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT})
4181c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) {
4191c3f7f17SFangrui Song         return typeInSet(0, {s8, s16, s32})(Query) ||
4201c3f7f17SFangrui Song           (Query.Opcode == G_ANYEXT && Query.Types[0] == s128) ||
4211c3f7f17SFangrui Song           (Is64Bit && Query.Types[0] == s64);
4221c3f7f17SFangrui Song       })
4231c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/8)
4241c3f7f17SFangrui Song       .clampScalar(0, s8, sMaxScalar)
4251c3f7f17SFangrui Song       .widenScalarToNextPow2(1, /*Min=*/8)
42611d7203cSEvgenii Kudriashov       .clampScalar(1, s8, sMaxScalar)
42711d7203cSEvgenii Kudriashov       .scalarize(0);
4281c3f7f17SFangrui Song 
4291c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_SEXT_INREG).lower();
4301c3f7f17SFangrui Song 
4311c3f7f17SFangrui Song   // fp constants
4321c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_FCONSTANT)
4331c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) -> bool {
434564b81dbSMalaySanghiIntel         return (typeInSet(0, {s32, s64})(Query)) ||
435564b81dbSMalaySanghiIntel                (UseX87 && typeInSet(0, {s80})(Query));
4361c3f7f17SFangrui Song       });
4371c3f7f17SFangrui Song 
4381c3f7f17SFangrui Song   // fp arithmetic
4391c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
4401c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) {
441564b81dbSMalaySanghiIntel         return (typeInSet(0, {s32, s64})(Query)) ||
442564b81dbSMalaySanghiIntel                (HasSSE1 && typeInSet(0, {v4s32})(Query)) ||
443564b81dbSMalaySanghiIntel                (HasSSE2 && typeInSet(0, {v2s64})(Query)) ||
4441c3f7f17SFangrui Song                (HasAVX && typeInSet(0, {v8s32, v4s64})(Query)) ||
445564b81dbSMalaySanghiIntel                (HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query)) ||
446564b81dbSMalaySanghiIntel                (UseX87 && typeInSet(0, {s80})(Query));
4471c3f7f17SFangrui Song       });
4481c3f7f17SFangrui Song 
4491c3f7f17SFangrui Song   // fp comparison
4501c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_FCMP)
4511c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) {
4521c3f7f17SFangrui Song         return (HasSSE1 && typePairInSet(0, 1, {{s8, s32}})(Query)) ||
4531c3f7f17SFangrui Song                (HasSSE2 && typePairInSet(0, 1, {{s8, s64}})(Query));
4541c3f7f17SFangrui Song       })
4551c3f7f17SFangrui Song       .clampScalar(0, s8, s8)
4561c3f7f17SFangrui Song       .clampScalar(1, s32, HasSSE2 ? s64 : s32)
4571c3f7f17SFangrui Song       .widenScalarToNextPow2(1);
4581c3f7f17SFangrui Song 
4591c3f7f17SFangrui Song   // fp conversions
4601c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_FPEXT).legalIf([=](const LegalityQuery &Query) {
4611c3f7f17SFangrui Song     return (HasSSE2 && typePairInSet(0, 1, {{s64, s32}})(Query)) ||
4621c3f7f17SFangrui Song            (HasAVX && typePairInSet(0, 1, {{v4s64, v4s32}})(Query)) ||
4631c3f7f17SFangrui Song            (HasAVX512 && typePairInSet(0, 1, {{v8s64, v8s32}})(Query));
4641c3f7f17SFangrui Song   });
4651c3f7f17SFangrui Song 
4661c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_FPTRUNC).legalIf(
4671c3f7f17SFangrui Song       [=](const LegalityQuery &Query) {
4681c3f7f17SFangrui Song         return (HasSSE2 && typePairInSet(0, 1, {{s32, s64}})(Query)) ||
4691c3f7f17SFangrui Song                (HasAVX && typePairInSet(0, 1, {{v4s32, v4s64}})(Query)) ||
4701c3f7f17SFangrui Song                (HasAVX512 && typePairInSet(0, 1, {{v8s32, v8s64}})(Query));
4711c3f7f17SFangrui Song       });
4721c3f7f17SFangrui Song 
4731c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_SITOFP)
4741c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) {
4751c3f7f17SFangrui Song         return (HasSSE1 &&
4761c3f7f17SFangrui Song                 (typePairInSet(0, 1, {{s32, s32}})(Query) ||
4771c3f7f17SFangrui Song                  (Is64Bit && typePairInSet(0, 1, {{s32, s64}})(Query)))) ||
4781c3f7f17SFangrui Song                (HasSSE2 &&
4791c3f7f17SFangrui Song                 (typePairInSet(0, 1, {{s64, s32}})(Query) ||
4801c3f7f17SFangrui Song                  (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));
4811c3f7f17SFangrui Song       })
4821c3f7f17SFangrui Song       .clampScalar(1, s32, sMaxScalar)
4831c3f7f17SFangrui Song       .widenScalarToNextPow2(1)
4841c3f7f17SFangrui Song       .clampScalar(0, s32, HasSSE2 ? s64 : s32)
4851c3f7f17SFangrui Song       .widenScalarToNextPow2(0);
4861c3f7f17SFangrui Song 
4871c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_FPTOSI)
4881c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) {
4891c3f7f17SFangrui Song         return (HasSSE1 &&
4901c3f7f17SFangrui Song                 (typePairInSet(0, 1, {{s32, s32}})(Query) ||
4911c3f7f17SFangrui Song                  (Is64Bit && typePairInSet(0, 1, {{s64, s32}})(Query)))) ||
4921c3f7f17SFangrui Song                (HasSSE2 &&
4931c3f7f17SFangrui Song                 (typePairInSet(0, 1, {{s32, s64}})(Query) ||
4941c3f7f17SFangrui Song                  (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));
4951c3f7f17SFangrui Song       })
4961c3f7f17SFangrui Song       .clampScalar(1, s32, HasSSE2 ? s64 : s32)
4971c3f7f17SFangrui Song       .widenScalarToNextPow2(0)
4981c3f7f17SFangrui Song       .clampScalar(0, s32, sMaxScalar)
4991c3f7f17SFangrui Song       .widenScalarToNextPow2(1);
5001c3f7f17SFangrui Song 
501*e9cb4409SEvgenii Kudriashov   // For G_UITOFP and G_FPTOUI without AVX512, we have to custom legalize types
502*e9cb4409SEvgenii Kudriashov   // <= s32 manually. Otherwise, in custom handler there is no way to
503*e9cb4409SEvgenii Kudriashov   // understand whether s32 is an original type and we need to promote it to
504*e9cb4409SEvgenii Kudriashov   // s64 or s32 is obtained after widening and we shouldn't widen it to s64.
505*e9cb4409SEvgenii Kudriashov   //
506*e9cb4409SEvgenii Kudriashov   // For AVX512 we simply widen types as there is direct mapping from opcodes
507*e9cb4409SEvgenii Kudriashov   // to asm instructions.
508*e9cb4409SEvgenii Kudriashov   getActionDefinitionsBuilder(G_UITOFP)
509*e9cb4409SEvgenii Kudriashov       .legalIf([=](const LegalityQuery &Query) {
510*e9cb4409SEvgenii Kudriashov         return HasAVX512 && typeInSet(0, {s32, s64})(Query) &&
511*e9cb4409SEvgenii Kudriashov                typeInSet(1, {s32, s64})(Query);
512*e9cb4409SEvgenii Kudriashov       })
513*e9cb4409SEvgenii Kudriashov       .customIf([=](const LegalityQuery &Query) {
514*e9cb4409SEvgenii Kudriashov         return !HasAVX512 &&
515*e9cb4409SEvgenii Kudriashov                ((HasSSE1 && typeIs(0, s32)(Query)) ||
516*e9cb4409SEvgenii Kudriashov                 (HasSSE2 && typeIs(0, s64)(Query))) &&
517*e9cb4409SEvgenii Kudriashov                scalarNarrowerThan(1, Is64Bit ? 64 : 32)(Query);
518*e9cb4409SEvgenii Kudriashov       })
519*e9cb4409SEvgenii Kudriashov       .lowerIf([=](const LegalityQuery &Query) {
520*e9cb4409SEvgenii Kudriashov         // Lower conversions from s64
521*e9cb4409SEvgenii Kudriashov         return !HasAVX512 &&
522*e9cb4409SEvgenii Kudriashov                ((HasSSE1 && typeIs(0, s32)(Query)) ||
523*e9cb4409SEvgenii Kudriashov                 (HasSSE2 && typeIs(0, s64)(Query))) &&
524*e9cb4409SEvgenii Kudriashov                (Is64Bit && typeIs(1, s64)(Query));
525*e9cb4409SEvgenii Kudriashov       })
526*e9cb4409SEvgenii Kudriashov       .clampScalar(0, s32, HasSSE2 ? s64 : s32)
527*e9cb4409SEvgenii Kudriashov       .widenScalarToNextPow2(0)
528*e9cb4409SEvgenii Kudriashov       .clampScalar(1, s32, sMaxScalar)
529*e9cb4409SEvgenii Kudriashov       .widenScalarToNextPow2(1);
530*e9cb4409SEvgenii Kudriashov 
531*e9cb4409SEvgenii Kudriashov   getActionDefinitionsBuilder(G_FPTOUI)
532*e9cb4409SEvgenii Kudriashov       .legalIf([=](const LegalityQuery &Query) {
533*e9cb4409SEvgenii Kudriashov         return HasAVX512 && typeInSet(0, {s32, s64})(Query) &&
534*e9cb4409SEvgenii Kudriashov                typeInSet(1, {s32, s64})(Query);
535*e9cb4409SEvgenii Kudriashov       })
536*e9cb4409SEvgenii Kudriashov       .customIf([=](const LegalityQuery &Query) {
537*e9cb4409SEvgenii Kudriashov         return !HasAVX512 &&
538*e9cb4409SEvgenii Kudriashov                ((HasSSE1 && typeIs(1, s32)(Query)) ||
539*e9cb4409SEvgenii Kudriashov                 (HasSSE2 && typeIs(1, s64)(Query))) &&
540*e9cb4409SEvgenii Kudriashov                scalarNarrowerThan(0, Is64Bit ? 64 : 32)(Query);
541*e9cb4409SEvgenii Kudriashov       })
542*e9cb4409SEvgenii Kudriashov       // TODO: replace with customized legalization using
543*e9cb4409SEvgenii Kudriashov       // specifics of cvttsd2si. The selection of this node requires
544*e9cb4409SEvgenii Kudriashov       // a vector type. Either G_SCALAR_TO_VECTOR is needed or more advanced
545*e9cb4409SEvgenii Kudriashov       // support of G_BUILD_VECTOR/G_INSERT_VECTOR_ELT is required beforehand.
546*e9cb4409SEvgenii Kudriashov       .lowerIf([=](const LegalityQuery &Query) {
547*e9cb4409SEvgenii Kudriashov         return !HasAVX512 &&
548*e9cb4409SEvgenii Kudriashov                ((HasSSE1 && typeIs(1, s32)(Query)) ||
549*e9cb4409SEvgenii Kudriashov                 (HasSSE2 && typeIs(1, s64)(Query))) &&
550*e9cb4409SEvgenii Kudriashov                (Is64Bit && typeIs(0, s64)(Query));
551*e9cb4409SEvgenii Kudriashov       })
552*e9cb4409SEvgenii Kudriashov       .clampScalar(0, s32, sMaxScalar)
553*e9cb4409SEvgenii Kudriashov       .widenScalarToNextPow2(0)
554*e9cb4409SEvgenii Kudriashov       .clampScalar(1, s32, HasSSE2 ? s64 : s32)
555*e9cb4409SEvgenii Kudriashov       .widenScalarToNextPow2(1);
556*e9cb4409SEvgenii Kudriashov 
5571c3f7f17SFangrui Song   // vector ops
55811d7203cSEvgenii Kudriashov   getActionDefinitionsBuilder(G_BUILD_VECTOR)
55911d7203cSEvgenii Kudriashov       .customIf([=](const LegalityQuery &Query) {
56011d7203cSEvgenii Kudriashov         return (HasSSE1 && typeInSet(0, {v4s32})(Query)) ||
56111d7203cSEvgenii Kudriashov                (HasSSE2 && typeInSet(0, {v2s64, v8s16, v16s8})(Query)) ||
56211d7203cSEvgenii Kudriashov                (HasAVX && typeInSet(0, {v4s64, v8s32, v16s16, v32s8})(Query)) ||
56311d7203cSEvgenii Kudriashov                (HasAVX512 && typeInSet(0, {v8s64, v16s32, v32s16, v64s8}));
56411d7203cSEvgenii Kudriashov       })
56511d7203cSEvgenii Kudriashov       .clampNumElements(0, v16s8, s8MaxVector)
56611d7203cSEvgenii Kudriashov       .clampNumElements(0, v8s16, s16MaxVector)
56711d7203cSEvgenii Kudriashov       .clampNumElements(0, v4s32, s32MaxVector)
56811d7203cSEvgenii Kudriashov       .clampNumElements(0, v2s64, s64MaxVector)
56911d7203cSEvgenii Kudriashov       .moreElementsToNextPow2(0);
57011d7203cSEvgenii Kudriashov 
5711c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_EXTRACT, G_INSERT})
5721c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) {
5731c3f7f17SFangrui Song         unsigned SubIdx = Query.Opcode == G_EXTRACT ? 0 : 1;
5741c3f7f17SFangrui Song         unsigned FullIdx = Query.Opcode == G_EXTRACT ? 1 : 0;
5751c3f7f17SFangrui Song         return (HasAVX && typePairInSet(SubIdx, FullIdx,
5761c3f7f17SFangrui Song                                         {{v16s8, v32s8},
5771c3f7f17SFangrui Song                                          {v8s16, v16s16},
5781c3f7f17SFangrui Song                                          {v4s32, v8s32},
5791c3f7f17SFangrui Song                                          {v2s64, v4s64}})(Query)) ||
5801c3f7f17SFangrui Song                (HasAVX512 && typePairInSet(SubIdx, FullIdx,
5811c3f7f17SFangrui Song                                            {{v16s8, v64s8},
5821c3f7f17SFangrui Song                                             {v32s8, v64s8},
5831c3f7f17SFangrui Song                                             {v8s16, v32s16},
5841c3f7f17SFangrui Song                                             {v16s16, v32s16},
5851c3f7f17SFangrui Song                                             {v4s32, v16s32},
5861c3f7f17SFangrui Song                                             {v8s32, v16s32},
5871c3f7f17SFangrui Song                                             {v2s64, v8s64},
5881c3f7f17SFangrui Song                                             {v4s64, v8s64}})(Query));
5891c3f7f17SFangrui Song       });
5901c3f7f17SFangrui Song 
5911c3f7f17SFangrui Song   // todo: only permit dst types up to max legal vector register size?
5921c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_CONCAT_VECTORS)
5931c3f7f17SFangrui Song       .legalIf([=](const LegalityQuery &Query) {
5941c3f7f17SFangrui Song         return (HasSSE1 && typePairInSet(1, 0,
5951c3f7f17SFangrui Song                                          {{v16s8, v32s8},
5961c3f7f17SFangrui Song                                           {v8s16, v16s16},
5971c3f7f17SFangrui Song                                           {v4s32, v8s32},
5981c3f7f17SFangrui Song                                           {v2s64, v4s64}})(Query)) ||
5991c3f7f17SFangrui Song                (HasAVX && typePairInSet(1, 0,
6001c3f7f17SFangrui Song                                         {{v16s8, v64s8},
6011c3f7f17SFangrui Song                                          {v32s8, v64s8},
6021c3f7f17SFangrui Song                                          {v8s16, v32s16},
6031c3f7f17SFangrui Song                                          {v16s16, v32s16},
6041c3f7f17SFangrui Song                                          {v4s32, v16s32},
6051c3f7f17SFangrui Song                                          {v8s32, v16s32},
6061c3f7f17SFangrui Song                                          {v2s64, v8s64},
6071c3f7f17SFangrui Song                                          {v4s64, v8s64}})(Query));
6081c3f7f17SFangrui Song       });
6091c3f7f17SFangrui Song 
6101c3f7f17SFangrui Song   // todo: vectors and address spaces
6111c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_SELECT)
612ef35da82SEvgenii Kudriashov       .legalFor({{s8, s32}, {s16, s32}, {s32, s32}, {s64, s32}, {p0, s32}})
6131c3f7f17SFangrui Song       .widenScalarToNextPow2(0, /*Min=*/8)
614ef35da82SEvgenii Kudriashov       .clampScalar(0, HasCMOV ? s16 : s8, sMaxScalar)
6151c3f7f17SFangrui Song       .clampScalar(1, s32, s32);
6161c3f7f17SFangrui Song 
6171c3f7f17SFangrui Song   // memory intrinsics
6181c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
6191c3f7f17SFangrui Song 
6201c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_DYN_STACKALLOC,
6211c3f7f17SFangrui Song                                G_STACKSAVE,
6221c3f7f17SFangrui Song                                G_STACKRESTORE}).lower();
6231c3f7f17SFangrui Song 
6241c3f7f17SFangrui Song   // fp intrinsics
6251c3f7f17SFangrui Song   getActionDefinitionsBuilder(G_INTRINSIC_ROUNDEVEN)
6261c3f7f17SFangrui Song       .scalarize(0)
6271c3f7f17SFangrui Song       .minScalar(0, LLT::scalar(32))
6281c3f7f17SFangrui Song       .libcall();
6291c3f7f17SFangrui Song 
6301c3f7f17SFangrui Song   getActionDefinitionsBuilder({G_FREEZE, G_CONSTANT_FOLD_BARRIER})
6311c3f7f17SFangrui Song     .legalFor({s8, s16, s32, s64, p0})
6321c3f7f17SFangrui Song     .widenScalarToNextPow2(0, /*Min=*/8)
6331c3f7f17SFangrui Song     .clampScalar(0, s8, sMaxScalar);
6341c3f7f17SFangrui Song 
6351c3f7f17SFangrui Song   getLegacyLegalizerInfo().computeTables();
6361c3f7f17SFangrui Song   verify(*STI.getInstrInfo());
6371c3f7f17SFangrui Song }
6381c3f7f17SFangrui Song 
63911d7203cSEvgenii Kudriashov bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
64011d7203cSEvgenii Kudriashov                                       LostDebugLocObserver &LocObserver) const {
64111d7203cSEvgenii Kudriashov   MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
64211d7203cSEvgenii Kudriashov   MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
64311d7203cSEvgenii Kudriashov   switch (MI.getOpcode()) {
64411d7203cSEvgenii Kudriashov   default:
64511d7203cSEvgenii Kudriashov     // No idea what to do.
64611d7203cSEvgenii Kudriashov     return false;
64711d7203cSEvgenii Kudriashov   case TargetOpcode::G_BUILD_VECTOR:
64811d7203cSEvgenii Kudriashov     return legalizeBuildVector(MI, MRI, Helper);
649*e9cb4409SEvgenii Kudriashov   case TargetOpcode::G_FPTOUI:
650*e9cb4409SEvgenii Kudriashov     return legalizeFPTOUI(MI, MRI, Helper);
651*e9cb4409SEvgenii Kudriashov   case TargetOpcode::G_UITOFP:
652*e9cb4409SEvgenii Kudriashov     return legalizeUITOFP(MI, MRI, Helper);
65311d7203cSEvgenii Kudriashov   }
65411d7203cSEvgenii Kudriashov   llvm_unreachable("expected switch to return");
65511d7203cSEvgenii Kudriashov }
65611d7203cSEvgenii Kudriashov 
65711d7203cSEvgenii Kudriashov bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI,
65811d7203cSEvgenii Kudriashov                                            MachineRegisterInfo &MRI,
65911d7203cSEvgenii Kudriashov                                            LegalizerHelper &Helper) const {
66011d7203cSEvgenii Kudriashov   MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
66111d7203cSEvgenii Kudriashov   const auto &BuildVector = cast<GBuildVector>(MI);
66211d7203cSEvgenii Kudriashov   Register Dst = BuildVector.getReg(0);
66311d7203cSEvgenii Kudriashov   LLT DstTy = MRI.getType(Dst);
66411d7203cSEvgenii Kudriashov   MachineFunction &MF = MIRBuilder.getMF();
66511d7203cSEvgenii Kudriashov   LLVMContext &Ctx = MF.getFunction().getContext();
66611d7203cSEvgenii Kudriashov   uint64_t DstTySize = DstTy.getScalarSizeInBits();
66711d7203cSEvgenii Kudriashov 
66811d7203cSEvgenii Kudriashov   SmallVector<Constant *, 4> CstIdxs;
66911d7203cSEvgenii Kudriashov   for (unsigned i = 0; i < BuildVector.getNumSources(); ++i) {
67011d7203cSEvgenii Kudriashov     Register Source = BuildVector.getSourceReg(i);
67111d7203cSEvgenii Kudriashov 
67211d7203cSEvgenii Kudriashov     auto ValueAndReg = getIConstantVRegValWithLookThrough(Source, MRI);
67311d7203cSEvgenii Kudriashov     if (ValueAndReg) {
67411d7203cSEvgenii Kudriashov       CstIdxs.emplace_back(ConstantInt::get(Ctx, ValueAndReg->Value));
67511d7203cSEvgenii Kudriashov       continue;
67611d7203cSEvgenii Kudriashov     }
67711d7203cSEvgenii Kudriashov 
67811d7203cSEvgenii Kudriashov     auto FPValueAndReg = getFConstantVRegValWithLookThrough(Source, MRI);
67911d7203cSEvgenii Kudriashov     if (FPValueAndReg) {
68011d7203cSEvgenii Kudriashov       CstIdxs.emplace_back(ConstantFP::get(Ctx, FPValueAndReg->Value));
68111d7203cSEvgenii Kudriashov       continue;
68211d7203cSEvgenii Kudriashov     }
68311d7203cSEvgenii Kudriashov 
68411d7203cSEvgenii Kudriashov     if (getOpcodeDef<GImplicitDef>(Source, MRI)) {
68511d7203cSEvgenii Kudriashov       CstIdxs.emplace_back(UndefValue::get(Type::getIntNTy(Ctx, DstTySize)));
68611d7203cSEvgenii Kudriashov       continue;
68711d7203cSEvgenii Kudriashov     }
68811d7203cSEvgenii Kudriashov     return false;
68911d7203cSEvgenii Kudriashov   }
69011d7203cSEvgenii Kudriashov 
69111d7203cSEvgenii Kudriashov   Constant *ConstVal = ConstantVector::get(CstIdxs);
69211d7203cSEvgenii Kudriashov 
69311d7203cSEvgenii Kudriashov   const DataLayout &DL = MIRBuilder.getDataLayout();
69411d7203cSEvgenii Kudriashov   unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace();
69511d7203cSEvgenii Kudriashov   Align Alignment(DL.getABITypeAlign(ConstVal->getType()));
69611d7203cSEvgenii Kudriashov   auto Addr = MIRBuilder.buildConstantPool(
69711d7203cSEvgenii Kudriashov       LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace)),
69811d7203cSEvgenii Kudriashov       MF.getConstantPool()->getConstantPoolIndex(ConstVal, Alignment));
69911d7203cSEvgenii Kudriashov   MachineMemOperand *MMO =
70011d7203cSEvgenii Kudriashov       MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
70111d7203cSEvgenii Kudriashov                               MachineMemOperand::MOLoad, DstTy, Alignment);
70211d7203cSEvgenii Kudriashov 
70311d7203cSEvgenii Kudriashov   MIRBuilder.buildLoad(Dst, Addr, *MMO);
70411d7203cSEvgenii Kudriashov   MI.eraseFromParent();
70511d7203cSEvgenii Kudriashov   return true;
70611d7203cSEvgenii Kudriashov }
70711d7203cSEvgenii Kudriashov 
708*e9cb4409SEvgenii Kudriashov bool X86LegalizerInfo::legalizeFPTOUI(MachineInstr &MI,
709*e9cb4409SEvgenii Kudriashov                                       MachineRegisterInfo &MRI,
710*e9cb4409SEvgenii Kudriashov                                       LegalizerHelper &Helper) const {
711*e9cb4409SEvgenii Kudriashov   MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
712*e9cb4409SEvgenii Kudriashov   auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
713*e9cb4409SEvgenii Kudriashov   unsigned DstSizeInBits = DstTy.getScalarSizeInBits();
714*e9cb4409SEvgenii Kudriashov   const LLT s32 = LLT::scalar(32);
715*e9cb4409SEvgenii Kudriashov   const LLT s64 = LLT::scalar(64);
716*e9cb4409SEvgenii Kudriashov 
717*e9cb4409SEvgenii Kudriashov   // Simply reuse FPTOSI when it is possible to widen the type
718*e9cb4409SEvgenii Kudriashov   if (DstSizeInBits <= 32) {
719*e9cb4409SEvgenii Kudriashov     auto Casted = MIRBuilder.buildFPTOSI(DstTy == s32 ? s64 : s32, Src);
720*e9cb4409SEvgenii Kudriashov     MIRBuilder.buildTrunc(Dst, Casted);
721*e9cb4409SEvgenii Kudriashov     MI.eraseFromParent();
722*e9cb4409SEvgenii Kudriashov     return true;
723*e9cb4409SEvgenii Kudriashov   }
724*e9cb4409SEvgenii Kudriashov 
725*e9cb4409SEvgenii Kudriashov   return false;
726*e9cb4409SEvgenii Kudriashov }
727*e9cb4409SEvgenii Kudriashov 
728*e9cb4409SEvgenii Kudriashov bool X86LegalizerInfo::legalizeUITOFP(MachineInstr &MI,
729*e9cb4409SEvgenii Kudriashov                                       MachineRegisterInfo &MRI,
730*e9cb4409SEvgenii Kudriashov                                       LegalizerHelper &Helper) const {
731*e9cb4409SEvgenii Kudriashov   MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
732*e9cb4409SEvgenii Kudriashov   auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
733*e9cb4409SEvgenii Kudriashov   const LLT s32 = LLT::scalar(32);
734*e9cb4409SEvgenii Kudriashov   const LLT s64 = LLT::scalar(64);
735*e9cb4409SEvgenii Kudriashov 
736*e9cb4409SEvgenii Kudriashov   // Simply reuse SITOFP when it is possible to widen the type
737*e9cb4409SEvgenii Kudriashov   if (SrcTy.getSizeInBits() <= 32) {
738*e9cb4409SEvgenii Kudriashov     auto Ext = MIRBuilder.buildZExt(SrcTy == s32 ? s64 : s32, Src);
739*e9cb4409SEvgenii Kudriashov     MIRBuilder.buildSITOFP(Dst, Ext);
740*e9cb4409SEvgenii Kudriashov     MI.eraseFromParent();
741*e9cb4409SEvgenii Kudriashov     return true;
742*e9cb4409SEvgenii Kudriashov   }
743*e9cb4409SEvgenii Kudriashov 
744*e9cb4409SEvgenii Kudriashov   return false;
745*e9cb4409SEvgenii Kudriashov }
746*e9cb4409SEvgenii Kudriashov 
7471c3f7f17SFangrui Song bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
7481c3f7f17SFangrui Song                                          MachineInstr &MI) const {
7491c3f7f17SFangrui Song   return true;
7501c3f7f17SFangrui Song }
751