15f757f3fSDimitry Andric //===- X86LegalizerInfo.cpp --------------------------------------*- C++ -*-==// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric /// \file 95f757f3fSDimitry Andric /// This file implements the targeting of the Machinelegalizer class for X86. 105f757f3fSDimitry Andric /// \todo This should be generated by TableGen. 115f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 125f757f3fSDimitry Andric 135f757f3fSDimitry Andric #include "X86LegalizerInfo.h" 145f757f3fSDimitry Andric #include "X86Subtarget.h" 155f757f3fSDimitry Andric #include "X86TargetMachine.h" 16*0fca6ea1SDimitry Andric #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" 175f757f3fSDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" 18*0fca6ea1SDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 19*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 205f757f3fSDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h" 215f757f3fSDimitry Andric #include "llvm/CodeGen/ValueTypes.h" 225f757f3fSDimitry Andric #include "llvm/IR/DerivedTypes.h" 235f757f3fSDimitry Andric #include "llvm/IR/Type.h" 245f757f3fSDimitry Andric 255f757f3fSDimitry Andric using namespace llvm; 265f757f3fSDimitry Andric using namespace TargetOpcode; 275f757f3fSDimitry Andric using namespace LegalizeActions; 285f757f3fSDimitry Andric using namespace LegalityPredicates; 295f757f3fSDimitry Andric 305f757f3fSDimitry Andric X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, 315f757f3fSDimitry Andric const X86TargetMachine &TM) 325f757f3fSDimitry Andric : Subtarget(STI) { 335f757f3fSDimitry Andric 345f757f3fSDimitry Andric bool Is64Bit = Subtarget.is64Bit(); 355f757f3fSDimitry Andric bool HasCMOV = Subtarget.canUseCMOV(); 365f757f3fSDimitry Andric bool HasSSE1 = Subtarget.hasSSE1(); 375f757f3fSDimitry Andric bool HasSSE2 = Subtarget.hasSSE2(); 385f757f3fSDimitry Andric bool HasSSE41 = Subtarget.hasSSE41(); 395f757f3fSDimitry Andric bool HasAVX = Subtarget.hasAVX(); 405f757f3fSDimitry Andric bool HasAVX2 = Subtarget.hasAVX2(); 415f757f3fSDimitry Andric bool HasAVX512 = Subtarget.hasAVX512(); 425f757f3fSDimitry Andric bool HasVLX = Subtarget.hasVLX(); 435f757f3fSDimitry Andric bool HasDQI = Subtarget.hasAVX512() && Subtarget.hasDQI(); 445f757f3fSDimitry Andric bool HasBWI = Subtarget.hasAVX512() && Subtarget.hasBWI(); 45*0fca6ea1SDimitry Andric bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87(); 465f757f3fSDimitry Andric 475f757f3fSDimitry Andric const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0)); 485f757f3fSDimitry Andric const LLT s1 = LLT::scalar(1); 495f757f3fSDimitry Andric const LLT s8 = LLT::scalar(8); 505f757f3fSDimitry Andric const LLT s16 = LLT::scalar(16); 515f757f3fSDimitry Andric const LLT s32 = LLT::scalar(32); 525f757f3fSDimitry Andric const LLT s64 = LLT::scalar(64); 535f757f3fSDimitry Andric const LLT s80 = LLT::scalar(80); 545f757f3fSDimitry Andric const LLT s128 = LLT::scalar(128); 555f757f3fSDimitry Andric const LLT sMaxScalar = Subtarget.is64Bit() ? s64 : s32; 565f757f3fSDimitry Andric const LLT v2s32 = LLT::fixed_vector(2, 32); 575f757f3fSDimitry Andric const LLT v4s8 = LLT::fixed_vector(4, 8); 585f757f3fSDimitry Andric 595f757f3fSDimitry Andric 605f757f3fSDimitry Andric const LLT v16s8 = LLT::fixed_vector(16, 8); 615f757f3fSDimitry Andric const LLT v8s16 = LLT::fixed_vector(8, 16); 625f757f3fSDimitry Andric const LLT v4s32 = LLT::fixed_vector(4, 32); 635f757f3fSDimitry Andric const LLT v2s64 = LLT::fixed_vector(2, 64); 645f757f3fSDimitry Andric const LLT v2p0 = LLT::fixed_vector(2, p0); 655f757f3fSDimitry Andric 665f757f3fSDimitry Andric const LLT v32s8 = LLT::fixed_vector(32, 8); 675f757f3fSDimitry Andric const LLT v16s16 = LLT::fixed_vector(16, 16); 685f757f3fSDimitry Andric const LLT v8s32 = LLT::fixed_vector(8, 32); 695f757f3fSDimitry Andric const LLT v4s64 = LLT::fixed_vector(4, 64); 705f757f3fSDimitry Andric const LLT v4p0 = LLT::fixed_vector(4, p0); 715f757f3fSDimitry Andric 725f757f3fSDimitry Andric const LLT v64s8 = LLT::fixed_vector(64, 8); 735f757f3fSDimitry Andric const LLT v32s16 = LLT::fixed_vector(32, 16); 745f757f3fSDimitry Andric const LLT v16s32 = LLT::fixed_vector(16, 32); 755f757f3fSDimitry Andric const LLT v8s64 = LLT::fixed_vector(8, 64); 765f757f3fSDimitry Andric 77*0fca6ea1SDimitry Andric const LLT s8MaxVector = HasAVX512 ? v64s8 : HasAVX ? v32s8 : v16s8; 78*0fca6ea1SDimitry Andric const LLT s16MaxVector = HasAVX512 ? v32s16 : HasAVX ? v16s16 : v8s16; 79*0fca6ea1SDimitry Andric const LLT s32MaxVector = HasAVX512 ? v16s32 : HasAVX ? v8s32 : v4s32; 80*0fca6ea1SDimitry Andric const LLT s64MaxVector = HasAVX512 ? v8s64 : HasAVX ? v4s64 : v2s64; 81*0fca6ea1SDimitry Andric 825f757f3fSDimitry Andric // todo: AVX512 bool vector predicate types 835f757f3fSDimitry Andric 845f757f3fSDimitry Andric // implicit/constants 855f757f3fSDimitry Andric getActionDefinitionsBuilder(G_IMPLICIT_DEF) 865f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 875f757f3fSDimitry Andric // 32/64-bits needs support for s64/s128 to handle cases: 885f757f3fSDimitry Andric // s64 = EXTEND (G_IMPLICIT_DEF s32) -> s64 = G_IMPLICIT_DEF 895f757f3fSDimitry Andric // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF 905f757f3fSDimitry Andric return typeInSet(0, {p0, s1, s8, s16, s32, s64})(Query) || 915f757f3fSDimitry Andric (Is64Bit && typeInSet(0, {s128})(Query)); 925f757f3fSDimitry Andric }); 935f757f3fSDimitry Andric 945f757f3fSDimitry Andric getActionDefinitionsBuilder(G_CONSTANT) 955f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 965f757f3fSDimitry Andric return typeInSet(0, {p0, s8, s16, s32})(Query) || 975f757f3fSDimitry Andric (Is64Bit && typeInSet(0, {s64})(Query)); 985f757f3fSDimitry Andric }) 995f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/8) 1005f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar); 1015f757f3fSDimitry Andric 1025f757f3fSDimitry Andric // merge/unmerge 1035f757f3fSDimitry Andric for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) { 1045f757f3fSDimitry Andric unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1; 1055f757f3fSDimitry Andric unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0; 1065f757f3fSDimitry Andric getActionDefinitionsBuilder(Op) 1075f757f3fSDimitry Andric .widenScalarToNextPow2(LitTyIdx, /*Min=*/8) 1085f757f3fSDimitry Andric .widenScalarToNextPow2(BigTyIdx, /*Min=*/16) 1095f757f3fSDimitry Andric .minScalar(LitTyIdx, s8) 1105f757f3fSDimitry Andric .minScalar(BigTyIdx, s32) 1115f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Q) { 1125f757f3fSDimitry Andric switch (Q.Types[BigTyIdx].getSizeInBits()) { 1135f757f3fSDimitry Andric case 16: 1145f757f3fSDimitry Andric case 32: 1155f757f3fSDimitry Andric case 64: 1165f757f3fSDimitry Andric case 128: 1175f757f3fSDimitry Andric case 256: 1185f757f3fSDimitry Andric case 512: 1195f757f3fSDimitry Andric break; 1205f757f3fSDimitry Andric default: 1215f757f3fSDimitry Andric return false; 1225f757f3fSDimitry Andric } 1235f757f3fSDimitry Andric switch (Q.Types[LitTyIdx].getSizeInBits()) { 1245f757f3fSDimitry Andric case 8: 1255f757f3fSDimitry Andric case 16: 1265f757f3fSDimitry Andric case 32: 1275f757f3fSDimitry Andric case 64: 1285f757f3fSDimitry Andric case 128: 1295f757f3fSDimitry Andric case 256: 1305f757f3fSDimitry Andric return true; 1315f757f3fSDimitry Andric default: 1325f757f3fSDimitry Andric return false; 1335f757f3fSDimitry Andric } 1345f757f3fSDimitry Andric }); 1355f757f3fSDimitry Andric } 1365f757f3fSDimitry Andric 1375f757f3fSDimitry Andric // integer addition/subtraction 1385f757f3fSDimitry Andric getActionDefinitionsBuilder({G_ADD, G_SUB}) 1395f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 1405f757f3fSDimitry Andric if (typeInSet(0, {s8, s16, s32})(Query)) 1415f757f3fSDimitry Andric return true; 1425f757f3fSDimitry Andric if (Is64Bit && typeInSet(0, {s64})(Query)) 1435f757f3fSDimitry Andric return true; 1445f757f3fSDimitry Andric if (HasSSE2 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query)) 1455f757f3fSDimitry Andric return true; 1465f757f3fSDimitry Andric if (HasAVX2 && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query)) 1475f757f3fSDimitry Andric return true; 1485f757f3fSDimitry Andric if (HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query)) 1495f757f3fSDimitry Andric return true; 1505f757f3fSDimitry Andric if (HasBWI && typeInSet(0, {v64s8, v32s16})(Query)) 1515f757f3fSDimitry Andric return true; 1525f757f3fSDimitry Andric return false; 1535f757f3fSDimitry Andric }) 1545f757f3fSDimitry Andric .clampMinNumElements(0, s8, 16) 1555f757f3fSDimitry Andric .clampMinNumElements(0, s16, 8) 1565f757f3fSDimitry Andric .clampMinNumElements(0, s32, 4) 1575f757f3fSDimitry Andric .clampMinNumElements(0, s64, 2) 1585f757f3fSDimitry Andric .clampMaxNumElements(0, s8, HasBWI ? 64 : (HasAVX2 ? 32 : 16)) 1595f757f3fSDimitry Andric .clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8)) 1605f757f3fSDimitry Andric .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4)) 1615f757f3fSDimitry Andric .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX2 ? 4 : 2)) 1625f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/32) 1635f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar) 1645f757f3fSDimitry Andric .scalarize(0); 1655f757f3fSDimitry Andric 1665f757f3fSDimitry Andric getActionDefinitionsBuilder({G_UADDE, G_UADDO, G_USUBE, G_USUBO}) 1675f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 1685f757f3fSDimitry Andric return typePairInSet(0, 1, {{s8, s1}, {s16, s1}, {s32, s1}})(Query) || 1695f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{s64, s1}})(Query)); 1705f757f3fSDimitry Andric }) 1715f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/32) 1725f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar) 1735f757f3fSDimitry Andric .clampScalar(1, s1, s1) 1745f757f3fSDimitry Andric .scalarize(0); 1755f757f3fSDimitry Andric 1765f757f3fSDimitry Andric // integer multiply 1775f757f3fSDimitry Andric getActionDefinitionsBuilder(G_MUL) 1785f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 1795f757f3fSDimitry Andric if (typeInSet(0, {s8, s16, s32})(Query)) 1805f757f3fSDimitry Andric return true; 1815f757f3fSDimitry Andric if (Is64Bit && typeInSet(0, {s64})(Query)) 1825f757f3fSDimitry Andric return true; 1835f757f3fSDimitry Andric if (HasSSE2 && typeInSet(0, {v8s16})(Query)) 1845f757f3fSDimitry Andric return true; 1855f757f3fSDimitry Andric if (HasSSE41 && typeInSet(0, {v4s32})(Query)) 1865f757f3fSDimitry Andric return true; 1875f757f3fSDimitry Andric if (HasAVX2 && typeInSet(0, {v16s16, v8s32})(Query)) 1885f757f3fSDimitry Andric return true; 1895f757f3fSDimitry Andric if (HasAVX512 && typeInSet(0, {v16s32})(Query)) 1905f757f3fSDimitry Andric return true; 1915f757f3fSDimitry Andric if (HasDQI && typeInSet(0, {v8s64})(Query)) 1925f757f3fSDimitry Andric return true; 1935f757f3fSDimitry Andric if (HasDQI && HasVLX && typeInSet(0, {v2s64, v4s64})(Query)) 1945f757f3fSDimitry Andric return true; 1955f757f3fSDimitry Andric if (HasBWI && typeInSet(0, {v32s16})(Query)) 1965f757f3fSDimitry Andric return true; 1975f757f3fSDimitry Andric return false; 1985f757f3fSDimitry Andric }) 1995f757f3fSDimitry Andric .clampMinNumElements(0, s16, 8) 2005f757f3fSDimitry Andric .clampMinNumElements(0, s32, 4) 2015f757f3fSDimitry Andric .clampMinNumElements(0, s64, HasVLX ? 2 : 8) 2025f757f3fSDimitry Andric .clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8)) 2035f757f3fSDimitry Andric .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4)) 2045f757f3fSDimitry Andric .clampMaxNumElements(0, s64, 8) 2055f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/32) 2065f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar) 2075f757f3fSDimitry Andric .scalarize(0); 2085f757f3fSDimitry Andric 2095f757f3fSDimitry Andric getActionDefinitionsBuilder({G_SMULH, G_UMULH}) 2105f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 2115f757f3fSDimitry Andric return typeInSet(0, {s8, s16, s32})(Query) || 2125f757f3fSDimitry Andric (Is64Bit && typeInSet(0, {s64})(Query)); 2135f757f3fSDimitry Andric }) 2145f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/32) 2155f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar) 2165f757f3fSDimitry Andric .scalarize(0); 2175f757f3fSDimitry Andric 2185f757f3fSDimitry Andric // integer divisions 2195f757f3fSDimitry Andric getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UDIV, G_UREM}) 2205f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 2215f757f3fSDimitry Andric return typeInSet(0, {s8, s16, s32})(Query) || 2225f757f3fSDimitry Andric (Is64Bit && typeInSet(0, {s64})(Query)); 2235f757f3fSDimitry Andric }) 224*0fca6ea1SDimitry Andric .libcallFor({s64}) 2255f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar); 2265f757f3fSDimitry Andric 2275f757f3fSDimitry Andric // integer shifts 2285f757f3fSDimitry Andric getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR}) 2295f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 2305f757f3fSDimitry Andric return typePairInSet(0, 1, {{s8, s8}, {s16, s8}, {s32, s8}})(Query) || 2315f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{s64, s8}})(Query)); 2325f757f3fSDimitry Andric }) 2335f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar) 2345f757f3fSDimitry Andric .clampScalar(1, s8, s8); 2355f757f3fSDimitry Andric 2365f757f3fSDimitry Andric // integer logic 2375f757f3fSDimitry Andric getActionDefinitionsBuilder({G_AND, G_OR, G_XOR}) 2385f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 2395f757f3fSDimitry Andric if (typeInSet(0, {s8, s16, s32})(Query)) 2405f757f3fSDimitry Andric return true; 2415f757f3fSDimitry Andric if (Is64Bit && typeInSet(0, {s64})(Query)) 2425f757f3fSDimitry Andric return true; 2435f757f3fSDimitry Andric if (HasSSE2 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query)) 2445f757f3fSDimitry Andric return true; 2455f757f3fSDimitry Andric if (HasAVX && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query)) 2465f757f3fSDimitry Andric return true; 2475f757f3fSDimitry Andric if (HasAVX512 && typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query)) 2485f757f3fSDimitry Andric return true; 2495f757f3fSDimitry Andric return false; 2505f757f3fSDimitry Andric }) 2515f757f3fSDimitry Andric .clampMinNumElements(0, s8, 16) 2525f757f3fSDimitry Andric .clampMinNumElements(0, s16, 8) 2535f757f3fSDimitry Andric .clampMinNumElements(0, s32, 4) 2545f757f3fSDimitry Andric .clampMinNumElements(0, s64, 2) 2555f757f3fSDimitry Andric .clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16)) 2565f757f3fSDimitry Andric .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8)) 2575f757f3fSDimitry Andric .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4)) 2585f757f3fSDimitry Andric .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2)) 2595f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/32) 2605f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar) 2615f757f3fSDimitry Andric .scalarize(0); 2625f757f3fSDimitry Andric 2635f757f3fSDimitry Andric // integer comparison 2645f757f3fSDimitry Andric const std::initializer_list<LLT> IntTypes32 = {s8, s16, s32, p0}; 2655f757f3fSDimitry Andric const std::initializer_list<LLT> IntTypes64 = {s8, s16, s32, s64, p0}; 2665f757f3fSDimitry Andric 2675f757f3fSDimitry Andric getActionDefinitionsBuilder(G_ICMP) 2685f757f3fSDimitry Andric .legalForCartesianProduct({s8}, Is64Bit ? IntTypes64 : IntTypes32) 2695f757f3fSDimitry Andric .clampScalar(0, s8, s8) 270*0fca6ea1SDimitry Andric .clampScalar(1, s8, sMaxScalar); 2715f757f3fSDimitry Andric 2725f757f3fSDimitry Andric // bswap 2735f757f3fSDimitry Andric getActionDefinitionsBuilder(G_BSWAP) 2745f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) { 2755f757f3fSDimitry Andric return Query.Types[0] == s32 || 2765f757f3fSDimitry Andric (Subtarget.is64Bit() && Query.Types[0] == s64); 2775f757f3fSDimitry Andric }) 2785f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/32) 2795f757f3fSDimitry Andric .clampScalar(0, s32, sMaxScalar); 2805f757f3fSDimitry Andric 2815f757f3fSDimitry Andric // popcount 2825f757f3fSDimitry Andric getActionDefinitionsBuilder(G_CTPOP) 2835f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 2845f757f3fSDimitry Andric return Subtarget.hasPOPCNT() && 2855f757f3fSDimitry Andric (typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) || 2865f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))); 2875f757f3fSDimitry Andric }) 2885f757f3fSDimitry Andric .widenScalarToNextPow2(1, /*Min=*/16) 2895f757f3fSDimitry Andric .clampScalar(1, s16, sMaxScalar) 2905f757f3fSDimitry Andric .scalarSameSizeAs(0, 1); 2915f757f3fSDimitry Andric 2925f757f3fSDimitry Andric // count leading zeros (LZCNT) 2935f757f3fSDimitry Andric getActionDefinitionsBuilder(G_CTLZ) 2945f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 2955f757f3fSDimitry Andric return Subtarget.hasLZCNT() && 2965f757f3fSDimitry Andric (typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) || 2975f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))); 2985f757f3fSDimitry Andric }) 2995f757f3fSDimitry Andric .widenScalarToNextPow2(1, /*Min=*/16) 3005f757f3fSDimitry Andric .clampScalar(1, s16, sMaxScalar) 3015f757f3fSDimitry Andric .scalarSameSizeAs(0, 1); 3025f757f3fSDimitry Andric 3035f757f3fSDimitry Andric // count trailing zeros 3045f757f3fSDimitry Andric getActionDefinitionsBuilder({G_CTTZ_ZERO_UNDEF, G_CTTZ}) 3055f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 3065f757f3fSDimitry Andric return (Query.Opcode == G_CTTZ_ZERO_UNDEF || Subtarget.hasBMI()) && 3075f757f3fSDimitry Andric (typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) || 3085f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))); 3095f757f3fSDimitry Andric }) 3105f757f3fSDimitry Andric .widenScalarToNextPow2(1, /*Min=*/16) 3115f757f3fSDimitry Andric .clampScalar(1, s16, sMaxScalar) 3125f757f3fSDimitry Andric .scalarSameSizeAs(0, 1); 3135f757f3fSDimitry Andric 3145f757f3fSDimitry Andric // control flow 3155f757f3fSDimitry Andric getActionDefinitionsBuilder(G_PHI) 3165f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 3175f757f3fSDimitry Andric return typeInSet(0, {s8, s16, s32, p0})(Query) || 3185f757f3fSDimitry Andric (Is64Bit && typeInSet(0, {s64})(Query)) || 3195f757f3fSDimitry Andric (HasSSE1 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query)) || 3205f757f3fSDimitry Andric (HasAVX && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query)) || 3215f757f3fSDimitry Andric (HasAVX512 && 3225f757f3fSDimitry Andric typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query)); 3235f757f3fSDimitry Andric }) 3245f757f3fSDimitry Andric .clampMinNumElements(0, s8, 16) 3255f757f3fSDimitry Andric .clampMinNumElements(0, s16, 8) 3265f757f3fSDimitry Andric .clampMinNumElements(0, s32, 4) 3275f757f3fSDimitry Andric .clampMinNumElements(0, s64, 2) 3285f757f3fSDimitry Andric .clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16)) 3295f757f3fSDimitry Andric .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8)) 3305f757f3fSDimitry Andric .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4)) 3315f757f3fSDimitry Andric .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2)) 3325f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/32) 3335f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar) 3345f757f3fSDimitry Andric .scalarize(0); 3355f757f3fSDimitry Andric 3365f757f3fSDimitry Andric getActionDefinitionsBuilder(G_BRCOND).legalFor({s1}); 3375f757f3fSDimitry Andric 3385f757f3fSDimitry Andric // pointer handling 3395f757f3fSDimitry Andric const std::initializer_list<LLT> PtrTypes32 = {s1, s8, s16, s32}; 3405f757f3fSDimitry Andric const std::initializer_list<LLT> PtrTypes64 = {s1, s8, s16, s32, s64}; 3415f757f3fSDimitry Andric 3425f757f3fSDimitry Andric getActionDefinitionsBuilder(G_PTRTOINT) 3435f757f3fSDimitry Andric .legalForCartesianProduct(Is64Bit ? PtrTypes64 : PtrTypes32, {p0}) 3445f757f3fSDimitry Andric .maxScalar(0, sMaxScalar) 3455f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min*/ 8); 3465f757f3fSDimitry Andric 3475f757f3fSDimitry Andric getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, sMaxScalar}}); 3485f757f3fSDimitry Andric 349*0fca6ea1SDimitry Andric getActionDefinitionsBuilder(G_CONSTANT_POOL).legalFor({p0}); 350*0fca6ea1SDimitry Andric 3515f757f3fSDimitry Andric getActionDefinitionsBuilder(G_PTR_ADD) 3525f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 3535f757f3fSDimitry Andric return typePairInSet(0, 1, {{p0, s32}})(Query) || 3545f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{p0, s64}})(Query)); 3555f757f3fSDimitry Andric }) 3565f757f3fSDimitry Andric .widenScalarToNextPow2(1, /*Min*/ 32) 3575f757f3fSDimitry Andric .clampScalar(1, s32, sMaxScalar); 3585f757f3fSDimitry Andric 3595f757f3fSDimitry Andric getActionDefinitionsBuilder({G_FRAME_INDEX, G_GLOBAL_VALUE}).legalFor({p0}); 3605f757f3fSDimitry Andric 3615f757f3fSDimitry Andric // load/store: add more corner cases 3625f757f3fSDimitry Andric for (unsigned Op : {G_LOAD, G_STORE}) { 3635f757f3fSDimitry Andric auto &Action = getActionDefinitionsBuilder(Op); 3645f757f3fSDimitry Andric Action.legalForTypesWithMemDesc({{s8, p0, s1, 1}, 3655f757f3fSDimitry Andric {s8, p0, s8, 1}, 3665f757f3fSDimitry Andric {s16, p0, s8, 1}, 3675f757f3fSDimitry Andric {s16, p0, s16, 1}, 3685f757f3fSDimitry Andric {s32, p0, s8, 1}, 3695f757f3fSDimitry Andric {s32, p0, s16, 1}, 3705f757f3fSDimitry Andric {s32, p0, s32, 1}, 3715f757f3fSDimitry Andric {s80, p0, s80, 1}, 3725f757f3fSDimitry Andric {p0, p0, p0, 1}, 3735f757f3fSDimitry Andric {v4s8, p0, v4s8, 1}}); 3745f757f3fSDimitry Andric if (Is64Bit) 3755f757f3fSDimitry Andric Action.legalForTypesWithMemDesc({{s64, p0, s8, 1}, 3765f757f3fSDimitry Andric {s64, p0, s16, 1}, 3775f757f3fSDimitry Andric {s64, p0, s32, 1}, 3785f757f3fSDimitry Andric {s64, p0, s64, 1}, 3795f757f3fSDimitry Andric {v2s32, p0, v2s32, 1}}); 3805f757f3fSDimitry Andric if (HasSSE1) 381*0fca6ea1SDimitry Andric Action.legalForTypesWithMemDesc({{v4s32, p0, v4s32, 1}}); 382*0fca6ea1SDimitry Andric if (HasSSE2) 3835f757f3fSDimitry Andric Action.legalForTypesWithMemDesc({{v16s8, p0, v16s8, 1}, 3845f757f3fSDimitry Andric {v8s16, p0, v8s16, 1}, 3855f757f3fSDimitry Andric {v2s64, p0, v2s64, 1}, 3865f757f3fSDimitry Andric {v2p0, p0, v2p0, 1}}); 3875f757f3fSDimitry Andric if (HasAVX) 3885f757f3fSDimitry Andric Action.legalForTypesWithMemDesc({{v32s8, p0, v32s8, 1}, 3895f757f3fSDimitry Andric {v16s16, p0, v16s16, 1}, 3905f757f3fSDimitry Andric {v8s32, p0, v8s32, 1}, 3915f757f3fSDimitry Andric {v4s64, p0, v4s64, 1}, 3925f757f3fSDimitry Andric {v4p0, p0, v4p0, 1}}); 3935f757f3fSDimitry Andric if (HasAVX512) 3945f757f3fSDimitry Andric Action.legalForTypesWithMemDesc({{v64s8, p0, v64s8, 1}, 3955f757f3fSDimitry Andric {v32s16, p0, v32s16, 1}, 3965f757f3fSDimitry Andric {v16s32, p0, v16s32, 1}, 3975f757f3fSDimitry Andric {v8s64, p0, v8s64, 1}}); 398*0fca6ea1SDimitry Andric Action.widenScalarToNextPow2(0, /*Min=*/8) 399*0fca6ea1SDimitry Andric .clampScalar(0, s8, sMaxScalar) 400*0fca6ea1SDimitry Andric .scalarize(0); 4015f757f3fSDimitry Andric } 4025f757f3fSDimitry Andric 4035f757f3fSDimitry Andric for (unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) { 4045f757f3fSDimitry Andric auto &Action = getActionDefinitionsBuilder(Op); 4055f757f3fSDimitry Andric Action.legalForTypesWithMemDesc({{s16, p0, s8, 1}, 4065f757f3fSDimitry Andric {s32, p0, s8, 1}, 4075f757f3fSDimitry Andric {s32, p0, s16, 1}}); 4085f757f3fSDimitry Andric if (Is64Bit) 4095f757f3fSDimitry Andric Action.legalForTypesWithMemDesc({{s64, p0, s8, 1}, 4105f757f3fSDimitry Andric {s64, p0, s16, 1}, 4115f757f3fSDimitry Andric {s64, p0, s32, 1}}); 4125f757f3fSDimitry Andric // TODO - SSE41/AVX2/AVX512F/AVX512BW vector extensions 4135f757f3fSDimitry Andric } 4145f757f3fSDimitry Andric 4155f757f3fSDimitry Andric // sext, zext, and anyext 4165f757f3fSDimitry Andric getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT}) 4175f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) { 4185f757f3fSDimitry Andric return typeInSet(0, {s8, s16, s32})(Query) || 4195f757f3fSDimitry Andric (Query.Opcode == G_ANYEXT && Query.Types[0] == s128) || 4205f757f3fSDimitry Andric (Is64Bit && Query.Types[0] == s64); 4215f757f3fSDimitry Andric }) 4225f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/8) 4235f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar) 4245f757f3fSDimitry Andric .widenScalarToNextPow2(1, /*Min=*/8) 425*0fca6ea1SDimitry Andric .clampScalar(1, s8, sMaxScalar) 426*0fca6ea1SDimitry Andric .scalarize(0); 4275f757f3fSDimitry Andric 4285f757f3fSDimitry Andric getActionDefinitionsBuilder(G_SEXT_INREG).lower(); 4295f757f3fSDimitry Andric 4305f757f3fSDimitry Andric // fp constants 4315f757f3fSDimitry Andric getActionDefinitionsBuilder(G_FCONSTANT) 4325f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) -> bool { 433*0fca6ea1SDimitry Andric return (typeInSet(0, {s32, s64})(Query)) || 434*0fca6ea1SDimitry Andric (UseX87 && typeInSet(0, {s80})(Query)); 4355f757f3fSDimitry Andric }); 4365f757f3fSDimitry Andric 4375f757f3fSDimitry Andric // fp arithmetic 4385f757f3fSDimitry Andric getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV}) 4395f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) { 440*0fca6ea1SDimitry Andric return (typeInSet(0, {s32, s64})(Query)) || 441*0fca6ea1SDimitry Andric (HasSSE1 && typeInSet(0, {v4s32})(Query)) || 442*0fca6ea1SDimitry Andric (HasSSE2 && typeInSet(0, {v2s64})(Query)) || 4435f757f3fSDimitry Andric (HasAVX && typeInSet(0, {v8s32, v4s64})(Query)) || 444*0fca6ea1SDimitry Andric (HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query)) || 445*0fca6ea1SDimitry Andric (UseX87 && typeInSet(0, {s80})(Query)); 4465f757f3fSDimitry Andric }); 4475f757f3fSDimitry Andric 4485f757f3fSDimitry Andric // fp comparison 4495f757f3fSDimitry Andric getActionDefinitionsBuilder(G_FCMP) 4505f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) { 4515f757f3fSDimitry Andric return (HasSSE1 && typePairInSet(0, 1, {{s8, s32}})(Query)) || 4525f757f3fSDimitry Andric (HasSSE2 && typePairInSet(0, 1, {{s8, s64}})(Query)); 4535f757f3fSDimitry Andric }) 4545f757f3fSDimitry Andric .clampScalar(0, s8, s8) 4555f757f3fSDimitry Andric .clampScalar(1, s32, HasSSE2 ? s64 : s32) 4565f757f3fSDimitry Andric .widenScalarToNextPow2(1); 4575f757f3fSDimitry Andric 4585f757f3fSDimitry Andric // fp conversions 4595f757f3fSDimitry Andric getActionDefinitionsBuilder(G_FPEXT).legalIf([=](const LegalityQuery &Query) { 4605f757f3fSDimitry Andric return (HasSSE2 && typePairInSet(0, 1, {{s64, s32}})(Query)) || 4615f757f3fSDimitry Andric (HasAVX && typePairInSet(0, 1, {{v4s64, v4s32}})(Query)) || 4625f757f3fSDimitry Andric (HasAVX512 && typePairInSet(0, 1, {{v8s64, v8s32}})(Query)); 4635f757f3fSDimitry Andric }); 4645f757f3fSDimitry Andric 4655f757f3fSDimitry Andric getActionDefinitionsBuilder(G_FPTRUNC).legalIf( 4665f757f3fSDimitry Andric [=](const LegalityQuery &Query) { 4675f757f3fSDimitry Andric return (HasSSE2 && typePairInSet(0, 1, {{s32, s64}})(Query)) || 4685f757f3fSDimitry Andric (HasAVX && typePairInSet(0, 1, {{v4s32, v4s64}})(Query)) || 4695f757f3fSDimitry Andric (HasAVX512 && typePairInSet(0, 1, {{v8s32, v8s64}})(Query)); 4705f757f3fSDimitry Andric }); 4715f757f3fSDimitry Andric 4725f757f3fSDimitry Andric getActionDefinitionsBuilder(G_SITOFP) 4735f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) { 4745f757f3fSDimitry Andric return (HasSSE1 && 4755f757f3fSDimitry Andric (typePairInSet(0, 1, {{s32, s32}})(Query) || 4765f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{s32, s64}})(Query)))) || 4775f757f3fSDimitry Andric (HasSSE2 && 4785f757f3fSDimitry Andric (typePairInSet(0, 1, {{s64, s32}})(Query) || 4795f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)))); 4805f757f3fSDimitry Andric }) 4815f757f3fSDimitry Andric .clampScalar(1, s32, sMaxScalar) 4825f757f3fSDimitry Andric .widenScalarToNextPow2(1) 4835f757f3fSDimitry Andric .clampScalar(0, s32, HasSSE2 ? s64 : s32) 4845f757f3fSDimitry Andric .widenScalarToNextPow2(0); 4855f757f3fSDimitry Andric 4865f757f3fSDimitry Andric getActionDefinitionsBuilder(G_FPTOSI) 4875f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) { 4885f757f3fSDimitry Andric return (HasSSE1 && 4895f757f3fSDimitry Andric (typePairInSet(0, 1, {{s32, s32}})(Query) || 4905f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{s64, s32}})(Query)))) || 4915f757f3fSDimitry Andric (HasSSE2 && 4925f757f3fSDimitry Andric (typePairInSet(0, 1, {{s32, s64}})(Query) || 4935f757f3fSDimitry Andric (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)))); 4945f757f3fSDimitry Andric }) 4955f757f3fSDimitry Andric .clampScalar(1, s32, HasSSE2 ? s64 : s32) 4965f757f3fSDimitry Andric .widenScalarToNextPow2(0) 4975f757f3fSDimitry Andric .clampScalar(0, s32, sMaxScalar) 4985f757f3fSDimitry Andric .widenScalarToNextPow2(1); 4995f757f3fSDimitry Andric 5005f757f3fSDimitry Andric // vector ops 501*0fca6ea1SDimitry Andric getActionDefinitionsBuilder(G_BUILD_VECTOR) 502*0fca6ea1SDimitry Andric .customIf([=](const LegalityQuery &Query) { 503*0fca6ea1SDimitry Andric return (HasSSE1 && typeInSet(0, {v4s32})(Query)) || 504*0fca6ea1SDimitry Andric (HasSSE2 && typeInSet(0, {v2s64, v8s16, v16s8})(Query)) || 505*0fca6ea1SDimitry Andric (HasAVX && typeInSet(0, {v4s64, v8s32, v16s16, v32s8})(Query)) || 506*0fca6ea1SDimitry Andric (HasAVX512 && typeInSet(0, {v8s64, v16s32, v32s16, v64s8})); 507*0fca6ea1SDimitry Andric }) 508*0fca6ea1SDimitry Andric .clampNumElements(0, v16s8, s8MaxVector) 509*0fca6ea1SDimitry Andric .clampNumElements(0, v8s16, s16MaxVector) 510*0fca6ea1SDimitry Andric .clampNumElements(0, v4s32, s32MaxVector) 511*0fca6ea1SDimitry Andric .clampNumElements(0, v2s64, s64MaxVector) 512*0fca6ea1SDimitry Andric .moreElementsToNextPow2(0); 513*0fca6ea1SDimitry Andric 5145f757f3fSDimitry Andric getActionDefinitionsBuilder({G_EXTRACT, G_INSERT}) 5155f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) { 5165f757f3fSDimitry Andric unsigned SubIdx = Query.Opcode == G_EXTRACT ? 0 : 1; 5175f757f3fSDimitry Andric unsigned FullIdx = Query.Opcode == G_EXTRACT ? 1 : 0; 5185f757f3fSDimitry Andric return (HasAVX && typePairInSet(SubIdx, FullIdx, 5195f757f3fSDimitry Andric {{v16s8, v32s8}, 5205f757f3fSDimitry Andric {v8s16, v16s16}, 5215f757f3fSDimitry Andric {v4s32, v8s32}, 5225f757f3fSDimitry Andric {v2s64, v4s64}})(Query)) || 5235f757f3fSDimitry Andric (HasAVX512 && typePairInSet(SubIdx, FullIdx, 5245f757f3fSDimitry Andric {{v16s8, v64s8}, 5255f757f3fSDimitry Andric {v32s8, v64s8}, 5265f757f3fSDimitry Andric {v8s16, v32s16}, 5275f757f3fSDimitry Andric {v16s16, v32s16}, 5285f757f3fSDimitry Andric {v4s32, v16s32}, 5295f757f3fSDimitry Andric {v8s32, v16s32}, 5305f757f3fSDimitry Andric {v2s64, v8s64}, 5315f757f3fSDimitry Andric {v4s64, v8s64}})(Query)); 5325f757f3fSDimitry Andric }); 5335f757f3fSDimitry Andric 5345f757f3fSDimitry Andric // todo: only permit dst types up to max legal vector register size? 5355f757f3fSDimitry Andric getActionDefinitionsBuilder(G_CONCAT_VECTORS) 5365f757f3fSDimitry Andric .legalIf([=](const LegalityQuery &Query) { 5375f757f3fSDimitry Andric return (HasSSE1 && typePairInSet(1, 0, 5385f757f3fSDimitry Andric {{v16s8, v32s8}, 5395f757f3fSDimitry Andric {v8s16, v16s16}, 5405f757f3fSDimitry Andric {v4s32, v8s32}, 5415f757f3fSDimitry Andric {v2s64, v4s64}})(Query)) || 5425f757f3fSDimitry Andric (HasAVX && typePairInSet(1, 0, 5435f757f3fSDimitry Andric {{v16s8, v64s8}, 5445f757f3fSDimitry Andric {v32s8, v64s8}, 5455f757f3fSDimitry Andric {v8s16, v32s16}, 5465f757f3fSDimitry Andric {v16s16, v32s16}, 5475f757f3fSDimitry Andric {v4s32, v16s32}, 5485f757f3fSDimitry Andric {v8s32, v16s32}, 5495f757f3fSDimitry Andric {v2s64, v8s64}, 5505f757f3fSDimitry Andric {v4s64, v8s64}})(Query)); 5515f757f3fSDimitry Andric }); 5525f757f3fSDimitry Andric 5535f757f3fSDimitry Andric // todo: vectors and address spaces 5545f757f3fSDimitry Andric getActionDefinitionsBuilder(G_SELECT) 5555f757f3fSDimitry Andric .legalFor({{s8, s32}, {s16, s32}, {s32, s32}, {s64, s32}, {p0, s32}}) 5565f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/8) 5575f757f3fSDimitry Andric .clampScalar(0, HasCMOV ? s16 : s8, sMaxScalar) 5585f757f3fSDimitry Andric .clampScalar(1, s32, s32); 5595f757f3fSDimitry Andric 5605f757f3fSDimitry Andric // memory intrinsics 5615f757f3fSDimitry Andric getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall(); 5625f757f3fSDimitry Andric 5635f757f3fSDimitry Andric getActionDefinitionsBuilder({G_DYN_STACKALLOC, 5645f757f3fSDimitry Andric G_STACKSAVE, 5655f757f3fSDimitry Andric G_STACKRESTORE}).lower(); 5665f757f3fSDimitry Andric 5675f757f3fSDimitry Andric // fp intrinsics 5685f757f3fSDimitry Andric getActionDefinitionsBuilder(G_INTRINSIC_ROUNDEVEN) 5695f757f3fSDimitry Andric .scalarize(0) 5705f757f3fSDimitry Andric .minScalar(0, LLT::scalar(32)) 5715f757f3fSDimitry Andric .libcall(); 5725f757f3fSDimitry Andric 5735f757f3fSDimitry Andric getActionDefinitionsBuilder({G_FREEZE, G_CONSTANT_FOLD_BARRIER}) 5745f757f3fSDimitry Andric .legalFor({s8, s16, s32, s64, p0}) 5755f757f3fSDimitry Andric .widenScalarToNextPow2(0, /*Min=*/8) 5765f757f3fSDimitry Andric .clampScalar(0, s8, sMaxScalar); 5775f757f3fSDimitry Andric 5785f757f3fSDimitry Andric getLegacyLegalizerInfo().computeTables(); 5795f757f3fSDimitry Andric verify(*STI.getInstrInfo()); 5805f757f3fSDimitry Andric } 5815f757f3fSDimitry Andric 582*0fca6ea1SDimitry Andric bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, 583*0fca6ea1SDimitry Andric LostDebugLocObserver &LocObserver) const { 584*0fca6ea1SDimitry Andric MachineIRBuilder &MIRBuilder = Helper.MIRBuilder; 585*0fca6ea1SDimitry Andric MachineRegisterInfo &MRI = *MIRBuilder.getMRI(); 586*0fca6ea1SDimitry Andric switch (MI.getOpcode()) { 587*0fca6ea1SDimitry Andric default: 588*0fca6ea1SDimitry Andric // No idea what to do. 589*0fca6ea1SDimitry Andric return false; 590*0fca6ea1SDimitry Andric case TargetOpcode::G_BUILD_VECTOR: 591*0fca6ea1SDimitry Andric return legalizeBuildVector(MI, MRI, Helper); 592*0fca6ea1SDimitry Andric } 593*0fca6ea1SDimitry Andric llvm_unreachable("expected switch to return"); 594*0fca6ea1SDimitry Andric } 595*0fca6ea1SDimitry Andric 596*0fca6ea1SDimitry Andric bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI, 597*0fca6ea1SDimitry Andric MachineRegisterInfo &MRI, 598*0fca6ea1SDimitry Andric LegalizerHelper &Helper) const { 599*0fca6ea1SDimitry Andric MachineIRBuilder &MIRBuilder = Helper.MIRBuilder; 600*0fca6ea1SDimitry Andric const auto &BuildVector = cast<GBuildVector>(MI); 601*0fca6ea1SDimitry Andric Register Dst = BuildVector.getReg(0); 602*0fca6ea1SDimitry Andric LLT DstTy = MRI.getType(Dst); 603*0fca6ea1SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 604*0fca6ea1SDimitry Andric LLVMContext &Ctx = MF.getFunction().getContext(); 605*0fca6ea1SDimitry Andric uint64_t DstTySize = DstTy.getScalarSizeInBits(); 606*0fca6ea1SDimitry Andric 607*0fca6ea1SDimitry Andric SmallVector<Constant *, 4> CstIdxs; 608*0fca6ea1SDimitry Andric for (unsigned i = 0; i < BuildVector.getNumSources(); ++i) { 609*0fca6ea1SDimitry Andric Register Source = BuildVector.getSourceReg(i); 610*0fca6ea1SDimitry Andric 611*0fca6ea1SDimitry Andric auto ValueAndReg = getIConstantVRegValWithLookThrough(Source, MRI); 612*0fca6ea1SDimitry Andric if (ValueAndReg) { 613*0fca6ea1SDimitry Andric CstIdxs.emplace_back(ConstantInt::get(Ctx, ValueAndReg->Value)); 614*0fca6ea1SDimitry Andric continue; 615*0fca6ea1SDimitry Andric } 616*0fca6ea1SDimitry Andric 617*0fca6ea1SDimitry Andric auto FPValueAndReg = getFConstantVRegValWithLookThrough(Source, MRI); 618*0fca6ea1SDimitry Andric if (FPValueAndReg) { 619*0fca6ea1SDimitry Andric CstIdxs.emplace_back(ConstantFP::get(Ctx, FPValueAndReg->Value)); 620*0fca6ea1SDimitry Andric continue; 621*0fca6ea1SDimitry Andric } 622*0fca6ea1SDimitry Andric 623*0fca6ea1SDimitry Andric if (getOpcodeDef<GImplicitDef>(Source, MRI)) { 624*0fca6ea1SDimitry Andric CstIdxs.emplace_back(UndefValue::get(Type::getIntNTy(Ctx, DstTySize))); 625*0fca6ea1SDimitry Andric continue; 626*0fca6ea1SDimitry Andric } 627*0fca6ea1SDimitry Andric return false; 628*0fca6ea1SDimitry Andric } 629*0fca6ea1SDimitry Andric 630*0fca6ea1SDimitry Andric Constant *ConstVal = ConstantVector::get(CstIdxs); 631*0fca6ea1SDimitry Andric 632*0fca6ea1SDimitry Andric const DataLayout &DL = MIRBuilder.getDataLayout(); 633*0fca6ea1SDimitry Andric unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace(); 634*0fca6ea1SDimitry Andric Align Alignment(DL.getABITypeAlign(ConstVal->getType())); 635*0fca6ea1SDimitry Andric auto Addr = MIRBuilder.buildConstantPool( 636*0fca6ea1SDimitry Andric LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace)), 637*0fca6ea1SDimitry Andric MF.getConstantPool()->getConstantPoolIndex(ConstVal, Alignment)); 638*0fca6ea1SDimitry Andric MachineMemOperand *MMO = 639*0fca6ea1SDimitry Andric MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF), 640*0fca6ea1SDimitry Andric MachineMemOperand::MOLoad, DstTy, Alignment); 641*0fca6ea1SDimitry Andric 642*0fca6ea1SDimitry Andric MIRBuilder.buildLoad(Dst, Addr, *MMO); 643*0fca6ea1SDimitry Andric MI.eraseFromParent(); 644*0fca6ea1SDimitry Andric return true; 645*0fca6ea1SDimitry Andric } 646*0fca6ea1SDimitry Andric 6475f757f3fSDimitry Andric bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper, 6485f757f3fSDimitry Andric MachineInstr &MI) const { 6495f757f3fSDimitry Andric return true; 6505f757f3fSDimitry Andric } 651