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