X86LegalizerInfo.cpp revision 327952
1//===- X86LegalizerInfo.cpp --------------------------------------*- C++ -*-==//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10/// This file implements the targeting of the Machinelegalizer class for X86.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
14#include "X86LegalizerInfo.h"
15#include "X86Subtarget.h"
16#include "X86TargetMachine.h"
17#include "llvm/CodeGen/TargetOpcodes.h"
18#include "llvm/CodeGen/ValueTypes.h"
19#include "llvm/IR/DerivedTypes.h"
20#include "llvm/IR/Type.h"
21
22using namespace llvm;
23using namespace TargetOpcode;
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, LegalizerInfo::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, LegalizerInfo::WidenScalar},
50                                             {2, LegalizerInfo::Unsupported}};
51  addAndInterleaveWithUnsupported(result, v);
52  auto Largest = result.back().first;
53  result.push_back({Largest + 1, LegalizerInfo::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}
85
86void X86LegalizerInfo::setLegalizerInfo32bit() {
87
88  const LLT p0 = LLT::pointer(0, TM.getPointerSize() * 8);
89  const LLT s1 = LLT::scalar(1);
90  const LLT s8 = LLT::scalar(8);
91  const LLT s16 = LLT::scalar(16);
92  const LLT s32 = LLT::scalar(32);
93  const LLT s64 = LLT::scalar(64);
94
95  for (auto Ty : {p0, s1, s8, s16, s32})
96    setAction({G_IMPLICIT_DEF, Ty}, Legal);
97
98  for (auto Ty : {s8, s16, s32, p0})
99    setAction({G_PHI, Ty}, Legal);
100
101  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
102    for (auto Ty : {s8, s16, s32})
103      setAction({BinOp, Ty}, Legal);
104
105  for (unsigned Op : {G_UADDE}) {
106    setAction({Op, s32}, Legal);
107    setAction({Op, 1, s1}, Legal);
108  }
109
110  for (unsigned MemOp : {G_LOAD, G_STORE}) {
111    for (auto Ty : {s8, s16, s32, p0})
112      setAction({MemOp, Ty}, Legal);
113
114    // And everything's fine in addrspace 0.
115    setAction({MemOp, 1, p0}, Legal);
116  }
117
118  // Pointer-handling
119  setAction({G_FRAME_INDEX, p0}, Legal);
120  setAction({G_GLOBAL_VALUE, p0}, Legal);
121
122  setAction({G_GEP, p0}, Legal);
123  setAction({G_GEP, 1, s32}, Legal);
124
125  // Control-flow
126  setAction({G_BRCOND, s1}, Legal);
127
128  // Constants
129  for (auto Ty : {s8, s16, s32, p0})
130    setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
131
132  // Extensions
133  for (auto Ty : {s8, s16, s32}) {
134    setAction({G_ZEXT, Ty}, Legal);
135    setAction({G_SEXT, Ty}, Legal);
136    setAction({G_ANYEXT, Ty}, Legal);
137  }
138
139  // Comparison
140  setAction({G_ICMP, s1}, Legal);
141
142  for (auto Ty : {s8, s16, s32, p0})
143    setAction({G_ICMP, 1, Ty}, Legal);
144
145  // Merge/Unmerge
146  for (const auto &Ty : {s16, s32, s64}) {
147    setAction({G_MERGE_VALUES, Ty}, Legal);
148    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
149  }
150  for (const auto &Ty : {s8, s16, s32}) {
151    setAction({G_MERGE_VALUES, 1, Ty}, Legal);
152    setAction({G_UNMERGE_VALUES, Ty}, Legal);
153  }
154}
155
156void X86LegalizerInfo::setLegalizerInfo64bit() {
157
158  if (!Subtarget.is64Bit())
159    return;
160
161  const LLT s64 = LLT::scalar(64);
162  const LLT s128 = LLT::scalar(128);
163
164  setAction({G_IMPLICIT_DEF, s64}, Legal);
165
166  setAction({G_PHI, s64}, Legal);
167
168  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
169    setAction({BinOp, s64}, Legal);
170
171  for (unsigned MemOp : {G_LOAD, G_STORE})
172    setAction({MemOp, s64}, Legal);
173
174  // Pointer-handling
175  setAction({G_GEP, 1, s64}, Legal);
176
177  // Constants
178  setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
179
180  // Extensions
181  for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
182    setAction({extOp, s64}, Legal);
183  }
184
185  // Comparison
186  setAction({G_ICMP, 1, s64}, Legal);
187
188  // Merge/Unmerge
189  setAction({G_MERGE_VALUES, s128}, Legal);
190  setAction({G_UNMERGE_VALUES, 1, s128}, Legal);
191  setAction({G_MERGE_VALUES, 1, s128}, Legal);
192  setAction({G_UNMERGE_VALUES, s128}, Legal);
193}
194
195void X86LegalizerInfo::setLegalizerInfoSSE1() {
196  if (!Subtarget.hasSSE1())
197    return;
198
199  const LLT s32 = LLT::scalar(32);
200  const LLT s64 = LLT::scalar(64);
201  const LLT v4s32 = LLT::vector(4, 32);
202  const LLT v2s64 = LLT::vector(2, 64);
203
204  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
205    for (auto Ty : {s32, v4s32})
206      setAction({BinOp, Ty}, Legal);
207
208  for (unsigned MemOp : {G_LOAD, G_STORE})
209    for (auto Ty : {v4s32, v2s64})
210      setAction({MemOp, Ty}, Legal);
211
212  // Constants
213  setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
214
215  // Merge/Unmerge
216  for (const auto &Ty : {v4s32, v2s64}) {
217    setAction({G_MERGE_VALUES, Ty}, Legal);
218    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
219  }
220  setAction({G_MERGE_VALUES, 1, s64}, Legal);
221  setAction({G_UNMERGE_VALUES, s64}, Legal);
222}
223
224void X86LegalizerInfo::setLegalizerInfoSSE2() {
225  if (!Subtarget.hasSSE2())
226    return;
227
228  const LLT s32 = LLT::scalar(32);
229  const LLT s64 = LLT::scalar(64);
230  const LLT v16s8 = LLT::vector(16, 8);
231  const LLT v8s16 = LLT::vector(8, 16);
232  const LLT v4s32 = LLT::vector(4, 32);
233  const LLT v2s64 = LLT::vector(2, 64);
234
235  const LLT v32s8 = LLT::vector(32, 8);
236  const LLT v16s16 = LLT::vector(16, 16);
237  const LLT v8s32 = LLT::vector(8, 32);
238  const LLT v4s64 = LLT::vector(4, 64);
239
240  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
241    for (auto Ty : {s64, v2s64})
242      setAction({BinOp, Ty}, Legal);
243
244  for (unsigned BinOp : {G_ADD, G_SUB})
245    for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
246      setAction({BinOp, Ty}, Legal);
247
248  setAction({G_MUL, v8s16}, Legal);
249
250  setAction({G_FPEXT, s64}, Legal);
251  setAction({G_FPEXT, 1, s32}, Legal);
252
253  // Constants
254  setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
255
256  // Merge/Unmerge
257  for (const auto &Ty :
258       {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
259    setAction({G_MERGE_VALUES, Ty}, Legal);
260    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
261  }
262  for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) {
263    setAction({G_MERGE_VALUES, 1, Ty}, Legal);
264    setAction({G_UNMERGE_VALUES, Ty}, Legal);
265  }
266}
267
268void X86LegalizerInfo::setLegalizerInfoSSE41() {
269  if (!Subtarget.hasSSE41())
270    return;
271
272  const LLT v4s32 = LLT::vector(4, 32);
273
274  setAction({G_MUL, v4s32}, Legal);
275}
276
277void X86LegalizerInfo::setLegalizerInfoAVX() {
278  if (!Subtarget.hasAVX())
279    return;
280
281  const LLT v16s8 = LLT::vector(16, 8);
282  const LLT v8s16 = LLT::vector(8, 16);
283  const LLT v4s32 = LLT::vector(4, 32);
284  const LLT v2s64 = LLT::vector(2, 64);
285
286  const LLT v32s8 = LLT::vector(32, 8);
287  const LLT v64s8 = LLT::vector(64, 8);
288  const LLT v16s16 = LLT::vector(16, 16);
289  const LLT v32s16 = LLT::vector(32, 16);
290  const LLT v8s32 = LLT::vector(8, 32);
291  const LLT v16s32 = LLT::vector(16, 32);
292  const LLT v4s64 = LLT::vector(4, 64);
293  const LLT v8s64 = LLT::vector(8, 64);
294
295  for (unsigned MemOp : {G_LOAD, G_STORE})
296    for (auto Ty : {v8s32, v4s64})
297      setAction({MemOp, Ty}, Legal);
298
299  for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
300    setAction({G_INSERT, Ty}, Legal);
301    setAction({G_EXTRACT, 1, Ty}, Legal);
302  }
303  for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
304    setAction({G_INSERT, 1, Ty}, Legal);
305    setAction({G_EXTRACT, Ty}, Legal);
306  }
307  // Merge/Unmerge
308  for (const auto &Ty :
309       {v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) {
310    setAction({G_MERGE_VALUES, Ty}, Legal);
311    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
312  }
313  for (const auto &Ty :
314       {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
315    setAction({G_MERGE_VALUES, 1, Ty}, Legal);
316    setAction({G_UNMERGE_VALUES, Ty}, Legal);
317  }
318}
319
320void X86LegalizerInfo::setLegalizerInfoAVX2() {
321  if (!Subtarget.hasAVX2())
322    return;
323
324  const LLT v32s8 = LLT::vector(32, 8);
325  const LLT v16s16 = LLT::vector(16, 16);
326  const LLT v8s32 = LLT::vector(8, 32);
327  const LLT v4s64 = LLT::vector(4, 64);
328
329  const LLT v64s8 = LLT::vector(64, 8);
330  const LLT v32s16 = LLT::vector(32, 16);
331  const LLT v16s32 = LLT::vector(16, 32);
332  const LLT v8s64 = LLT::vector(8, 64);
333
334  for (unsigned BinOp : {G_ADD, G_SUB})
335    for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
336      setAction({BinOp, Ty}, Legal);
337
338  for (auto Ty : {v16s16, v8s32})
339    setAction({G_MUL, Ty}, Legal);
340
341  // Merge/Unmerge
342  for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) {
343    setAction({G_MERGE_VALUES, Ty}, Legal);
344    setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
345  }
346  for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) {
347    setAction({G_MERGE_VALUES, 1, Ty}, Legal);
348    setAction({G_UNMERGE_VALUES, Ty}, Legal);
349  }
350}
351
352void X86LegalizerInfo::setLegalizerInfoAVX512() {
353  if (!Subtarget.hasAVX512())
354    return;
355
356  const LLT v16s8 = LLT::vector(16, 8);
357  const LLT v8s16 = LLT::vector(8, 16);
358  const LLT v4s32 = LLT::vector(4, 32);
359  const LLT v2s64 = LLT::vector(2, 64);
360
361  const LLT v32s8 = LLT::vector(32, 8);
362  const LLT v16s16 = LLT::vector(16, 16);
363  const LLT v8s32 = LLT::vector(8, 32);
364  const LLT v4s64 = LLT::vector(4, 64);
365
366  const LLT v64s8 = LLT::vector(64, 8);
367  const LLT v32s16 = LLT::vector(32, 16);
368  const LLT v16s32 = LLT::vector(16, 32);
369  const LLT v8s64 = LLT::vector(8, 64);
370
371  for (unsigned BinOp : {G_ADD, G_SUB})
372    for (auto Ty : {v16s32, v8s64})
373      setAction({BinOp, Ty}, Legal);
374
375  setAction({G_MUL, v16s32}, Legal);
376
377  for (unsigned MemOp : {G_LOAD, G_STORE})
378    for (auto Ty : {v16s32, v8s64})
379      setAction({MemOp, Ty}, Legal);
380
381  for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
382    setAction({G_INSERT, Ty}, Legal);
383    setAction({G_EXTRACT, 1, Ty}, Legal);
384  }
385  for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
386    setAction({G_INSERT, 1, Ty}, Legal);
387    setAction({G_EXTRACT, Ty}, Legal);
388  }
389
390  /************ VLX *******************/
391  if (!Subtarget.hasVLX())
392    return;
393
394  for (auto Ty : {v4s32, v8s32})
395    setAction({G_MUL, Ty}, Legal);
396}
397
398void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
399  if (!(Subtarget.hasAVX512() && Subtarget.hasDQI()))
400    return;
401
402  const LLT v8s64 = LLT::vector(8, 64);
403
404  setAction({G_MUL, v8s64}, Legal);
405
406  /************ VLX *******************/
407  if (!Subtarget.hasVLX())
408    return;
409
410  const LLT v2s64 = LLT::vector(2, 64);
411  const LLT v4s64 = LLT::vector(4, 64);
412
413  for (auto Ty : {v2s64, v4s64})
414    setAction({G_MUL, Ty}, Legal);
415}
416
417void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
418  if (!(Subtarget.hasAVX512() && Subtarget.hasBWI()))
419    return;
420
421  const LLT v64s8 = LLT::vector(64, 8);
422  const LLT v32s16 = LLT::vector(32, 16);
423
424  for (unsigned BinOp : {G_ADD, G_SUB})
425    for (auto Ty : {v64s8, v32s16})
426      setAction({BinOp, Ty}, Legal);
427
428  setAction({G_MUL, v32s16}, Legal);
429
430  /************ VLX *******************/
431  if (!Subtarget.hasVLX())
432    return;
433
434  const LLT v8s16 = LLT::vector(8, 16);
435  const LLT v16s16 = LLT::vector(16, 16);
436
437  for (auto Ty : {v8s16, v16s16})
438    setAction({G_MUL, Ty}, Legal);
439}
440