X86LegalizerInfo.cpp revision 355940
1//===- X86LegalizerInfo.cpp --------------------------------------*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements the targeting of the Machinelegalizer class for X86.
10/// \todo This should be generated by TableGen.
11//===----------------------------------------------------------------------===//
12
13#include "X86LegalizerInfo.h"
14#include "X86Subtarget.h"
15#include "X86TargetMachine.h"
16#include "llvm/CodeGen/TargetOpcodes.h"
17#include "llvm/CodeGen/ValueTypes.h"
18#include "llvm/IR/DerivedTypes.h"
19#include "llvm/IR/Type.h"
20
21using namespace llvm;
22using namespace TargetOpcode;
23using namespace LegalizeActions;
24
25/// FIXME: The following static functions are SizeChangeStrategy functions
26/// that are meant to temporarily mimic the behaviour of the old legalization
27/// based on doubling/halving non-legal types as closely as possible. This is
28/// not entirly possible as only legalizing the types that are exactly a power
29/// of 2 times the size of the legal types would require specifying all those
30/// sizes explicitly.
31/// In practice, not specifying those isn't a problem, and the below functions
32/// should disappear quickly as we add support for legalizing non-power-of-2
33/// sized types further.
34static void
35addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result,
36                                const LegalizerInfo::SizeAndActionsVec &v) {
37  for (unsigned i = 0; i < v.size(); ++i) {
38    result.push_back(v[i]);
39    if (i + 1 < v[i].first && i + 1 < v.size() &&
40        v[i + 1].first != v[i].first + 1)
41      result.push_back({v[i].first + 1, Unsupported});
42  }
43}
44
45static LegalizerInfo::SizeAndActionsVec
46widen_1(const LegalizerInfo::SizeAndActionsVec &v) {
47  assert(v.size() >= 1);
48  assert(v[0].first > 1);
49  LegalizerInfo::SizeAndActionsVec result = {{1, WidenScalar},
50                                             {2, Unsupported}};
51  addAndInterleaveWithUnsupported(result, v);
52  auto Largest = result.back().first;
53  result.push_back({Largest + 1, Unsupported});
54  return result;
55}
56
57X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
58                                   const X86TargetMachine &TM)
59    : Subtarget(STI), TM(TM) {
60
61  setLegalizerInfo32bit();
62  setLegalizerInfo64bit();
63  setLegalizerInfoSSE1();
64  setLegalizerInfoSSE2();
65  setLegalizerInfoSSE41();
66  setLegalizerInfoAVX();
67  setLegalizerInfoAVX2();
68  setLegalizerInfoAVX512();
69  setLegalizerInfoAVX512DQ();
70  setLegalizerInfoAVX512BW();
71
72  setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1);
73  for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR})
74    setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1);
75  for (unsigned MemOp : {G_LOAD, G_STORE})
76    setLegalizeScalarToDifferentSizeStrategy(MemOp, 0,
77       narrowToSmallerAndWidenToSmallest);
78  setLegalizeScalarToDifferentSizeStrategy(
79      G_GEP, 1, widenToLargerTypesUnsupportedOtherwise);
80  setLegalizeScalarToDifferentSizeStrategy(
81      G_CONSTANT, 0, widenToLargerTypesAndNarrowToLargest);
82
83  computeTables();
84  verify(*STI.getInstrInfo());
85}
86
87void X86LegalizerInfo::setLegalizerInfo32bit() {
88
89  const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
90  const LLT s1 = LLT::scalar(1);
91  const LLT s8 = LLT::scalar(8);
92  const LLT s16 = LLT::scalar(16);
93  const LLT s32 = LLT::scalar(32);
94  const LLT s64 = LLT::scalar(64);
95  const LLT s128 = LLT::scalar(128);
96
97  for (auto Ty : {p0, s1, s8, s16, s32})
98    setAction({G_IMPLICIT_DEF, Ty}, Legal);
99
100  for (auto Ty : {s8, s16, s32, p0})
101    setAction({G_PHI, Ty}, Legal);
102
103  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
104    for (auto Ty : {s8, s16, s32})
105      setAction({BinOp, Ty}, Legal);
106
107  for (unsigned Op : {G_UADDE}) {
108    setAction({Op, s32}, Legal);
109    setAction({Op, 1, s1}, Legal);
110  }
111
112  for (unsigned MemOp : {G_LOAD, G_STORE}) {
113    for (auto Ty : {s8, s16, s32, p0})
114      setAction({MemOp, Ty}, Legal);
115
116    // And everything's fine in addrspace 0.
117    setAction({MemOp, 1, p0}, Legal);
118  }
119
120  // Pointer-handling
121  setAction({G_FRAME_INDEX, p0}, Legal);
122  setAction({G_GLOBAL_VALUE, p0}, Legal);
123
124  setAction({G_GEP, p0}, Legal);
125  setAction({G_GEP, 1, s32}, Legal);
126
127  if (!Subtarget.is64Bit()) {
128    getActionDefinitionsBuilder(G_PTRTOINT)
129        .legalForCartesianProduct({s1, s8, s16, s32}, {p0})
130        .maxScalar(0, s32)
131        .widenScalarToNextPow2(0, /*Min*/ 8);
132    getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}});
133
134    // Shifts and SDIV
135    getActionDefinitionsBuilder(
136        {G_SDIV, G_SREM, G_UDIV, G_UREM})
137      .legalFor({s8, s16, s32})
138      .clampScalar(0, s8, s32);
139
140    getActionDefinitionsBuilder(
141        {G_SHL, G_LSHR, G_ASHR})
142      .legalFor({{s8, s8}, {s16, s8}, {s32, s8}})
143      .clampScalar(0, s8, s32)
144      .clampScalar(1, s8, s8);
145  }
146
147  // Control-flow
148  setAction({G_BRCOND, s1}, Legal);
149
150  // Constants
151  for (auto Ty : {s8, s16, s32, p0})
152    setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
153
154  // Extensions
155  for (auto Ty : {s8, s16, s32}) {
156    setAction({G_ZEXT, Ty}, Legal);
157    setAction({G_SEXT, Ty}, Legal);
158    setAction({G_ANYEXT, Ty}, Legal);
159  }
160  setAction({G_ANYEXT, s128}, Legal);
161
162  // Comparison
163  setAction({G_ICMP, s1}, Legal);
164
165  for (auto Ty : {s8, s16, s32, p0})
166    setAction({G_ICMP, 1, Ty}, Legal);
167
168  // Merge/Unmerge
169  for (const auto &Ty : {s16, s32, s64}) {
170    setAction({G_MERGE_VALUES, Ty}, Legal);
171    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
172  }
173  for (const auto &Ty : {s8, s16, s32}) {
174    setAction({G_MERGE_VALUES, 1, Ty}, Legal);
175    setAction({G_UNMERGE_VALUES, Ty}, Legal);
176  }
177}
178
179void X86LegalizerInfo::setLegalizerInfo64bit() {
180
181  if (!Subtarget.is64Bit())
182    return;
183
184  const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
185  const LLT s1 = LLT::scalar(1);
186  const LLT s8 = LLT::scalar(8);
187  const LLT s16 = LLT::scalar(16);
188  const LLT s32 = LLT::scalar(32);
189  const LLT s64 = LLT::scalar(64);
190  const LLT s128 = LLT::scalar(128);
191
192  setAction({G_IMPLICIT_DEF, s64}, Legal);
193  // Need to have that, as tryFoldImplicitDef will create this pattern:
194  // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF
195  setAction({G_IMPLICIT_DEF, s128}, Legal);
196
197  setAction({G_PHI, s64}, Legal);
198
199  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
200    setAction({BinOp, s64}, Legal);
201
202  for (unsigned MemOp : {G_LOAD, G_STORE})
203    setAction({MemOp, s64}, Legal);
204
205  // Pointer-handling
206  setAction({G_GEP, 1, s64}, Legal);
207  getActionDefinitionsBuilder(G_PTRTOINT)
208      .legalForCartesianProduct({s1, s8, s16, s32, s64}, {p0})
209      .maxScalar(0, s64)
210      .widenScalarToNextPow2(0, /*Min*/ 8);
211  getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s64}});
212
213  // Constants
214  setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
215
216  // Extensions
217  for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
218    setAction({extOp, s64}, Legal);
219  }
220
221  getActionDefinitionsBuilder(G_SITOFP)
222    .legalForCartesianProduct({s32, s64})
223      .clampScalar(1, s32, s64)
224      .widenScalarToNextPow2(1)
225      .clampScalar(0, s32, s64)
226      .widenScalarToNextPow2(0);
227
228  getActionDefinitionsBuilder(G_FPTOSI)
229      .legalForCartesianProduct({s32, s64})
230      .clampScalar(1, s32, s64)
231      .widenScalarToNextPow2(0)
232      .clampScalar(0, s32, s64)
233      .widenScalarToNextPow2(1);
234
235  // Comparison
236  setAction({G_ICMP, 1, s64}, Legal);
237
238  getActionDefinitionsBuilder(G_FCMP)
239      .legalForCartesianProduct({s8}, {s32, s64})
240      .clampScalar(0, s8, s8)
241      .clampScalar(1, s32, s64)
242      .widenScalarToNextPow2(1);
243
244  // Divisions
245  getActionDefinitionsBuilder(
246      {G_SDIV, G_SREM, G_UDIV, G_UREM})
247      .legalFor({s8, s16, s32, s64})
248      .clampScalar(0, s8, s64);
249
250  // Shifts
251  getActionDefinitionsBuilder(
252    {G_SHL, G_LSHR, G_ASHR})
253    .legalFor({{s8, s8}, {s16, s8}, {s32, s8}, {s64, s8}})
254    .clampScalar(0, s8, s64)
255    .clampScalar(1, s8, s8);
256
257  // Merge/Unmerge
258  setAction({G_MERGE_VALUES, s128}, Legal);
259  setAction({G_UNMERGE_VALUES, 1, s128}, Legal);
260  setAction({G_MERGE_VALUES, 1, s128}, Legal);
261  setAction({G_UNMERGE_VALUES, s128}, Legal);
262}
263
264void X86LegalizerInfo::setLegalizerInfoSSE1() {
265  if (!Subtarget.hasSSE1())
266    return;
267
268  const LLT s32 = LLT::scalar(32);
269  const LLT s64 = LLT::scalar(64);
270  const LLT v4s32 = LLT::vector(4, 32);
271  const LLT v2s64 = LLT::vector(2, 64);
272
273  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
274    for (auto Ty : {s32, v4s32})
275      setAction({BinOp, Ty}, Legal);
276
277  for (unsigned MemOp : {G_LOAD, G_STORE})
278    for (auto Ty : {v4s32, v2s64})
279      setAction({MemOp, Ty}, Legal);
280
281  // Constants
282  setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
283
284  // Merge/Unmerge
285  for (const auto &Ty : {v4s32, v2s64}) {
286    setAction({G_CONCAT_VECTORS, Ty}, Legal);
287    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
288  }
289  setAction({G_MERGE_VALUES, 1, s64}, Legal);
290  setAction({G_UNMERGE_VALUES, s64}, Legal);
291}
292
293void X86LegalizerInfo::setLegalizerInfoSSE2() {
294  if (!Subtarget.hasSSE2())
295    return;
296
297  const LLT s32 = LLT::scalar(32);
298  const LLT s64 = LLT::scalar(64);
299  const LLT v16s8 = LLT::vector(16, 8);
300  const LLT v8s16 = LLT::vector(8, 16);
301  const LLT v4s32 = LLT::vector(4, 32);
302  const LLT v2s64 = LLT::vector(2, 64);
303
304  const LLT v32s8 = LLT::vector(32, 8);
305  const LLT v16s16 = LLT::vector(16, 16);
306  const LLT v8s32 = LLT::vector(8, 32);
307  const LLT v4s64 = LLT::vector(4, 64);
308
309  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
310    for (auto Ty : {s64, v2s64})
311      setAction({BinOp, Ty}, Legal);
312
313  for (unsigned BinOp : {G_ADD, G_SUB})
314    for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
315      setAction({BinOp, Ty}, Legal);
316
317  setAction({G_MUL, v8s16}, Legal);
318
319  setAction({G_FPEXT, s64}, Legal);
320  setAction({G_FPEXT, 1, s32}, Legal);
321
322  setAction({G_FPTRUNC, s32}, Legal);
323  setAction({G_FPTRUNC, 1, s64}, Legal);
324
325  // Constants
326  setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
327
328  // Merge/Unmerge
329  for (const auto &Ty :
330       {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
331    setAction({G_CONCAT_VECTORS, Ty}, Legal);
332    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
333  }
334  for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) {
335    setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
336    setAction({G_UNMERGE_VALUES, Ty}, Legal);
337  }
338}
339
340void X86LegalizerInfo::setLegalizerInfoSSE41() {
341  if (!Subtarget.hasSSE41())
342    return;
343
344  const LLT v4s32 = LLT::vector(4, 32);
345
346  setAction({G_MUL, v4s32}, Legal);
347}
348
349void X86LegalizerInfo::setLegalizerInfoAVX() {
350  if (!Subtarget.hasAVX())
351    return;
352
353  const LLT v16s8 = LLT::vector(16, 8);
354  const LLT v8s16 = LLT::vector(8, 16);
355  const LLT v4s32 = LLT::vector(4, 32);
356  const LLT v2s64 = LLT::vector(2, 64);
357
358  const LLT v32s8 = LLT::vector(32, 8);
359  const LLT v64s8 = LLT::vector(64, 8);
360  const LLT v16s16 = LLT::vector(16, 16);
361  const LLT v32s16 = LLT::vector(32, 16);
362  const LLT v8s32 = LLT::vector(8, 32);
363  const LLT v16s32 = LLT::vector(16, 32);
364  const LLT v4s64 = LLT::vector(4, 64);
365  const LLT v8s64 = LLT::vector(8, 64);
366
367  for (unsigned MemOp : {G_LOAD, G_STORE})
368    for (auto Ty : {v8s32, v4s64})
369      setAction({MemOp, Ty}, Legal);
370
371  for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
372    setAction({G_INSERT, Ty}, Legal);
373    setAction({G_EXTRACT, 1, Ty}, Legal);
374  }
375  for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
376    setAction({G_INSERT, 1, Ty}, Legal);
377    setAction({G_EXTRACT, Ty}, Legal);
378  }
379  // Merge/Unmerge
380  for (const auto &Ty :
381       {v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) {
382    setAction({G_CONCAT_VECTORS, Ty}, Legal);
383    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
384  }
385  for (const auto &Ty :
386       {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
387    setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
388    setAction({G_UNMERGE_VALUES, Ty}, Legal);
389  }
390}
391
392void X86LegalizerInfo::setLegalizerInfoAVX2() {
393  if (!Subtarget.hasAVX2())
394    return;
395
396  const LLT v32s8 = LLT::vector(32, 8);
397  const LLT v16s16 = LLT::vector(16, 16);
398  const LLT v8s32 = LLT::vector(8, 32);
399  const LLT v4s64 = LLT::vector(4, 64);
400
401  const LLT v64s8 = LLT::vector(64, 8);
402  const LLT v32s16 = LLT::vector(32, 16);
403  const LLT v16s32 = LLT::vector(16, 32);
404  const LLT v8s64 = LLT::vector(8, 64);
405
406  for (unsigned BinOp : {G_ADD, G_SUB})
407    for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
408      setAction({BinOp, Ty}, Legal);
409
410  for (auto Ty : {v16s16, v8s32})
411    setAction({G_MUL, Ty}, Legal);
412
413  // Merge/Unmerge
414  for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) {
415    setAction({G_CONCAT_VECTORS, Ty}, Legal);
416    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
417  }
418  for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) {
419    setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
420    setAction({G_UNMERGE_VALUES, Ty}, Legal);
421  }
422}
423
424void X86LegalizerInfo::setLegalizerInfoAVX512() {
425  if (!Subtarget.hasAVX512())
426    return;
427
428  const LLT v16s8 = LLT::vector(16, 8);
429  const LLT v8s16 = LLT::vector(8, 16);
430  const LLT v4s32 = LLT::vector(4, 32);
431  const LLT v2s64 = LLT::vector(2, 64);
432
433  const LLT v32s8 = LLT::vector(32, 8);
434  const LLT v16s16 = LLT::vector(16, 16);
435  const LLT v8s32 = LLT::vector(8, 32);
436  const LLT v4s64 = LLT::vector(4, 64);
437
438  const LLT v64s8 = LLT::vector(64, 8);
439  const LLT v32s16 = LLT::vector(32, 16);
440  const LLT v16s32 = LLT::vector(16, 32);
441  const LLT v8s64 = LLT::vector(8, 64);
442
443  for (unsigned BinOp : {G_ADD, G_SUB})
444    for (auto Ty : {v16s32, v8s64})
445      setAction({BinOp, Ty}, Legal);
446
447  setAction({G_MUL, v16s32}, Legal);
448
449  for (unsigned MemOp : {G_LOAD, G_STORE})
450    for (auto Ty : {v16s32, v8s64})
451      setAction({MemOp, Ty}, Legal);
452
453  for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
454    setAction({G_INSERT, Ty}, Legal);
455    setAction({G_EXTRACT, 1, Ty}, Legal);
456  }
457  for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
458    setAction({G_INSERT, 1, Ty}, Legal);
459    setAction({G_EXTRACT, Ty}, Legal);
460  }
461
462  /************ VLX *******************/
463  if (!Subtarget.hasVLX())
464    return;
465
466  for (auto Ty : {v4s32, v8s32})
467    setAction({G_MUL, Ty}, Legal);
468}
469
470void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
471  if (!(Subtarget.hasAVX512() && Subtarget.hasDQI()))
472    return;
473
474  const LLT v8s64 = LLT::vector(8, 64);
475
476  setAction({G_MUL, v8s64}, Legal);
477
478  /************ VLX *******************/
479  if (!Subtarget.hasVLX())
480    return;
481
482  const LLT v2s64 = LLT::vector(2, 64);
483  const LLT v4s64 = LLT::vector(4, 64);
484
485  for (auto Ty : {v2s64, v4s64})
486    setAction({G_MUL, Ty}, Legal);
487}
488
489void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
490  if (!(Subtarget.hasAVX512() && Subtarget.hasBWI()))
491    return;
492
493  const LLT v64s8 = LLT::vector(64, 8);
494  const LLT v32s16 = LLT::vector(32, 16);
495
496  for (unsigned BinOp : {G_ADD, G_SUB})
497    for (auto Ty : {v64s8, v32s16})
498      setAction({BinOp, Ty}, Legal);
499
500  setAction({G_MUL, v32s16}, Legal);
501
502  /************ VLX *******************/
503  if (!Subtarget.hasVLX())
504    return;
505
506  const LLT v8s16 = LLT::vector(8, 16);
507  const LLT v16s16 = LLT::vector(16, 16);
508
509  for (auto Ty : {v8s16, v16s16})
510    setAction({G_MUL, Ty}, Legal);
511}
512