1317017Sdim//===- X86LegalizerInfo.cpp --------------------------------------*- C++ -*-==//
2317017Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6317017Sdim//
7317017Sdim//===----------------------------------------------------------------------===//
8317017Sdim/// \file
9317017Sdim/// This file implements the targeting of the Machinelegalizer class for X86.
10317017Sdim/// \todo This should be generated by TableGen.
11317017Sdim//===----------------------------------------------------------------------===//
12317017Sdim
13317017Sdim#include "X86LegalizerInfo.h"
14317017Sdim#include "X86Subtarget.h"
15317017Sdim#include "X86TargetMachine.h"
16360784Sdim#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
17327952Sdim#include "llvm/CodeGen/TargetOpcodes.h"
18317017Sdim#include "llvm/CodeGen/ValueTypes.h"
19317017Sdim#include "llvm/IR/DerivedTypes.h"
20317017Sdim#include "llvm/IR/Type.h"
21317017Sdim
22317017Sdimusing namespace llvm;
23317017Sdimusing namespace TargetOpcode;
24341825Sdimusing namespace LegalizeActions;
25317017Sdim
26327952Sdim/// FIXME: The following static functions are SizeChangeStrategy functions
27327952Sdim/// that are meant to temporarily mimic the behaviour of the old legalization
28327952Sdim/// based on doubling/halving non-legal types as closely as possible. This is
29327952Sdim/// not entirly possible as only legalizing the types that are exactly a power
30327952Sdim/// of 2 times the size of the legal types would require specifying all those
31327952Sdim/// sizes explicitly.
32327952Sdim/// In practice, not specifying those isn't a problem, and the below functions
33327952Sdim/// should disappear quickly as we add support for legalizing non-power-of-2
34327952Sdim/// sized types further.
35327952Sdimstatic void
36327952SdimaddAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result,
37327952Sdim                                const LegalizerInfo::SizeAndActionsVec &v) {
38327952Sdim  for (unsigned i = 0; i < v.size(); ++i) {
39327952Sdim    result.push_back(v[i]);
40327952Sdim    if (i + 1 < v[i].first && i + 1 < v.size() &&
41327952Sdim        v[i + 1].first != v[i].first + 1)
42341825Sdim      result.push_back({v[i].first + 1, Unsupported});
43327952Sdim  }
44327952Sdim}
45317017Sdim
46327952Sdimstatic LegalizerInfo::SizeAndActionsVec
47327952Sdimwiden_1(const LegalizerInfo::SizeAndActionsVec &v) {
48327952Sdim  assert(v.size() >= 1);
49327952Sdim  assert(v[0].first > 1);
50341825Sdim  LegalizerInfo::SizeAndActionsVec result = {{1, WidenScalar},
51341825Sdim                                             {2, Unsupported}};
52327952Sdim  addAndInterleaveWithUnsupported(result, v);
53327952Sdim  auto Largest = result.back().first;
54341825Sdim  result.push_back({Largest + 1, Unsupported});
55327952Sdim  return result;
56327952Sdim}
57327952Sdim
58317017SdimX86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
59317017Sdim                                   const X86TargetMachine &TM)
60317017Sdim    : Subtarget(STI), TM(TM) {
61317017Sdim
62317017Sdim  setLegalizerInfo32bit();
63317017Sdim  setLegalizerInfo64bit();
64317017Sdim  setLegalizerInfoSSE1();
65317017Sdim  setLegalizerInfoSSE2();
66317969Sdim  setLegalizerInfoSSE41();
67319164Sdim  setLegalizerInfoAVX();
68317969Sdim  setLegalizerInfoAVX2();
69317969Sdim  setLegalizerInfoAVX512();
70317969Sdim  setLegalizerInfoAVX512DQ();
71317969Sdim  setLegalizerInfoAVX512BW();
72317017Sdim
73327952Sdim  setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1);
74327952Sdim  for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR})
75327952Sdim    setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1);
76327952Sdim  for (unsigned MemOp : {G_LOAD, G_STORE})
77327952Sdim    setLegalizeScalarToDifferentSizeStrategy(MemOp, 0,
78327952Sdim       narrowToSmallerAndWidenToSmallest);
79327952Sdim  setLegalizeScalarToDifferentSizeStrategy(
80360784Sdim      G_PTR_ADD, 1, widenToLargerTypesUnsupportedOtherwise);
81327952Sdim  setLegalizeScalarToDifferentSizeStrategy(
82327952Sdim      G_CONSTANT, 0, widenToLargerTypesAndNarrowToLargest);
83327952Sdim
84317017Sdim  computeTables();
85341825Sdim  verify(*STI.getInstrInfo());
86317017Sdim}
87317017Sdim
88360784Sdimbool X86LegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
89360784Sdim                                         MachineRegisterInfo &MRI,
90360784Sdim                                         MachineIRBuilder &MIRBuilder) const {
91360784Sdim  switch (MI.getIntrinsicID()) {
92360784Sdim  case Intrinsic::memcpy:
93360784Sdim  case Intrinsic::memset:
94360784Sdim  case Intrinsic::memmove:
95360784Sdim    if (createMemLibcall(MIRBuilder, MRI, MI) ==
96360784Sdim        LegalizerHelper::UnableToLegalize)
97360784Sdim      return false;
98360784Sdim    MI.eraseFromParent();
99360784Sdim    return true;
100360784Sdim  default:
101360784Sdim    break;
102360784Sdim  }
103360784Sdim  return true;
104360784Sdim}
105360784Sdim
106317017Sdimvoid X86LegalizerInfo::setLegalizerInfo32bit() {
107317017Sdim
108341825Sdim  const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
109317017Sdim  const LLT s1 = LLT::scalar(1);
110317017Sdim  const LLT s8 = LLT::scalar(8);
111317017Sdim  const LLT s16 = LLT::scalar(16);
112317017Sdim  const LLT s32 = LLT::scalar(32);
113317017Sdim  const LLT s64 = LLT::scalar(64);
114341825Sdim  const LLT s128 = LLT::scalar(128);
115317017Sdim
116327952Sdim  for (auto Ty : {p0, s1, s8, s16, s32})
117327952Sdim    setAction({G_IMPLICIT_DEF, Ty}, Legal);
118327952Sdim
119327952Sdim  for (auto Ty : {s8, s16, s32, p0})
120327952Sdim    setAction({G_PHI, Ty}, Legal);
121327952Sdim
122320572Sdim  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
123317017Sdim    for (auto Ty : {s8, s16, s32})
124317017Sdim      setAction({BinOp, Ty}, Legal);
125317017Sdim
126318477Sdim  for (unsigned Op : {G_UADDE}) {
127318477Sdim    setAction({Op, s32}, Legal);
128318477Sdim    setAction({Op, 1, s1}, Legal);
129318477Sdim  }
130318477Sdim
131317017Sdim  for (unsigned MemOp : {G_LOAD, G_STORE}) {
132317017Sdim    for (auto Ty : {s8, s16, s32, p0})
133317017Sdim      setAction({MemOp, Ty}, Legal);
134317017Sdim
135317017Sdim    // And everything's fine in addrspace 0.
136317017Sdim    setAction({MemOp, 1, p0}, Legal);
137317017Sdim  }
138317017Sdim
139317017Sdim  // Pointer-handling
140317017Sdim  setAction({G_FRAME_INDEX, p0}, Legal);
141320970Sdim  setAction({G_GLOBAL_VALUE, p0}, Legal);
142317017Sdim
143360784Sdim  setAction({G_PTR_ADD, p0}, Legal);
144360784Sdim  setAction({G_PTR_ADD, 1, s32}, Legal);
145317969Sdim
146341825Sdim  if (!Subtarget.is64Bit()) {
147341825Sdim    getActionDefinitionsBuilder(G_PTRTOINT)
148341825Sdim        .legalForCartesianProduct({s1, s8, s16, s32}, {p0})
149341825Sdim        .maxScalar(0, s32)
150341825Sdim        .widenScalarToNextPow2(0, /*Min*/ 8);
151341825Sdim    getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}});
152341825Sdim
153341825Sdim    // Shifts and SDIV
154344779Sdim    getActionDefinitionsBuilder(
155353358Sdim        {G_SDIV, G_SREM, G_UDIV, G_UREM})
156353358Sdim      .legalFor({s8, s16, s32})
157353358Sdim      .clampScalar(0, s8, s32);
158353358Sdim
159353358Sdim    getActionDefinitionsBuilder(
160353358Sdim        {G_SHL, G_LSHR, G_ASHR})
161353358Sdim      .legalFor({{s8, s8}, {s16, s8}, {s32, s8}})
162353358Sdim      .clampScalar(0, s8, s32)
163353358Sdim      .clampScalar(1, s8, s8);
164341825Sdim  }
165341825Sdim
166327952Sdim  // Control-flow
167327952Sdim  setAction({G_BRCOND, s1}, Legal);
168317969Sdim
169317017Sdim  // Constants
170317017Sdim  for (auto Ty : {s8, s16, s32, p0})
171317017Sdim    setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
172317017Sdim
173317778Sdim  // Extensions
174320970Sdim  for (auto Ty : {s8, s16, s32}) {
175320970Sdim    setAction({G_ZEXT, Ty}, Legal);
176320970Sdim    setAction({G_SEXT, Ty}, Legal);
177327952Sdim    setAction({G_ANYEXT, Ty}, Legal);
178320970Sdim  }
179341825Sdim  setAction({G_ANYEXT, s128}, Legal);
180360784Sdim  getActionDefinitionsBuilder(G_SEXT_INREG).lower();
181317778Sdim
182318384Sdim  // Comparison
183318384Sdim  setAction({G_ICMP, s1}, Legal);
184318384Sdim
185318384Sdim  for (auto Ty : {s8, s16, s32, p0})
186318384Sdim    setAction({G_ICMP, 1, Ty}, Legal);
187327952Sdim
188327952Sdim  // Merge/Unmerge
189327952Sdim  for (const auto &Ty : {s16, s32, s64}) {
190327952Sdim    setAction({G_MERGE_VALUES, Ty}, Legal);
191327952Sdim    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
192327952Sdim  }
193327952Sdim  for (const auto &Ty : {s8, s16, s32}) {
194327952Sdim    setAction({G_MERGE_VALUES, 1, Ty}, Legal);
195327952Sdim    setAction({G_UNMERGE_VALUES, Ty}, Legal);
196327952Sdim  }
197317017Sdim}
198317017Sdim
199317017Sdimvoid X86LegalizerInfo::setLegalizerInfo64bit() {
200317017Sdim
201317017Sdim  if (!Subtarget.is64Bit())
202317017Sdim    return;
203317017Sdim
204341825Sdim  const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
205341825Sdim  const LLT s1 = LLT::scalar(1);
206341825Sdim  const LLT s8 = LLT::scalar(8);
207341825Sdim  const LLT s16 = LLT::scalar(16);
208341825Sdim  const LLT s32 = LLT::scalar(32);
209317017Sdim  const LLT s64 = LLT::scalar(64);
210327952Sdim  const LLT s128 = LLT::scalar(128);
211317017Sdim
212327952Sdim  setAction({G_IMPLICIT_DEF, s64}, Legal);
213341825Sdim  // Need to have that, as tryFoldImplicitDef will create this pattern:
214341825Sdim  // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF
215341825Sdim  setAction({G_IMPLICIT_DEF, s128}, Legal);
216327952Sdim
217327952Sdim  setAction({G_PHI, s64}, Legal);
218327952Sdim
219320572Sdim  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
220327952Sdim    setAction({BinOp, s64}, Legal);
221317017Sdim
222327952Sdim  for (unsigned MemOp : {G_LOAD, G_STORE})
223327952Sdim    setAction({MemOp, s64}, Legal);
224317017Sdim
225317017Sdim  // Pointer-handling
226360784Sdim  setAction({G_PTR_ADD, 1, s64}, Legal);
227341825Sdim  getActionDefinitionsBuilder(G_PTRTOINT)
228341825Sdim      .legalForCartesianProduct({s1, s8, s16, s32, s64}, {p0})
229341825Sdim      .maxScalar(0, s64)
230341825Sdim      .widenScalarToNextPow2(0, /*Min*/ 8);
231341825Sdim  getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s64}});
232317969Sdim
233317017Sdim  // Constants
234327952Sdim  setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
235317017Sdim
236317778Sdim  // Extensions
237327952Sdim  for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
238327952Sdim    setAction({extOp, s64}, Legal);
239317778Sdim  }
240317778Sdim
241341825Sdim  getActionDefinitionsBuilder(G_SITOFP)
242341825Sdim    .legalForCartesianProduct({s32, s64})
243341825Sdim      .clampScalar(1, s32, s64)
244341825Sdim      .widenScalarToNextPow2(1)
245341825Sdim      .clampScalar(0, s32, s64)
246341825Sdim      .widenScalarToNextPow2(0);
247341825Sdim
248344779Sdim  getActionDefinitionsBuilder(G_FPTOSI)
249344779Sdim      .legalForCartesianProduct({s32, s64})
250344779Sdim      .clampScalar(1, s32, s64)
251344779Sdim      .widenScalarToNextPow2(0)
252344779Sdim      .clampScalar(0, s32, s64)
253344779Sdim      .widenScalarToNextPow2(1);
254344779Sdim
255318384Sdim  // Comparison
256327952Sdim  setAction({G_ICMP, 1, s64}, Legal);
257318384Sdim
258344779Sdim  getActionDefinitionsBuilder(G_FCMP)
259344779Sdim      .legalForCartesianProduct({s8}, {s32, s64})
260344779Sdim      .clampScalar(0, s8, s8)
261344779Sdim      .clampScalar(1, s32, s64)
262344779Sdim      .widenScalarToNextPow2(1);
263344779Sdim
264353358Sdim  // Divisions
265344779Sdim  getActionDefinitionsBuilder(
266353358Sdim      {G_SDIV, G_SREM, G_UDIV, G_UREM})
267344779Sdim      .legalFor({s8, s16, s32, s64})
268344779Sdim      .clampScalar(0, s8, s64);
269341825Sdim
270353358Sdim  // Shifts
271353358Sdim  getActionDefinitionsBuilder(
272353358Sdim    {G_SHL, G_LSHR, G_ASHR})
273353358Sdim    .legalFor({{s8, s8}, {s16, s8}, {s32, s8}, {s64, s8}})
274353358Sdim    .clampScalar(0, s8, s64)
275353358Sdim    .clampScalar(1, s8, s8);
276353358Sdim
277327952Sdim  // Merge/Unmerge
278327952Sdim  setAction({G_MERGE_VALUES, s128}, Legal);
279327952Sdim  setAction({G_UNMERGE_VALUES, 1, s128}, Legal);
280327952Sdim  setAction({G_MERGE_VALUES, 1, s128}, Legal);
281327952Sdim  setAction({G_UNMERGE_VALUES, s128}, Legal);
282317017Sdim}
283317017Sdim
284317017Sdimvoid X86LegalizerInfo::setLegalizerInfoSSE1() {
285317017Sdim  if (!Subtarget.hasSSE1())
286317017Sdim    return;
287317017Sdim
288317017Sdim  const LLT s32 = LLT::scalar(32);
289327952Sdim  const LLT s64 = LLT::scalar(64);
290317017Sdim  const LLT v4s32 = LLT::vector(4, 32);
291317017Sdim  const LLT v2s64 = LLT::vector(2, 64);
292317017Sdim
293317017Sdim  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
294317017Sdim    for (auto Ty : {s32, v4s32})
295317017Sdim      setAction({BinOp, Ty}, Legal);
296317017Sdim
297317017Sdim  for (unsigned MemOp : {G_LOAD, G_STORE})
298317017Sdim    for (auto Ty : {v4s32, v2s64})
299317017Sdim      setAction({MemOp, Ty}, Legal);
300327952Sdim
301327952Sdim  // Constants
302327952Sdim  setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
303327952Sdim
304327952Sdim  // Merge/Unmerge
305327952Sdim  for (const auto &Ty : {v4s32, v2s64}) {
306344779Sdim    setAction({G_CONCAT_VECTORS, Ty}, Legal);
307327952Sdim    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
308327952Sdim  }
309327952Sdim  setAction({G_MERGE_VALUES, 1, s64}, Legal);
310327952Sdim  setAction({G_UNMERGE_VALUES, s64}, Legal);
311317017Sdim}
312317017Sdim
313317017Sdimvoid X86LegalizerInfo::setLegalizerInfoSSE2() {
314317017Sdim  if (!Subtarget.hasSSE2())
315317017Sdim    return;
316317017Sdim
317327952Sdim  const LLT s32 = LLT::scalar(32);
318317017Sdim  const LLT s64 = LLT::scalar(64);
319318681Sdim  const LLT v16s8 = LLT::vector(16, 8);
320317969Sdim  const LLT v8s16 = LLT::vector(8, 16);
321317017Sdim  const LLT v4s32 = LLT::vector(4, 32);
322317017Sdim  const LLT v2s64 = LLT::vector(2, 64);
323317017Sdim
324327952Sdim  const LLT v32s8 = LLT::vector(32, 8);
325327952Sdim  const LLT v16s16 = LLT::vector(16, 16);
326327952Sdim  const LLT v8s32 = LLT::vector(8, 32);
327327952Sdim  const LLT v4s64 = LLT::vector(4, 64);
328327952Sdim
329317017Sdim  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
330317017Sdim    for (auto Ty : {s64, v2s64})
331317017Sdim      setAction({BinOp, Ty}, Legal);
332317017Sdim
333317017Sdim  for (unsigned BinOp : {G_ADD, G_SUB})
334318681Sdim    for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
335317017Sdim      setAction({BinOp, Ty}, Legal);
336317969Sdim
337317969Sdim  setAction({G_MUL, v8s16}, Legal);
338327952Sdim
339327952Sdim  setAction({G_FPEXT, s64}, Legal);
340327952Sdim  setAction({G_FPEXT, 1, s32}, Legal);
341327952Sdim
342344779Sdim  setAction({G_FPTRUNC, s32}, Legal);
343344779Sdim  setAction({G_FPTRUNC, 1, s64}, Legal);
344344779Sdim
345327952Sdim  // Constants
346327952Sdim  setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
347327952Sdim
348327952Sdim  // Merge/Unmerge
349327952Sdim  for (const auto &Ty :
350327952Sdim       {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
351344779Sdim    setAction({G_CONCAT_VECTORS, Ty}, Legal);
352327952Sdim    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
353327952Sdim  }
354327952Sdim  for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) {
355344779Sdim    setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
356327952Sdim    setAction({G_UNMERGE_VALUES, Ty}, Legal);
357327952Sdim  }
358317017Sdim}
359317969Sdim
360317969Sdimvoid X86LegalizerInfo::setLegalizerInfoSSE41() {
361317969Sdim  if (!Subtarget.hasSSE41())
362317969Sdim    return;
363317969Sdim
364317969Sdim  const LLT v4s32 = LLT::vector(4, 32);
365317969Sdim
366317969Sdim  setAction({G_MUL, v4s32}, Legal);
367317969Sdim}
368317969Sdim
369319164Sdimvoid X86LegalizerInfo::setLegalizerInfoAVX() {
370319164Sdim  if (!Subtarget.hasAVX())
371319164Sdim    return;
372319164Sdim
373320397Sdim  const LLT v16s8 = LLT::vector(16, 8);
374320397Sdim  const LLT v8s16 = LLT::vector(8, 16);
375320397Sdim  const LLT v4s32 = LLT::vector(4, 32);
376320397Sdim  const LLT v2s64 = LLT::vector(2, 64);
377320397Sdim
378320397Sdim  const LLT v32s8 = LLT::vector(32, 8);
379327952Sdim  const LLT v64s8 = LLT::vector(64, 8);
380320397Sdim  const LLT v16s16 = LLT::vector(16, 16);
381327952Sdim  const LLT v32s16 = LLT::vector(32, 16);
382319164Sdim  const LLT v8s32 = LLT::vector(8, 32);
383327952Sdim  const LLT v16s32 = LLT::vector(16, 32);
384319164Sdim  const LLT v4s64 = LLT::vector(4, 64);
385327952Sdim  const LLT v8s64 = LLT::vector(8, 64);
386319164Sdim
387319164Sdim  for (unsigned MemOp : {G_LOAD, G_STORE})
388319164Sdim    for (auto Ty : {v8s32, v4s64})
389319164Sdim      setAction({MemOp, Ty}, Legal);
390320397Sdim
391320572Sdim  for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
392320397Sdim    setAction({G_INSERT, Ty}, Legal);
393320572Sdim    setAction({G_EXTRACT, 1, Ty}, Legal);
394320572Sdim  }
395320572Sdim  for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
396320397Sdim    setAction({G_INSERT, 1, Ty}, Legal);
397320572Sdim    setAction({G_EXTRACT, Ty}, Legal);
398320572Sdim  }
399327952Sdim  // Merge/Unmerge
400327952Sdim  for (const auto &Ty :
401327952Sdim       {v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) {
402344779Sdim    setAction({G_CONCAT_VECTORS, Ty}, Legal);
403327952Sdim    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
404327952Sdim  }
405327952Sdim  for (const auto &Ty :
406327952Sdim       {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
407344779Sdim    setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
408327952Sdim    setAction({G_UNMERGE_VALUES, Ty}, Legal);
409327952Sdim  }
410319164Sdim}
411319164Sdim
412317969Sdimvoid X86LegalizerInfo::setLegalizerInfoAVX2() {
413317969Sdim  if (!Subtarget.hasAVX2())
414317969Sdim    return;
415317969Sdim
416318681Sdim  const LLT v32s8 = LLT::vector(32, 8);
417317969Sdim  const LLT v16s16 = LLT::vector(16, 16);
418317969Sdim  const LLT v8s32 = LLT::vector(8, 32);
419318681Sdim  const LLT v4s64 = LLT::vector(4, 64);
420317969Sdim
421327952Sdim  const LLT v64s8 = LLT::vector(64, 8);
422327952Sdim  const LLT v32s16 = LLT::vector(32, 16);
423327952Sdim  const LLT v16s32 = LLT::vector(16, 32);
424327952Sdim  const LLT v8s64 = LLT::vector(8, 64);
425327952Sdim
426318681Sdim  for (unsigned BinOp : {G_ADD, G_SUB})
427318681Sdim    for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
428318681Sdim      setAction({BinOp, Ty}, Legal);
429318681Sdim
430317969Sdim  for (auto Ty : {v16s16, v8s32})
431317969Sdim    setAction({G_MUL, Ty}, Legal);
432327952Sdim
433327952Sdim  // Merge/Unmerge
434327952Sdim  for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) {
435344779Sdim    setAction({G_CONCAT_VECTORS, Ty}, Legal);
436327952Sdim    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
437327952Sdim  }
438327952Sdim  for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) {
439344779Sdim    setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
440327952Sdim    setAction({G_UNMERGE_VALUES, Ty}, Legal);
441327952Sdim  }
442317969Sdim}
443317969Sdim
444317969Sdimvoid X86LegalizerInfo::setLegalizerInfoAVX512() {
445317969Sdim  if (!Subtarget.hasAVX512())
446317969Sdim    return;
447317969Sdim
448320397Sdim  const LLT v16s8 = LLT::vector(16, 8);
449320397Sdim  const LLT v8s16 = LLT::vector(8, 16);
450320397Sdim  const LLT v4s32 = LLT::vector(4, 32);
451320397Sdim  const LLT v2s64 = LLT::vector(2, 64);
452320397Sdim
453320397Sdim  const LLT v32s8 = LLT::vector(32, 8);
454320397Sdim  const LLT v16s16 = LLT::vector(16, 16);
455320397Sdim  const LLT v8s32 = LLT::vector(8, 32);
456320397Sdim  const LLT v4s64 = LLT::vector(4, 64);
457320397Sdim
458320397Sdim  const LLT v64s8 = LLT::vector(64, 8);
459320397Sdim  const LLT v32s16 = LLT::vector(32, 16);
460317969Sdim  const LLT v16s32 = LLT::vector(16, 32);
461318681Sdim  const LLT v8s64 = LLT::vector(8, 64);
462317969Sdim
463318681Sdim  for (unsigned BinOp : {G_ADD, G_SUB})
464318681Sdim    for (auto Ty : {v16s32, v8s64})
465318681Sdim      setAction({BinOp, Ty}, Legal);
466318681Sdim
467317969Sdim  setAction({G_MUL, v16s32}, Legal);
468317969Sdim
469319164Sdim  for (unsigned MemOp : {G_LOAD, G_STORE})
470319164Sdim    for (auto Ty : {v16s32, v8s64})
471319164Sdim      setAction({MemOp, Ty}, Legal);
472319164Sdim
473320572Sdim  for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
474320397Sdim    setAction({G_INSERT, Ty}, Legal);
475320572Sdim    setAction({G_EXTRACT, 1, Ty}, Legal);
476320572Sdim  }
477320572Sdim  for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
478320397Sdim    setAction({G_INSERT, 1, Ty}, Legal);
479320572Sdim    setAction({G_EXTRACT, Ty}, Legal);
480320572Sdim  }
481320397Sdim
482317969Sdim  /************ VLX *******************/
483317969Sdim  if (!Subtarget.hasVLX())
484317969Sdim    return;
485317969Sdim
486317969Sdim  for (auto Ty : {v4s32, v8s32})
487317969Sdim    setAction({G_MUL, Ty}, Legal);
488317969Sdim}
489317969Sdim
490317969Sdimvoid X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
491317969Sdim  if (!(Subtarget.hasAVX512() && Subtarget.hasDQI()))
492317969Sdim    return;
493317969Sdim
494317969Sdim  const LLT v8s64 = LLT::vector(8, 64);
495317969Sdim
496317969Sdim  setAction({G_MUL, v8s64}, Legal);
497317969Sdim
498317969Sdim  /************ VLX *******************/
499317969Sdim  if (!Subtarget.hasVLX())
500317969Sdim    return;
501317969Sdim
502317969Sdim  const LLT v2s64 = LLT::vector(2, 64);
503317969Sdim  const LLT v4s64 = LLT::vector(4, 64);
504317969Sdim
505317969Sdim  for (auto Ty : {v2s64, v4s64})
506317969Sdim    setAction({G_MUL, Ty}, Legal);
507317969Sdim}
508317969Sdim
509317969Sdimvoid X86LegalizerInfo::setLegalizerInfoAVX512BW() {
510317969Sdim  if (!(Subtarget.hasAVX512() && Subtarget.hasBWI()))
511317969Sdim    return;
512317969Sdim
513318681Sdim  const LLT v64s8 = LLT::vector(64, 8);
514317969Sdim  const LLT v32s16 = LLT::vector(32, 16);
515317969Sdim
516318681Sdim  for (unsigned BinOp : {G_ADD, G_SUB})
517318681Sdim    for (auto Ty : {v64s8, v32s16})
518318681Sdim      setAction({BinOp, Ty}, Legal);
519318681Sdim
520317969Sdim  setAction({G_MUL, v32s16}, Legal);
521317969Sdim
522317969Sdim  /************ VLX *******************/
523317969Sdim  if (!Subtarget.hasVLX())
524317969Sdim    return;
525317969Sdim
526317969Sdim  const LLT v8s16 = LLT::vector(8, 16);
527317969Sdim  const LLT v16s16 = LLT::vector(16, 16);
528317969Sdim
529317969Sdim  for (auto Ty : {v8s16, v16s16})
530317969Sdim    setAction({G_MUL, Ty}, Legal);
531317969Sdim}
532