X86LegalizerInfo.cpp revision 318681
1317017Sdim//===- X86LegalizerInfo.cpp --------------------------------------*- C++ -*-==//
2317017Sdim//
3317017Sdim//                     The LLVM Compiler Infrastructure
4317017Sdim//
5317017Sdim// This file is distributed under the University of Illinois Open Source
6317017Sdim// License. See LICENSE.TXT for details.
7317017Sdim//
8317017Sdim//===----------------------------------------------------------------------===//
9317017Sdim/// \file
10317017Sdim/// This file implements the targeting of the Machinelegalizer class for X86.
11317017Sdim/// \todo This should be generated by TableGen.
12317017Sdim//===----------------------------------------------------------------------===//
13317017Sdim
14317017Sdim#include "X86LegalizerInfo.h"
15317017Sdim#include "X86Subtarget.h"
16317017Sdim#include "X86TargetMachine.h"
17317017Sdim#include "llvm/CodeGen/ValueTypes.h"
18317017Sdim#include "llvm/IR/DerivedTypes.h"
19317017Sdim#include "llvm/IR/Type.h"
20317017Sdim#include "llvm/Target/TargetOpcodes.h"
21317017Sdim
22317017Sdimusing namespace llvm;
23317017Sdimusing namespace TargetOpcode;
24317017Sdim
25317017Sdim#ifndef LLVM_BUILD_GLOBAL_ISEL
26317017Sdim#error "You shouldn't build this"
27317017Sdim#endif
28317017Sdim
29317017SdimX86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
30317017Sdim                                   const X86TargetMachine &TM)
31317017Sdim    : Subtarget(STI), TM(TM) {
32317017Sdim
33317017Sdim  setLegalizerInfo32bit();
34317017Sdim  setLegalizerInfo64bit();
35317017Sdim  setLegalizerInfoSSE1();
36317017Sdim  setLegalizerInfoSSE2();
37317969Sdim  setLegalizerInfoSSE41();
38317969Sdim  setLegalizerInfoAVX2();
39317969Sdim  setLegalizerInfoAVX512();
40317969Sdim  setLegalizerInfoAVX512DQ();
41317969Sdim  setLegalizerInfoAVX512BW();
42317017Sdim
43317017Sdim  computeTables();
44317017Sdim}
45317017Sdim
46317017Sdimvoid X86LegalizerInfo::setLegalizerInfo32bit() {
47317017Sdim
48317017Sdim  if (Subtarget.is64Bit())
49317017Sdim    return;
50317017Sdim
51317017Sdim  const LLT p0 = LLT::pointer(0, 32);
52317017Sdim  const LLT s1 = LLT::scalar(1);
53317017Sdim  const LLT s8 = LLT::scalar(8);
54317017Sdim  const LLT s16 = LLT::scalar(16);
55317017Sdim  const LLT s32 = LLT::scalar(32);
56317017Sdim  const LLT s64 = LLT::scalar(64);
57317017Sdim
58317969Sdim  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL})
59317017Sdim    for (auto Ty : {s8, s16, s32})
60317017Sdim      setAction({BinOp, Ty}, Legal);
61317017Sdim
62318477Sdim  for (unsigned Op : {G_UADDE}) {
63318477Sdim    setAction({Op, s32}, Legal);
64318477Sdim    setAction({Op, 1, s1}, Legal);
65318477Sdim  }
66318477Sdim
67317017Sdim  for (unsigned MemOp : {G_LOAD, G_STORE}) {
68317017Sdim    for (auto Ty : {s8, s16, s32, p0})
69317017Sdim      setAction({MemOp, Ty}, Legal);
70317017Sdim
71317017Sdim    // And everything's fine in addrspace 0.
72317017Sdim    setAction({MemOp, 1, p0}, Legal);
73317017Sdim  }
74317017Sdim
75317017Sdim  // Pointer-handling
76317017Sdim  setAction({G_FRAME_INDEX, p0}, Legal);
77317017Sdim
78317969Sdim  setAction({G_GEP, p0}, Legal);
79317969Sdim  setAction({G_GEP, 1, s32}, Legal);
80317969Sdim
81317969Sdim  for (auto Ty : {s1, s8, s16})
82317969Sdim    setAction({G_GEP, 1, Ty}, WidenScalar);
83317969Sdim
84317017Sdim  // Constants
85317017Sdim  for (auto Ty : {s8, s16, s32, p0})
86317017Sdim    setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
87317017Sdim
88317017Sdim  setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar);
89317017Sdim  setAction({TargetOpcode::G_CONSTANT, s64}, NarrowScalar);
90317778Sdim
91317778Sdim  // Extensions
92317778Sdim  setAction({G_ZEXT, s32}, Legal);
93317778Sdim  setAction({G_SEXT, s32}, Legal);
94317778Sdim
95318384Sdim  for (auto Ty : {s1, s8, s16}) {
96317778Sdim    setAction({G_ZEXT, 1, Ty}, Legal);
97317778Sdim    setAction({G_SEXT, 1, Ty}, Legal);
98317778Sdim  }
99318384Sdim
100318384Sdim  // Comparison
101318384Sdim  setAction({G_ICMP, s1}, Legal);
102318384Sdim
103318384Sdim  for (auto Ty : {s8, s16, s32, p0})
104318384Sdim    setAction({G_ICMP, 1, Ty}, Legal);
105317017Sdim}
106317017Sdim
107317017Sdimvoid X86LegalizerInfo::setLegalizerInfo64bit() {
108317017Sdim
109317017Sdim  if (!Subtarget.is64Bit())
110317017Sdim    return;
111317017Sdim
112317017Sdim  const LLT p0 = LLT::pointer(0, TM.getPointerSize() * 8);
113317017Sdim  const LLT s1 = LLT::scalar(1);
114317017Sdim  const LLT s8 = LLT::scalar(8);
115317017Sdim  const LLT s16 = LLT::scalar(16);
116317017Sdim  const LLT s32 = LLT::scalar(32);
117317017Sdim  const LLT s64 = LLT::scalar(64);
118317017Sdim
119317969Sdim  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL})
120317017Sdim    for (auto Ty : {s8, s16, s32, s64})
121317017Sdim      setAction({BinOp, Ty}, Legal);
122317017Sdim
123317017Sdim  for (unsigned MemOp : {G_LOAD, G_STORE}) {
124317017Sdim    for (auto Ty : {s8, s16, s32, s64, p0})
125317017Sdim      setAction({MemOp, Ty}, Legal);
126317017Sdim
127317017Sdim    // And everything's fine in addrspace 0.
128317017Sdim    setAction({MemOp, 1, p0}, Legal);
129317017Sdim  }
130317017Sdim
131317017Sdim  // Pointer-handling
132317017Sdim  setAction({G_FRAME_INDEX, p0}, Legal);
133317017Sdim
134317969Sdim  setAction({G_GEP, p0}, Legal);
135317969Sdim  setAction({G_GEP, 1, s32}, Legal);
136317969Sdim  setAction({G_GEP, 1, s64}, Legal);
137317969Sdim
138317969Sdim  for (auto Ty : {s1, s8, s16})
139317969Sdim    setAction({G_GEP, 1, Ty}, WidenScalar);
140317969Sdim
141317017Sdim  // Constants
142317017Sdim  for (auto Ty : {s8, s16, s32, s64, p0})
143317017Sdim    setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
144317017Sdim
145317017Sdim  setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar);
146317778Sdim
147317778Sdim  // Extensions
148317778Sdim  for (auto Ty : {s32, s64}) {
149317778Sdim    setAction({G_ZEXT, Ty}, Legal);
150317778Sdim    setAction({G_SEXT, Ty}, Legal);
151317778Sdim  }
152317778Sdim
153318384Sdim  for (auto Ty : {s1, s8, s16, s32}) {
154317778Sdim    setAction({G_ZEXT, 1, Ty}, Legal);
155317778Sdim    setAction({G_SEXT, 1, Ty}, Legal);
156317778Sdim  }
157318384Sdim
158318384Sdim  // Comparison
159318384Sdim  setAction({G_ICMP, s1}, Legal);
160318384Sdim
161318384Sdim  for (auto Ty : {s8, s16, s32, s64, p0})
162318384Sdim    setAction({G_ICMP, 1, Ty}, Legal);
163317017Sdim}
164317017Sdim
165317017Sdimvoid X86LegalizerInfo::setLegalizerInfoSSE1() {
166317017Sdim  if (!Subtarget.hasSSE1())
167317017Sdim    return;
168317017Sdim
169317017Sdim  const LLT s32 = LLT::scalar(32);
170317017Sdim  const LLT v4s32 = LLT::vector(4, 32);
171317017Sdim  const LLT v2s64 = LLT::vector(2, 64);
172317017Sdim
173317017Sdim  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
174317017Sdim    for (auto Ty : {s32, v4s32})
175317017Sdim      setAction({BinOp, Ty}, Legal);
176317017Sdim
177317017Sdim  for (unsigned MemOp : {G_LOAD, G_STORE})
178317017Sdim    for (auto Ty : {v4s32, v2s64})
179317017Sdim      setAction({MemOp, Ty}, Legal);
180317017Sdim}
181317017Sdim
182317017Sdimvoid X86LegalizerInfo::setLegalizerInfoSSE2() {
183317017Sdim  if (!Subtarget.hasSSE2())
184317017Sdim    return;
185317017Sdim
186317017Sdim  const LLT s64 = LLT::scalar(64);
187318681Sdim  const LLT v16s8 = LLT::vector(16, 8);
188317969Sdim  const LLT v8s16 = LLT::vector(8, 16);
189317017Sdim  const LLT v4s32 = LLT::vector(4, 32);
190317017Sdim  const LLT v2s64 = LLT::vector(2, 64);
191317017Sdim
192317017Sdim  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
193317017Sdim    for (auto Ty : {s64, v2s64})
194317017Sdim      setAction({BinOp, Ty}, Legal);
195317017Sdim
196317017Sdim  for (unsigned BinOp : {G_ADD, G_SUB})
197318681Sdim    for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
198317017Sdim      setAction({BinOp, Ty}, Legal);
199317969Sdim
200317969Sdim  setAction({G_MUL, v8s16}, Legal);
201317017Sdim}
202317969Sdim
203317969Sdimvoid X86LegalizerInfo::setLegalizerInfoSSE41() {
204317969Sdim  if (!Subtarget.hasSSE41())
205317969Sdim    return;
206317969Sdim
207317969Sdim  const LLT v4s32 = LLT::vector(4, 32);
208317969Sdim
209317969Sdim  setAction({G_MUL, v4s32}, Legal);
210317969Sdim}
211317969Sdim
212317969Sdimvoid X86LegalizerInfo::setLegalizerInfoAVX2() {
213317969Sdim  if (!Subtarget.hasAVX2())
214317969Sdim    return;
215317969Sdim
216318681Sdim  const LLT v32s8 = LLT::vector(32, 8);
217317969Sdim  const LLT v16s16 = LLT::vector(16, 16);
218317969Sdim  const LLT v8s32 = LLT::vector(8, 32);
219318681Sdim  const LLT v4s64 = LLT::vector(4, 64);
220317969Sdim
221318681Sdim  for (unsigned BinOp : {G_ADD, G_SUB})
222318681Sdim    for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
223318681Sdim      setAction({BinOp, Ty}, Legal);
224318681Sdim
225317969Sdim  for (auto Ty : {v16s16, v8s32})
226317969Sdim    setAction({G_MUL, Ty}, Legal);
227317969Sdim}
228317969Sdim
229317969Sdimvoid X86LegalizerInfo::setLegalizerInfoAVX512() {
230317969Sdim  if (!Subtarget.hasAVX512())
231317969Sdim    return;
232317969Sdim
233317969Sdim  const LLT v16s32 = LLT::vector(16, 32);
234318681Sdim  const LLT v8s64 = LLT::vector(8, 64);
235317969Sdim
236318681Sdim  for (unsigned BinOp : {G_ADD, G_SUB})
237318681Sdim    for (auto Ty : {v16s32, v8s64})
238318681Sdim      setAction({BinOp, Ty}, Legal);
239318681Sdim
240317969Sdim  setAction({G_MUL, v16s32}, Legal);
241317969Sdim
242317969Sdim  /************ VLX *******************/
243317969Sdim  if (!Subtarget.hasVLX())
244317969Sdim    return;
245317969Sdim
246317969Sdim  const LLT v4s32 = LLT::vector(4, 32);
247317969Sdim  const LLT v8s32 = LLT::vector(8, 32);
248317969Sdim
249317969Sdim  for (auto Ty : {v4s32, v8s32})
250317969Sdim    setAction({G_MUL, Ty}, Legal);
251317969Sdim}
252317969Sdim
253317969Sdimvoid X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
254317969Sdim  if (!(Subtarget.hasAVX512() && Subtarget.hasDQI()))
255317969Sdim    return;
256317969Sdim
257317969Sdim  const LLT v8s64 = LLT::vector(8, 64);
258317969Sdim
259317969Sdim  setAction({G_MUL, v8s64}, Legal);
260317969Sdim
261317969Sdim  /************ VLX *******************/
262317969Sdim  if (!Subtarget.hasVLX())
263317969Sdim    return;
264317969Sdim
265317969Sdim  const LLT v2s64 = LLT::vector(2, 64);
266317969Sdim  const LLT v4s64 = LLT::vector(4, 64);
267317969Sdim
268317969Sdim  for (auto Ty : {v2s64, v4s64})
269317969Sdim    setAction({G_MUL, Ty}, Legal);
270317969Sdim}
271317969Sdim
272317969Sdimvoid X86LegalizerInfo::setLegalizerInfoAVX512BW() {
273317969Sdim  if (!(Subtarget.hasAVX512() && Subtarget.hasBWI()))
274317969Sdim    return;
275317969Sdim
276318681Sdim  const LLT v64s8 = LLT::vector(64, 8);
277317969Sdim  const LLT v32s16 = LLT::vector(32, 16);
278317969Sdim
279318681Sdim  for (unsigned BinOp : {G_ADD, G_SUB})
280318681Sdim    for (auto Ty : {v64s8, v32s16})
281318681Sdim      setAction({BinOp, Ty}, Legal);
282318681Sdim
283317969Sdim  setAction({G_MUL, v32s16}, Legal);
284317969Sdim
285317969Sdim  /************ VLX *******************/
286317969Sdim  if (!Subtarget.hasVLX())
287317969Sdim    return;
288317969Sdim
289317969Sdim  const LLT v8s16 = LLT::vector(8, 16);
290317969Sdim  const LLT v16s16 = LLT::vector(16, 16);
291317969Sdim
292317969Sdim  for (auto Ty : {v8s16, v16s16})
293317969Sdim    setAction({G_MUL, Ty}, Legal);
294317969Sdim}
295