Path: blob/main/contrib/llvm-project/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
35294 views
//===- X86LegalizerInfo.cpp --------------------------------------*- C++ -*-==//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8/// This file implements the targeting of the Machinelegalizer class for X86.9/// \todo This should be generated by TableGen.10//===----------------------------------------------------------------------===//1112#include "X86LegalizerInfo.h"13#include "X86Subtarget.h"14#include "X86TargetMachine.h"15#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"16#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"17#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"18#include "llvm/CodeGen/MachineConstantPool.h"19#include "llvm/CodeGen/TargetOpcodes.h"20#include "llvm/CodeGen/ValueTypes.h"21#include "llvm/IR/DerivedTypes.h"22#include "llvm/IR/Type.h"2324using namespace llvm;25using namespace TargetOpcode;26using namespace LegalizeActions;27using namespace LegalityPredicates;2829X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,30const X86TargetMachine &TM)31: Subtarget(STI) {3233bool Is64Bit = Subtarget.is64Bit();34bool HasCMOV = Subtarget.canUseCMOV();35bool HasSSE1 = Subtarget.hasSSE1();36bool HasSSE2 = Subtarget.hasSSE2();37bool HasSSE41 = Subtarget.hasSSE41();38bool HasAVX = Subtarget.hasAVX();39bool HasAVX2 = Subtarget.hasAVX2();40bool HasAVX512 = Subtarget.hasAVX512();41bool HasVLX = Subtarget.hasVLX();42bool HasDQI = Subtarget.hasAVX512() && Subtarget.hasDQI();43bool HasBWI = Subtarget.hasAVX512() && Subtarget.hasBWI();44bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();4546const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));47const LLT s1 = LLT::scalar(1);48const LLT s8 = LLT::scalar(8);49const LLT s16 = LLT::scalar(16);50const LLT s32 = LLT::scalar(32);51const LLT s64 = LLT::scalar(64);52const LLT s80 = LLT::scalar(80);53const LLT s128 = LLT::scalar(128);54const LLT sMaxScalar = Subtarget.is64Bit() ? s64 : s32;55const LLT v2s32 = LLT::fixed_vector(2, 32);56const LLT v4s8 = LLT::fixed_vector(4, 8);575859const LLT v16s8 = LLT::fixed_vector(16, 8);60const LLT v8s16 = LLT::fixed_vector(8, 16);61const LLT v4s32 = LLT::fixed_vector(4, 32);62const LLT v2s64 = LLT::fixed_vector(2, 64);63const LLT v2p0 = LLT::fixed_vector(2, p0);6465const LLT v32s8 = LLT::fixed_vector(32, 8);66const LLT v16s16 = LLT::fixed_vector(16, 16);67const LLT v8s32 = LLT::fixed_vector(8, 32);68const LLT v4s64 = LLT::fixed_vector(4, 64);69const LLT v4p0 = LLT::fixed_vector(4, p0);7071const LLT v64s8 = LLT::fixed_vector(64, 8);72const LLT v32s16 = LLT::fixed_vector(32, 16);73const LLT v16s32 = LLT::fixed_vector(16, 32);74const LLT v8s64 = LLT::fixed_vector(8, 64);7576const LLT s8MaxVector = HasAVX512 ? v64s8 : HasAVX ? v32s8 : v16s8;77const LLT s16MaxVector = HasAVX512 ? v32s16 : HasAVX ? v16s16 : v8s16;78const LLT s32MaxVector = HasAVX512 ? v16s32 : HasAVX ? v8s32 : v4s32;79const LLT s64MaxVector = HasAVX512 ? v8s64 : HasAVX ? v4s64 : v2s64;8081// todo: AVX512 bool vector predicate types8283// implicit/constants84getActionDefinitionsBuilder(G_IMPLICIT_DEF)85.legalIf([=](const LegalityQuery &Query) -> bool {86// 32/64-bits needs support for s64/s128 to handle cases:87// s64 = EXTEND (G_IMPLICIT_DEF s32) -> s64 = G_IMPLICIT_DEF88// s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF89return typeInSet(0, {p0, s1, s8, s16, s32, s64})(Query) ||90(Is64Bit && typeInSet(0, {s128})(Query));91});9293getActionDefinitionsBuilder(G_CONSTANT)94.legalIf([=](const LegalityQuery &Query) -> bool {95return typeInSet(0, {p0, s8, s16, s32})(Query) ||96(Is64Bit && typeInSet(0, {s64})(Query));97})98.widenScalarToNextPow2(0, /*Min=*/8)99.clampScalar(0, s8, sMaxScalar);100101// merge/unmerge102for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {103unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;104unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;105getActionDefinitionsBuilder(Op)106.widenScalarToNextPow2(LitTyIdx, /*Min=*/8)107.widenScalarToNextPow2(BigTyIdx, /*Min=*/16)108.minScalar(LitTyIdx, s8)109.minScalar(BigTyIdx, s32)110.legalIf([=](const LegalityQuery &Q) {111switch (Q.Types[BigTyIdx].getSizeInBits()) {112case 16:113case 32:114case 64:115case 128:116case 256:117case 512:118break;119default:120return false;121}122switch (Q.Types[LitTyIdx].getSizeInBits()) {123case 8:124case 16:125case 32:126case 64:127case 128:128case 256:129return true;130default:131return false;132}133});134}135136// integer addition/subtraction137getActionDefinitionsBuilder({G_ADD, G_SUB})138.legalIf([=](const LegalityQuery &Query) -> bool {139if (typeInSet(0, {s8, s16, s32})(Query))140return true;141if (Is64Bit && typeInSet(0, {s64})(Query))142return true;143if (HasSSE2 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))144return true;145if (HasAVX2 && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))146return true;147if (HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query))148return true;149if (HasBWI && typeInSet(0, {v64s8, v32s16})(Query))150return true;151return false;152})153.clampMinNumElements(0, s8, 16)154.clampMinNumElements(0, s16, 8)155.clampMinNumElements(0, s32, 4)156.clampMinNumElements(0, s64, 2)157.clampMaxNumElements(0, s8, HasBWI ? 64 : (HasAVX2 ? 32 : 16))158.clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8))159.clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4))160.clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX2 ? 4 : 2))161.widenScalarToNextPow2(0, /*Min=*/32)162.clampScalar(0, s8, sMaxScalar)163.scalarize(0);164165getActionDefinitionsBuilder({G_UADDE, G_UADDO, G_USUBE, G_USUBO})166.legalIf([=](const LegalityQuery &Query) -> bool {167return typePairInSet(0, 1, {{s8, s1}, {s16, s1}, {s32, s1}})(Query) ||168(Is64Bit && typePairInSet(0, 1, {{s64, s1}})(Query));169})170.widenScalarToNextPow2(0, /*Min=*/32)171.clampScalar(0, s8, sMaxScalar)172.clampScalar(1, s1, s1)173.scalarize(0);174175// integer multiply176getActionDefinitionsBuilder(G_MUL)177.legalIf([=](const LegalityQuery &Query) -> bool {178if (typeInSet(0, {s8, s16, s32})(Query))179return true;180if (Is64Bit && typeInSet(0, {s64})(Query))181return true;182if (HasSSE2 && typeInSet(0, {v8s16})(Query))183return true;184if (HasSSE41 && typeInSet(0, {v4s32})(Query))185return true;186if (HasAVX2 && typeInSet(0, {v16s16, v8s32})(Query))187return true;188if (HasAVX512 && typeInSet(0, {v16s32})(Query))189return true;190if (HasDQI && typeInSet(0, {v8s64})(Query))191return true;192if (HasDQI && HasVLX && typeInSet(0, {v2s64, v4s64})(Query))193return true;194if (HasBWI && typeInSet(0, {v32s16})(Query))195return true;196return false;197})198.clampMinNumElements(0, s16, 8)199.clampMinNumElements(0, s32, 4)200.clampMinNumElements(0, s64, HasVLX ? 2 : 8)201.clampMaxNumElements(0, s16, HasBWI ? 32 : (HasAVX2 ? 16 : 8))202.clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX2 ? 8 : 4))203.clampMaxNumElements(0, s64, 8)204.widenScalarToNextPow2(0, /*Min=*/32)205.clampScalar(0, s8, sMaxScalar)206.scalarize(0);207208getActionDefinitionsBuilder({G_SMULH, G_UMULH})209.legalIf([=](const LegalityQuery &Query) -> bool {210return typeInSet(0, {s8, s16, s32})(Query) ||211(Is64Bit && typeInSet(0, {s64})(Query));212})213.widenScalarToNextPow2(0, /*Min=*/32)214.clampScalar(0, s8, sMaxScalar)215.scalarize(0);216217// integer divisions218getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UDIV, G_UREM})219.legalIf([=](const LegalityQuery &Query) -> bool {220return typeInSet(0, {s8, s16, s32})(Query) ||221(Is64Bit && typeInSet(0, {s64})(Query));222})223.libcallFor({s64})224.clampScalar(0, s8, sMaxScalar);225226// integer shifts227getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})228.legalIf([=](const LegalityQuery &Query) -> bool {229return typePairInSet(0, 1, {{s8, s8}, {s16, s8}, {s32, s8}})(Query) ||230(Is64Bit && typePairInSet(0, 1, {{s64, s8}})(Query));231})232.clampScalar(0, s8, sMaxScalar)233.clampScalar(1, s8, s8);234235// integer logic236getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})237.legalIf([=](const LegalityQuery &Query) -> bool {238if (typeInSet(0, {s8, s16, s32})(Query))239return true;240if (Is64Bit && typeInSet(0, {s64})(Query))241return true;242if (HasSSE2 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query))243return true;244if (HasAVX && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query))245return true;246if (HasAVX512 && typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query))247return true;248return false;249})250.clampMinNumElements(0, s8, 16)251.clampMinNumElements(0, s16, 8)252.clampMinNumElements(0, s32, 4)253.clampMinNumElements(0, s64, 2)254.clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16))255.clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))256.clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))257.clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))258.widenScalarToNextPow2(0, /*Min=*/32)259.clampScalar(0, s8, sMaxScalar)260.scalarize(0);261262// integer comparison263const std::initializer_list<LLT> IntTypes32 = {s8, s16, s32, p0};264const std::initializer_list<LLT> IntTypes64 = {s8, s16, s32, s64, p0};265266getActionDefinitionsBuilder(G_ICMP)267.legalForCartesianProduct({s8}, Is64Bit ? IntTypes64 : IntTypes32)268.clampScalar(0, s8, s8)269.clampScalar(1, s8, sMaxScalar);270271// bswap272getActionDefinitionsBuilder(G_BSWAP)273.legalIf([=](const LegalityQuery &Query) {274return Query.Types[0] == s32 ||275(Subtarget.is64Bit() && Query.Types[0] == s64);276})277.widenScalarToNextPow2(0, /*Min=*/32)278.clampScalar(0, s32, sMaxScalar);279280// popcount281getActionDefinitionsBuilder(G_CTPOP)282.legalIf([=](const LegalityQuery &Query) -> bool {283return Subtarget.hasPOPCNT() &&284(typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) ||285(Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)));286})287.widenScalarToNextPow2(1, /*Min=*/16)288.clampScalar(1, s16, sMaxScalar)289.scalarSameSizeAs(0, 1);290291// count leading zeros (LZCNT)292getActionDefinitionsBuilder(G_CTLZ)293.legalIf([=](const LegalityQuery &Query) -> bool {294return Subtarget.hasLZCNT() &&295(typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) ||296(Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)));297})298.widenScalarToNextPow2(1, /*Min=*/16)299.clampScalar(1, s16, sMaxScalar)300.scalarSameSizeAs(0, 1);301302// count trailing zeros303getActionDefinitionsBuilder({G_CTTZ_ZERO_UNDEF, G_CTTZ})304.legalIf([=](const LegalityQuery &Query) -> bool {305return (Query.Opcode == G_CTTZ_ZERO_UNDEF || Subtarget.hasBMI()) &&306(typePairInSet(0, 1, {{s16, s16}, {s32, s32}})(Query) ||307(Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)));308})309.widenScalarToNextPow2(1, /*Min=*/16)310.clampScalar(1, s16, sMaxScalar)311.scalarSameSizeAs(0, 1);312313// control flow314getActionDefinitionsBuilder(G_PHI)315.legalIf([=](const LegalityQuery &Query) -> bool {316return typeInSet(0, {s8, s16, s32, p0})(Query) ||317(Is64Bit && typeInSet(0, {s64})(Query)) ||318(HasSSE1 && typeInSet(0, {v16s8, v8s16, v4s32, v2s64})(Query)) ||319(HasAVX && typeInSet(0, {v32s8, v16s16, v8s32, v4s64})(Query)) ||320(HasAVX512 &&321typeInSet(0, {v64s8, v32s16, v16s32, v8s64})(Query));322})323.clampMinNumElements(0, s8, 16)324.clampMinNumElements(0, s16, 8)325.clampMinNumElements(0, s32, 4)326.clampMinNumElements(0, s64, 2)327.clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16))328.clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))329.clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))330.clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))331.widenScalarToNextPow2(0, /*Min=*/32)332.clampScalar(0, s8, sMaxScalar)333.scalarize(0);334335getActionDefinitionsBuilder(G_BRCOND).legalFor({s1});336337// pointer handling338const std::initializer_list<LLT> PtrTypes32 = {s1, s8, s16, s32};339const std::initializer_list<LLT> PtrTypes64 = {s1, s8, s16, s32, s64};340341getActionDefinitionsBuilder(G_PTRTOINT)342.legalForCartesianProduct(Is64Bit ? PtrTypes64 : PtrTypes32, {p0})343.maxScalar(0, sMaxScalar)344.widenScalarToNextPow2(0, /*Min*/ 8);345346getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, sMaxScalar}});347348getActionDefinitionsBuilder(G_CONSTANT_POOL).legalFor({p0});349350getActionDefinitionsBuilder(G_PTR_ADD)351.legalIf([=](const LegalityQuery &Query) -> bool {352return typePairInSet(0, 1, {{p0, s32}})(Query) ||353(Is64Bit && typePairInSet(0, 1, {{p0, s64}})(Query));354})355.widenScalarToNextPow2(1, /*Min*/ 32)356.clampScalar(1, s32, sMaxScalar);357358getActionDefinitionsBuilder({G_FRAME_INDEX, G_GLOBAL_VALUE}).legalFor({p0});359360// load/store: add more corner cases361for (unsigned Op : {G_LOAD, G_STORE}) {362auto &Action = getActionDefinitionsBuilder(Op);363Action.legalForTypesWithMemDesc({{s8, p0, s1, 1},364{s8, p0, s8, 1},365{s16, p0, s8, 1},366{s16, p0, s16, 1},367{s32, p0, s8, 1},368{s32, p0, s16, 1},369{s32, p0, s32, 1},370{s80, p0, s80, 1},371{p0, p0, p0, 1},372{v4s8, p0, v4s8, 1}});373if (Is64Bit)374Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},375{s64, p0, s16, 1},376{s64, p0, s32, 1},377{s64, p0, s64, 1},378{v2s32, p0, v2s32, 1}});379if (HasSSE1)380Action.legalForTypesWithMemDesc({{v4s32, p0, v4s32, 1}});381if (HasSSE2)382Action.legalForTypesWithMemDesc({{v16s8, p0, v16s8, 1},383{v8s16, p0, v8s16, 1},384{v2s64, p0, v2s64, 1},385{v2p0, p0, v2p0, 1}});386if (HasAVX)387Action.legalForTypesWithMemDesc({{v32s8, p0, v32s8, 1},388{v16s16, p0, v16s16, 1},389{v8s32, p0, v8s32, 1},390{v4s64, p0, v4s64, 1},391{v4p0, p0, v4p0, 1}});392if (HasAVX512)393Action.legalForTypesWithMemDesc({{v64s8, p0, v64s8, 1},394{v32s16, p0, v32s16, 1},395{v16s32, p0, v16s32, 1},396{v8s64, p0, v8s64, 1}});397Action.widenScalarToNextPow2(0, /*Min=*/8)398.clampScalar(0, s8, sMaxScalar)399.scalarize(0);400}401402for (unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {403auto &Action = getActionDefinitionsBuilder(Op);404Action.legalForTypesWithMemDesc({{s16, p0, s8, 1},405{s32, p0, s8, 1},406{s32, p0, s16, 1}});407if (Is64Bit)408Action.legalForTypesWithMemDesc({{s64, p0, s8, 1},409{s64, p0, s16, 1},410{s64, p0, s32, 1}});411// TODO - SSE41/AVX2/AVX512F/AVX512BW vector extensions412}413414// sext, zext, and anyext415getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT})416.legalIf([=](const LegalityQuery &Query) {417return typeInSet(0, {s8, s16, s32})(Query) ||418(Query.Opcode == G_ANYEXT && Query.Types[0] == s128) ||419(Is64Bit && Query.Types[0] == s64);420})421.widenScalarToNextPow2(0, /*Min=*/8)422.clampScalar(0, s8, sMaxScalar)423.widenScalarToNextPow2(1, /*Min=*/8)424.clampScalar(1, s8, sMaxScalar)425.scalarize(0);426427getActionDefinitionsBuilder(G_SEXT_INREG).lower();428429// fp constants430getActionDefinitionsBuilder(G_FCONSTANT)431.legalIf([=](const LegalityQuery &Query) -> bool {432return (typeInSet(0, {s32, s64})(Query)) ||433(UseX87 && typeInSet(0, {s80})(Query));434});435436// fp arithmetic437getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})438.legalIf([=](const LegalityQuery &Query) {439return (typeInSet(0, {s32, s64})(Query)) ||440(HasSSE1 && typeInSet(0, {v4s32})(Query)) ||441(HasSSE2 && typeInSet(0, {v2s64})(Query)) ||442(HasAVX && typeInSet(0, {v8s32, v4s64})(Query)) ||443(HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query)) ||444(UseX87 && typeInSet(0, {s80})(Query));445});446447// fp comparison448getActionDefinitionsBuilder(G_FCMP)449.legalIf([=](const LegalityQuery &Query) {450return (HasSSE1 && typePairInSet(0, 1, {{s8, s32}})(Query)) ||451(HasSSE2 && typePairInSet(0, 1, {{s8, s64}})(Query));452})453.clampScalar(0, s8, s8)454.clampScalar(1, s32, HasSSE2 ? s64 : s32)455.widenScalarToNextPow2(1);456457// fp conversions458getActionDefinitionsBuilder(G_FPEXT).legalIf([=](const LegalityQuery &Query) {459return (HasSSE2 && typePairInSet(0, 1, {{s64, s32}})(Query)) ||460(HasAVX && typePairInSet(0, 1, {{v4s64, v4s32}})(Query)) ||461(HasAVX512 && typePairInSet(0, 1, {{v8s64, v8s32}})(Query));462});463464getActionDefinitionsBuilder(G_FPTRUNC).legalIf(465[=](const LegalityQuery &Query) {466return (HasSSE2 && typePairInSet(0, 1, {{s32, s64}})(Query)) ||467(HasAVX && typePairInSet(0, 1, {{v4s32, v4s64}})(Query)) ||468(HasAVX512 && typePairInSet(0, 1, {{v8s32, v8s64}})(Query));469});470471getActionDefinitionsBuilder(G_SITOFP)472.legalIf([=](const LegalityQuery &Query) {473return (HasSSE1 &&474(typePairInSet(0, 1, {{s32, s32}})(Query) ||475(Is64Bit && typePairInSet(0, 1, {{s32, s64}})(Query)))) ||476(HasSSE2 &&477(typePairInSet(0, 1, {{s64, s32}})(Query) ||478(Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));479})480.clampScalar(1, s32, sMaxScalar)481.widenScalarToNextPow2(1)482.clampScalar(0, s32, HasSSE2 ? s64 : s32)483.widenScalarToNextPow2(0);484485getActionDefinitionsBuilder(G_FPTOSI)486.legalIf([=](const LegalityQuery &Query) {487return (HasSSE1 &&488(typePairInSet(0, 1, {{s32, s32}})(Query) ||489(Is64Bit && typePairInSet(0, 1, {{s64, s32}})(Query)))) ||490(HasSSE2 &&491(typePairInSet(0, 1, {{s32, s64}})(Query) ||492(Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));493})494.clampScalar(1, s32, HasSSE2 ? s64 : s32)495.widenScalarToNextPow2(0)496.clampScalar(0, s32, sMaxScalar)497.widenScalarToNextPow2(1);498499// vector ops500getActionDefinitionsBuilder(G_BUILD_VECTOR)501.customIf([=](const LegalityQuery &Query) {502return (HasSSE1 && typeInSet(0, {v4s32})(Query)) ||503(HasSSE2 && typeInSet(0, {v2s64, v8s16, v16s8})(Query)) ||504(HasAVX && typeInSet(0, {v4s64, v8s32, v16s16, v32s8})(Query)) ||505(HasAVX512 && typeInSet(0, {v8s64, v16s32, v32s16, v64s8}));506})507.clampNumElements(0, v16s8, s8MaxVector)508.clampNumElements(0, v8s16, s16MaxVector)509.clampNumElements(0, v4s32, s32MaxVector)510.clampNumElements(0, v2s64, s64MaxVector)511.moreElementsToNextPow2(0);512513getActionDefinitionsBuilder({G_EXTRACT, G_INSERT})514.legalIf([=](const LegalityQuery &Query) {515unsigned SubIdx = Query.Opcode == G_EXTRACT ? 0 : 1;516unsigned FullIdx = Query.Opcode == G_EXTRACT ? 1 : 0;517return (HasAVX && typePairInSet(SubIdx, FullIdx,518{{v16s8, v32s8},519{v8s16, v16s16},520{v4s32, v8s32},521{v2s64, v4s64}})(Query)) ||522(HasAVX512 && typePairInSet(SubIdx, FullIdx,523{{v16s8, v64s8},524{v32s8, v64s8},525{v8s16, v32s16},526{v16s16, v32s16},527{v4s32, v16s32},528{v8s32, v16s32},529{v2s64, v8s64},530{v4s64, v8s64}})(Query));531});532533// todo: only permit dst types up to max legal vector register size?534getActionDefinitionsBuilder(G_CONCAT_VECTORS)535.legalIf([=](const LegalityQuery &Query) {536return (HasSSE1 && typePairInSet(1, 0,537{{v16s8, v32s8},538{v8s16, v16s16},539{v4s32, v8s32},540{v2s64, v4s64}})(Query)) ||541(HasAVX && typePairInSet(1, 0,542{{v16s8, v64s8},543{v32s8, v64s8},544{v8s16, v32s16},545{v16s16, v32s16},546{v4s32, v16s32},547{v8s32, v16s32},548{v2s64, v8s64},549{v4s64, v8s64}})(Query));550});551552// todo: vectors and address spaces553getActionDefinitionsBuilder(G_SELECT)554.legalFor({{s8, s32}, {s16, s32}, {s32, s32}, {s64, s32}, {p0, s32}})555.widenScalarToNextPow2(0, /*Min=*/8)556.clampScalar(0, HasCMOV ? s16 : s8, sMaxScalar)557.clampScalar(1, s32, s32);558559// memory intrinsics560getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();561562getActionDefinitionsBuilder({G_DYN_STACKALLOC,563G_STACKSAVE,564G_STACKRESTORE}).lower();565566// fp intrinsics567getActionDefinitionsBuilder(G_INTRINSIC_ROUNDEVEN)568.scalarize(0)569.minScalar(0, LLT::scalar(32))570.libcall();571572getActionDefinitionsBuilder({G_FREEZE, G_CONSTANT_FOLD_BARRIER})573.legalFor({s8, s16, s32, s64, p0})574.widenScalarToNextPow2(0, /*Min=*/8)575.clampScalar(0, s8, sMaxScalar);576577getLegacyLegalizerInfo().computeTables();578verify(*STI.getInstrInfo());579}580581bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,582LostDebugLocObserver &LocObserver) const {583MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;584MachineRegisterInfo &MRI = *MIRBuilder.getMRI();585switch (MI.getOpcode()) {586default:587// No idea what to do.588return false;589case TargetOpcode::G_BUILD_VECTOR:590return legalizeBuildVector(MI, MRI, Helper);591}592llvm_unreachable("expected switch to return");593}594595bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI,596MachineRegisterInfo &MRI,597LegalizerHelper &Helper) const {598MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;599const auto &BuildVector = cast<GBuildVector>(MI);600Register Dst = BuildVector.getReg(0);601LLT DstTy = MRI.getType(Dst);602MachineFunction &MF = MIRBuilder.getMF();603LLVMContext &Ctx = MF.getFunction().getContext();604uint64_t DstTySize = DstTy.getScalarSizeInBits();605606SmallVector<Constant *, 4> CstIdxs;607for (unsigned i = 0; i < BuildVector.getNumSources(); ++i) {608Register Source = BuildVector.getSourceReg(i);609610auto ValueAndReg = getIConstantVRegValWithLookThrough(Source, MRI);611if (ValueAndReg) {612CstIdxs.emplace_back(ConstantInt::get(Ctx, ValueAndReg->Value));613continue;614}615616auto FPValueAndReg = getFConstantVRegValWithLookThrough(Source, MRI);617if (FPValueAndReg) {618CstIdxs.emplace_back(ConstantFP::get(Ctx, FPValueAndReg->Value));619continue;620}621622if (getOpcodeDef<GImplicitDef>(Source, MRI)) {623CstIdxs.emplace_back(UndefValue::get(Type::getIntNTy(Ctx, DstTySize)));624continue;625}626return false;627}628629Constant *ConstVal = ConstantVector::get(CstIdxs);630631const DataLayout &DL = MIRBuilder.getDataLayout();632unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace();633Align Alignment(DL.getABITypeAlign(ConstVal->getType()));634auto Addr = MIRBuilder.buildConstantPool(635LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace)),636MF.getConstantPool()->getConstantPoolIndex(ConstVal, Alignment));637MachineMemOperand *MMO =638MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),639MachineMemOperand::MOLoad, DstTy, Alignment);640641MIRBuilder.buildLoad(Dst, Addr, *MMO);642MI.eraseFromParent();643return true;644}645646bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,647MachineInstr &MI) const {648return true;649}650651652