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/ValueTypes.h"
18 #include "llvm/IR/DerivedTypes.h"
19 #include "llvm/IR/Type.h"
20 #include "llvm/Target/TargetOpcodes.h"
21 
22 using namespace llvm;
23 using 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.
34 static void
35 addAndInterleaveWithUnsupported(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 
45 static LegalizerInfo::SizeAndActionsVec
46 widen_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 
57 X86LegalizerInfo::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 
86 void 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 
94   for (auto Ty : {p0, s1, s8, s16, s32})
95     setAction({G_IMPLICIT_DEF, Ty}, Legal);
96 
97   for (auto Ty : {s8, s16, s32, p0})
98     setAction({G_PHI, Ty}, Legal);
99 
100   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
101     for (auto Ty : {s8, s16, s32})
102       setAction({BinOp, Ty}, Legal);
103 
104   for (unsigned Op : {G_UADDE}) {
105     setAction({Op, s32}, Legal);
106     setAction({Op, 1, s1}, Legal);
107   }
108 
109   for (unsigned MemOp : {G_LOAD, G_STORE}) {
110     for (auto Ty : {s8, s16, s32, p0})
111       setAction({MemOp, Ty}, Legal);
112 
113     // And everything's fine in addrspace 0.
114     setAction({MemOp, 1, p0}, Legal);
115   }
116 
117   // Pointer-handling
118   setAction({G_FRAME_INDEX, p0}, Legal);
119   setAction({G_GLOBAL_VALUE, p0}, Legal);
120 
121   setAction({G_GEP, p0}, Legal);
122   setAction({G_GEP, 1, s32}, Legal);
123 
124   // Control-flow
125   setAction({G_BRCOND, s1}, Legal);
126 
127   // Constants
128   for (auto Ty : {s8, s16, s32, p0})
129     setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
130 
131   // Extensions
132   for (auto Ty : {s8, s16, s32}) {
133     setAction({G_ZEXT, Ty}, Legal);
134     setAction({G_SEXT, Ty}, Legal);
135     setAction({G_ANYEXT, Ty}, Legal);
136   }
137 
138   // Comparison
139   setAction({G_ICMP, s1}, Legal);
140 
141   for (auto Ty : {s8, s16, s32, p0})
142     setAction({G_ICMP, 1, Ty}, Legal);
143 }
144 
145 void X86LegalizerInfo::setLegalizerInfo64bit() {
146 
147   if (!Subtarget.is64Bit())
148     return;
149 
150   const LLT s64 = LLT::scalar(64);
151 
152   setAction({G_IMPLICIT_DEF, s64}, Legal);
153 
154   setAction({G_PHI, s64}, Legal);
155 
156   for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
157     setAction({BinOp, s64}, Legal);
158 
159   for (unsigned MemOp : {G_LOAD, G_STORE})
160     setAction({MemOp, s64}, Legal);
161 
162   // Pointer-handling
163   setAction({G_GEP, 1, s64}, Legal);
164 
165   // Constants
166   setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
167 
168   // Extensions
169   for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
170     setAction({extOp, s64}, Legal);
171   }
172 
173   // Comparison
174   setAction({G_ICMP, 1, s64}, Legal);
175 }
176 
177 void X86LegalizerInfo::setLegalizerInfoSSE1() {
178   if (!Subtarget.hasSSE1())
179     return;
180 
181   const LLT s32 = LLT::scalar(32);
182   const LLT v4s32 = LLT::vector(4, 32);
183   const LLT v2s64 = LLT::vector(2, 64);
184 
185   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
186     for (auto Ty : {s32, v4s32})
187       setAction({BinOp, Ty}, Legal);
188 
189   for (unsigned MemOp : {G_LOAD, G_STORE})
190     for (auto Ty : {v4s32, v2s64})
191       setAction({MemOp, Ty}, Legal);
192 
193   // Constants
194   setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
195 }
196 
197 void X86LegalizerInfo::setLegalizerInfoSSE2() {
198   if (!Subtarget.hasSSE2())
199     return;
200 
201   const LLT s32 = LLT::scalar(32);
202   const LLT s64 = LLT::scalar(64);
203   const LLT v16s8 = LLT::vector(16, 8);
204   const LLT v8s16 = LLT::vector(8, 16);
205   const LLT v4s32 = LLT::vector(4, 32);
206   const LLT v2s64 = LLT::vector(2, 64);
207 
208   for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
209     for (auto Ty : {s64, v2s64})
210       setAction({BinOp, Ty}, Legal);
211 
212   for (unsigned BinOp : {G_ADD, G_SUB})
213     for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
214       setAction({BinOp, Ty}, Legal);
215 
216   setAction({G_MUL, v8s16}, Legal);
217 
218   setAction({G_FPEXT, s64}, Legal);
219   setAction({G_FPEXT, 1, s32}, Legal);
220 
221   // Constants
222   setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
223 }
224 
225 void X86LegalizerInfo::setLegalizerInfoSSE41() {
226   if (!Subtarget.hasSSE41())
227     return;
228 
229   const LLT v4s32 = LLT::vector(4, 32);
230 
231   setAction({G_MUL, v4s32}, Legal);
232 }
233 
234 void X86LegalizerInfo::setLegalizerInfoAVX() {
235   if (!Subtarget.hasAVX())
236     return;
237 
238   const LLT v16s8 = LLT::vector(16, 8);
239   const LLT v8s16 = LLT::vector(8, 16);
240   const LLT v4s32 = LLT::vector(4, 32);
241   const LLT v2s64 = LLT::vector(2, 64);
242 
243   const LLT v32s8 = LLT::vector(32, 8);
244   const LLT v16s16 = LLT::vector(16, 16);
245   const LLT v8s32 = LLT::vector(8, 32);
246   const LLT v4s64 = LLT::vector(4, 64);
247 
248   for (unsigned MemOp : {G_LOAD, G_STORE})
249     for (auto Ty : {v8s32, v4s64})
250       setAction({MemOp, Ty}, Legal);
251 
252   for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
253     setAction({G_INSERT, Ty}, Legal);
254     setAction({G_EXTRACT, 1, Ty}, Legal);
255   }
256   for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
257     setAction({G_INSERT, 1, Ty}, Legal);
258     setAction({G_EXTRACT, Ty}, Legal);
259   }
260 }
261 
262 void X86LegalizerInfo::setLegalizerInfoAVX2() {
263   if (!Subtarget.hasAVX2())
264     return;
265 
266   const LLT v32s8 = LLT::vector(32, 8);
267   const LLT v16s16 = LLT::vector(16, 16);
268   const LLT v8s32 = LLT::vector(8, 32);
269   const LLT v4s64 = LLT::vector(4, 64);
270 
271   for (unsigned BinOp : {G_ADD, G_SUB})
272     for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
273       setAction({BinOp, Ty}, Legal);
274 
275   for (auto Ty : {v16s16, v8s32})
276     setAction({G_MUL, Ty}, Legal);
277 }
278 
279 void X86LegalizerInfo::setLegalizerInfoAVX512() {
280   if (!Subtarget.hasAVX512())
281     return;
282 
283   const LLT v16s8 = LLT::vector(16, 8);
284   const LLT v8s16 = LLT::vector(8, 16);
285   const LLT v4s32 = LLT::vector(4, 32);
286   const LLT v2s64 = LLT::vector(2, 64);
287 
288   const LLT v32s8 = LLT::vector(32, 8);
289   const LLT v16s16 = LLT::vector(16, 16);
290   const LLT v8s32 = LLT::vector(8, 32);
291   const LLT v4s64 = LLT::vector(4, 64);
292 
293   const LLT v64s8 = LLT::vector(64, 8);
294   const LLT v32s16 = LLT::vector(32, 16);
295   const LLT v16s32 = LLT::vector(16, 32);
296   const LLT v8s64 = LLT::vector(8, 64);
297 
298   for (unsigned BinOp : {G_ADD, G_SUB})
299     for (auto Ty : {v16s32, v8s64})
300       setAction({BinOp, Ty}, Legal);
301 
302   setAction({G_MUL, v16s32}, Legal);
303 
304   for (unsigned MemOp : {G_LOAD, G_STORE})
305     for (auto Ty : {v16s32, v8s64})
306       setAction({MemOp, Ty}, Legal);
307 
308   for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
309     setAction({G_INSERT, Ty}, Legal);
310     setAction({G_EXTRACT, 1, Ty}, Legal);
311   }
312   for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
313     setAction({G_INSERT, 1, Ty}, Legal);
314     setAction({G_EXTRACT, Ty}, Legal);
315   }
316 
317   /************ VLX *******************/
318   if (!Subtarget.hasVLX())
319     return;
320 
321   for (auto Ty : {v4s32, v8s32})
322     setAction({G_MUL, Ty}, Legal);
323 }
324 
325 void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
326   if (!(Subtarget.hasAVX512() && Subtarget.hasDQI()))
327     return;
328 
329   const LLT v8s64 = LLT::vector(8, 64);
330 
331   setAction({G_MUL, v8s64}, Legal);
332 
333   /************ VLX *******************/
334   if (!Subtarget.hasVLX())
335     return;
336 
337   const LLT v2s64 = LLT::vector(2, 64);
338   const LLT v4s64 = LLT::vector(4, 64);
339 
340   for (auto Ty : {v2s64, v4s64})
341     setAction({G_MUL, Ty}, Legal);
342 }
343 
344 void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
345   if (!(Subtarget.hasAVX512() && Subtarget.hasBWI()))
346     return;
347 
348   const LLT v64s8 = LLT::vector(64, 8);
349   const LLT v32s16 = LLT::vector(32, 16);
350 
351   for (unsigned BinOp : {G_ADD, G_SUB})
352     for (auto Ty : {v64s8, v32s16})
353       setAction({BinOp, Ty}, Legal);
354 
355   setAction({G_MUL, v32s16}, Legal);
356 
357   /************ VLX *******************/
358   if (!Subtarget.hasVLX())
359     return;
360 
361   const LLT v8s16 = LLT::vector(8, 16);
362   const LLT v16s16 = LLT::vector(16, 16);
363 
364   for (auto Ty : {v8s16, v16s16})
365     setAction({G_MUL, Ty}, Legal);
366 }
367