1 //===- AMDGPULegalizerInfo.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
10 /// AMDGPU.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
13 
14 #if defined(_MSC_VER) || defined(__MINGW32__)
15 // According to Microsoft, one must set _USE_MATH_DEFINES in order to get M_PI
16 // from the Visual C++ cmath / math.h headers:
17 // https://docs.microsoft.com/en-us/cpp/c-runtime-library/math-constants?view=vs-2019
18 #define _USE_MATH_DEFINES
19 #endif
20 
21 #include "AMDGPU.h"
22 #include "AMDGPULegalizerInfo.h"
23 #include "AMDGPUTargetMachine.h"
24 #include "SIMachineFunctionInfo.h"
25 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
26 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
27 #include "llvm/CodeGen/TargetOpcodes.h"
28 #include "llvm/CodeGen/ValueTypes.h"
29 #include "llvm/IR/DerivedTypes.h"
30 #include "llvm/IR/DiagnosticInfo.h"
31 #include "llvm/IR/Type.h"
32 #include "llvm/Support/Debug.h"
33 
34 #define DEBUG_TYPE "amdgpu-legalinfo"
35 
36 using namespace llvm;
37 using namespace LegalizeActions;
38 using namespace LegalizeMutations;
39 using namespace LegalityPredicates;
40 
41 
42 static LegalityPredicate isMultiple32(unsigned TypeIdx,
43                                       unsigned MaxSize = 512) {
44   return [=](const LegalityQuery &Query) {
45     const LLT Ty = Query.Types[TypeIdx];
46     const LLT EltTy = Ty.getScalarType();
47     return Ty.getSizeInBits() <= MaxSize && EltTy.getSizeInBits() % 32 == 0;
48   };
49 }
50 
51 static LegalityPredicate isSmallOddVector(unsigned TypeIdx) {
52   return [=](const LegalityQuery &Query) {
53     const LLT Ty = Query.Types[TypeIdx];
54     return Ty.isVector() &&
55            Ty.getNumElements() % 2 != 0 &&
56            Ty.getElementType().getSizeInBits() < 32;
57   };
58 }
59 
60 static LegalizeMutation oneMoreElement(unsigned TypeIdx) {
61   return [=](const LegalityQuery &Query) {
62     const LLT Ty = Query.Types[TypeIdx];
63     const LLT EltTy = Ty.getElementType();
64     return std::make_pair(TypeIdx, LLT::vector(Ty.getNumElements() + 1, EltTy));
65   };
66 }
67 
68 static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx) {
69   return [=](const LegalityQuery &Query) {
70     const LLT Ty = Query.Types[TypeIdx];
71     const LLT EltTy = Ty.getElementType();
72     unsigned Size = Ty.getSizeInBits();
73     unsigned Pieces = (Size + 63) / 64;
74     unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
75     return std::make_pair(TypeIdx, LLT::scalarOrVector(NewNumElts, EltTy));
76   };
77 }
78 
79 // Increase the number of vector elements to reach the next multiple of 32-bit
80 // type.
81 static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx) {
82   return [=](const LegalityQuery &Query) {
83     const LLT Ty = Query.Types[TypeIdx];
84 
85     const LLT EltTy = Ty.getElementType();
86     const int Size = Ty.getSizeInBits();
87     const int EltSize = EltTy.getSizeInBits();
88     const int NextMul32 = (Size + 31) / 32;
89 
90     assert(EltSize < 32);
91 
92     const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
93     return std::make_pair(TypeIdx, LLT::vector(NewNumElts, EltTy));
94   };
95 }
96 
97 static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size) {
98   return [=](const LegalityQuery &Query) {
99     const LLT QueryTy = Query.Types[TypeIdx];
100     return QueryTy.isVector() && QueryTy.getSizeInBits() < Size;
101   };
102 }
103 
104 static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size) {
105   return [=](const LegalityQuery &Query) {
106     const LLT QueryTy = Query.Types[TypeIdx];
107     return QueryTy.isVector() && QueryTy.getSizeInBits() > Size;
108   };
109 }
110 
111 static LegalityPredicate numElementsNotEven(unsigned TypeIdx) {
112   return [=](const LegalityQuery &Query) {
113     const LLT QueryTy = Query.Types[TypeIdx];
114     return QueryTy.isVector() && QueryTy.getNumElements() % 2 != 0;
115   };
116 }
117 
118 // Any combination of 32 or 64-bit elements up to 512 bits, and multiples of
119 // v2s16.
120 static LegalityPredicate isRegisterType(unsigned TypeIdx) {
121   return [=](const LegalityQuery &Query) {
122     const LLT Ty = Query.Types[TypeIdx];
123     if (Ty.isVector()) {
124       const int EltSize = Ty.getElementType().getSizeInBits();
125       return EltSize == 32 || EltSize == 64 ||
126             (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
127              EltSize == 128 || EltSize == 256;
128     }
129 
130     return Ty.getSizeInBits() % 32 == 0 && Ty.getSizeInBits() <= 512;
131   };
132 }
133 
134 static LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT Type) {
135   return [=](const LegalityQuery &Query) {
136     return Query.Types[TypeIdx].getElementType() == Type;
137   };
138 }
139 
140 static LegalityPredicate isWideScalarTruncStore(unsigned TypeIdx) {
141   return [=](const LegalityQuery &Query) {
142     const LLT Ty = Query.Types[TypeIdx];
143     return !Ty.isVector() && Ty.getSizeInBits() > 32 &&
144            Query.MMODescrs[0].SizeInBits < Ty.getSizeInBits();
145   };
146 }
147 
148 AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
149                                          const GCNTargetMachine &TM)
150   :  ST(ST_) {
151   using namespace TargetOpcode;
152 
153   auto GetAddrSpacePtr = [&TM](unsigned AS) {
154     return LLT::pointer(AS, TM.getPointerSizeInBits(AS));
155   };
156 
157   const LLT S1 = LLT::scalar(1);
158   const LLT S8 = LLT::scalar(8);
159   const LLT S16 = LLT::scalar(16);
160   const LLT S32 = LLT::scalar(32);
161   const LLT S64 = LLT::scalar(64);
162   const LLT S96 = LLT::scalar(96);
163   const LLT S128 = LLT::scalar(128);
164   const LLT S256 = LLT::scalar(256);
165   const LLT S512 = LLT::scalar(512);
166 
167   const LLT V2S16 = LLT::vector(2, 16);
168   const LLT V4S16 = LLT::vector(4, 16);
169 
170   const LLT V2S32 = LLT::vector(2, 32);
171   const LLT V3S32 = LLT::vector(3, 32);
172   const LLT V4S32 = LLT::vector(4, 32);
173   const LLT V5S32 = LLT::vector(5, 32);
174   const LLT V6S32 = LLT::vector(6, 32);
175   const LLT V7S32 = LLT::vector(7, 32);
176   const LLT V8S32 = LLT::vector(8, 32);
177   const LLT V9S32 = LLT::vector(9, 32);
178   const LLT V10S32 = LLT::vector(10, 32);
179   const LLT V11S32 = LLT::vector(11, 32);
180   const LLT V12S32 = LLT::vector(12, 32);
181   const LLT V13S32 = LLT::vector(13, 32);
182   const LLT V14S32 = LLT::vector(14, 32);
183   const LLT V15S32 = LLT::vector(15, 32);
184   const LLT V16S32 = LLT::vector(16, 32);
185 
186   const LLT V2S64 = LLT::vector(2, 64);
187   const LLT V3S64 = LLT::vector(3, 64);
188   const LLT V4S64 = LLT::vector(4, 64);
189   const LLT V5S64 = LLT::vector(5, 64);
190   const LLT V6S64 = LLT::vector(6, 64);
191   const LLT V7S64 = LLT::vector(7, 64);
192   const LLT V8S64 = LLT::vector(8, 64);
193 
194   std::initializer_list<LLT> AllS32Vectors =
195     {V2S32, V3S32, V4S32, V5S32, V6S32, V7S32, V8S32,
196      V9S32, V10S32, V11S32, V12S32, V13S32, V14S32, V15S32, V16S32};
197   std::initializer_list<LLT> AllS64Vectors =
198     {V2S64, V3S64, V4S64, V5S64, V6S64, V7S64, V8S64};
199 
200   const LLT GlobalPtr = GetAddrSpacePtr(AMDGPUAS::GLOBAL_ADDRESS);
201   const LLT ConstantPtr = GetAddrSpacePtr(AMDGPUAS::CONSTANT_ADDRESS);
202   const LLT Constant32Ptr = GetAddrSpacePtr(AMDGPUAS::CONSTANT_ADDRESS_32BIT);
203   const LLT LocalPtr = GetAddrSpacePtr(AMDGPUAS::LOCAL_ADDRESS);
204   const LLT RegionPtr = GetAddrSpacePtr(AMDGPUAS::REGION_ADDRESS);
205   const LLT FlatPtr = GetAddrSpacePtr(AMDGPUAS::FLAT_ADDRESS);
206   const LLT PrivatePtr = GetAddrSpacePtr(AMDGPUAS::PRIVATE_ADDRESS);
207 
208   const LLT CodePtr = FlatPtr;
209 
210   const std::initializer_list<LLT> AddrSpaces64 = {
211     GlobalPtr, ConstantPtr, FlatPtr
212   };
213 
214   const std::initializer_list<LLT> AddrSpaces32 = {
215     LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
216   };
217 
218   const std::initializer_list<LLT> FPTypesBase = {
219     S32, S64
220   };
221 
222   const std::initializer_list<LLT> FPTypes16 = {
223     S32, S64, S16
224   };
225 
226   const std::initializer_list<LLT> FPTypesPK16 = {
227     S32, S64, S16, V2S16
228   };
229 
230   setAction({G_BRCOND, S1}, Legal);
231 
232   // TODO: All multiples of 32, vectors of pointers, all v2s16 pairs, more
233   // elements for v3s16
234   getActionDefinitionsBuilder(G_PHI)
235     .legalFor({S32, S64, V2S16, V4S16, S1, S128, S256})
236     .legalFor(AllS32Vectors)
237     .legalFor(AllS64Vectors)
238     .legalFor(AddrSpaces64)
239     .legalFor(AddrSpaces32)
240     .clampScalar(0, S32, S256)
241     .widenScalarToNextPow2(0, 32)
242     .clampMaxNumElements(0, S32, 16)
243     .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
244     .legalIf(isPointer(0));
245 
246   if (ST.has16BitInsts()) {
247     getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL})
248       .legalFor({S32, S16})
249       .clampScalar(0, S16, S32)
250       .scalarize(0);
251   } else {
252     getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL})
253       .legalFor({S32})
254       .clampScalar(0, S32, S32)
255       .scalarize(0);
256   }
257 
258   getActionDefinitionsBuilder({G_UMULH, G_SMULH})
259     .legalFor({S32})
260     .clampScalar(0, S32, S32)
261     .scalarize(0);
262 
263   // Report legal for any types we can handle anywhere. For the cases only legal
264   // on the SALU, RegBankSelect will be able to re-legalize.
265   getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
266     .legalFor({S32, S1, S64, V2S32, S16, V2S16, V4S16})
267     .clampScalar(0, S32, S64)
268     .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
269     .fewerElementsIf(vectorWiderThan(0, 32), fewerEltsToSize64Vector(0))
270     .widenScalarToNextPow2(0)
271     .scalarize(0);
272 
273   getActionDefinitionsBuilder({G_UADDO, G_SADDO, G_USUBO, G_SSUBO,
274                                G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
275     .legalFor({{S32, S1}})
276     .clampScalar(0, S32, S32);
277 
278   getActionDefinitionsBuilder(G_BITCAST)
279     .legalForCartesianProduct({S32, V2S16})
280     .legalForCartesianProduct({S64, V2S32, V4S16})
281     .legalForCartesianProduct({V2S64, V4S32})
282     // Don't worry about the size constraint.
283     .legalIf(all(isPointer(0), isPointer(1)))
284     // FIXME: Testing hack
285     .legalForCartesianProduct({S16, LLT::vector(2, 8), });
286 
287   getActionDefinitionsBuilder(G_FCONSTANT)
288     .legalFor({S32, S64, S16})
289     .clampScalar(0, S16, S64);
290 
291   getActionDefinitionsBuilder(G_IMPLICIT_DEF)
292     .legalFor({S1, S32, S64, S16, V2S32, V4S32, V2S16, V4S16, GlobalPtr,
293                ConstantPtr, LocalPtr, FlatPtr, PrivatePtr})
294     .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
295     .clampScalarOrElt(0, S32, S512)
296     .legalIf(isMultiple32(0))
297     .widenScalarToNextPow2(0, 32)
298     .clampMaxNumElements(0, S32, 16);
299 
300 
301   // FIXME: i1 operands to intrinsics should always be legal, but other i1
302   // values may not be legal.  We need to figure out how to distinguish
303   // between these two scenarios.
304   getActionDefinitionsBuilder(G_CONSTANT)
305     .legalFor({S1, S32, S64, S16, GlobalPtr,
306                LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
307     .clampScalar(0, S32, S64)
308     .widenScalarToNextPow2(0)
309     .legalIf(isPointer(0));
310 
311   setAction({G_FRAME_INDEX, PrivatePtr}, Legal);
312   getActionDefinitionsBuilder(G_GLOBAL_VALUE).customFor({LocalPtr});
313 
314 
315   auto &FPOpActions = getActionDefinitionsBuilder(
316     { G_FADD, G_FMUL, G_FMA, G_FCANONICALIZE})
317     .legalFor({S32, S64});
318   auto &TrigActions = getActionDefinitionsBuilder({G_FSIN, G_FCOS})
319     .customFor({S32, S64});
320 
321   if (ST.has16BitInsts()) {
322     if (ST.hasVOP3PInsts())
323       FPOpActions.legalFor({S16, V2S16});
324     else
325       FPOpActions.legalFor({S16});
326 
327     TrigActions.customFor({S16});
328   }
329 
330   auto &MinNumMaxNum = getActionDefinitionsBuilder({
331       G_FMINNUM, G_FMAXNUM, G_FMINNUM_IEEE, G_FMAXNUM_IEEE});
332 
333   if (ST.hasVOP3PInsts()) {
334     MinNumMaxNum.customFor(FPTypesPK16)
335       .clampMaxNumElements(0, S16, 2)
336       .clampScalar(0, S16, S64)
337       .scalarize(0);
338   } else if (ST.has16BitInsts()) {
339     MinNumMaxNum.customFor(FPTypes16)
340       .clampScalar(0, S16, S64)
341       .scalarize(0);
342   } else {
343     MinNumMaxNum.customFor(FPTypesBase)
344       .clampScalar(0, S32, S64)
345       .scalarize(0);
346   }
347 
348   if (ST.hasVOP3PInsts())
349     FPOpActions.clampMaxNumElements(0, S16, 2);
350 
351   FPOpActions
352     .scalarize(0)
353     .clampScalar(0, ST.has16BitInsts() ? S16 : S32, S64);
354 
355   TrigActions
356     .scalarize(0)
357     .clampScalar(0, ST.has16BitInsts() ? S16 : S32, S64);
358 
359   getActionDefinitionsBuilder({G_FNEG, G_FABS})
360     .legalFor(FPTypesPK16)
361     .clampMaxNumElements(0, S16, 2)
362     .scalarize(0)
363     .clampScalar(0, S16, S64);
364 
365   // TODO: Implement
366   getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM}).lower();
367 
368   if (ST.has16BitInsts()) {
369     getActionDefinitionsBuilder({G_FSQRT, G_FFLOOR})
370       .legalFor({S32, S64, S16})
371       .scalarize(0)
372       .clampScalar(0, S16, S64);
373   } else {
374     getActionDefinitionsBuilder({G_FSQRT, G_FFLOOR})
375       .legalFor({S32, S64})
376       .scalarize(0)
377       .clampScalar(0, S32, S64);
378   }
379 
380   getActionDefinitionsBuilder(G_FPTRUNC)
381     .legalFor({{S32, S64}, {S16, S32}})
382     .scalarize(0);
383 
384   getActionDefinitionsBuilder(G_FPEXT)
385     .legalFor({{S64, S32}, {S32, S16}})
386     .lowerFor({{S64, S16}}) // FIXME: Implement
387     .scalarize(0);
388 
389   // TODO: Verify V_BFI_B32 is generated from expanded bit ops.
390   getActionDefinitionsBuilder(G_FCOPYSIGN).lower();
391 
392   getActionDefinitionsBuilder(G_FSUB)
393       // Use actual fsub instruction
394       .legalFor({S32})
395       // Must use fadd + fneg
396       .lowerFor({S64, S16, V2S16})
397       .scalarize(0)
398       .clampScalar(0, S32, S64);
399 
400   // Whether this is legal depends on the floating point mode for the function.
401   auto &FMad = getActionDefinitionsBuilder(G_FMAD);
402   if (ST.hasMadF16())
403     FMad.customFor({S32, S16});
404   else
405     FMad.customFor({S32});
406   FMad.scalarize(0)
407       .lower();
408 
409   getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT})
410     .legalFor({{S64, S32}, {S32, S16}, {S64, S16},
411                {S32, S1}, {S64, S1}, {S16, S1},
412                {S96, S32},
413                // FIXME: Hack
414                {S64, LLT::scalar(33)},
415                {S32, S8}, {S128, S32}, {S128, S64}, {S32, LLT::scalar(24)}})
416     .scalarize(0);
417 
418   getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
419     .legalFor({{S32, S32}, {S64, S32}, {S16, S32}})
420     .lowerFor({{S32, S64}})
421     .customFor({{S64, S64}})
422     .scalarize(0);
423 
424   getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
425     .legalFor({{S32, S32}, {S32, S64}})
426     .scalarize(0);
427 
428   getActionDefinitionsBuilder(G_INTRINSIC_ROUND)
429     .legalFor({S32, S64})
430     .scalarize(0);
431 
432   if (ST.getGeneration() >= AMDGPUSubtarget::SEA_ISLANDS) {
433     getActionDefinitionsBuilder({G_INTRINSIC_TRUNC, G_FCEIL, G_FRINT})
434       .legalFor({S32, S64})
435       .clampScalar(0, S32, S64)
436       .scalarize(0);
437   } else {
438     getActionDefinitionsBuilder({G_INTRINSIC_TRUNC, G_FCEIL, G_FRINT})
439       .legalFor({S32})
440       .customFor({S64})
441       .clampScalar(0, S32, S64)
442       .scalarize(0);
443   }
444 
445   getActionDefinitionsBuilder(G_GEP)
446     .legalForCartesianProduct(AddrSpaces64, {S64})
447     .legalForCartesianProduct(AddrSpaces32, {S32})
448     .scalarize(0);
449 
450   getActionDefinitionsBuilder(G_PTR_MASK)
451     .scalarize(0)
452     .alwaysLegal();
453 
454   setAction({G_BLOCK_ADDR, CodePtr}, Legal);
455 
456   auto &CmpBuilder =
457     getActionDefinitionsBuilder(G_ICMP)
458     .legalForCartesianProduct(
459       {S1}, {S32, S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
460     .legalFor({{S1, S32}, {S1, S64}});
461   if (ST.has16BitInsts()) {
462     CmpBuilder.legalFor({{S1, S16}});
463   }
464 
465   CmpBuilder
466     .widenScalarToNextPow2(1)
467     .clampScalar(1, S32, S64)
468     .scalarize(0)
469     .legalIf(all(typeIs(0, S1), isPointer(1)));
470 
471   getActionDefinitionsBuilder(G_FCMP)
472     .legalForCartesianProduct({S1}, ST.has16BitInsts() ? FPTypes16 : FPTypesBase)
473     .widenScalarToNextPow2(1)
474     .clampScalar(1, S32, S64)
475     .scalarize(0);
476 
477   // FIXME: fexp, flog2, flog10 needs to be custom lowered.
478   getActionDefinitionsBuilder({G_FPOW, G_FEXP, G_FEXP2,
479                                G_FLOG, G_FLOG2, G_FLOG10})
480     .legalFor({S32})
481     .scalarize(0);
482 
483   // The 64-bit versions produce 32-bit results, but only on the SALU.
484   getActionDefinitionsBuilder({G_CTLZ, G_CTLZ_ZERO_UNDEF,
485                                G_CTTZ, G_CTTZ_ZERO_UNDEF,
486                                G_CTPOP})
487     .legalFor({{S32, S32}, {S32, S64}})
488     .clampScalar(0, S32, S32)
489     .clampScalar(1, S32, S64)
490     .scalarize(0)
491     .widenScalarToNextPow2(0, 32)
492     .widenScalarToNextPow2(1, 32);
493 
494   // TODO: Expand for > s32
495   getActionDefinitionsBuilder({G_BSWAP, G_BITREVERSE})
496     .legalFor({S32})
497     .clampScalar(0, S32, S32)
498     .scalarize(0);
499 
500   if (ST.has16BitInsts()) {
501     if (ST.hasVOP3PInsts()) {
502       getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
503         .legalFor({S32, S16, V2S16})
504         .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
505         .clampMaxNumElements(0, S16, 2)
506         .clampScalar(0, S16, S32)
507         .widenScalarToNextPow2(0)
508         .scalarize(0);
509     } else {
510       getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
511         .legalFor({S32, S16})
512         .widenScalarToNextPow2(0)
513         .clampScalar(0, S16, S32)
514         .scalarize(0);
515     }
516   } else {
517     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
518       .legalFor({S32})
519       .clampScalar(0, S32, S32)
520       .widenScalarToNextPow2(0)
521       .scalarize(0);
522   }
523 
524   auto smallerThan = [](unsigned TypeIdx0, unsigned TypeIdx1) {
525     return [=](const LegalityQuery &Query) {
526       return Query.Types[TypeIdx0].getSizeInBits() <
527              Query.Types[TypeIdx1].getSizeInBits();
528     };
529   };
530 
531   auto greaterThan = [](unsigned TypeIdx0, unsigned TypeIdx1) {
532     return [=](const LegalityQuery &Query) {
533       return Query.Types[TypeIdx0].getSizeInBits() >
534              Query.Types[TypeIdx1].getSizeInBits();
535     };
536   };
537 
538   getActionDefinitionsBuilder(G_INTTOPTR)
539     // List the common cases
540     .legalForCartesianProduct(AddrSpaces64, {S64})
541     .legalForCartesianProduct(AddrSpaces32, {S32})
542     .scalarize(0)
543     // Accept any address space as long as the size matches
544     .legalIf(sameSize(0, 1))
545     .widenScalarIf(smallerThan(1, 0),
546       [](const LegalityQuery &Query) {
547         return std::make_pair(1, LLT::scalar(Query.Types[0].getSizeInBits()));
548       })
549     .narrowScalarIf(greaterThan(1, 0),
550       [](const LegalityQuery &Query) {
551         return std::make_pair(1, LLT::scalar(Query.Types[0].getSizeInBits()));
552       });
553 
554   getActionDefinitionsBuilder(G_PTRTOINT)
555     // List the common cases
556     .legalForCartesianProduct(AddrSpaces64, {S64})
557     .legalForCartesianProduct(AddrSpaces32, {S32})
558     .scalarize(0)
559     // Accept any address space as long as the size matches
560     .legalIf(sameSize(0, 1))
561     .widenScalarIf(smallerThan(0, 1),
562       [](const LegalityQuery &Query) {
563         return std::make_pair(0, LLT::scalar(Query.Types[1].getSizeInBits()));
564       })
565     .narrowScalarIf(
566       greaterThan(0, 1),
567       [](const LegalityQuery &Query) {
568         return std::make_pair(0, LLT::scalar(Query.Types[1].getSizeInBits()));
569       });
570 
571   getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
572     .scalarize(0)
573     .custom();
574 
575   // TODO: Should load to s16 be legal? Most loads extend to 32-bits, but we
576   // handle some operations by just promoting the register during
577   // selection. There are also d16 loads on GFX9+ which preserve the high bits.
578   auto maxSizeForAddrSpace = [this](unsigned AS) -> unsigned {
579     switch (AS) {
580     // FIXME: Private element size.
581     case AMDGPUAS::PRIVATE_ADDRESS:
582       return 32;
583     // FIXME: Check subtarget
584     case AMDGPUAS::LOCAL_ADDRESS:
585       return ST.useDS128() ? 128 : 64;
586 
587     // Treat constant and global as identical. SMRD loads are sometimes usable
588     // for global loads (ideally constant address space should be eliminated)
589     // depending on the context. Legality cannot be context dependent, but
590     // RegBankSelect can split the load as necessary depending on the pointer
591     // register bank/uniformity and if the memory is invariant or not written in
592     // a kernel.
593     case AMDGPUAS::CONSTANT_ADDRESS:
594     case AMDGPUAS::GLOBAL_ADDRESS:
595       return 512;
596     default:
597       return 128;
598     }
599   };
600 
601   const auto needToSplitLoad = [=](const LegalityQuery &Query) -> bool {
602     const LLT DstTy = Query.Types[0];
603 
604     // Split vector extloads.
605     unsigned MemSize = Query.MMODescrs[0].SizeInBits;
606     if (DstTy.isVector() && DstTy.getSizeInBits() > MemSize)
607       return true;
608 
609     const LLT PtrTy = Query.Types[1];
610     unsigned AS = PtrTy.getAddressSpace();
611     if (MemSize > maxSizeForAddrSpace(AS))
612       return true;
613 
614     // Catch weird sized loads that don't evenly divide into the access sizes
615     // TODO: May be able to widen depending on alignment etc.
616     unsigned NumRegs = MemSize / 32;
617     if (NumRegs == 3 && !ST.hasDwordx3LoadStores())
618       return true;
619 
620     unsigned Align = Query.MMODescrs[0].AlignInBits;
621     if (Align < MemSize) {
622       const SITargetLowering *TLI = ST.getTargetLowering();
623       return !TLI->allowsMisalignedMemoryAccessesImpl(MemSize, AS, Align / 8);
624     }
625 
626     return false;
627   };
628 
629   unsigned GlobalAlign32 = ST.hasUnalignedBufferAccess() ? 0 : 32;
630   unsigned GlobalAlign16 = ST.hasUnalignedBufferAccess() ? 0 : 16;
631   unsigned GlobalAlign8 = ST.hasUnalignedBufferAccess() ? 0 : 8;
632 
633   // TODO: Refine based on subtargets which support unaligned access or 128-bit
634   // LDS
635   // TODO: Unsupported flat for SI.
636 
637   for (unsigned Op : {G_LOAD, G_STORE}) {
638     const bool IsStore = Op == G_STORE;
639 
640     auto &Actions = getActionDefinitionsBuilder(Op);
641     // Whitelist the common cases.
642     // TODO: Pointer loads
643     // TODO: Wide constant loads
644     // TODO: Only CI+ has 3x loads
645     // TODO: Loads to s16 on gfx9
646     Actions.legalForTypesWithMemDesc({{S32, GlobalPtr, 32, GlobalAlign32},
647                                       {V2S32, GlobalPtr, 64, GlobalAlign32},
648                                       {V3S32, GlobalPtr, 96, GlobalAlign32},
649                                       {S96, GlobalPtr, 96, GlobalAlign32},
650                                       {V4S32, GlobalPtr, 128, GlobalAlign32},
651                                       {S128, GlobalPtr, 128, GlobalAlign32},
652                                       {S64, GlobalPtr, 64, GlobalAlign32},
653                                       {V2S64, GlobalPtr, 128, GlobalAlign32},
654                                       {V2S16, GlobalPtr, 32, GlobalAlign32},
655                                       {S32, GlobalPtr, 8, GlobalAlign8},
656                                       {S32, GlobalPtr, 16, GlobalAlign16},
657 
658                                       {S32, LocalPtr, 32, 32},
659                                       {S64, LocalPtr, 64, 32},
660                                       {V2S32, LocalPtr, 64, 32},
661                                       {S32, LocalPtr, 8, 8},
662                                       {S32, LocalPtr, 16, 16},
663                                       {V2S16, LocalPtr, 32, 32},
664 
665                                       {S32, PrivatePtr, 32, 32},
666                                       {S32, PrivatePtr, 8, 8},
667                                       {S32, PrivatePtr, 16, 16},
668                                       {V2S16, PrivatePtr, 32, 32},
669 
670                                       {S32, FlatPtr, 32, GlobalAlign32},
671                                       {S32, FlatPtr, 16, GlobalAlign16},
672                                       {S32, FlatPtr, 8, GlobalAlign8},
673                                       {V2S16, FlatPtr, 32, GlobalAlign32},
674 
675                                       {S32, ConstantPtr, 32, GlobalAlign32},
676                                       {V2S32, ConstantPtr, 64, GlobalAlign32},
677                                       {V3S32, ConstantPtr, 96, GlobalAlign32},
678                                       {V4S32, ConstantPtr, 128, GlobalAlign32},
679                                       {S64, ConstantPtr, 64, GlobalAlign32},
680                                       {S128, ConstantPtr, 128, GlobalAlign32},
681                                       {V2S32, ConstantPtr, 32, GlobalAlign32}});
682     Actions
683         .customIf(typeIs(1, Constant32Ptr))
684         .narrowScalarIf(
685             [=](const LegalityQuery &Query) -> bool {
686               return !Query.Types[0].isVector() && needToSplitLoad(Query);
687             },
688             [=](const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
689               const LLT DstTy = Query.Types[0];
690               const LLT PtrTy = Query.Types[1];
691 
692               const unsigned DstSize = DstTy.getSizeInBits();
693               unsigned MemSize = Query.MMODescrs[0].SizeInBits;
694 
695               // Split extloads.
696               if (DstSize > MemSize)
697                 return std::make_pair(0, LLT::scalar(MemSize));
698 
699               if (DstSize > 32 && (DstSize % 32 != 0)) {
700                 // FIXME: Need a way to specify non-extload of larger size if
701                 // suitably aligned.
702                 return std::make_pair(0, LLT::scalar(32 * (DstSize / 32)));
703               }
704 
705               unsigned MaxSize = maxSizeForAddrSpace(PtrTy.getAddressSpace());
706               if (MemSize > MaxSize)
707                 return std::make_pair(0, LLT::scalar(MaxSize));
708 
709               unsigned Align = Query.MMODescrs[0].AlignInBits;
710               return std::make_pair(0, LLT::scalar(Align));
711             })
712         .fewerElementsIf(
713             [=](const LegalityQuery &Query) -> bool {
714               return Query.Types[0].isVector() && needToSplitLoad(Query);
715             },
716             [=](const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
717               const LLT DstTy = Query.Types[0];
718               const LLT PtrTy = Query.Types[1];
719 
720               LLT EltTy = DstTy.getElementType();
721               unsigned MaxSize = maxSizeForAddrSpace(PtrTy.getAddressSpace());
722 
723               // Split if it's too large for the address space.
724               if (Query.MMODescrs[0].SizeInBits > MaxSize) {
725                 unsigned NumElts = DstTy.getNumElements();
726                 unsigned NumPieces = Query.MMODescrs[0].SizeInBits / MaxSize;
727 
728                 // FIXME: Refine when odd breakdowns handled
729                 // The scalars will need to be re-legalized.
730                 if (NumPieces == 1 || NumPieces >= NumElts ||
731                     NumElts % NumPieces != 0)
732                   return std::make_pair(0, EltTy);
733 
734                 return std::make_pair(0,
735                                       LLT::vector(NumElts / NumPieces, EltTy));
736               }
737 
738               // Need to split because of alignment.
739               unsigned Align = Query.MMODescrs[0].AlignInBits;
740               unsigned EltSize = EltTy.getSizeInBits();
741               if (EltSize > Align &&
742                   (EltSize / Align < DstTy.getNumElements())) {
743                 return std::make_pair(0, LLT::vector(EltSize / Align, EltTy));
744               }
745 
746               // May need relegalization for the scalars.
747               return std::make_pair(0, EltTy);
748             })
749         .minScalar(0, S32);
750 
751     if (IsStore)
752       Actions.narrowScalarIf(isWideScalarTruncStore(0), changeTo(0, S32));
753 
754     // TODO: Need a bitcast lower option?
755     Actions
756         .legalIf([=](const LegalityQuery &Query) {
757           const LLT Ty0 = Query.Types[0];
758           unsigned Size = Ty0.getSizeInBits();
759           unsigned MemSize = Query.MMODescrs[0].SizeInBits;
760           unsigned Align = Query.MMODescrs[0].AlignInBits;
761 
762           // No extending vector loads.
763           if (Size > MemSize && Ty0.isVector())
764             return false;
765 
766           // FIXME: Widening store from alignment not valid.
767           if (MemSize < Size)
768             MemSize = std::max(MemSize, Align);
769 
770           switch (MemSize) {
771           case 8:
772           case 16:
773             return Size == 32;
774           case 32:
775           case 64:
776           case 128:
777             return true;
778           case 96:
779             return ST.hasDwordx3LoadStores();
780           case 256:
781           case 512:
782             return true;
783           default:
784             return false;
785           }
786         })
787         .widenScalarToNextPow2(0)
788         // TODO: v3s32->v4s32 with alignment
789         .moreElementsIf(vectorSmallerThan(0, 32), moreEltsToNext32Bit(0));
790   }
791 
792   auto &ExtLoads = getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
793                        .legalForTypesWithMemDesc({{S32, GlobalPtr, 8, 8},
794                                                   {S32, GlobalPtr, 16, 2 * 8},
795                                                   {S32, LocalPtr, 8, 8},
796                                                   {S32, LocalPtr, 16, 16},
797                                                   {S32, PrivatePtr, 8, 8},
798                                                   {S32, PrivatePtr, 16, 16},
799                                                   {S32, ConstantPtr, 8, 8},
800                                                   {S32, ConstantPtr, 16, 2 * 8}});
801   if (ST.hasFlatAddressSpace()) {
802     ExtLoads.legalForTypesWithMemDesc(
803         {{S32, FlatPtr, 8, 8}, {S32, FlatPtr, 16, 16}});
804   }
805 
806   ExtLoads.clampScalar(0, S32, S32)
807           .widenScalarToNextPow2(0)
808           .unsupportedIfMemSizeNotPow2()
809           .lower();
810 
811   auto &Atomics = getActionDefinitionsBuilder(
812     {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
813      G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
814      G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
815      G_ATOMICRMW_UMIN, G_ATOMIC_CMPXCHG})
816     .legalFor({{S32, GlobalPtr}, {S32, LocalPtr},
817                {S64, GlobalPtr}, {S64, LocalPtr}});
818   if (ST.hasFlatAddressSpace()) {
819     Atomics.legalFor({{S32, FlatPtr}, {S64, FlatPtr}});
820   }
821 
822   getActionDefinitionsBuilder(G_ATOMICRMW_FADD)
823     .legalFor({{S32, LocalPtr}});
824 
825   // TODO: Pointer types, any 32-bit or 64-bit vector
826   getActionDefinitionsBuilder(G_SELECT)
827     .legalForCartesianProduct({S32, S64, S16, V2S32, V2S16, V4S16,
828           GlobalPtr, LocalPtr, FlatPtr, PrivatePtr,
829           LLT::vector(2, LocalPtr), LLT::vector(2, PrivatePtr)}, {S1})
830     .clampScalar(0, S16, S64)
831     .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
832     .fewerElementsIf(numElementsNotEven(0), scalarize(0))
833     .scalarize(1)
834     .clampMaxNumElements(0, S32, 2)
835     .clampMaxNumElements(0, LocalPtr, 2)
836     .clampMaxNumElements(0, PrivatePtr, 2)
837     .scalarize(0)
838     .widenScalarToNextPow2(0)
839     .legalIf(all(isPointer(0), typeIs(1, S1)));
840 
841   // TODO: Only the low 4/5/6 bits of the shift amount are observed, so we can
842   // be more flexible with the shift amount type.
843   auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
844     .legalFor({{S32, S32}, {S64, S32}});
845   if (ST.has16BitInsts()) {
846     if (ST.hasVOP3PInsts()) {
847       Shifts.legalFor({{S16, S32}, {S16, S16}, {V2S16, V2S16}})
848             .clampMaxNumElements(0, S16, 2);
849     } else
850       Shifts.legalFor({{S16, S32}, {S16, S16}});
851 
852     Shifts.clampScalar(1, S16, S32);
853     Shifts.clampScalar(0, S16, S64);
854     Shifts.widenScalarToNextPow2(0, 16);
855   } else {
856     // Make sure we legalize the shift amount type first, as the general
857     // expansion for the shifted type will produce much worse code if it hasn't
858     // been truncated already.
859     Shifts.clampScalar(1, S32, S32);
860     Shifts.clampScalar(0, S32, S64);
861     Shifts.widenScalarToNextPow2(0, 32);
862   }
863   Shifts.scalarize(0);
864 
865   for (unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
866     unsigned VecTypeIdx = Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
867     unsigned EltTypeIdx = Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
868     unsigned IdxTypeIdx = 2;
869 
870     getActionDefinitionsBuilder(Op)
871       .customIf([=](const LegalityQuery &Query) {
872           const LLT EltTy = Query.Types[EltTypeIdx];
873           const LLT VecTy = Query.Types[VecTypeIdx];
874           const LLT IdxTy = Query.Types[IdxTypeIdx];
875           return (EltTy.getSizeInBits() == 16 ||
876                   EltTy.getSizeInBits() % 32 == 0) &&
877                  VecTy.getSizeInBits() % 32 == 0 &&
878                  VecTy.getSizeInBits() <= 512 &&
879                  IdxTy.getSizeInBits() == 32;
880         })
881       .clampScalar(EltTypeIdx, S32, S64)
882       .clampScalar(VecTypeIdx, S32, S64)
883       .clampScalar(IdxTypeIdx, S32, S32);
884   }
885 
886   getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
887     .unsupportedIf([=](const LegalityQuery &Query) {
888         const LLT &EltTy = Query.Types[1].getElementType();
889         return Query.Types[0] != EltTy;
890       });
891 
892   for (unsigned Op : {G_EXTRACT, G_INSERT}) {
893     unsigned BigTyIdx = Op == G_EXTRACT ? 1 : 0;
894     unsigned LitTyIdx = Op == G_EXTRACT ? 0 : 1;
895 
896     // FIXME: Doesn't handle extract of illegal sizes.
897     getActionDefinitionsBuilder(Op)
898       .legalIf([=](const LegalityQuery &Query) {
899           const LLT BigTy = Query.Types[BigTyIdx];
900           const LLT LitTy = Query.Types[LitTyIdx];
901           return (BigTy.getSizeInBits() % 32 == 0) &&
902                  (LitTy.getSizeInBits() % 16 == 0);
903         })
904       .widenScalarIf(
905         [=](const LegalityQuery &Query) {
906           const LLT BigTy = Query.Types[BigTyIdx];
907           return (BigTy.getScalarSizeInBits() < 16);
908         },
909         LegalizeMutations::widenScalarOrEltToNextPow2(BigTyIdx, 16))
910       .widenScalarIf(
911         [=](const LegalityQuery &Query) {
912           const LLT LitTy = Query.Types[LitTyIdx];
913           return (LitTy.getScalarSizeInBits() < 16);
914         },
915         LegalizeMutations::widenScalarOrEltToNextPow2(LitTyIdx, 16))
916       .moreElementsIf(isSmallOddVector(BigTyIdx), oneMoreElement(BigTyIdx))
917       .widenScalarToNextPow2(BigTyIdx, 32);
918 
919   }
920 
921   auto &BuildVector = getActionDefinitionsBuilder(G_BUILD_VECTOR)
922     .legalForCartesianProduct(AllS32Vectors, {S32})
923     .legalForCartesianProduct(AllS64Vectors, {S64})
924     .clampNumElements(0, V16S32, V16S32)
925     .clampNumElements(0, V2S64, V8S64);
926 
927   if (ST.hasScalarPackInsts())
928     BuildVector.legalFor({V2S16, S32});
929 
930   BuildVector
931     .minScalarSameAs(1, 0)
932     .legalIf(isRegisterType(0))
933     .minScalarOrElt(0, S32);
934 
935   if (ST.hasScalarPackInsts()) {
936     getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
937       .legalFor({V2S16, S32})
938       .lower();
939   } else {
940     getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
941       .lower();
942   }
943 
944   getActionDefinitionsBuilder(G_CONCAT_VECTORS)
945     .legalIf(isRegisterType(0));
946 
947   // TODO: Don't fully scalarize v2s16 pieces
948   getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
949 
950   // Merge/Unmerge
951   for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
952     unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;
953     unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;
954 
955     auto notValidElt = [=](const LegalityQuery &Query, unsigned TypeIdx) {
956       const LLT &Ty = Query.Types[TypeIdx];
957       if (Ty.isVector()) {
958         const LLT &EltTy = Ty.getElementType();
959         if (EltTy.getSizeInBits() < 8 || EltTy.getSizeInBits() > 64)
960           return true;
961         if (!isPowerOf2_32(EltTy.getSizeInBits()))
962           return true;
963       }
964       return false;
965     };
966 
967     getActionDefinitionsBuilder(Op)
968       .widenScalarToNextPow2(LitTyIdx, /*Min*/ 16)
969       // Clamp the little scalar to s8-s256 and make it a power of 2. It's not
970       // worth considering the multiples of 64 since 2*192 and 2*384 are not
971       // valid.
972       .clampScalar(LitTyIdx, S16, S256)
973       .widenScalarToNextPow2(LitTyIdx, /*Min*/ 32)
974       .moreElementsIf(isSmallOddVector(BigTyIdx), oneMoreElement(BigTyIdx))
975       .fewerElementsIf(all(typeIs(0, S16), vectorWiderThan(1, 32),
976                            elementTypeIs(1, S16)),
977                        changeTo(1, V2S16))
978       // Break up vectors with weird elements into scalars
979       .fewerElementsIf(
980         [=](const LegalityQuery &Query) { return notValidElt(Query, 0); },
981         scalarize(0))
982       .fewerElementsIf(
983         [=](const LegalityQuery &Query) { return notValidElt(Query, 1); },
984         scalarize(1))
985       .clampScalar(BigTyIdx, S32, S512)
986       .lowerFor({{S16, V2S16}})
987       .widenScalarIf(
988         [=](const LegalityQuery &Query) {
989           const LLT &Ty = Query.Types[BigTyIdx];
990           return !isPowerOf2_32(Ty.getSizeInBits()) &&
991                  Ty.getSizeInBits() % 16 != 0;
992         },
993         [=](const LegalityQuery &Query) {
994           // Pick the next power of 2, or a multiple of 64 over 128.
995           // Whichever is smaller.
996           const LLT &Ty = Query.Types[BigTyIdx];
997           unsigned NewSizeInBits = 1 << Log2_32_Ceil(Ty.getSizeInBits() + 1);
998           if (NewSizeInBits >= 256) {
999             unsigned RoundedTo = alignTo<64>(Ty.getSizeInBits() + 1);
1000             if (RoundedTo < NewSizeInBits)
1001               NewSizeInBits = RoundedTo;
1002           }
1003           return std::make_pair(BigTyIdx, LLT::scalar(NewSizeInBits));
1004         })
1005       .legalIf([=](const LegalityQuery &Query) {
1006           const LLT &BigTy = Query.Types[BigTyIdx];
1007           const LLT &LitTy = Query.Types[LitTyIdx];
1008 
1009           if (BigTy.isVector() && BigTy.getSizeInBits() < 32)
1010             return false;
1011           if (LitTy.isVector() && LitTy.getSizeInBits() < 32)
1012             return false;
1013 
1014           return BigTy.getSizeInBits() % 16 == 0 &&
1015                  LitTy.getSizeInBits() % 16 == 0 &&
1016                  BigTy.getSizeInBits() <= 512;
1017         })
1018       // Any vectors left are the wrong size. Scalarize them.
1019       .scalarize(0)
1020       .scalarize(1);
1021   }
1022 
1023   getActionDefinitionsBuilder(G_SEXT_INREG).lower();
1024 
1025   computeTables();
1026   verify(*ST.getInstrInfo());
1027 }
1028 
1029 bool AMDGPULegalizerInfo::legalizeCustom(MachineInstr &MI,
1030                                          MachineRegisterInfo &MRI,
1031                                          MachineIRBuilder &B,
1032                                          GISelChangeObserver &Observer) const {
1033   switch (MI.getOpcode()) {
1034   case TargetOpcode::G_ADDRSPACE_CAST:
1035     return legalizeAddrSpaceCast(MI, MRI, B);
1036   case TargetOpcode::G_FRINT:
1037     return legalizeFrint(MI, MRI, B);
1038   case TargetOpcode::G_FCEIL:
1039     return legalizeFceil(MI, MRI, B);
1040   case TargetOpcode::G_INTRINSIC_TRUNC:
1041     return legalizeIntrinsicTrunc(MI, MRI, B);
1042   case TargetOpcode::G_SITOFP:
1043     return legalizeITOFP(MI, MRI, B, true);
1044   case TargetOpcode::G_UITOFP:
1045     return legalizeITOFP(MI, MRI, B, false);
1046   case TargetOpcode::G_FMINNUM:
1047   case TargetOpcode::G_FMAXNUM:
1048   case TargetOpcode::G_FMINNUM_IEEE:
1049   case TargetOpcode::G_FMAXNUM_IEEE:
1050     return legalizeMinNumMaxNum(MI, MRI, B);
1051   case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1052     return legalizeExtractVectorElt(MI, MRI, B);
1053   case TargetOpcode::G_INSERT_VECTOR_ELT:
1054     return legalizeInsertVectorElt(MI, MRI, B);
1055   case TargetOpcode::G_FSIN:
1056   case TargetOpcode::G_FCOS:
1057     return legalizeSinCos(MI, MRI, B);
1058   case TargetOpcode::G_GLOBAL_VALUE:
1059     return legalizeGlobalValue(MI, MRI, B);
1060   case TargetOpcode::G_LOAD:
1061     return legalizeLoad(MI, MRI, B, Observer);
1062   case TargetOpcode::G_FMAD:
1063     return legalizeFMad(MI, MRI, B);
1064   default:
1065     return false;
1066   }
1067 
1068   llvm_unreachable("expected switch to return");
1069 }
1070 
1071 Register AMDGPULegalizerInfo::getSegmentAperture(
1072   unsigned AS,
1073   MachineRegisterInfo &MRI,
1074   MachineIRBuilder &B) const {
1075   MachineFunction &MF = B.getMF();
1076   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1077   const LLT S32 = LLT::scalar(32);
1078 
1079   if (ST.hasApertureRegs()) {
1080     // FIXME: Use inline constants (src_{shared, private}_base) instead of
1081     // getreg.
1082     unsigned Offset = AS == AMDGPUAS::LOCAL_ADDRESS ?
1083         AMDGPU::Hwreg::OFFSET_SRC_SHARED_BASE :
1084         AMDGPU::Hwreg::OFFSET_SRC_PRIVATE_BASE;
1085     unsigned WidthM1 = AS == AMDGPUAS::LOCAL_ADDRESS ?
1086         AMDGPU::Hwreg::WIDTH_M1_SRC_SHARED_BASE :
1087         AMDGPU::Hwreg::WIDTH_M1_SRC_PRIVATE_BASE;
1088     unsigned Encoding =
1089         AMDGPU::Hwreg::ID_MEM_BASES << AMDGPU::Hwreg::ID_SHIFT_ |
1090         Offset << AMDGPU::Hwreg::OFFSET_SHIFT_ |
1091         WidthM1 << AMDGPU::Hwreg::WIDTH_M1_SHIFT_;
1092 
1093     Register ApertureReg = MRI.createGenericVirtualRegister(S32);
1094     Register GetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1095 
1096     B.buildInstr(AMDGPU::S_GETREG_B32)
1097       .addDef(GetReg)
1098       .addImm(Encoding);
1099     MRI.setType(GetReg, S32);
1100 
1101     auto ShiftAmt = B.buildConstant(S32, WidthM1 + 1);
1102     B.buildInstr(TargetOpcode::G_SHL)
1103       .addDef(ApertureReg)
1104       .addUse(GetReg)
1105       .addUse(ShiftAmt.getReg(0));
1106 
1107     return ApertureReg;
1108   }
1109 
1110   Register QueuePtr = MRI.createGenericVirtualRegister(
1111     LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64));
1112 
1113   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1114   if (!loadInputValue(QueuePtr, B, &MFI->getArgInfo().QueuePtr))
1115     return Register();
1116 
1117   // Offset into amd_queue_t for group_segment_aperture_base_hi /
1118   // private_segment_aperture_base_hi.
1119   uint32_t StructOffset = (AS == AMDGPUAS::LOCAL_ADDRESS) ? 0x40 : 0x44;
1120 
1121   // FIXME: Don't use undef
1122   Value *V = UndefValue::get(PointerType::get(
1123                                Type::getInt8Ty(MF.getFunction().getContext()),
1124                                AMDGPUAS::CONSTANT_ADDRESS));
1125 
1126   MachinePointerInfo PtrInfo(V, StructOffset);
1127   MachineMemOperand *MMO = MF.getMachineMemOperand(
1128     PtrInfo,
1129     MachineMemOperand::MOLoad |
1130     MachineMemOperand::MODereferenceable |
1131     MachineMemOperand::MOInvariant,
1132     4,
1133     MinAlign(64, StructOffset));
1134 
1135   Register LoadResult = MRI.createGenericVirtualRegister(S32);
1136   Register LoadAddr;
1137 
1138   B.materializeGEP(LoadAddr, QueuePtr, LLT::scalar(64), StructOffset);
1139   B.buildLoad(LoadResult, LoadAddr, *MMO);
1140   return LoadResult;
1141 }
1142 
1143 bool AMDGPULegalizerInfo::legalizeAddrSpaceCast(
1144   MachineInstr &MI, MachineRegisterInfo &MRI,
1145   MachineIRBuilder &B) const {
1146   MachineFunction &MF = B.getMF();
1147 
1148   B.setInstr(MI);
1149 
1150   const LLT S32 = LLT::scalar(32);
1151   Register Dst = MI.getOperand(0).getReg();
1152   Register Src = MI.getOperand(1).getReg();
1153 
1154   LLT DstTy = MRI.getType(Dst);
1155   LLT SrcTy = MRI.getType(Src);
1156   unsigned DestAS = DstTy.getAddressSpace();
1157   unsigned SrcAS = SrcTy.getAddressSpace();
1158 
1159   // TODO: Avoid reloading from the queue ptr for each cast, or at least each
1160   // vector element.
1161   assert(!DstTy.isVector());
1162 
1163   const AMDGPUTargetMachine &TM
1164     = static_cast<const AMDGPUTargetMachine &>(MF.getTarget());
1165 
1166   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1167   if (ST.getTargetLowering()->isNoopAddrSpaceCast(SrcAS, DestAS)) {
1168     MI.setDesc(B.getTII().get(TargetOpcode::G_BITCAST));
1169     return true;
1170   }
1171 
1172   if (DestAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) {
1173     // Truncate.
1174     B.buildExtract(Dst, Src, 0);
1175     MI.eraseFromParent();
1176     return true;
1177   }
1178 
1179   if (SrcAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) {
1180     const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
1181     uint32_t AddrHiVal = Info->get32BitAddressHighBits();
1182 
1183     // FIXME: This is a bit ugly due to creating a merge of 2 pointers to
1184     // another. Merge operands are required to be the same type, but creating an
1185     // extra ptrtoint would be kind of pointless.
1186     auto HighAddr = B.buildConstant(
1187       LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS_32BIT, 32), AddrHiVal);
1188     B.buildMerge(Dst, {Src, HighAddr.getReg(0)});
1189     MI.eraseFromParent();
1190     return true;
1191   }
1192 
1193   if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
1194     assert(DestAS == AMDGPUAS::LOCAL_ADDRESS ||
1195            DestAS == AMDGPUAS::PRIVATE_ADDRESS);
1196     unsigned NullVal = TM.getNullPointerValue(DestAS);
1197 
1198     auto SegmentNull = B.buildConstant(DstTy, NullVal);
1199     auto FlatNull = B.buildConstant(SrcTy, 0);
1200 
1201     Register PtrLo32 = MRI.createGenericVirtualRegister(DstTy);
1202 
1203     // Extract low 32-bits of the pointer.
1204     B.buildExtract(PtrLo32, Src, 0);
1205 
1206     Register CmpRes = MRI.createGenericVirtualRegister(LLT::scalar(1));
1207     B.buildICmp(CmpInst::ICMP_NE, CmpRes, Src, FlatNull.getReg(0));
1208     B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
1209 
1210     MI.eraseFromParent();
1211     return true;
1212   }
1213 
1214   if (SrcAS != AMDGPUAS::LOCAL_ADDRESS && SrcAS != AMDGPUAS::PRIVATE_ADDRESS)
1215     return false;
1216 
1217   if (!ST.hasFlatAddressSpace())
1218     return false;
1219 
1220   auto SegmentNull =
1221       B.buildConstant(SrcTy, TM.getNullPointerValue(SrcAS));
1222   auto FlatNull =
1223       B.buildConstant(DstTy, TM.getNullPointerValue(DestAS));
1224 
1225   Register ApertureReg = getSegmentAperture(DestAS, MRI, B);
1226   if (!ApertureReg.isValid())
1227     return false;
1228 
1229   Register CmpRes = MRI.createGenericVirtualRegister(LLT::scalar(1));
1230   B.buildICmp(CmpInst::ICMP_NE, CmpRes, Src, SegmentNull.getReg(0));
1231 
1232   Register BuildPtr = MRI.createGenericVirtualRegister(DstTy);
1233 
1234   // Coerce the type of the low half of the result so we can use merge_values.
1235   Register SrcAsInt = MRI.createGenericVirtualRegister(S32);
1236   B.buildInstr(TargetOpcode::G_PTRTOINT)
1237     .addDef(SrcAsInt)
1238     .addUse(Src);
1239 
1240   // TODO: Should we allow mismatched types but matching sizes in merges to
1241   // avoid the ptrtoint?
1242   B.buildMerge(BuildPtr, {SrcAsInt, ApertureReg});
1243   B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull.getReg(0));
1244 
1245   MI.eraseFromParent();
1246   return true;
1247 }
1248 
1249 bool AMDGPULegalizerInfo::legalizeFrint(
1250   MachineInstr &MI, MachineRegisterInfo &MRI,
1251   MachineIRBuilder &B) const {
1252   B.setInstr(MI);
1253 
1254   Register Src = MI.getOperand(1).getReg();
1255   LLT Ty = MRI.getType(Src);
1256   assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
1257 
1258   APFloat C1Val(APFloat::IEEEdouble(), "0x1.0p+52");
1259   APFloat C2Val(APFloat::IEEEdouble(), "0x1.fffffffffffffp+51");
1260 
1261   auto C1 = B.buildFConstant(Ty, C1Val);
1262   auto CopySign = B.buildFCopysign(Ty, C1, Src);
1263 
1264   // TODO: Should this propagate fast-math-flags?
1265   auto Tmp1 = B.buildFAdd(Ty, Src, CopySign);
1266   auto Tmp2 = B.buildFSub(Ty, Tmp1, CopySign);
1267 
1268   auto C2 = B.buildFConstant(Ty, C2Val);
1269   auto Fabs = B.buildFAbs(Ty, Src);
1270 
1271   auto Cond = B.buildFCmp(CmpInst::FCMP_OGT, LLT::scalar(1), Fabs, C2);
1272   B.buildSelect(MI.getOperand(0).getReg(), Cond, Src, Tmp2);
1273   return true;
1274 }
1275 
1276 bool AMDGPULegalizerInfo::legalizeFceil(
1277   MachineInstr &MI, MachineRegisterInfo &MRI,
1278   MachineIRBuilder &B) const {
1279   B.setInstr(MI);
1280 
1281   const LLT S1 = LLT::scalar(1);
1282   const LLT S64 = LLT::scalar(64);
1283 
1284   Register Src = MI.getOperand(1).getReg();
1285   assert(MRI.getType(Src) == S64);
1286 
1287   // result = trunc(src)
1288   // if (src > 0.0 && src != result)
1289   //   result += 1.0
1290 
1291   auto Trunc = B.buildInstr(TargetOpcode::G_INTRINSIC_TRUNC, {S64}, {Src});
1292 
1293   const auto Zero = B.buildFConstant(S64, 0.0);
1294   const auto One = B.buildFConstant(S64, 1.0);
1295   auto Lt0 = B.buildFCmp(CmpInst::FCMP_OGT, S1, Src, Zero);
1296   auto NeTrunc = B.buildFCmp(CmpInst::FCMP_ONE, S1, Src, Trunc);
1297   auto And = B.buildAnd(S1, Lt0, NeTrunc);
1298   auto Add = B.buildSelect(S64, And, One, Zero);
1299 
1300   // TODO: Should this propagate fast-math-flags?
1301   B.buildFAdd(MI.getOperand(0).getReg(), Trunc, Add);
1302   return true;
1303 }
1304 
1305 static MachineInstrBuilder extractF64Exponent(unsigned Hi,
1306                                               MachineIRBuilder &B) {
1307   const unsigned FractBits = 52;
1308   const unsigned ExpBits = 11;
1309   LLT S32 = LLT::scalar(32);
1310 
1311   auto Const0 = B.buildConstant(S32, FractBits - 32);
1312   auto Const1 = B.buildConstant(S32, ExpBits);
1313 
1314   auto ExpPart = B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {S32}, false)
1315     .addUse(Const0.getReg(0))
1316     .addUse(Const1.getReg(0));
1317 
1318   return B.buildSub(S32, ExpPart, B.buildConstant(S32, 1023));
1319 }
1320 
1321 bool AMDGPULegalizerInfo::legalizeIntrinsicTrunc(
1322   MachineInstr &MI, MachineRegisterInfo &MRI,
1323   MachineIRBuilder &B) const {
1324   B.setInstr(MI);
1325 
1326   const LLT S1 = LLT::scalar(1);
1327   const LLT S32 = LLT::scalar(32);
1328   const LLT S64 = LLT::scalar(64);
1329 
1330   Register Src = MI.getOperand(1).getReg();
1331   assert(MRI.getType(Src) == S64);
1332 
1333   // TODO: Should this use extract since the low half is unused?
1334   auto Unmerge = B.buildUnmerge({S32, S32}, Src);
1335   Register Hi = Unmerge.getReg(1);
1336 
1337   // Extract the upper half, since this is where we will find the sign and
1338   // exponent.
1339   auto Exp = extractF64Exponent(Hi, B);
1340 
1341   const unsigned FractBits = 52;
1342 
1343   // Extract the sign bit.
1344   const auto SignBitMask = B.buildConstant(S32, UINT32_C(1) << 31);
1345   auto SignBit = B.buildAnd(S32, Hi, SignBitMask);
1346 
1347   const auto FractMask = B.buildConstant(S64, (UINT64_C(1) << FractBits) - 1);
1348 
1349   const auto Zero32 = B.buildConstant(S32, 0);
1350 
1351   // Extend back to 64-bits.
1352   auto SignBit64 = B.buildMerge(S64, {Zero32.getReg(0), SignBit.getReg(0)});
1353 
1354   auto Shr = B.buildAShr(S64, FractMask, Exp);
1355   auto Not = B.buildNot(S64, Shr);
1356   auto Tmp0 = B.buildAnd(S64, Src, Not);
1357   auto FiftyOne = B.buildConstant(S32, FractBits - 1);
1358 
1359   auto ExpLt0 = B.buildICmp(CmpInst::ICMP_SLT, S1, Exp, Zero32);
1360   auto ExpGt51 = B.buildICmp(CmpInst::ICMP_SGT, S1, Exp, FiftyOne);
1361 
1362   auto Tmp1 = B.buildSelect(S64, ExpLt0, SignBit64, Tmp0);
1363   B.buildSelect(MI.getOperand(0).getReg(), ExpGt51, Src, Tmp1);
1364   return true;
1365 }
1366 
1367 bool AMDGPULegalizerInfo::legalizeITOFP(
1368   MachineInstr &MI, MachineRegisterInfo &MRI,
1369   MachineIRBuilder &B, bool Signed) const {
1370   B.setInstr(MI);
1371 
1372   Register Dst = MI.getOperand(0).getReg();
1373   Register Src = MI.getOperand(1).getReg();
1374 
1375   const LLT S64 = LLT::scalar(64);
1376   const LLT S32 = LLT::scalar(32);
1377 
1378   assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S64);
1379 
1380   auto Unmerge = B.buildUnmerge({S32, S32}, Src);
1381 
1382   auto CvtHi = Signed ?
1383     B.buildSITOFP(S64, Unmerge.getReg(1)) :
1384     B.buildUITOFP(S64, Unmerge.getReg(1));
1385 
1386   auto CvtLo = B.buildUITOFP(S64, Unmerge.getReg(0));
1387 
1388   auto ThirtyTwo = B.buildConstant(S32, 32);
1389   auto LdExp = B.buildIntrinsic(Intrinsic::amdgcn_ldexp, {S64}, false)
1390     .addUse(CvtHi.getReg(0))
1391     .addUse(ThirtyTwo.getReg(0));
1392 
1393   // TODO: Should this propagate fast-math-flags?
1394   B.buildFAdd(Dst, LdExp, CvtLo);
1395   MI.eraseFromParent();
1396   return true;
1397 }
1398 
1399 bool AMDGPULegalizerInfo::legalizeMinNumMaxNum(
1400   MachineInstr &MI, MachineRegisterInfo &MRI,
1401   MachineIRBuilder &B) const {
1402   MachineFunction &MF = B.getMF();
1403   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1404 
1405   const bool IsIEEEOp = MI.getOpcode() == AMDGPU::G_FMINNUM_IEEE ||
1406                         MI.getOpcode() == AMDGPU::G_FMAXNUM_IEEE;
1407 
1408   // With ieee_mode disabled, the instructions have the correct behavior
1409   // already for G_FMINNUM/G_FMAXNUM
1410   if (!MFI->getMode().IEEE)
1411     return !IsIEEEOp;
1412 
1413   if (IsIEEEOp)
1414     return true;
1415 
1416   MachineIRBuilder HelperBuilder(MI);
1417   GISelObserverWrapper DummyObserver;
1418   LegalizerHelper Helper(MF, DummyObserver, HelperBuilder);
1419   HelperBuilder.setInstr(MI);
1420   return Helper.lowerFMinNumMaxNum(MI) == LegalizerHelper::Legalized;
1421 }
1422 
1423 bool AMDGPULegalizerInfo::legalizeExtractVectorElt(
1424   MachineInstr &MI, MachineRegisterInfo &MRI,
1425   MachineIRBuilder &B) const {
1426   // TODO: Should move some of this into LegalizerHelper.
1427 
1428   // TODO: Promote dynamic indexing of s16 to s32
1429   // TODO: Dynamic s64 indexing is only legal for SGPR.
1430   Optional<int64_t> IdxVal = getConstantVRegVal(MI.getOperand(2).getReg(), MRI);
1431   if (!IdxVal) // Dynamic case will be selected to register indexing.
1432     return true;
1433 
1434   Register Dst = MI.getOperand(0).getReg();
1435   Register Vec = MI.getOperand(1).getReg();
1436 
1437   LLT VecTy = MRI.getType(Vec);
1438   LLT EltTy = VecTy.getElementType();
1439   assert(EltTy == MRI.getType(Dst));
1440 
1441   B.setInstr(MI);
1442 
1443   if (IdxVal.getValue() < VecTy.getNumElements())
1444     B.buildExtract(Dst, Vec, IdxVal.getValue() * EltTy.getSizeInBits());
1445   else
1446     B.buildUndef(Dst);
1447 
1448   MI.eraseFromParent();
1449   return true;
1450 }
1451 
1452 bool AMDGPULegalizerInfo::legalizeInsertVectorElt(
1453   MachineInstr &MI, MachineRegisterInfo &MRI,
1454   MachineIRBuilder &B) const {
1455   // TODO: Should move some of this into LegalizerHelper.
1456 
1457   // TODO: Promote dynamic indexing of s16 to s32
1458   // TODO: Dynamic s64 indexing is only legal for SGPR.
1459   Optional<int64_t> IdxVal = getConstantVRegVal(MI.getOperand(3).getReg(), MRI);
1460   if (!IdxVal) // Dynamic case will be selected to register indexing.
1461     return true;
1462 
1463   Register Dst = MI.getOperand(0).getReg();
1464   Register Vec = MI.getOperand(1).getReg();
1465   Register Ins = MI.getOperand(2).getReg();
1466 
1467   LLT VecTy = MRI.getType(Vec);
1468   LLT EltTy = VecTy.getElementType();
1469   assert(EltTy == MRI.getType(Ins));
1470 
1471   B.setInstr(MI);
1472 
1473   if (IdxVal.getValue() < VecTy.getNumElements())
1474     B.buildInsert(Dst, Vec, Ins, IdxVal.getValue() * EltTy.getSizeInBits());
1475   else
1476     B.buildUndef(Dst);
1477 
1478   MI.eraseFromParent();
1479   return true;
1480 }
1481 
1482 bool AMDGPULegalizerInfo::legalizeSinCos(
1483   MachineInstr &MI, MachineRegisterInfo &MRI,
1484   MachineIRBuilder &B) const {
1485   B.setInstr(MI);
1486 
1487   Register DstReg = MI.getOperand(0).getReg();
1488   Register SrcReg = MI.getOperand(1).getReg();
1489   LLT Ty = MRI.getType(DstReg);
1490   unsigned Flags = MI.getFlags();
1491 
1492   Register TrigVal;
1493   auto OneOver2Pi = B.buildFConstant(Ty, 0.5 / M_PI);
1494   if (ST.hasTrigReducedRange()) {
1495     auto MulVal = B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
1496     TrigVal = B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty}, false)
1497       .addUse(MulVal.getReg(0))
1498       .setMIFlags(Flags).getReg(0);
1499   } else
1500     TrigVal = B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
1501 
1502   Intrinsic::ID TrigIntrin = MI.getOpcode() == AMDGPU::G_FSIN ?
1503     Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
1504   B.buildIntrinsic(TrigIntrin, makeArrayRef<Register>(DstReg), false)
1505     .addUse(TrigVal)
1506     .setMIFlags(Flags);
1507   MI.eraseFromParent();
1508   return true;
1509 }
1510 
1511 bool AMDGPULegalizerInfo::legalizeGlobalValue(
1512   MachineInstr &MI, MachineRegisterInfo &MRI,
1513   MachineIRBuilder &B) const {
1514   Register DstReg = MI.getOperand(0).getReg();
1515   LLT Ty = MRI.getType(DstReg);
1516   unsigned AS = Ty.getAddressSpace();
1517 
1518   const GlobalValue *GV = MI.getOperand(1).getGlobal();
1519   MachineFunction &MF = B.getMF();
1520   SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1521 
1522   if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
1523     B.setInstr(MI);
1524 
1525     if (!MFI->isEntryFunction()) {
1526       const Function &Fn = MF.getFunction();
1527       DiagnosticInfoUnsupported BadLDSDecl(
1528         Fn, "local memory global used by non-kernel function", MI.getDebugLoc());
1529       Fn.getContext().diagnose(BadLDSDecl);
1530     }
1531 
1532     // TODO: We could emit code to handle the initialization somewhere.
1533     if (!AMDGPUTargetLowering::hasDefinedInitializer(GV)) {
1534       B.buildConstant(DstReg, MFI->allocateLDSGlobal(B.getDataLayout(), *GV));
1535       MI.eraseFromParent();
1536       return true;
1537     }
1538   } else
1539     return false;
1540 
1541   const Function &Fn = MF.getFunction();
1542   DiagnosticInfoUnsupported BadInit(
1543     Fn, "unsupported initializer for address space", MI.getDebugLoc());
1544   Fn.getContext().diagnose(BadInit);
1545   return true;
1546 }
1547 
1548 bool AMDGPULegalizerInfo::legalizeLoad(
1549   MachineInstr &MI, MachineRegisterInfo &MRI,
1550   MachineIRBuilder &B, GISelChangeObserver &Observer) const {
1551   B.setInstr(MI);
1552   LLT ConstPtr = LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64);
1553   auto Cast = B.buildAddrSpaceCast(ConstPtr, MI.getOperand(1).getReg());
1554   Observer.changingInstr(MI);
1555   MI.getOperand(1).setReg(Cast.getReg(0));
1556   Observer.changedInstr(MI);
1557   return true;
1558 }
1559 
1560 bool AMDGPULegalizerInfo::legalizeFMad(
1561   MachineInstr &MI, MachineRegisterInfo &MRI,
1562   MachineIRBuilder &B) const {
1563   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1564   assert(Ty.isScalar());
1565 
1566   // TODO: Always legal with future ftz flag.
1567   if (Ty == LLT::scalar(32) && !ST.hasFP32Denormals())
1568     return true;
1569   if (Ty == LLT::scalar(16) && !ST.hasFP16Denormals())
1570     return true;
1571 
1572   MachineFunction &MF = B.getMF();
1573 
1574   MachineIRBuilder HelperBuilder(MI);
1575   GISelObserverWrapper DummyObserver;
1576   LegalizerHelper Helper(MF, DummyObserver, HelperBuilder);
1577   HelperBuilder.setMBB(*MI.getParent());
1578   return Helper.lowerFMad(MI) == LegalizerHelper::Legalized;
1579 }
1580 
1581 // Return the use branch instruction, otherwise null if the usage is invalid.
1582 static MachineInstr *verifyCFIntrinsic(MachineInstr &MI,
1583                                        MachineRegisterInfo &MRI) {
1584   Register CondDef = MI.getOperand(0).getReg();
1585   if (!MRI.hasOneNonDBGUse(CondDef))
1586     return nullptr;
1587 
1588   MachineInstr &UseMI = *MRI.use_instr_nodbg_begin(CondDef);
1589   return UseMI.getParent() == MI.getParent() &&
1590     UseMI.getOpcode() == AMDGPU::G_BRCOND ? &UseMI : nullptr;
1591 }
1592 
1593 Register AMDGPULegalizerInfo::getLiveInRegister(MachineRegisterInfo &MRI,
1594                                                 Register Reg, LLT Ty) const {
1595   Register LiveIn = MRI.getLiveInVirtReg(Reg);
1596   if (LiveIn)
1597     return LiveIn;
1598 
1599   Register NewReg = MRI.createGenericVirtualRegister(Ty);
1600   MRI.addLiveIn(Reg, NewReg);
1601   return NewReg;
1602 }
1603 
1604 bool AMDGPULegalizerInfo::loadInputValue(Register DstReg, MachineIRBuilder &B,
1605                                          const ArgDescriptor *Arg) const {
1606   if (!Arg->isRegister() || !Arg->getRegister().isValid())
1607     return false; // TODO: Handle these
1608 
1609   assert(Arg->getRegister().isPhysical());
1610 
1611   MachineRegisterInfo &MRI = *B.getMRI();
1612 
1613   LLT Ty = MRI.getType(DstReg);
1614   Register LiveIn = getLiveInRegister(MRI, Arg->getRegister(), Ty);
1615 
1616   if (Arg->isMasked()) {
1617     // TODO: Should we try to emit this once in the entry block?
1618     const LLT S32 = LLT::scalar(32);
1619     const unsigned Mask = Arg->getMask();
1620     const unsigned Shift = countTrailingZeros<unsigned>(Mask);
1621 
1622     auto ShiftAmt = B.buildConstant(S32, Shift);
1623     auto LShr = B.buildLShr(S32, LiveIn, ShiftAmt);
1624     B.buildAnd(DstReg, LShr, B.buildConstant(S32, Mask >> Shift));
1625   } else
1626     B.buildCopy(DstReg, LiveIn);
1627 
1628   // Insert the argument copy if it doens't already exist.
1629   // FIXME: It seems EmitLiveInCopies isn't called anywhere?
1630   if (!MRI.getVRegDef(LiveIn)) {
1631     // FIXME: Should have scoped insert pt
1632     MachineBasicBlock &OrigInsBB = B.getMBB();
1633     auto OrigInsPt = B.getInsertPt();
1634 
1635     MachineBasicBlock &EntryMBB = B.getMF().front();
1636     EntryMBB.addLiveIn(Arg->getRegister());
1637     B.setInsertPt(EntryMBB, EntryMBB.begin());
1638     B.buildCopy(LiveIn, Arg->getRegister());
1639 
1640     B.setInsertPt(OrigInsBB, OrigInsPt);
1641   }
1642 
1643   return true;
1644 }
1645 
1646 bool AMDGPULegalizerInfo::legalizePreloadedArgIntrin(
1647   MachineInstr &MI,
1648   MachineRegisterInfo &MRI,
1649   MachineIRBuilder &B,
1650   AMDGPUFunctionArgInfo::PreloadedValue ArgType) const {
1651   B.setInstr(MI);
1652 
1653   const SIMachineFunctionInfo *MFI = B.getMF().getInfo<SIMachineFunctionInfo>();
1654 
1655   const ArgDescriptor *Arg;
1656   const TargetRegisterClass *RC;
1657   std::tie(Arg, RC) = MFI->getPreloadedValue(ArgType);
1658   if (!Arg) {
1659     LLVM_DEBUG(dbgs() << "Required arg register missing\n");
1660     return false;
1661   }
1662 
1663   if (loadInputValue(MI.getOperand(0).getReg(), B, Arg)) {
1664     MI.eraseFromParent();
1665     return true;
1666   }
1667 
1668   return false;
1669 }
1670 
1671 bool AMDGPULegalizerInfo::legalizeFDIVFast(MachineInstr &MI,
1672                                            MachineRegisterInfo &MRI,
1673                                            MachineIRBuilder &B) const {
1674   B.setInstr(MI);
1675   Register Res = MI.getOperand(0).getReg();
1676   Register LHS = MI.getOperand(2).getReg();
1677   Register RHS = MI.getOperand(3).getReg();
1678   uint16_t Flags = MI.getFlags();
1679 
1680   LLT S32 = LLT::scalar(32);
1681   LLT S1 = LLT::scalar(1);
1682 
1683   auto Abs = B.buildFAbs(S32, RHS, Flags);
1684   const APFloat C0Val(1.0f);
1685 
1686   auto C0 = B.buildConstant(S32, 0x6f800000);
1687   auto C1 = B.buildConstant(S32, 0x2f800000);
1688   auto C2 = B.buildConstant(S32, FloatToBits(1.0f));
1689 
1690   auto CmpRes = B.buildFCmp(CmpInst::FCMP_OGT, S1, Abs, C0, Flags);
1691   auto Sel = B.buildSelect(S32, CmpRes, C1, C2, Flags);
1692 
1693   auto Mul0 = B.buildFMul(S32, RHS, Sel, Flags);
1694 
1695   auto RCP = B.buildIntrinsic(Intrinsic::amdgcn_rcp, {S32}, false)
1696     .addUse(Mul0.getReg(0))
1697     .setMIFlags(Flags);
1698 
1699   auto Mul1 = B.buildFMul(S32, LHS, RCP, Flags);
1700 
1701   B.buildFMul(Res, Sel, Mul1, Flags);
1702 
1703   MI.eraseFromParent();
1704   return true;
1705 }
1706 
1707 bool AMDGPULegalizerInfo::legalizeImplicitArgPtr(MachineInstr &MI,
1708                                                  MachineRegisterInfo &MRI,
1709                                                  MachineIRBuilder &B) const {
1710   const SIMachineFunctionInfo *MFI = B.getMF().getInfo<SIMachineFunctionInfo>();
1711   if (!MFI->isEntryFunction()) {
1712     return legalizePreloadedArgIntrin(MI, MRI, B,
1713                                       AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR);
1714   }
1715 
1716   B.setInstr(MI);
1717 
1718   uint64_t Offset =
1719     ST.getTargetLowering()->getImplicitParameterOffset(
1720       B.getMF(), AMDGPUTargetLowering::FIRST_IMPLICIT);
1721   Register DstReg = MI.getOperand(0).getReg();
1722   LLT DstTy = MRI.getType(DstReg);
1723   LLT IdxTy = LLT::scalar(DstTy.getSizeInBits());
1724 
1725   const ArgDescriptor *Arg;
1726   const TargetRegisterClass *RC;
1727   std::tie(Arg, RC)
1728     = MFI->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
1729   if (!Arg)
1730     return false;
1731 
1732   Register KernargPtrReg = MRI.createGenericVirtualRegister(DstTy);
1733   if (!loadInputValue(KernargPtrReg, B, Arg))
1734     return false;
1735 
1736   B.buildGEP(DstReg, KernargPtrReg, B.buildConstant(IdxTy, Offset).getReg(0));
1737   MI.eraseFromParent();
1738   return true;
1739 }
1740 
1741 bool AMDGPULegalizerInfo::legalizeIsAddrSpace(MachineInstr &MI,
1742                                               MachineRegisterInfo &MRI,
1743                                               MachineIRBuilder &B,
1744                                               unsigned AddrSpace) const {
1745   B.setInstr(MI);
1746   Register ApertureReg = getSegmentAperture(AddrSpace, MRI, B);
1747   auto Hi32 = B.buildExtract(LLT::scalar(32), MI.getOperand(2).getReg(), 32);
1748   B.buildICmp(ICmpInst::ICMP_EQ, MI.getOperand(0), Hi32, ApertureReg);
1749   MI.eraseFromParent();
1750   return true;
1751 }
1752 
1753 bool AMDGPULegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
1754                                             MachineRegisterInfo &MRI,
1755                                             MachineIRBuilder &B) const {
1756   // Replace the use G_BRCOND with the exec manipulate and branch pseudos.
1757   switch (MI.getOperand(MI.getNumExplicitDefs()).getIntrinsicID()) {
1758   case Intrinsic::amdgcn_if: {
1759     if (MachineInstr *BrCond = verifyCFIntrinsic(MI, MRI)) {
1760       const SIRegisterInfo *TRI
1761         = static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
1762 
1763       B.setInstr(*BrCond);
1764       Register Def = MI.getOperand(1).getReg();
1765       Register Use = MI.getOperand(3).getReg();
1766       B.buildInstr(AMDGPU::SI_IF)
1767         .addDef(Def)
1768         .addUse(Use)
1769         .addMBB(BrCond->getOperand(1).getMBB());
1770 
1771       MRI.setRegClass(Def, TRI->getWaveMaskRegClass());
1772       MRI.setRegClass(Use, TRI->getWaveMaskRegClass());
1773       MI.eraseFromParent();
1774       BrCond->eraseFromParent();
1775       return true;
1776     }
1777 
1778     return false;
1779   }
1780   case Intrinsic::amdgcn_loop: {
1781     if (MachineInstr *BrCond = verifyCFIntrinsic(MI, MRI)) {
1782       const SIRegisterInfo *TRI
1783         = static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
1784 
1785       B.setInstr(*BrCond);
1786       Register Reg = MI.getOperand(2).getReg();
1787       B.buildInstr(AMDGPU::SI_LOOP)
1788         .addUse(Reg)
1789         .addMBB(BrCond->getOperand(1).getMBB());
1790       MI.eraseFromParent();
1791       BrCond->eraseFromParent();
1792       MRI.setRegClass(Reg, TRI->getWaveMaskRegClass());
1793       return true;
1794     }
1795 
1796     return false;
1797   }
1798   case Intrinsic::amdgcn_kernarg_segment_ptr:
1799     return legalizePreloadedArgIntrin(
1800       MI, MRI, B, AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
1801   case Intrinsic::amdgcn_implicitarg_ptr:
1802     return legalizeImplicitArgPtr(MI, MRI, B);
1803   case Intrinsic::amdgcn_workitem_id_x:
1804     return legalizePreloadedArgIntrin(MI, MRI, B,
1805                                       AMDGPUFunctionArgInfo::WORKITEM_ID_X);
1806   case Intrinsic::amdgcn_workitem_id_y:
1807     return legalizePreloadedArgIntrin(MI, MRI, B,
1808                                       AMDGPUFunctionArgInfo::WORKITEM_ID_Y);
1809   case Intrinsic::amdgcn_workitem_id_z:
1810     return legalizePreloadedArgIntrin(MI, MRI, B,
1811                                       AMDGPUFunctionArgInfo::WORKITEM_ID_Z);
1812   case Intrinsic::amdgcn_workgroup_id_x:
1813     return legalizePreloadedArgIntrin(MI, MRI, B,
1814                                       AMDGPUFunctionArgInfo::WORKGROUP_ID_X);
1815   case Intrinsic::amdgcn_workgroup_id_y:
1816     return legalizePreloadedArgIntrin(MI, MRI, B,
1817                                       AMDGPUFunctionArgInfo::WORKGROUP_ID_Y);
1818   case Intrinsic::amdgcn_workgroup_id_z:
1819     return legalizePreloadedArgIntrin(MI, MRI, B,
1820                                       AMDGPUFunctionArgInfo::WORKGROUP_ID_Z);
1821   case Intrinsic::amdgcn_dispatch_ptr:
1822     return legalizePreloadedArgIntrin(MI, MRI, B,
1823                                       AMDGPUFunctionArgInfo::DISPATCH_PTR);
1824   case Intrinsic::amdgcn_queue_ptr:
1825     return legalizePreloadedArgIntrin(MI, MRI, B,
1826                                       AMDGPUFunctionArgInfo::QUEUE_PTR);
1827   case Intrinsic::amdgcn_implicit_buffer_ptr:
1828     return legalizePreloadedArgIntrin(
1829       MI, MRI, B, AMDGPUFunctionArgInfo::IMPLICIT_BUFFER_PTR);
1830   case Intrinsic::amdgcn_dispatch_id:
1831     return legalizePreloadedArgIntrin(MI, MRI, B,
1832                                       AMDGPUFunctionArgInfo::DISPATCH_ID);
1833   case Intrinsic::amdgcn_fdiv_fast:
1834     return legalizeFDIVFast(MI, MRI, B);
1835   case Intrinsic::amdgcn_is_shared:
1836     return legalizeIsAddrSpace(MI, MRI, B, AMDGPUAS::LOCAL_ADDRESS);
1837   case Intrinsic::amdgcn_is_private:
1838     return legalizeIsAddrSpace(MI, MRI, B, AMDGPUAS::PRIVATE_ADDRESS);
1839   case Intrinsic::amdgcn_wavefrontsize: {
1840     B.setInstr(MI);
1841     B.buildConstant(MI.getOperand(0), ST.getWavefrontSize());
1842     MI.eraseFromParent();
1843     return true;
1844   }
1845   default:
1846     return true;
1847   }
1848 
1849   return true;
1850 }
1851