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 "AMDGPULegalizerInfo.h"
22 
23 #include "AMDGPU.h"
24 #include "AMDGPUGlobalISelUtils.h"
25 #include "AMDGPUTargetMachine.h"
26 #include "SIMachineFunctionInfo.h"
27 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
28 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
29 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
30 #include "llvm/CodeGen/TargetOpcodes.h"
31 #include "llvm/CodeGen/ValueTypes.h"
32 #include "llvm/IR/DerivedTypes.h"
33 #include "llvm/IR/DiagnosticInfo.h"
34 #include "llvm/IR/Type.h"
35 #include "llvm/Support/Debug.h"
36 
37 #define DEBUG_TYPE "amdgpu-legalinfo"
38 
39 using namespace llvm;
40 using namespace LegalizeActions;
41 using namespace LegalizeMutations;
42 using namespace LegalityPredicates;
43 using namespace MIPatternMatch;
44 
45 static LegalityPredicate isMultiple32(unsigned TypeIdx,
46                                       unsigned MaxSize = 1024) {
47   return [=](const LegalityQuery &Query) {
48     const LLT Ty = Query.Types[TypeIdx];
49     const LLT EltTy = Ty.getScalarType();
50     return Ty.getSizeInBits() <= MaxSize && EltTy.getSizeInBits() % 32 == 0;
51   };
52 }
53 
54 static LegalityPredicate sizeIs(unsigned TypeIdx, unsigned Size) {
55   return [=](const LegalityQuery &Query) {
56     return Query.Types[TypeIdx].getSizeInBits() == Size;
57   };
58 }
59 
60 static LegalityPredicate isSmallOddVector(unsigned TypeIdx) {
61   return [=](const LegalityQuery &Query) {
62     const LLT Ty = Query.Types[TypeIdx];
63     return Ty.isVector() &&
64            Ty.getNumElements() % 2 != 0 &&
65            Ty.getElementType().getSizeInBits() < 32 &&
66            Ty.getSizeInBits() % 32 != 0;
67   };
68 }
69 
70 static LegalityPredicate isWideVec16(unsigned TypeIdx) {
71   return [=](const LegalityQuery &Query) {
72     const LLT Ty = Query.Types[TypeIdx];
73     const LLT EltTy = Ty.getScalarType();
74     return EltTy.getSizeInBits() == 16 && Ty.getNumElements() > 2;
75   };
76 }
77 
78 static LegalizeMutation oneMoreElement(unsigned TypeIdx) {
79   return [=](const LegalityQuery &Query) {
80     const LLT Ty = Query.Types[TypeIdx];
81     const LLT EltTy = Ty.getElementType();
82     return std::make_pair(TypeIdx, LLT::vector(Ty.getNumElements() + 1, EltTy));
83   };
84 }
85 
86 static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx) {
87   return [=](const LegalityQuery &Query) {
88     const LLT Ty = Query.Types[TypeIdx];
89     const LLT EltTy = Ty.getElementType();
90     unsigned Size = Ty.getSizeInBits();
91     unsigned Pieces = (Size + 63) / 64;
92     unsigned NewNumElts = (Ty.getNumElements() + 1) / Pieces;
93     return std::make_pair(TypeIdx, LLT::scalarOrVector(NewNumElts, EltTy));
94   };
95 }
96 
97 // Increase the number of vector elements to reach the next multiple of 32-bit
98 // type.
99 static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx) {
100   return [=](const LegalityQuery &Query) {
101     const LLT Ty = Query.Types[TypeIdx];
102 
103     const LLT EltTy = Ty.getElementType();
104     const int Size = Ty.getSizeInBits();
105     const int EltSize = EltTy.getSizeInBits();
106     const int NextMul32 = (Size + 31) / 32;
107 
108     assert(EltSize < 32);
109 
110     const int NewNumElts = (32 * NextMul32 + EltSize - 1) / EltSize;
111     return std::make_pair(TypeIdx, LLT::vector(NewNumElts, EltTy));
112   };
113 }
114 
115 static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size) {
116   return [=](const LegalityQuery &Query) {
117     const LLT QueryTy = Query.Types[TypeIdx];
118     return QueryTy.isVector() && QueryTy.getSizeInBits() < Size;
119   };
120 }
121 
122 static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size) {
123   return [=](const LegalityQuery &Query) {
124     const LLT QueryTy = Query.Types[TypeIdx];
125     return QueryTy.isVector() && QueryTy.getSizeInBits() > Size;
126   };
127 }
128 
129 static LegalityPredicate numElementsNotEven(unsigned TypeIdx) {
130   return [=](const LegalityQuery &Query) {
131     const LLT QueryTy = Query.Types[TypeIdx];
132     return QueryTy.isVector() && QueryTy.getNumElements() % 2 != 0;
133   };
134 }
135 
136 // Any combination of 32 or 64-bit elements up to 1024 bits, and multiples of
137 // v2s16.
138 static LegalityPredicate isRegisterType(unsigned TypeIdx) {
139   return [=](const LegalityQuery &Query) {
140     const LLT Ty = Query.Types[TypeIdx];
141     if (Ty.isVector()) {
142       const int EltSize = Ty.getElementType().getSizeInBits();
143       return EltSize == 32 || EltSize == 64 ||
144             (EltSize == 16 && Ty.getNumElements() % 2 == 0) ||
145              EltSize == 128 || EltSize == 256;
146     }
147 
148     return Ty.getSizeInBits() % 32 == 0 && Ty.getSizeInBits() <= 1024;
149   };
150 }
151 
152 static LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT Type) {
153   return [=](const LegalityQuery &Query) {
154     const LLT QueryTy = Query.Types[TypeIdx];
155     return QueryTy.isVector() && QueryTy.getElementType() == Type;
156   };
157 }
158 
159 static LegalityPredicate isWideScalarTruncStore(unsigned TypeIdx) {
160   return [=](const LegalityQuery &Query) {
161     const LLT Ty = Query.Types[TypeIdx];
162     return !Ty.isVector() && Ty.getSizeInBits() > 32 &&
163            Query.MMODescrs[0].SizeInBits < Ty.getSizeInBits();
164   };
165 }
166 
167 AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
168                                          const GCNTargetMachine &TM)
169   :  ST(ST_) {
170   using namespace TargetOpcode;
171 
172   auto GetAddrSpacePtr = [&TM](unsigned AS) {
173     return LLT::pointer(AS, TM.getPointerSizeInBits(AS));
174   };
175 
176   const LLT S1 = LLT::scalar(1);
177   const LLT S8 = LLT::scalar(8);
178   const LLT S16 = LLT::scalar(16);
179   const LLT S32 = LLT::scalar(32);
180   const LLT S64 = LLT::scalar(64);
181   const LLT S96 = LLT::scalar(96);
182   const LLT S128 = LLT::scalar(128);
183   const LLT S256 = LLT::scalar(256);
184   const LLT S1024 = LLT::scalar(1024);
185 
186   const LLT V2S16 = LLT::vector(2, 16);
187   const LLT V4S16 = LLT::vector(4, 16);
188 
189   const LLT V2S32 = LLT::vector(2, 32);
190   const LLT V3S32 = LLT::vector(3, 32);
191   const LLT V4S32 = LLT::vector(4, 32);
192   const LLT V5S32 = LLT::vector(5, 32);
193   const LLT V6S32 = LLT::vector(6, 32);
194   const LLT V7S32 = LLT::vector(7, 32);
195   const LLT V8S32 = LLT::vector(8, 32);
196   const LLT V9S32 = LLT::vector(9, 32);
197   const LLT V10S32 = LLT::vector(10, 32);
198   const LLT V11S32 = LLT::vector(11, 32);
199   const LLT V12S32 = LLT::vector(12, 32);
200   const LLT V13S32 = LLT::vector(13, 32);
201   const LLT V14S32 = LLT::vector(14, 32);
202   const LLT V15S32 = LLT::vector(15, 32);
203   const LLT V16S32 = LLT::vector(16, 32);
204   const LLT V32S32 = LLT::vector(32, 32);
205 
206   const LLT V2S64 = LLT::vector(2, 64);
207   const LLT V3S64 = LLT::vector(3, 64);
208   const LLT V4S64 = LLT::vector(4, 64);
209   const LLT V5S64 = LLT::vector(5, 64);
210   const LLT V6S64 = LLT::vector(6, 64);
211   const LLT V7S64 = LLT::vector(7, 64);
212   const LLT V8S64 = LLT::vector(8, 64);
213   const LLT V16S64 = LLT::vector(16, 64);
214 
215   std::initializer_list<LLT> AllS32Vectors =
216     {V2S32, V3S32, V4S32, V5S32, V6S32, V7S32, V8S32,
217      V9S32, V10S32, V11S32, V12S32, V13S32, V14S32, V15S32, V16S32, V32S32};
218   std::initializer_list<LLT> AllS64Vectors =
219     {V2S64, V3S64, V4S64, V5S64, V6S64, V7S64, V8S64, V16S64};
220 
221   const LLT GlobalPtr = GetAddrSpacePtr(AMDGPUAS::GLOBAL_ADDRESS);
222   const LLT ConstantPtr = GetAddrSpacePtr(AMDGPUAS::CONSTANT_ADDRESS);
223   const LLT Constant32Ptr = GetAddrSpacePtr(AMDGPUAS::CONSTANT_ADDRESS_32BIT);
224   const LLT LocalPtr = GetAddrSpacePtr(AMDGPUAS::LOCAL_ADDRESS);
225   const LLT RegionPtr = GetAddrSpacePtr(AMDGPUAS::REGION_ADDRESS);
226   const LLT FlatPtr = GetAddrSpacePtr(AMDGPUAS::FLAT_ADDRESS);
227   const LLT PrivatePtr = GetAddrSpacePtr(AMDGPUAS::PRIVATE_ADDRESS);
228 
229   const LLT CodePtr = FlatPtr;
230 
231   const std::initializer_list<LLT> AddrSpaces64 = {
232     GlobalPtr, ConstantPtr, FlatPtr
233   };
234 
235   const std::initializer_list<LLT> AddrSpaces32 = {
236     LocalPtr, PrivatePtr, Constant32Ptr, RegionPtr
237   };
238 
239   const std::initializer_list<LLT> FPTypesBase = {
240     S32, S64
241   };
242 
243   const std::initializer_list<LLT> FPTypes16 = {
244     S32, S64, S16
245   };
246 
247   const std::initializer_list<LLT> FPTypesPK16 = {
248     S32, S64, S16, V2S16
249   };
250 
251   const LLT MinLegalScalarShiftTy = ST.has16BitInsts() ? S16 : S32;
252 
253   setAction({G_BRCOND, S1}, Legal); // VCC branches
254   setAction({G_BRCOND, S32}, Legal); // SCC branches
255 
256   // TODO: All multiples of 32, vectors of pointers, all v2s16 pairs, more
257   // elements for v3s16
258   getActionDefinitionsBuilder(G_PHI)
259     .legalFor({S32, S64, V2S16, V4S16, S1, S128, S256})
260     .legalFor(AllS32Vectors)
261     .legalFor(AllS64Vectors)
262     .legalFor(AddrSpaces64)
263     .legalFor(AddrSpaces32)
264     .clampScalar(0, S32, S256)
265     .widenScalarToNextPow2(0, 32)
266     .clampMaxNumElements(0, S32, 16)
267     .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
268     .legalIf(isPointer(0));
269 
270   if (ST.has16BitInsts()) {
271     getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL})
272       .legalFor({S32, S16})
273       .clampScalar(0, S16, S32)
274       .scalarize(0);
275   } else {
276     getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL})
277       .legalFor({S32})
278       .clampScalar(0, S32, S32)
279       .scalarize(0);
280   }
281 
282   // FIXME: Not really legal. Placeholder for custom lowering.
283   getActionDefinitionsBuilder({G_SDIV, G_UDIV, G_SREM, G_UREM})
284     .legalFor({S32, S64})
285     .clampScalar(0, S32, S64)
286     .widenScalarToNextPow2(0, 32)
287     .scalarize(0);
288 
289   getActionDefinitionsBuilder({G_UMULH, G_SMULH})
290     .legalFor({S32})
291     .clampScalar(0, S32, S32)
292     .scalarize(0);
293 
294   // Report legal for any types we can handle anywhere. For the cases only legal
295   // on the SALU, RegBankSelect will be able to re-legalize.
296   getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
297     .legalFor({S32, S1, S64, V2S32, S16, V2S16, V4S16})
298     .clampScalar(0, S32, S64)
299     .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
300     .fewerElementsIf(vectorWiderThan(0, 64), fewerEltsToSize64Vector(0))
301     .widenScalarToNextPow2(0)
302     .scalarize(0);
303 
304   getActionDefinitionsBuilder({G_UADDO, G_USUBO,
305                                G_UADDE, G_SADDE, G_USUBE, G_SSUBE})
306     .legalFor({{S32, S1}, {S32, S32}})
307     .clampScalar(0, S32, S32)
308     .scalarize(0); // TODO: Implement.
309 
310   getActionDefinitionsBuilder(G_BITCAST)
311     // Don't worry about the size constraint.
312     .legalIf(all(isRegisterType(0), isRegisterType(1)))
313     // FIXME: Testing hack
314     .legalForCartesianProduct({S16, LLT::vector(2, 8), })
315     .lower();
316 
317 
318   getActionDefinitionsBuilder(G_CONSTANT)
319     .legalFor({S1, S32, S64, S16, GlobalPtr,
320                LocalPtr, ConstantPtr, PrivatePtr, FlatPtr })
321     .clampScalar(0, S32, S64)
322     .widenScalarToNextPow2(0)
323     .legalIf(isPointer(0));
324 
325   getActionDefinitionsBuilder(G_FCONSTANT)
326     .legalFor({S32, S64, S16})
327     .clampScalar(0, S16, S64);
328 
329   getActionDefinitionsBuilder(G_IMPLICIT_DEF)
330     .legalFor({S1, S32, S64, S16, V2S32, V4S32, V2S16, V4S16, GlobalPtr,
331                ConstantPtr, LocalPtr, FlatPtr, PrivatePtr})
332     .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
333     .clampScalarOrElt(0, S32, S1024)
334     .legalIf(isMultiple32(0))
335     .widenScalarToNextPow2(0, 32)
336     .clampMaxNumElements(0, S32, 16);
337 
338   setAction({G_FRAME_INDEX, PrivatePtr}, Legal);
339   getActionDefinitionsBuilder(G_GLOBAL_VALUE)
340     .customFor({LocalPtr, GlobalPtr, ConstantPtr, Constant32Ptr});
341   setAction({G_BLOCK_ADDR, CodePtr}, Legal);
342 
343   auto &FPOpActions = getActionDefinitionsBuilder(
344     { G_FADD, G_FMUL, G_FMA, G_FCANONICALIZE})
345     .legalFor({S32, S64});
346   auto &TrigActions = getActionDefinitionsBuilder({G_FSIN, G_FCOS})
347     .customFor({S32, S64});
348   auto &FDIVActions = getActionDefinitionsBuilder(G_FDIV)
349     .customFor({S32, S64});
350 
351   if (ST.has16BitInsts()) {
352     if (ST.hasVOP3PInsts())
353       FPOpActions.legalFor({S16, V2S16});
354     else
355       FPOpActions.legalFor({S16});
356 
357     TrigActions.customFor({S16});
358     FDIVActions.customFor({S16});
359   }
360 
361   auto &MinNumMaxNum = getActionDefinitionsBuilder({
362       G_FMINNUM, G_FMAXNUM, G_FMINNUM_IEEE, G_FMAXNUM_IEEE});
363 
364   if (ST.hasVOP3PInsts()) {
365     MinNumMaxNum.customFor(FPTypesPK16)
366       .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
367       .clampMaxNumElements(0, S16, 2)
368       .clampScalar(0, S16, S64)
369       .scalarize(0);
370   } else if (ST.has16BitInsts()) {
371     MinNumMaxNum.customFor(FPTypes16)
372       .clampScalar(0, S16, S64)
373       .scalarize(0);
374   } else {
375     MinNumMaxNum.customFor(FPTypesBase)
376       .clampScalar(0, S32, S64)
377       .scalarize(0);
378   }
379 
380   if (ST.hasVOP3PInsts())
381     FPOpActions.clampMaxNumElements(0, S16, 2);
382 
383   FPOpActions
384     .scalarize(0)
385     .clampScalar(0, ST.has16BitInsts() ? S16 : S32, S64);
386 
387   TrigActions
388     .scalarize(0)
389     .clampScalar(0, ST.has16BitInsts() ? S16 : S32, S64);
390 
391   FDIVActions
392     .scalarize(0)
393     .clampScalar(0, ST.has16BitInsts() ? S16 : S32, S64);
394 
395   getActionDefinitionsBuilder({G_FNEG, G_FABS})
396     .legalFor(FPTypesPK16)
397     .clampMaxNumElements(0, S16, 2)
398     .scalarize(0)
399     .clampScalar(0, S16, S64);
400 
401   if (ST.has16BitInsts()) {
402     getActionDefinitionsBuilder({G_FSQRT, G_FFLOOR})
403       .legalFor({S32, S64, S16})
404       .scalarize(0)
405       .clampScalar(0, S16, S64);
406   } else {
407     getActionDefinitionsBuilder({G_FSQRT, G_FFLOOR})
408       .legalFor({S32, S64})
409       .scalarize(0)
410       .clampScalar(0, S32, S64);
411   }
412 
413   getActionDefinitionsBuilder(G_FPTRUNC)
414     .legalFor({{S32, S64}, {S16, S32}})
415     .scalarize(0);
416 
417   getActionDefinitionsBuilder(G_FPEXT)
418     .legalFor({{S64, S32}, {S32, S16}})
419     .lowerFor({{S64, S16}}) // FIXME: Implement
420     .scalarize(0);
421 
422   getActionDefinitionsBuilder(G_FSUB)
423       // Use actual fsub instruction
424       .legalFor({S32})
425       // Must use fadd + fneg
426       .lowerFor({S64, S16, V2S16})
427       .scalarize(0)
428       .clampScalar(0, S32, S64);
429 
430   // Whether this is legal depends on the floating point mode for the function.
431   auto &FMad = getActionDefinitionsBuilder(G_FMAD);
432   if (ST.hasMadF16())
433     FMad.customFor({S32, S16});
434   else
435     FMad.customFor({S32});
436   FMad.scalarize(0)
437       .lower();
438 
439   getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT})
440     .legalFor({{S64, S32}, {S32, S16}, {S64, S16},
441                {S32, S1}, {S64, S1}, {S16, S1},
442                {S96, S32},
443                // FIXME: Hack
444                {S64, LLT::scalar(33)},
445                {S32, S8}, {S32, LLT::scalar(24)}})
446     .scalarize(0)
447     .clampScalar(0, S32, S64);
448 
449   // TODO: Split s1->s64 during regbankselect for VALU.
450   auto &IToFP = getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
451     .legalFor({{S32, S32}, {S64, S32}, {S16, S32}})
452     .lowerFor({{S32, S64}})
453     .lowerIf(typeIs(1, S1))
454     .customFor({{S64, S64}});
455   if (ST.has16BitInsts())
456     IToFP.legalFor({{S16, S16}});
457   IToFP.clampScalar(1, S32, S64)
458        .scalarize(0);
459 
460   auto &FPToI = getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
461     .legalFor({{S32, S32}, {S32, S64}, {S32, S16}})
462     .customFor({{S64, S64}});
463   if (ST.has16BitInsts())
464     FPToI.legalFor({{S16, S16}});
465   else
466     FPToI.minScalar(1, S32);
467 
468   FPToI.minScalar(0, S32)
469        .scalarize(0)
470        .lower();
471 
472   getActionDefinitionsBuilder(G_INTRINSIC_ROUND)
473     .scalarize(0)
474     .lower();
475 
476   if (ST.has16BitInsts()) {
477     getActionDefinitionsBuilder({G_INTRINSIC_TRUNC, G_FCEIL, G_FRINT})
478       .legalFor({S16, S32, S64})
479       .clampScalar(0, S16, S64)
480       .scalarize(0);
481   } else if (ST.getGeneration() >= AMDGPUSubtarget::SEA_ISLANDS) {
482     getActionDefinitionsBuilder({G_INTRINSIC_TRUNC, G_FCEIL, G_FRINT})
483       .legalFor({S32, S64})
484       .clampScalar(0, S32, S64)
485       .scalarize(0);
486   } else {
487     getActionDefinitionsBuilder({G_INTRINSIC_TRUNC, G_FCEIL, G_FRINT})
488       .legalFor({S32})
489       .customFor({S64})
490       .clampScalar(0, S32, S64)
491       .scalarize(0);
492   }
493 
494   getActionDefinitionsBuilder({G_PTR_ADD, G_PTR_MASK})
495     .scalarize(0)
496     .alwaysLegal();
497 
498   auto &CmpBuilder =
499     getActionDefinitionsBuilder(G_ICMP)
500     // The compare output type differs based on the register bank of the output,
501     // so make both s1 and s32 legal.
502     //
503     // Scalar compares producing output in scc will be promoted to s32, as that
504     // is the allocatable register type that will be needed for the copy from
505     // scc. This will be promoted during RegBankSelect, and we assume something
506     // before that won't try to use s32 result types.
507     //
508     // Vector compares producing an output in vcc/SGPR will use s1 in VCC reg
509     // bank.
510     .legalForCartesianProduct(
511       {S1}, {S32, S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr})
512     .legalForCartesianProduct(
513       {S32}, {S32, S64, GlobalPtr, LocalPtr, ConstantPtr, PrivatePtr, FlatPtr});
514   if (ST.has16BitInsts()) {
515     CmpBuilder.legalFor({{S1, S16}});
516   }
517 
518   CmpBuilder
519     .widenScalarToNextPow2(1)
520     .clampScalar(1, S32, S64)
521     .scalarize(0)
522     .legalIf(all(typeInSet(0, {S1, S32}), isPointer(1)));
523 
524   getActionDefinitionsBuilder(G_FCMP)
525     .legalForCartesianProduct({S1}, ST.has16BitInsts() ? FPTypes16 : FPTypesBase)
526     .widenScalarToNextPow2(1)
527     .clampScalar(1, S32, S64)
528     .scalarize(0);
529 
530   // FIXME: fexp, flog2, flog10 needs to be custom lowered.
531   getActionDefinitionsBuilder({G_FPOW, G_FEXP, G_FEXP2,
532                                G_FLOG2})
533     .legalFor({S32})
534     .scalarize(0);
535 
536   getActionDefinitionsBuilder({G_FLOG, G_FLOG10})
537     .customFor({S32})
538     .clampScalar(0, S32, S32)
539     .scalarize(0);
540 
541   // The 64-bit versions produce 32-bit results, but only on the SALU.
542   getActionDefinitionsBuilder({G_CTLZ, G_CTLZ_ZERO_UNDEF,
543                                G_CTTZ, G_CTTZ_ZERO_UNDEF,
544                                G_CTPOP})
545     .legalFor({{S32, S32}, {S32, S64}})
546     .clampScalar(0, S32, S32)
547     .clampScalar(1, S32, S64)
548     .scalarize(0)
549     .widenScalarToNextPow2(0, 32)
550     .widenScalarToNextPow2(1, 32);
551 
552   // TODO: Expand for > s32
553   getActionDefinitionsBuilder({G_BSWAP, G_BITREVERSE})
554     .legalFor({S32})
555     .clampScalar(0, S32, S32)
556     .scalarize(0);
557 
558   if (ST.has16BitInsts()) {
559     if (ST.hasVOP3PInsts()) {
560       getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
561         .legalFor({S32, S16, V2S16})
562         .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
563         .clampMaxNumElements(0, S16, 2)
564         .clampScalar(0, S16, S32)
565         .widenScalarToNextPow2(0)
566         .scalarize(0);
567     } else {
568       getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
569         .legalFor({S32, S16})
570         .widenScalarToNextPow2(0)
571         .clampScalar(0, S16, S32)
572         .scalarize(0);
573     }
574   } else {
575     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
576       .legalFor({S32})
577       .clampScalar(0, S32, S32)
578       .widenScalarToNextPow2(0)
579       .scalarize(0);
580   }
581 
582   auto smallerThan = [](unsigned TypeIdx0, unsigned TypeIdx1) {
583     return [=](const LegalityQuery &Query) {
584       return Query.Types[TypeIdx0].getSizeInBits() <
585              Query.Types[TypeIdx1].getSizeInBits();
586     };
587   };
588 
589   auto greaterThan = [](unsigned TypeIdx0, unsigned TypeIdx1) {
590     return [=](const LegalityQuery &Query) {
591       return Query.Types[TypeIdx0].getSizeInBits() >
592              Query.Types[TypeIdx1].getSizeInBits();
593     };
594   };
595 
596   getActionDefinitionsBuilder(G_INTTOPTR)
597     // List the common cases
598     .legalForCartesianProduct(AddrSpaces64, {S64})
599     .legalForCartesianProduct(AddrSpaces32, {S32})
600     .scalarize(0)
601     // Accept any address space as long as the size matches
602     .legalIf(sameSize(0, 1))
603     .widenScalarIf(smallerThan(1, 0),
604       [](const LegalityQuery &Query) {
605         return std::make_pair(1, LLT::scalar(Query.Types[0].getSizeInBits()));
606       })
607     .narrowScalarIf(greaterThan(1, 0),
608       [](const LegalityQuery &Query) {
609         return std::make_pair(1, LLT::scalar(Query.Types[0].getSizeInBits()));
610       });
611 
612   getActionDefinitionsBuilder(G_PTRTOINT)
613     // List the common cases
614     .legalForCartesianProduct(AddrSpaces64, {S64})
615     .legalForCartesianProduct(AddrSpaces32, {S32})
616     .scalarize(0)
617     // Accept any address space as long as the size matches
618     .legalIf(sameSize(0, 1))
619     .widenScalarIf(smallerThan(0, 1),
620       [](const LegalityQuery &Query) {
621         return std::make_pair(0, LLT::scalar(Query.Types[1].getSizeInBits()));
622       })
623     .narrowScalarIf(
624       greaterThan(0, 1),
625       [](const LegalityQuery &Query) {
626         return std::make_pair(0, LLT::scalar(Query.Types[1].getSizeInBits()));
627       });
628 
629   getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
630     .scalarize(0)
631     .custom();
632 
633   // TODO: Should load to s16 be legal? Most loads extend to 32-bits, but we
634   // handle some operations by just promoting the register during
635   // selection. There are also d16 loads on GFX9+ which preserve the high bits.
636   auto maxSizeForAddrSpace = [this](unsigned AS, bool IsLoad) -> unsigned {
637     switch (AS) {
638     // FIXME: Private element size.
639     case AMDGPUAS::PRIVATE_ADDRESS:
640       return 32;
641     // FIXME: Check subtarget
642     case AMDGPUAS::LOCAL_ADDRESS:
643       return ST.useDS128() ? 128 : 64;
644 
645     // Treat constant and global as identical. SMRD loads are sometimes usable
646     // for global loads (ideally constant address space should be eliminated)
647     // depending on the context. Legality cannot be context dependent, but
648     // RegBankSelect can split the load as necessary depending on the pointer
649     // register bank/uniformity and if the memory is invariant or not written in
650     // a kernel.
651     case AMDGPUAS::CONSTANT_ADDRESS:
652     case AMDGPUAS::GLOBAL_ADDRESS:
653       return IsLoad ? 512 : 128;
654     default:
655       return 128;
656     }
657   };
658 
659   const auto needToSplitMemOp = [=](const LegalityQuery &Query, bool IsLoad) -> bool {
660     const LLT DstTy = Query.Types[0];
661 
662     // Split vector extloads.
663     unsigned MemSize = Query.MMODescrs[0].SizeInBits;
664     unsigned Align = Query.MMODescrs[0].AlignInBits;
665 
666     if (MemSize < DstTy.getSizeInBits())
667       MemSize = std::max(MemSize, Align);
668 
669     if (DstTy.isVector() && DstTy.getSizeInBits() > MemSize)
670       return true;
671 
672     const LLT PtrTy = Query.Types[1];
673     unsigned AS = PtrTy.getAddressSpace();
674     if (MemSize > maxSizeForAddrSpace(AS, IsLoad))
675       return true;
676 
677     // Catch weird sized loads that don't evenly divide into the access sizes
678     // TODO: May be able to widen depending on alignment etc.
679     unsigned NumRegs = MemSize / 32;
680     if (NumRegs == 3 && !ST.hasDwordx3LoadStores())
681       return true;
682 
683     if (Align < MemSize) {
684       const SITargetLowering *TLI = ST.getTargetLowering();
685       return !TLI->allowsMisalignedMemoryAccessesImpl(MemSize, AS, Align / 8);
686     }
687 
688     return false;
689   };
690 
691   unsigned GlobalAlign32 = ST.hasUnalignedBufferAccess() ? 0 : 32;
692   unsigned GlobalAlign16 = ST.hasUnalignedBufferAccess() ? 0 : 16;
693   unsigned GlobalAlign8 = ST.hasUnalignedBufferAccess() ? 0 : 8;
694 
695   // TODO: Refine based on subtargets which support unaligned access or 128-bit
696   // LDS
697   // TODO: Unsupported flat for SI.
698 
699   for (unsigned Op : {G_LOAD, G_STORE}) {
700     const bool IsStore = Op == G_STORE;
701 
702     auto &Actions = getActionDefinitionsBuilder(Op);
703     // Whitelist the common cases.
704     // TODO: Pointer loads
705     // TODO: Wide constant loads
706     // TODO: Only CI+ has 3x loads
707     // TODO: Loads to s16 on gfx9
708     Actions.legalForTypesWithMemDesc({{S32, GlobalPtr, 32, GlobalAlign32},
709                                       {V2S32, GlobalPtr, 64, GlobalAlign32},
710                                       {V3S32, GlobalPtr, 96, GlobalAlign32},
711                                       {S96, GlobalPtr, 96, GlobalAlign32},
712                                       {V4S32, GlobalPtr, 128, GlobalAlign32},
713                                       {S128, GlobalPtr, 128, GlobalAlign32},
714                                       {S64, GlobalPtr, 64, GlobalAlign32},
715                                       {V2S64, GlobalPtr, 128, GlobalAlign32},
716                                       {V2S16, GlobalPtr, 32, GlobalAlign32},
717                                       {S32, GlobalPtr, 8, GlobalAlign8},
718                                       {S32, GlobalPtr, 16, GlobalAlign16},
719 
720                                       {S32, LocalPtr, 32, 32},
721                                       {S64, LocalPtr, 64, 32},
722                                       {V2S32, LocalPtr, 64, 32},
723                                       {S32, LocalPtr, 8, 8},
724                                       {S32, LocalPtr, 16, 16},
725                                       {V2S16, LocalPtr, 32, 32},
726 
727                                       {S32, PrivatePtr, 32, 32},
728                                       {S32, PrivatePtr, 8, 8},
729                                       {S32, PrivatePtr, 16, 16},
730                                       {V2S16, PrivatePtr, 32, 32},
731 
732                                       {S32, FlatPtr, 32, GlobalAlign32},
733                                       {S32, FlatPtr, 16, GlobalAlign16},
734                                       {S32, FlatPtr, 8, GlobalAlign8},
735                                       {V2S16, FlatPtr, 32, GlobalAlign32},
736 
737                                       {S32, ConstantPtr, 32, GlobalAlign32},
738                                       {V2S32, ConstantPtr, 64, GlobalAlign32},
739                                       {V3S32, ConstantPtr, 96, GlobalAlign32},
740                                       {V4S32, ConstantPtr, 128, GlobalAlign32},
741                                       {S64, ConstantPtr, 64, GlobalAlign32},
742                                       {S128, ConstantPtr, 128, GlobalAlign32},
743                                       {V2S32, ConstantPtr, 32, GlobalAlign32}});
744     Actions
745         .customIf(typeIs(1, Constant32Ptr))
746         .narrowScalarIf(
747             [=](const LegalityQuery &Query) -> bool {
748               return !Query.Types[0].isVector() &&
749                      needToSplitMemOp(Query, Op == G_LOAD);
750             },
751             [=](const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
752               const LLT DstTy = Query.Types[0];
753               const LLT PtrTy = Query.Types[1];
754 
755               const unsigned DstSize = DstTy.getSizeInBits();
756               unsigned MemSize = Query.MMODescrs[0].SizeInBits;
757 
758               // Split extloads.
759               if (DstSize > MemSize)
760                 return std::make_pair(0, LLT::scalar(MemSize));
761 
762               if (DstSize > 32 && (DstSize % 32 != 0)) {
763                 // FIXME: Need a way to specify non-extload of larger size if
764                 // suitably aligned.
765                 return std::make_pair(0, LLT::scalar(32 * (DstSize / 32)));
766               }
767 
768               unsigned MaxSize = maxSizeForAddrSpace(PtrTy.getAddressSpace(),
769                                                      Op == G_LOAD);
770               if (MemSize > MaxSize)
771                 return std::make_pair(0, LLT::scalar(MaxSize));
772 
773               unsigned Align = Query.MMODescrs[0].AlignInBits;
774               return std::make_pair(0, LLT::scalar(Align));
775             })
776         .fewerElementsIf(
777             [=](const LegalityQuery &Query) -> bool {
778               return Query.Types[0].isVector() &&
779                      needToSplitMemOp(Query, Op == G_LOAD);
780             },
781             [=](const LegalityQuery &Query) -> std::pair<unsigned, LLT> {
782               const LLT DstTy = Query.Types[0];
783               const LLT PtrTy = Query.Types[1];
784 
785               LLT EltTy = DstTy.getElementType();
786               unsigned MaxSize = maxSizeForAddrSpace(PtrTy.getAddressSpace(),
787                                                      Op == G_LOAD);
788 
789               // Split if it's too large for the address space.
790               if (Query.MMODescrs[0].SizeInBits > MaxSize) {
791                 unsigned NumElts = DstTy.getNumElements();
792                 unsigned EltSize = EltTy.getSizeInBits();
793 
794                 if (MaxSize % EltSize == 0) {
795                   return std::make_pair(
796                     0, LLT::scalarOrVector(MaxSize / EltSize, EltTy));
797                 }
798 
799                 unsigned NumPieces = Query.MMODescrs[0].SizeInBits / MaxSize;
800 
801                 // FIXME: Refine when odd breakdowns handled
802                 // The scalars will need to be re-legalized.
803                 if (NumPieces == 1 || NumPieces >= NumElts ||
804                     NumElts % NumPieces != 0)
805                   return std::make_pair(0, EltTy);
806 
807                 return std::make_pair(0,
808                                       LLT::vector(NumElts / NumPieces, EltTy));
809               }
810 
811               // Need to split because of alignment.
812               unsigned Align = Query.MMODescrs[0].AlignInBits;
813               unsigned EltSize = EltTy.getSizeInBits();
814               if (EltSize > Align &&
815                   (EltSize / Align < DstTy.getNumElements())) {
816                 return std::make_pair(0, LLT::vector(EltSize / Align, EltTy));
817               }
818 
819               // May need relegalization for the scalars.
820               return std::make_pair(0, EltTy);
821             })
822         .minScalar(0, S32);
823 
824     if (IsStore)
825       Actions.narrowScalarIf(isWideScalarTruncStore(0), changeTo(0, S32));
826 
827     // TODO: Need a bitcast lower option?
828     Actions
829         .legalIf([=](const LegalityQuery &Query) {
830           const LLT Ty0 = Query.Types[0];
831           unsigned Size = Ty0.getSizeInBits();
832           unsigned MemSize = Query.MMODescrs[0].SizeInBits;
833           unsigned Align = Query.MMODescrs[0].AlignInBits;
834 
835           // FIXME: Widening store from alignment not valid.
836           if (MemSize < Size)
837             MemSize = std::max(MemSize, Align);
838 
839           // No extending vector loads.
840           if (Size > MemSize && Ty0.isVector())
841             return false;
842 
843           switch (MemSize) {
844           case 8:
845           case 16:
846             return Size == 32;
847           case 32:
848           case 64:
849           case 128:
850             return true;
851           case 96:
852             return ST.hasDwordx3LoadStores();
853           case 256:
854           case 512:
855             return true;
856           default:
857             return false;
858           }
859         })
860         .widenScalarToNextPow2(0)
861         // TODO: v3s32->v4s32 with alignment
862         .moreElementsIf(vectorSmallerThan(0, 32), moreEltsToNext32Bit(0));
863   }
864 
865   auto &ExtLoads = getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
866                        .legalForTypesWithMemDesc({{S32, GlobalPtr, 8, 8},
867                                                   {S32, GlobalPtr, 16, 2 * 8},
868                                                   {S32, LocalPtr, 8, 8},
869                                                   {S32, LocalPtr, 16, 16},
870                                                   {S32, PrivatePtr, 8, 8},
871                                                   {S32, PrivatePtr, 16, 16},
872                                                   {S32, ConstantPtr, 8, 8},
873                                                   {S32, ConstantPtr, 16, 2 * 8}});
874   if (ST.hasFlatAddressSpace()) {
875     ExtLoads.legalForTypesWithMemDesc(
876         {{S32, FlatPtr, 8, 8}, {S32, FlatPtr, 16, 16}});
877   }
878 
879   ExtLoads.clampScalar(0, S32, S32)
880           .widenScalarToNextPow2(0)
881           .unsupportedIfMemSizeNotPow2()
882           .lower();
883 
884   auto &Atomics = getActionDefinitionsBuilder(
885     {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB,
886      G_ATOMICRMW_AND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR,
887      G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
888      G_ATOMICRMW_UMIN})
889     .legalFor({{S32, GlobalPtr}, {S32, LocalPtr},
890                {S64, GlobalPtr}, {S64, LocalPtr}});
891   if (ST.hasFlatAddressSpace()) {
892     Atomics.legalFor({{S32, FlatPtr}, {S64, FlatPtr}});
893   }
894 
895   getActionDefinitionsBuilder(G_ATOMICRMW_FADD)
896     .legalFor({{S32, LocalPtr}});
897 
898   // BUFFER/FLAT_ATOMIC_CMP_SWAP on GCN GPUs needs input marshalling, and output
899   // demarshalling
900   getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
901     .customFor({{S32, GlobalPtr}, {S64, GlobalPtr},
902                 {S32, FlatPtr}, {S64, FlatPtr}})
903     .legalFor({{S32, LocalPtr}, {S64, LocalPtr},
904                {S32, RegionPtr}, {S64, RegionPtr}});
905   // TODO: Pointer types, any 32-bit or 64-bit vector
906 
907   // Condition should be s32 for scalar, s1 for vector.
908   getActionDefinitionsBuilder(G_SELECT)
909     .legalForCartesianProduct({S32, S64, S16, V2S32, V2S16, V4S16,
910           GlobalPtr, LocalPtr, FlatPtr, PrivatePtr,
911           LLT::vector(2, LocalPtr), LLT::vector(2, PrivatePtr)}, {S1, S32})
912     .clampScalar(0, S16, S64)
913     .moreElementsIf(isSmallOddVector(0), oneMoreElement(0))
914     .fewerElementsIf(numElementsNotEven(0), scalarize(0))
915     .scalarize(1)
916     .clampMaxNumElements(0, S32, 2)
917     .clampMaxNumElements(0, LocalPtr, 2)
918     .clampMaxNumElements(0, PrivatePtr, 2)
919     .scalarize(0)
920     .widenScalarToNextPow2(0)
921     .legalIf(all(isPointer(0), typeInSet(1, {S1, S32})));
922 
923   // TODO: Only the low 4/5/6 bits of the shift amount are observed, so we can
924   // be more flexible with the shift amount type.
925   auto &Shifts = getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR})
926     .legalFor({{S32, S32}, {S64, S32}});
927   if (ST.has16BitInsts()) {
928     if (ST.hasVOP3PInsts()) {
929       Shifts.legalFor({{S16, S32}, {S16, S16}, {V2S16, V2S16}})
930             .clampMaxNumElements(0, S16, 2);
931     } else
932       Shifts.legalFor({{S16, S32}, {S16, S16}});
933 
934     // TODO: Support 16-bit shift amounts
935     Shifts.clampScalar(1, S32, S32);
936     Shifts.clampScalar(0, S16, S64);
937     Shifts.widenScalarToNextPow2(0, 16);
938   } else {
939     // Make sure we legalize the shift amount type first, as the general
940     // expansion for the shifted type will produce much worse code if it hasn't
941     // been truncated already.
942     Shifts.clampScalar(1, S32, S32);
943     Shifts.clampScalar(0, S32, S64);
944     Shifts.widenScalarToNextPow2(0, 32);
945   }
946   Shifts.scalarize(0);
947 
948   for (unsigned Op : {G_EXTRACT_VECTOR_ELT, G_INSERT_VECTOR_ELT}) {
949     unsigned VecTypeIdx = Op == G_EXTRACT_VECTOR_ELT ? 1 : 0;
950     unsigned EltTypeIdx = Op == G_EXTRACT_VECTOR_ELT ? 0 : 1;
951     unsigned IdxTypeIdx = 2;
952 
953     getActionDefinitionsBuilder(Op)
954       .customIf([=](const LegalityQuery &Query) {
955           const LLT EltTy = Query.Types[EltTypeIdx];
956           const LLT VecTy = Query.Types[VecTypeIdx];
957           const LLT IdxTy = Query.Types[IdxTypeIdx];
958           return (EltTy.getSizeInBits() == 16 ||
959                   EltTy.getSizeInBits() % 32 == 0) &&
960                  VecTy.getSizeInBits() % 32 == 0 &&
961                  VecTy.getSizeInBits() <= 1024 &&
962                  IdxTy.getSizeInBits() == 32;
963         })
964       .clampScalar(EltTypeIdx, S32, S64)
965       .clampScalar(VecTypeIdx, S32, S64)
966       .clampScalar(IdxTypeIdx, S32, S32);
967   }
968 
969   getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
970     .unsupportedIf([=](const LegalityQuery &Query) {
971         const LLT &EltTy = Query.Types[1].getElementType();
972         return Query.Types[0] != EltTy;
973       });
974 
975   for (unsigned Op : {G_EXTRACT, G_INSERT}) {
976     unsigned BigTyIdx = Op == G_EXTRACT ? 1 : 0;
977     unsigned LitTyIdx = Op == G_EXTRACT ? 0 : 1;
978 
979     // FIXME: Doesn't handle extract of illegal sizes.
980     getActionDefinitionsBuilder(Op)
981       .lowerIf(all(typeIs(LitTyIdx, S16), sizeIs(BigTyIdx, 32)))
982       // FIXME: Multiples of 16 should not be legal.
983       .legalIf([=](const LegalityQuery &Query) {
984           const LLT BigTy = Query.Types[BigTyIdx];
985           const LLT LitTy = Query.Types[LitTyIdx];
986           return (BigTy.getSizeInBits() % 32 == 0) &&
987                  (LitTy.getSizeInBits() % 16 == 0);
988         })
989       .widenScalarIf(
990         [=](const LegalityQuery &Query) {
991           const LLT BigTy = Query.Types[BigTyIdx];
992           return (BigTy.getScalarSizeInBits() < 16);
993         },
994         LegalizeMutations::widenScalarOrEltToNextPow2(BigTyIdx, 16))
995       .widenScalarIf(
996         [=](const LegalityQuery &Query) {
997           const LLT LitTy = Query.Types[LitTyIdx];
998           return (LitTy.getScalarSizeInBits() < 16);
999         },
1000         LegalizeMutations::widenScalarOrEltToNextPow2(LitTyIdx, 16))
1001       .moreElementsIf(isSmallOddVector(BigTyIdx), oneMoreElement(BigTyIdx))
1002       .widenScalarToNextPow2(BigTyIdx, 32);
1003 
1004   }
1005 
1006   auto &BuildVector = getActionDefinitionsBuilder(G_BUILD_VECTOR)
1007     .legalForCartesianProduct(AllS32Vectors, {S32})
1008     .legalForCartesianProduct(AllS64Vectors, {S64})
1009     .clampNumElements(0, V16S32, V32S32)
1010     .clampNumElements(0, V2S64, V16S64)
1011     .fewerElementsIf(isWideVec16(0), changeTo(0, V2S16));
1012 
1013   if (ST.hasScalarPackInsts())
1014     BuildVector.legalFor({V2S16, S32});
1015 
1016   BuildVector
1017     .minScalarSameAs(1, 0)
1018     .legalIf(isRegisterType(0))
1019     .minScalarOrElt(0, S32);
1020 
1021   if (ST.hasScalarPackInsts()) {
1022     getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
1023       .legalFor({V2S16, S32})
1024       .lower();
1025   } else {
1026     getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC)
1027       .lower();
1028   }
1029 
1030   getActionDefinitionsBuilder(G_CONCAT_VECTORS)
1031     .legalIf(isRegisterType(0));
1032 
1033   // TODO: Don't fully scalarize v2s16 pieces? Or combine out thosse
1034   // pre-legalize.
1035   if (ST.hasVOP3PInsts()) {
1036     getActionDefinitionsBuilder(G_SHUFFLE_VECTOR)
1037       .customFor({V2S16, V2S16})
1038       .lower();
1039   } else
1040     getActionDefinitionsBuilder(G_SHUFFLE_VECTOR).lower();
1041 
1042   // Merge/Unmerge
1043   for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
1044     unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;
1045     unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;
1046 
1047     auto notValidElt = [=](const LegalityQuery &Query, unsigned TypeIdx) {
1048       const LLT &Ty = Query.Types[TypeIdx];
1049       if (Ty.isVector()) {
1050         const LLT &EltTy = Ty.getElementType();
1051         if (EltTy.getSizeInBits() < 8 || EltTy.getSizeInBits() > 64)
1052           return true;
1053         if (!isPowerOf2_32(EltTy.getSizeInBits()))
1054           return true;
1055       }
1056       return false;
1057     };
1058 
1059     auto &Builder = getActionDefinitionsBuilder(Op)
1060       // Try to widen to s16 first for small types.
1061       // TODO: Only do this on targets with legal s16 shifts
1062       .minScalarOrEltIf(narrowerThan(LitTyIdx, 16), LitTyIdx, S16)
1063 
1064       .widenScalarToNextPow2(LitTyIdx, /*Min*/ 16)
1065       .lowerFor({{S16, V2S16}})
1066       .moreElementsIf(isSmallOddVector(BigTyIdx), oneMoreElement(BigTyIdx))
1067       .fewerElementsIf(all(typeIs(0, S16), vectorWiderThan(1, 32),
1068                            elementTypeIs(1, S16)),
1069                        changeTo(1, V2S16))
1070       // Clamp the little scalar to s8-s256 and make it a power of 2. It's not
1071       // worth considering the multiples of 64 since 2*192 and 2*384 are not
1072       // valid.
1073       .clampScalar(LitTyIdx, S32, S256)
1074       .widenScalarToNextPow2(LitTyIdx, /*Min*/ 32)
1075       // Break up vectors with weird elements into scalars
1076       .fewerElementsIf(
1077         [=](const LegalityQuery &Query) { return notValidElt(Query, 0); },
1078         scalarize(0))
1079       .fewerElementsIf(
1080         [=](const LegalityQuery &Query) { return notValidElt(Query, 1); },
1081         scalarize(1))
1082       .clampScalar(BigTyIdx, S32, S1024);
1083 
1084     if (Op == G_MERGE_VALUES) {
1085       Builder.widenScalarIf(
1086         // TODO: Use 16-bit shifts if legal for 8-bit values?
1087         [=](const LegalityQuery &Query) {
1088           const LLT Ty = Query.Types[LitTyIdx];
1089           return Ty.getSizeInBits() < 32;
1090         },
1091         changeTo(LitTyIdx, S32));
1092     }
1093 
1094     Builder.widenScalarIf(
1095       [=](const LegalityQuery &Query) {
1096         const LLT Ty = Query.Types[BigTyIdx];
1097         return !isPowerOf2_32(Ty.getSizeInBits()) &&
1098           Ty.getSizeInBits() % 16 != 0;
1099       },
1100       [=](const LegalityQuery &Query) {
1101         // Pick the next power of 2, or a multiple of 64 over 128.
1102         // Whichever is smaller.
1103         const LLT &Ty = Query.Types[BigTyIdx];
1104         unsigned NewSizeInBits = 1 << Log2_32_Ceil(Ty.getSizeInBits() + 1);
1105         if (NewSizeInBits >= 256) {
1106           unsigned RoundedTo = alignTo<64>(Ty.getSizeInBits() + 1);
1107           if (RoundedTo < NewSizeInBits)
1108             NewSizeInBits = RoundedTo;
1109         }
1110         return std::make_pair(BigTyIdx, LLT::scalar(NewSizeInBits));
1111       })
1112       .legalIf([=](const LegalityQuery &Query) {
1113           const LLT &BigTy = Query.Types[BigTyIdx];
1114           const LLT &LitTy = Query.Types[LitTyIdx];
1115 
1116           if (BigTy.isVector() && BigTy.getSizeInBits() < 32)
1117             return false;
1118           if (LitTy.isVector() && LitTy.getSizeInBits() < 32)
1119             return false;
1120 
1121           return BigTy.getSizeInBits() % 16 == 0 &&
1122                  LitTy.getSizeInBits() % 16 == 0 &&
1123                  BigTy.getSizeInBits() <= 1024;
1124         })
1125       // Any vectors left are the wrong size. Scalarize them.
1126       .scalarize(0)
1127       .scalarize(1);
1128   }
1129 
1130   // TODO: Make legal for s32, s64. s64 case needs break down in regbankselect.
1131   auto &SextInReg = getActionDefinitionsBuilder(G_SEXT_INREG);
1132   if (ST.hasVOP3PInsts()) {
1133     SextInReg.lowerFor({{S32}, {S64}, {S16}, {V2S16}})
1134       // Prefer to reduce vector widths for 16-bit vectors before lowering, to
1135       // get more vector shift opportunities, since we'll get those when
1136       // expanded.
1137       .fewerElementsIf(elementTypeIs(0, S16), changeTo(0, V2S16));
1138   } else if (ST.has16BitInsts()) {
1139     SextInReg.lowerFor({{S32}, {S64}, {S16}});
1140   } else {
1141     // Prefer to promote to s32 before lowering if we don't have 16-bit
1142     // shifts. This avoid a lot of intermediate truncate and extend operations.
1143     SextInReg.lowerFor({{S32}, {S64}});
1144   }
1145 
1146   SextInReg
1147     .scalarize(0)
1148     .clampScalar(0, MinLegalScalarShiftTy, S64)
1149     .lower();
1150 
1151   getActionDefinitionsBuilder(G_READCYCLECOUNTER)
1152     .legalFor({S64});
1153 
1154   getActionDefinitionsBuilder({
1155       // TODO: Verify V_BFI_B32 is generated from expanded bit ops
1156       G_FCOPYSIGN,
1157 
1158       G_ATOMIC_CMPXCHG_WITH_SUCCESS,
1159       G_READ_REGISTER,
1160       G_WRITE_REGISTER,
1161 
1162       G_SADDO, G_SSUBO,
1163 
1164        // TODO: Implement
1165       G_FMINIMUM, G_FMAXIMUM
1166     }).lower();
1167 
1168   getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
1169         G_DYN_STACKALLOC, G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
1170         G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
1171     .unsupported();
1172 
1173   computeTables();
1174   verify(*ST.getInstrInfo());
1175 }
1176 
1177 bool AMDGPULegalizerInfo::legalizeCustom(MachineInstr &MI,
1178                                          MachineRegisterInfo &MRI,
1179                                          MachineIRBuilder &B,
1180                                          GISelChangeObserver &Observer) const {
1181   switch (MI.getOpcode()) {
1182   case TargetOpcode::G_ADDRSPACE_CAST:
1183     return legalizeAddrSpaceCast(MI, MRI, B);
1184   case TargetOpcode::G_FRINT:
1185     return legalizeFrint(MI, MRI, B);
1186   case TargetOpcode::G_FCEIL:
1187     return legalizeFceil(MI, MRI, B);
1188   case TargetOpcode::G_INTRINSIC_TRUNC:
1189     return legalizeIntrinsicTrunc(MI, MRI, B);
1190   case TargetOpcode::G_SITOFP:
1191     return legalizeITOFP(MI, MRI, B, true);
1192   case TargetOpcode::G_UITOFP:
1193     return legalizeITOFP(MI, MRI, B, false);
1194   case TargetOpcode::G_FPTOSI:
1195     return legalizeFPTOI(MI, MRI, B, true);
1196   case TargetOpcode::G_FPTOUI:
1197     return legalizeFPTOI(MI, MRI, B, false);
1198   case TargetOpcode::G_FMINNUM:
1199   case TargetOpcode::G_FMAXNUM:
1200   case TargetOpcode::G_FMINNUM_IEEE:
1201   case TargetOpcode::G_FMAXNUM_IEEE:
1202     return legalizeMinNumMaxNum(MI, MRI, B);
1203   case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1204     return legalizeExtractVectorElt(MI, MRI, B);
1205   case TargetOpcode::G_INSERT_VECTOR_ELT:
1206     return legalizeInsertVectorElt(MI, MRI, B);
1207   case TargetOpcode::G_SHUFFLE_VECTOR:
1208     return legalizeShuffleVector(MI, MRI, B);
1209   case TargetOpcode::G_FSIN:
1210   case TargetOpcode::G_FCOS:
1211     return legalizeSinCos(MI, MRI, B);
1212   case TargetOpcode::G_GLOBAL_VALUE:
1213     return legalizeGlobalValue(MI, MRI, B);
1214   case TargetOpcode::G_LOAD:
1215     return legalizeLoad(MI, MRI, B, Observer);
1216   case TargetOpcode::G_FMAD:
1217     return legalizeFMad(MI, MRI, B);
1218   case TargetOpcode::G_FDIV:
1219     return legalizeFDIV(MI, MRI, B);
1220   case TargetOpcode::G_ATOMIC_CMPXCHG:
1221     return legalizeAtomicCmpXChg(MI, MRI, B);
1222   case TargetOpcode::G_FLOG:
1223     return legalizeFlog(MI, B, 1.0f / numbers::log2ef);
1224   case TargetOpcode::G_FLOG10:
1225     return legalizeFlog(MI, B, numbers::ln2f / numbers::ln10f);
1226   default:
1227     return false;
1228   }
1229 
1230   llvm_unreachable("expected switch to return");
1231 }
1232 
1233 Register AMDGPULegalizerInfo::getSegmentAperture(
1234   unsigned AS,
1235   MachineRegisterInfo &MRI,
1236   MachineIRBuilder &B) const {
1237   MachineFunction &MF = B.getMF();
1238   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1239   const LLT S32 = LLT::scalar(32);
1240 
1241   assert(AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::PRIVATE_ADDRESS);
1242 
1243   if (ST.hasApertureRegs()) {
1244     // FIXME: Use inline constants (src_{shared, private}_base) instead of
1245     // getreg.
1246     unsigned Offset = AS == AMDGPUAS::LOCAL_ADDRESS ?
1247         AMDGPU::Hwreg::OFFSET_SRC_SHARED_BASE :
1248         AMDGPU::Hwreg::OFFSET_SRC_PRIVATE_BASE;
1249     unsigned WidthM1 = AS == AMDGPUAS::LOCAL_ADDRESS ?
1250         AMDGPU::Hwreg::WIDTH_M1_SRC_SHARED_BASE :
1251         AMDGPU::Hwreg::WIDTH_M1_SRC_PRIVATE_BASE;
1252     unsigned Encoding =
1253         AMDGPU::Hwreg::ID_MEM_BASES << AMDGPU::Hwreg::ID_SHIFT_ |
1254         Offset << AMDGPU::Hwreg::OFFSET_SHIFT_ |
1255         WidthM1 << AMDGPU::Hwreg::WIDTH_M1_SHIFT_;
1256 
1257     Register GetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1258 
1259     B.buildInstr(AMDGPU::S_GETREG_B32)
1260       .addDef(GetReg)
1261       .addImm(Encoding);
1262     MRI.setType(GetReg, S32);
1263 
1264     auto ShiftAmt = B.buildConstant(S32, WidthM1 + 1);
1265     return B.buildShl(S32, GetReg, ShiftAmt).getReg(0);
1266   }
1267 
1268   Register QueuePtr = MRI.createGenericVirtualRegister(
1269     LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64));
1270 
1271   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1272   if (!loadInputValue(QueuePtr, B, &MFI->getArgInfo().QueuePtr))
1273     return Register();
1274 
1275   // Offset into amd_queue_t for group_segment_aperture_base_hi /
1276   // private_segment_aperture_base_hi.
1277   uint32_t StructOffset = (AS == AMDGPUAS::LOCAL_ADDRESS) ? 0x40 : 0x44;
1278 
1279   // TODO: can we be smarter about machine pointer info?
1280   MachinePointerInfo PtrInfo(AMDGPUAS::CONSTANT_ADDRESS);
1281   MachineMemOperand *MMO = MF.getMachineMemOperand(
1282     PtrInfo,
1283     MachineMemOperand::MOLoad |
1284     MachineMemOperand::MODereferenceable |
1285     MachineMemOperand::MOInvariant,
1286     4,
1287     MinAlign(64, StructOffset));
1288 
1289   Register LoadAddr;
1290 
1291   B.materializePtrAdd(LoadAddr, QueuePtr, LLT::scalar(64), StructOffset);
1292   return B.buildLoad(S32, LoadAddr, *MMO).getReg(0);
1293 }
1294 
1295 bool AMDGPULegalizerInfo::legalizeAddrSpaceCast(
1296   MachineInstr &MI, MachineRegisterInfo &MRI,
1297   MachineIRBuilder &B) const {
1298   MachineFunction &MF = B.getMF();
1299 
1300   B.setInstr(MI);
1301 
1302   const LLT S32 = LLT::scalar(32);
1303   Register Dst = MI.getOperand(0).getReg();
1304   Register Src = MI.getOperand(1).getReg();
1305 
1306   LLT DstTy = MRI.getType(Dst);
1307   LLT SrcTy = MRI.getType(Src);
1308   unsigned DestAS = DstTy.getAddressSpace();
1309   unsigned SrcAS = SrcTy.getAddressSpace();
1310 
1311   // TODO: Avoid reloading from the queue ptr for each cast, or at least each
1312   // vector element.
1313   assert(!DstTy.isVector());
1314 
1315   const AMDGPUTargetMachine &TM
1316     = static_cast<const AMDGPUTargetMachine &>(MF.getTarget());
1317 
1318   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1319   if (ST.getTargetLowering()->isNoopAddrSpaceCast(SrcAS, DestAS)) {
1320     MI.setDesc(B.getTII().get(TargetOpcode::G_BITCAST));
1321     return true;
1322   }
1323 
1324   if (DestAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) {
1325     // Truncate.
1326     B.buildExtract(Dst, Src, 0);
1327     MI.eraseFromParent();
1328     return true;
1329   }
1330 
1331   if (SrcAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) {
1332     const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
1333     uint32_t AddrHiVal = Info->get32BitAddressHighBits();
1334 
1335     // FIXME: This is a bit ugly due to creating a merge of 2 pointers to
1336     // another. Merge operands are required to be the same type, but creating an
1337     // extra ptrtoint would be kind of pointless.
1338     auto HighAddr = B.buildConstant(
1339       LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS_32BIT, 32), AddrHiVal);
1340     B.buildMerge(Dst, {Src, HighAddr.getReg(0)});
1341     MI.eraseFromParent();
1342     return true;
1343   }
1344 
1345   if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
1346     assert(DestAS == AMDGPUAS::LOCAL_ADDRESS ||
1347            DestAS == AMDGPUAS::PRIVATE_ADDRESS);
1348     unsigned NullVal = TM.getNullPointerValue(DestAS);
1349 
1350     auto SegmentNull = B.buildConstant(DstTy, NullVal);
1351     auto FlatNull = B.buildConstant(SrcTy, 0);
1352 
1353     // Extract low 32-bits of the pointer.
1354     auto PtrLo32 = B.buildExtract(DstTy, Src, 0);
1355 
1356     auto CmpRes =
1357         B.buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), Src, FlatNull.getReg(0));
1358     B.buildSelect(Dst, CmpRes, PtrLo32, SegmentNull.getReg(0));
1359 
1360     MI.eraseFromParent();
1361     return true;
1362   }
1363 
1364   if (SrcAS != AMDGPUAS::LOCAL_ADDRESS && SrcAS != AMDGPUAS::PRIVATE_ADDRESS)
1365     return false;
1366 
1367   if (!ST.hasFlatAddressSpace())
1368     return false;
1369 
1370   auto SegmentNull =
1371       B.buildConstant(SrcTy, TM.getNullPointerValue(SrcAS));
1372   auto FlatNull =
1373       B.buildConstant(DstTy, TM.getNullPointerValue(DestAS));
1374 
1375   Register ApertureReg = getSegmentAperture(SrcAS, MRI, B);
1376   if (!ApertureReg.isValid())
1377     return false;
1378 
1379   auto CmpRes =
1380       B.buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), Src, SegmentNull.getReg(0));
1381 
1382   // Coerce the type of the low half of the result so we can use merge_values.
1383   Register SrcAsInt = B.buildPtrToInt(S32, Src).getReg(0);
1384 
1385   // TODO: Should we allow mismatched types but matching sizes in merges to
1386   // avoid the ptrtoint?
1387   auto BuildPtr = B.buildMerge(DstTy, {SrcAsInt, ApertureReg});
1388   B.buildSelect(Dst, CmpRes, BuildPtr, FlatNull);
1389 
1390   MI.eraseFromParent();
1391   return true;
1392 }
1393 
1394 bool AMDGPULegalizerInfo::legalizeFrint(
1395   MachineInstr &MI, MachineRegisterInfo &MRI,
1396   MachineIRBuilder &B) const {
1397   B.setInstr(MI);
1398 
1399   Register Src = MI.getOperand(1).getReg();
1400   LLT Ty = MRI.getType(Src);
1401   assert(Ty.isScalar() && Ty.getSizeInBits() == 64);
1402 
1403   APFloat C1Val(APFloat::IEEEdouble(), "0x1.0p+52");
1404   APFloat C2Val(APFloat::IEEEdouble(), "0x1.fffffffffffffp+51");
1405 
1406   auto C1 = B.buildFConstant(Ty, C1Val);
1407   auto CopySign = B.buildFCopysign(Ty, C1, Src);
1408 
1409   // TODO: Should this propagate fast-math-flags?
1410   auto Tmp1 = B.buildFAdd(Ty, Src, CopySign);
1411   auto Tmp2 = B.buildFSub(Ty, Tmp1, CopySign);
1412 
1413   auto C2 = B.buildFConstant(Ty, C2Val);
1414   auto Fabs = B.buildFAbs(Ty, Src);
1415 
1416   auto Cond = B.buildFCmp(CmpInst::FCMP_OGT, LLT::scalar(1), Fabs, C2);
1417   B.buildSelect(MI.getOperand(0).getReg(), Cond, Src, Tmp2);
1418   return true;
1419 }
1420 
1421 bool AMDGPULegalizerInfo::legalizeFceil(
1422   MachineInstr &MI, MachineRegisterInfo &MRI,
1423   MachineIRBuilder &B) const {
1424   B.setInstr(MI);
1425 
1426   const LLT S1 = LLT::scalar(1);
1427   const LLT S64 = LLT::scalar(64);
1428 
1429   Register Src = MI.getOperand(1).getReg();
1430   assert(MRI.getType(Src) == S64);
1431 
1432   // result = trunc(src)
1433   // if (src > 0.0 && src != result)
1434   //   result += 1.0
1435 
1436   auto Trunc = B.buildIntrinsicTrunc(S64, Src);
1437 
1438   const auto Zero = B.buildFConstant(S64, 0.0);
1439   const auto One = B.buildFConstant(S64, 1.0);
1440   auto Lt0 = B.buildFCmp(CmpInst::FCMP_OGT, S1, Src, Zero);
1441   auto NeTrunc = B.buildFCmp(CmpInst::FCMP_ONE, S1, Src, Trunc);
1442   auto And = B.buildAnd(S1, Lt0, NeTrunc);
1443   auto Add = B.buildSelect(S64, And, One, Zero);
1444 
1445   // TODO: Should this propagate fast-math-flags?
1446   B.buildFAdd(MI.getOperand(0).getReg(), Trunc, Add);
1447   return true;
1448 }
1449 
1450 static MachineInstrBuilder extractF64Exponent(unsigned Hi,
1451                                               MachineIRBuilder &B) {
1452   const unsigned FractBits = 52;
1453   const unsigned ExpBits = 11;
1454   LLT S32 = LLT::scalar(32);
1455 
1456   auto Const0 = B.buildConstant(S32, FractBits - 32);
1457   auto Const1 = B.buildConstant(S32, ExpBits);
1458 
1459   auto ExpPart = B.buildIntrinsic(Intrinsic::amdgcn_ubfe, {S32}, false)
1460     .addUse(Const0.getReg(0))
1461     .addUse(Const1.getReg(0));
1462 
1463   return B.buildSub(S32, ExpPart, B.buildConstant(S32, 1023));
1464 }
1465 
1466 bool AMDGPULegalizerInfo::legalizeIntrinsicTrunc(
1467   MachineInstr &MI, MachineRegisterInfo &MRI,
1468   MachineIRBuilder &B) const {
1469   B.setInstr(MI);
1470 
1471   const LLT S1 = LLT::scalar(1);
1472   const LLT S32 = LLT::scalar(32);
1473   const LLT S64 = LLT::scalar(64);
1474 
1475   Register Src = MI.getOperand(1).getReg();
1476   assert(MRI.getType(Src) == S64);
1477 
1478   // TODO: Should this use extract since the low half is unused?
1479   auto Unmerge = B.buildUnmerge({S32, S32}, Src);
1480   Register Hi = Unmerge.getReg(1);
1481 
1482   // Extract the upper half, since this is where we will find the sign and
1483   // exponent.
1484   auto Exp = extractF64Exponent(Hi, B);
1485 
1486   const unsigned FractBits = 52;
1487 
1488   // Extract the sign bit.
1489   const auto SignBitMask = B.buildConstant(S32, UINT32_C(1) << 31);
1490   auto SignBit = B.buildAnd(S32, Hi, SignBitMask);
1491 
1492   const auto FractMask = B.buildConstant(S64, (UINT64_C(1) << FractBits) - 1);
1493 
1494   const auto Zero32 = B.buildConstant(S32, 0);
1495 
1496   // Extend back to 64-bits.
1497   auto SignBit64 = B.buildMerge(S64, {Zero32.getReg(0), SignBit.getReg(0)});
1498 
1499   auto Shr = B.buildAShr(S64, FractMask, Exp);
1500   auto Not = B.buildNot(S64, Shr);
1501   auto Tmp0 = B.buildAnd(S64, Src, Not);
1502   auto FiftyOne = B.buildConstant(S32, FractBits - 1);
1503 
1504   auto ExpLt0 = B.buildICmp(CmpInst::ICMP_SLT, S1, Exp, Zero32);
1505   auto ExpGt51 = B.buildICmp(CmpInst::ICMP_SGT, S1, Exp, FiftyOne);
1506 
1507   auto Tmp1 = B.buildSelect(S64, ExpLt0, SignBit64, Tmp0);
1508   B.buildSelect(MI.getOperand(0).getReg(), ExpGt51, Src, Tmp1);
1509   return true;
1510 }
1511 
1512 bool AMDGPULegalizerInfo::legalizeITOFP(
1513   MachineInstr &MI, MachineRegisterInfo &MRI,
1514   MachineIRBuilder &B, bool Signed) const {
1515   B.setInstr(MI);
1516 
1517   Register Dst = MI.getOperand(0).getReg();
1518   Register Src = MI.getOperand(1).getReg();
1519 
1520   const LLT S64 = LLT::scalar(64);
1521   const LLT S32 = LLT::scalar(32);
1522 
1523   assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S64);
1524 
1525   auto Unmerge = B.buildUnmerge({S32, S32}, Src);
1526 
1527   auto CvtHi = Signed ?
1528     B.buildSITOFP(S64, Unmerge.getReg(1)) :
1529     B.buildUITOFP(S64, Unmerge.getReg(1));
1530 
1531   auto CvtLo = B.buildUITOFP(S64, Unmerge.getReg(0));
1532 
1533   auto ThirtyTwo = B.buildConstant(S32, 32);
1534   auto LdExp = B.buildIntrinsic(Intrinsic::amdgcn_ldexp, {S64}, false)
1535     .addUse(CvtHi.getReg(0))
1536     .addUse(ThirtyTwo.getReg(0));
1537 
1538   // TODO: Should this propagate fast-math-flags?
1539   B.buildFAdd(Dst, LdExp, CvtLo);
1540   MI.eraseFromParent();
1541   return true;
1542 }
1543 
1544 // TODO: Copied from DAG implementation. Verify logic and document how this
1545 // actually works.
1546 bool AMDGPULegalizerInfo::legalizeFPTOI(
1547   MachineInstr &MI, MachineRegisterInfo &MRI,
1548   MachineIRBuilder &B, bool Signed) const {
1549   B.setInstr(MI);
1550 
1551   Register Dst = MI.getOperand(0).getReg();
1552   Register Src = MI.getOperand(1).getReg();
1553 
1554   const LLT S64 = LLT::scalar(64);
1555   const LLT S32 = LLT::scalar(32);
1556 
1557   assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S64);
1558 
1559   unsigned Flags = MI.getFlags();
1560 
1561   auto Trunc = B.buildIntrinsicTrunc(S64, Src, Flags);
1562   auto K0 = B.buildFConstant(S64, BitsToDouble(UINT64_C(0x3df0000000000000)));
1563   auto K1 = B.buildFConstant(S64, BitsToDouble(UINT64_C(0xc1f0000000000000)));
1564 
1565   auto Mul = B.buildFMul(S64, Trunc, K0, Flags);
1566   auto FloorMul = B.buildFFloor(S64, Mul, Flags);
1567   auto Fma = B.buildFMA(S64, FloorMul, K1, Trunc, Flags);
1568 
1569   auto Hi = Signed ?
1570     B.buildFPTOSI(S32, FloorMul) :
1571     B.buildFPTOUI(S32, FloorMul);
1572   auto Lo = B.buildFPTOUI(S32, Fma);
1573 
1574   B.buildMerge(Dst, { Lo.getReg(0), Hi.getReg(0) });
1575   MI.eraseFromParent();
1576 
1577   return true;
1578 }
1579 
1580 bool AMDGPULegalizerInfo::legalizeMinNumMaxNum(
1581   MachineInstr &MI, MachineRegisterInfo &MRI,
1582   MachineIRBuilder &B) const {
1583   MachineFunction &MF = B.getMF();
1584   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1585 
1586   const bool IsIEEEOp = MI.getOpcode() == AMDGPU::G_FMINNUM_IEEE ||
1587                         MI.getOpcode() == AMDGPU::G_FMAXNUM_IEEE;
1588 
1589   // With ieee_mode disabled, the instructions have the correct behavior
1590   // already for G_FMINNUM/G_FMAXNUM
1591   if (!MFI->getMode().IEEE)
1592     return !IsIEEEOp;
1593 
1594   if (IsIEEEOp)
1595     return true;
1596 
1597   MachineIRBuilder HelperBuilder(MI);
1598   GISelObserverWrapper DummyObserver;
1599   LegalizerHelper Helper(MF, DummyObserver, HelperBuilder);
1600   HelperBuilder.setInstr(MI);
1601   return Helper.lowerFMinNumMaxNum(MI) == LegalizerHelper::Legalized;
1602 }
1603 
1604 bool AMDGPULegalizerInfo::legalizeExtractVectorElt(
1605   MachineInstr &MI, MachineRegisterInfo &MRI,
1606   MachineIRBuilder &B) const {
1607   // TODO: Should move some of this into LegalizerHelper.
1608 
1609   // TODO: Promote dynamic indexing of s16 to s32
1610   // TODO: Dynamic s64 indexing is only legal for SGPR.
1611   Optional<int64_t> IdxVal = getConstantVRegVal(MI.getOperand(2).getReg(), MRI);
1612   if (!IdxVal) // Dynamic case will be selected to register indexing.
1613     return true;
1614 
1615   Register Dst = MI.getOperand(0).getReg();
1616   Register Vec = MI.getOperand(1).getReg();
1617 
1618   LLT VecTy = MRI.getType(Vec);
1619   LLT EltTy = VecTy.getElementType();
1620   assert(EltTy == MRI.getType(Dst));
1621 
1622   B.setInstr(MI);
1623 
1624   if (IdxVal.getValue() < VecTy.getNumElements())
1625     B.buildExtract(Dst, Vec, IdxVal.getValue() * EltTy.getSizeInBits());
1626   else
1627     B.buildUndef(Dst);
1628 
1629   MI.eraseFromParent();
1630   return true;
1631 }
1632 
1633 bool AMDGPULegalizerInfo::legalizeInsertVectorElt(
1634   MachineInstr &MI, MachineRegisterInfo &MRI,
1635   MachineIRBuilder &B) const {
1636   // TODO: Should move some of this into LegalizerHelper.
1637 
1638   // TODO: Promote dynamic indexing of s16 to s32
1639   // TODO: Dynamic s64 indexing is only legal for SGPR.
1640   Optional<int64_t> IdxVal = getConstantVRegVal(MI.getOperand(3).getReg(), MRI);
1641   if (!IdxVal) // Dynamic case will be selected to register indexing.
1642     return true;
1643 
1644   Register Dst = MI.getOperand(0).getReg();
1645   Register Vec = MI.getOperand(1).getReg();
1646   Register Ins = MI.getOperand(2).getReg();
1647 
1648   LLT VecTy = MRI.getType(Vec);
1649   LLT EltTy = VecTy.getElementType();
1650   assert(EltTy == MRI.getType(Ins));
1651 
1652   B.setInstr(MI);
1653 
1654   if (IdxVal.getValue() < VecTy.getNumElements())
1655     B.buildInsert(Dst, Vec, Ins, IdxVal.getValue() * EltTy.getSizeInBits());
1656   else
1657     B.buildUndef(Dst);
1658 
1659   MI.eraseFromParent();
1660   return true;
1661 }
1662 
1663 static bool isLegalVOP3PShuffleMask(ArrayRef<int> Mask) {
1664   assert(Mask.size() == 2);
1665 
1666   // If one half is undef, the other is trivially in the same reg.
1667   if (Mask[0] == -1 || Mask[1] == -1)
1668     return true;
1669   return ((Mask[0] == 0 || Mask[0] == 1) && (Mask[1] == 0 || Mask[1] == 1)) ||
1670          ((Mask[0] == 2 || Mask[0] == 3) && (Mask[1] == 2 || Mask[1] == 3));
1671 }
1672 
1673 bool AMDGPULegalizerInfo::legalizeShuffleVector(
1674   MachineInstr &MI, MachineRegisterInfo &MRI,
1675   MachineIRBuilder &B) const {
1676   const LLT V2S16 = LLT::vector(2, 16);
1677 
1678   Register Dst = MI.getOperand(0).getReg();
1679   Register Src0 = MI.getOperand(1).getReg();
1680   LLT DstTy = MRI.getType(Dst);
1681   LLT SrcTy = MRI.getType(Src0);
1682 
1683   if (SrcTy == V2S16 && DstTy == V2S16 &&
1684       isLegalVOP3PShuffleMask(MI.getOperand(3).getShuffleMask()))
1685     return true;
1686 
1687   MachineIRBuilder HelperBuilder(MI);
1688   GISelObserverWrapper DummyObserver;
1689   LegalizerHelper Helper(B.getMF(), DummyObserver, HelperBuilder);
1690   HelperBuilder.setInstr(MI);
1691   return Helper.lowerShuffleVector(MI) == LegalizerHelper::Legalized;
1692 }
1693 
1694 bool AMDGPULegalizerInfo::legalizeSinCos(
1695   MachineInstr &MI, MachineRegisterInfo &MRI,
1696   MachineIRBuilder &B) const {
1697   B.setInstr(MI);
1698 
1699   Register DstReg = MI.getOperand(0).getReg();
1700   Register SrcReg = MI.getOperand(1).getReg();
1701   LLT Ty = MRI.getType(DstReg);
1702   unsigned Flags = MI.getFlags();
1703 
1704   Register TrigVal;
1705   auto OneOver2Pi = B.buildFConstant(Ty, 0.5 / M_PI);
1706   if (ST.hasTrigReducedRange()) {
1707     auto MulVal = B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags);
1708     TrigVal = B.buildIntrinsic(Intrinsic::amdgcn_fract, {Ty}, false)
1709       .addUse(MulVal.getReg(0))
1710       .setMIFlags(Flags).getReg(0);
1711   } else
1712     TrigVal = B.buildFMul(Ty, SrcReg, OneOver2Pi, Flags).getReg(0);
1713 
1714   Intrinsic::ID TrigIntrin = MI.getOpcode() == AMDGPU::G_FSIN ?
1715     Intrinsic::amdgcn_sin : Intrinsic::amdgcn_cos;
1716   B.buildIntrinsic(TrigIntrin, makeArrayRef<Register>(DstReg), false)
1717     .addUse(TrigVal)
1718     .setMIFlags(Flags);
1719   MI.eraseFromParent();
1720   return true;
1721 }
1722 
1723 bool AMDGPULegalizerInfo::buildPCRelGlobalAddress(
1724   Register DstReg, LLT PtrTy,
1725   MachineIRBuilder &B, const GlobalValue *GV,
1726   unsigned Offset, unsigned GAFlags) const {
1727   // In order to support pc-relative addressing, SI_PC_ADD_REL_OFFSET is lowered
1728   // to the following code sequence:
1729   //
1730   // For constant address space:
1731   //   s_getpc_b64 s[0:1]
1732   //   s_add_u32 s0, s0, $symbol
1733   //   s_addc_u32 s1, s1, 0
1734   //
1735   //   s_getpc_b64 returns the address of the s_add_u32 instruction and then
1736   //   a fixup or relocation is emitted to replace $symbol with a literal
1737   //   constant, which is a pc-relative offset from the encoding of the $symbol
1738   //   operand to the global variable.
1739   //
1740   // For global address space:
1741   //   s_getpc_b64 s[0:1]
1742   //   s_add_u32 s0, s0, $symbol@{gotpc}rel32@lo
1743   //   s_addc_u32 s1, s1, $symbol@{gotpc}rel32@hi
1744   //
1745   //   s_getpc_b64 returns the address of the s_add_u32 instruction and then
1746   //   fixups or relocations are emitted to replace $symbol@*@lo and
1747   //   $symbol@*@hi with lower 32 bits and higher 32 bits of a literal constant,
1748   //   which is a 64-bit pc-relative offset from the encoding of the $symbol
1749   //   operand to the global variable.
1750   //
1751   // What we want here is an offset from the value returned by s_getpc
1752   // (which is the address of the s_add_u32 instruction) to the global
1753   // variable, but since the encoding of $symbol starts 4 bytes after the start
1754   // of the s_add_u32 instruction, we end up with an offset that is 4 bytes too
1755   // small. This requires us to add 4 to the global variable offset in order to
1756   // compute the correct address.
1757 
1758   LLT ConstPtrTy = LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64);
1759 
1760   Register PCReg = PtrTy.getSizeInBits() != 32 ? DstReg :
1761     B.getMRI()->createGenericVirtualRegister(ConstPtrTy);
1762 
1763   MachineInstrBuilder MIB = B.buildInstr(AMDGPU::SI_PC_ADD_REL_OFFSET)
1764     .addDef(PCReg);
1765 
1766   MIB.addGlobalAddress(GV, Offset + 4, GAFlags);
1767   if (GAFlags == SIInstrInfo::MO_NONE)
1768     MIB.addImm(0);
1769   else
1770     MIB.addGlobalAddress(GV, Offset + 4, GAFlags + 1);
1771 
1772   B.getMRI()->setRegClass(PCReg, &AMDGPU::SReg_64RegClass);
1773 
1774   if (PtrTy.getSizeInBits() == 32)
1775     B.buildExtract(DstReg, PCReg, 0);
1776   return true;
1777  }
1778 
1779 bool AMDGPULegalizerInfo::legalizeGlobalValue(
1780   MachineInstr &MI, MachineRegisterInfo &MRI,
1781   MachineIRBuilder &B) const {
1782   Register DstReg = MI.getOperand(0).getReg();
1783   LLT Ty = MRI.getType(DstReg);
1784   unsigned AS = Ty.getAddressSpace();
1785 
1786   const GlobalValue *GV = MI.getOperand(1).getGlobal();
1787   MachineFunction &MF = B.getMF();
1788   SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1789   B.setInstr(MI);
1790 
1791   if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
1792     if (!MFI->isEntryFunction()) {
1793       const Function &Fn = MF.getFunction();
1794       DiagnosticInfoUnsupported BadLDSDecl(
1795         Fn, "local memory global used by non-kernel function", MI.getDebugLoc());
1796       Fn.getContext().diagnose(BadLDSDecl);
1797     }
1798 
1799     // TODO: We could emit code to handle the initialization somewhere.
1800     if (!AMDGPUTargetLowering::hasDefinedInitializer(GV)) {
1801       const SITargetLowering *TLI = ST.getTargetLowering();
1802       if (!TLI->shouldUseLDSConstAddress(GV)) {
1803         MI.getOperand(1).setTargetFlags(SIInstrInfo::MO_ABS32_LO);
1804         return true; // Leave in place;
1805       }
1806 
1807       B.buildConstant(DstReg, MFI->allocateLDSGlobal(B.getDataLayout(), *GV));
1808       MI.eraseFromParent();
1809       return true;
1810     }
1811 
1812     const Function &Fn = MF.getFunction();
1813     DiagnosticInfoUnsupported BadInit(
1814       Fn, "unsupported initializer for address space", MI.getDebugLoc());
1815     Fn.getContext().diagnose(BadInit);
1816     return true;
1817   }
1818 
1819   const SITargetLowering *TLI = ST.getTargetLowering();
1820 
1821   if (TLI->shouldEmitFixup(GV)) {
1822     buildPCRelGlobalAddress(DstReg, Ty, B, GV, 0);
1823     MI.eraseFromParent();
1824     return true;
1825   }
1826 
1827   if (TLI->shouldEmitPCReloc(GV)) {
1828     buildPCRelGlobalAddress(DstReg, Ty, B, GV, 0, SIInstrInfo::MO_REL32);
1829     MI.eraseFromParent();
1830     return true;
1831   }
1832 
1833   LLT PtrTy = LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64);
1834   Register GOTAddr = MRI.createGenericVirtualRegister(PtrTy);
1835 
1836   MachineMemOperand *GOTMMO = MF.getMachineMemOperand(
1837     MachinePointerInfo::getGOT(MF),
1838     MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
1839     MachineMemOperand::MOInvariant,
1840     8 /*Size*/, 8 /*Align*/);
1841 
1842   buildPCRelGlobalAddress(GOTAddr, PtrTy, B, GV, 0, SIInstrInfo::MO_GOTPCREL32);
1843 
1844   if (Ty.getSizeInBits() == 32) {
1845     // Truncate if this is a 32-bit constant adrdess.
1846     auto Load = B.buildLoad(PtrTy, GOTAddr, *GOTMMO);
1847     B.buildExtract(DstReg, Load, 0);
1848   } else
1849     B.buildLoad(DstReg, GOTAddr, *GOTMMO);
1850 
1851   MI.eraseFromParent();
1852   return true;
1853 }
1854 
1855 bool AMDGPULegalizerInfo::legalizeLoad(
1856   MachineInstr &MI, MachineRegisterInfo &MRI,
1857   MachineIRBuilder &B, GISelChangeObserver &Observer) const {
1858   B.setInstr(MI);
1859   LLT ConstPtr = LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64);
1860   auto Cast = B.buildAddrSpaceCast(ConstPtr, MI.getOperand(1).getReg());
1861   Observer.changingInstr(MI);
1862   MI.getOperand(1).setReg(Cast.getReg(0));
1863   Observer.changedInstr(MI);
1864   return true;
1865 }
1866 
1867 bool AMDGPULegalizerInfo::legalizeFMad(
1868   MachineInstr &MI, MachineRegisterInfo &MRI,
1869   MachineIRBuilder &B) const {
1870   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1871   assert(Ty.isScalar());
1872 
1873   MachineFunction &MF = B.getMF();
1874   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1875 
1876   // TODO: Always legal with future ftz flag.
1877   if (Ty == LLT::scalar(32) && !MFI->getMode().FP32Denormals)
1878     return true;
1879   if (Ty == LLT::scalar(16) && !MFI->getMode().FP64FP16Denormals)
1880     return true;
1881 
1882 
1883   MachineIRBuilder HelperBuilder(MI);
1884   GISelObserverWrapper DummyObserver;
1885   LegalizerHelper Helper(MF, DummyObserver, HelperBuilder);
1886   HelperBuilder.setMBB(*MI.getParent());
1887   return Helper.lowerFMad(MI) == LegalizerHelper::Legalized;
1888 }
1889 
1890 bool AMDGPULegalizerInfo::legalizeAtomicCmpXChg(
1891   MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const {
1892   Register DstReg = MI.getOperand(0).getReg();
1893   Register PtrReg = MI.getOperand(1).getReg();
1894   Register CmpVal = MI.getOperand(2).getReg();
1895   Register NewVal = MI.getOperand(3).getReg();
1896 
1897   assert(SITargetLowering::isFlatGlobalAddrSpace(
1898            MRI.getType(PtrReg).getAddressSpace()) &&
1899          "this should not have been custom lowered");
1900 
1901   LLT ValTy = MRI.getType(CmpVal);
1902   LLT VecTy = LLT::vector(2, ValTy);
1903 
1904   B.setInstr(MI);
1905   Register PackedVal = B.buildBuildVector(VecTy, { NewVal, CmpVal }).getReg(0);
1906 
1907   B.buildInstr(AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG)
1908     .addDef(DstReg)
1909     .addUse(PtrReg)
1910     .addUse(PackedVal)
1911     .setMemRefs(MI.memoperands());
1912 
1913   MI.eraseFromParent();
1914   return true;
1915 }
1916 
1917 bool AMDGPULegalizerInfo::legalizeFlog(
1918   MachineInstr &MI, MachineIRBuilder &B, double Log2BaseInverted) const {
1919   Register Dst = MI.getOperand(0).getReg();
1920   Register Src = MI.getOperand(1).getReg();
1921   LLT Ty = B.getMRI()->getType(Dst);
1922   unsigned Flags = MI.getFlags();
1923   B.setInstr(MI);
1924 
1925   auto Log2Operand = B.buildFLog2(Ty, Src, Flags);
1926   auto Log2BaseInvertedOperand = B.buildFConstant(Ty, Log2BaseInverted);
1927 
1928   B.buildFMul(Dst, Log2Operand, Log2BaseInvertedOperand, Flags);
1929   MI.eraseFromParent();
1930   return true;
1931 }
1932 
1933 // Return the use branch instruction, otherwise null if the usage is invalid.
1934 static MachineInstr *verifyCFIntrinsic(MachineInstr &MI,
1935                                        MachineRegisterInfo &MRI,
1936                                        MachineInstr *&Br) {
1937   Register CondDef = MI.getOperand(0).getReg();
1938   if (!MRI.hasOneNonDBGUse(CondDef))
1939     return nullptr;
1940 
1941   MachineInstr &UseMI = *MRI.use_instr_nodbg_begin(CondDef);
1942   if (UseMI.getParent() != MI.getParent() ||
1943       UseMI.getOpcode() != AMDGPU::G_BRCOND)
1944     return nullptr;
1945 
1946   // Make sure the cond br is followed by a G_BR
1947   MachineBasicBlock::iterator Next = std::next(UseMI.getIterator());
1948   if (Next != MI.getParent()->end()) {
1949     if (Next->getOpcode() != AMDGPU::G_BR)
1950       return nullptr;
1951     Br = &*Next;
1952   }
1953 
1954   return &UseMI;
1955 }
1956 
1957 Register AMDGPULegalizerInfo::getLiveInRegister(MachineRegisterInfo &MRI,
1958                                                 Register Reg, LLT Ty) const {
1959   Register LiveIn = MRI.getLiveInVirtReg(Reg);
1960   if (LiveIn)
1961     return LiveIn;
1962 
1963   Register NewReg = MRI.createGenericVirtualRegister(Ty);
1964   MRI.addLiveIn(Reg, NewReg);
1965   return NewReg;
1966 }
1967 
1968 bool AMDGPULegalizerInfo::loadInputValue(Register DstReg, MachineIRBuilder &B,
1969                                          const ArgDescriptor *Arg) const {
1970   if (!Arg->isRegister() || !Arg->getRegister().isValid())
1971     return false; // TODO: Handle these
1972 
1973   assert(Arg->getRegister().isPhysical());
1974 
1975   MachineRegisterInfo &MRI = *B.getMRI();
1976 
1977   LLT Ty = MRI.getType(DstReg);
1978   Register LiveIn = getLiveInRegister(MRI, Arg->getRegister(), Ty);
1979 
1980   if (Arg->isMasked()) {
1981     // TODO: Should we try to emit this once in the entry block?
1982     const LLT S32 = LLT::scalar(32);
1983     const unsigned Mask = Arg->getMask();
1984     const unsigned Shift = countTrailingZeros<unsigned>(Mask);
1985 
1986     Register AndMaskSrc = LiveIn;
1987 
1988     if (Shift != 0) {
1989       auto ShiftAmt = B.buildConstant(S32, Shift);
1990       AndMaskSrc = B.buildLShr(S32, LiveIn, ShiftAmt).getReg(0);
1991     }
1992 
1993     B.buildAnd(DstReg, AndMaskSrc, B.buildConstant(S32, Mask >> Shift));
1994   } else
1995     B.buildCopy(DstReg, LiveIn);
1996 
1997   // Insert the argument copy if it doens't already exist.
1998   // FIXME: It seems EmitLiveInCopies isn't called anywhere?
1999   if (!MRI.getVRegDef(LiveIn)) {
2000     // FIXME: Should have scoped insert pt
2001     MachineBasicBlock &OrigInsBB = B.getMBB();
2002     auto OrigInsPt = B.getInsertPt();
2003 
2004     MachineBasicBlock &EntryMBB = B.getMF().front();
2005     EntryMBB.addLiveIn(Arg->getRegister());
2006     B.setInsertPt(EntryMBB, EntryMBB.begin());
2007     B.buildCopy(LiveIn, Arg->getRegister());
2008 
2009     B.setInsertPt(OrigInsBB, OrigInsPt);
2010   }
2011 
2012   return true;
2013 }
2014 
2015 bool AMDGPULegalizerInfo::legalizePreloadedArgIntrin(
2016   MachineInstr &MI,
2017   MachineRegisterInfo &MRI,
2018   MachineIRBuilder &B,
2019   AMDGPUFunctionArgInfo::PreloadedValue ArgType) const {
2020   B.setInstr(MI);
2021 
2022   const SIMachineFunctionInfo *MFI = B.getMF().getInfo<SIMachineFunctionInfo>();
2023 
2024   const ArgDescriptor *Arg;
2025   const TargetRegisterClass *RC;
2026   std::tie(Arg, RC) = MFI->getPreloadedValue(ArgType);
2027   if (!Arg) {
2028     LLVM_DEBUG(dbgs() << "Required arg register missing\n");
2029     return false;
2030   }
2031 
2032   if (loadInputValue(MI.getOperand(0).getReg(), B, Arg)) {
2033     MI.eraseFromParent();
2034     return true;
2035   }
2036 
2037   return false;
2038 }
2039 
2040 bool AMDGPULegalizerInfo::legalizeFDIV(MachineInstr &MI,
2041                                        MachineRegisterInfo &MRI,
2042                                        MachineIRBuilder &B) const {
2043   B.setInstr(MI);
2044   Register Dst = MI.getOperand(0).getReg();
2045   LLT DstTy = MRI.getType(Dst);
2046   LLT S16 = LLT::scalar(16);
2047   LLT S32 = LLT::scalar(32);
2048   LLT S64 = LLT::scalar(64);
2049 
2050   if (legalizeFastUnsafeFDIV(MI, MRI, B))
2051     return true;
2052 
2053   if (DstTy == S16)
2054     return legalizeFDIV16(MI, MRI, B);
2055   if (DstTy == S32)
2056     return legalizeFDIV32(MI, MRI, B);
2057   if (DstTy == S64)
2058     return legalizeFDIV64(MI, MRI, B);
2059 
2060   return false;
2061 }
2062 
2063 bool AMDGPULegalizerInfo::legalizeFastUnsafeFDIV(MachineInstr &MI,
2064                                                  MachineRegisterInfo &MRI,
2065                                                  MachineIRBuilder &B) const {
2066   Register Res = MI.getOperand(0).getReg();
2067   Register LHS = MI.getOperand(1).getReg();
2068   Register RHS = MI.getOperand(2).getReg();
2069 
2070   uint16_t Flags = MI.getFlags();
2071 
2072   LLT ResTy = MRI.getType(Res);
2073   LLT S32 = LLT::scalar(32);
2074   LLT S64 = LLT::scalar(64);
2075 
2076   const MachineFunction &MF = B.getMF();
2077   bool Unsafe =
2078     MF.getTarget().Options.UnsafeFPMath || MI.getFlag(MachineInstr::FmArcp);
2079 
2080   if (!MF.getTarget().Options.UnsafeFPMath && ResTy == S64)
2081     return false;
2082 
2083   if (!Unsafe && ResTy == S32 &&
2084       MF.getInfo<SIMachineFunctionInfo>()->getMode().FP32Denormals)
2085     return false;
2086 
2087   if (auto CLHS = getConstantFPVRegVal(LHS, MRI)) {
2088     // 1 / x -> RCP(x)
2089     if (CLHS->isExactlyValue(1.0)) {
2090       B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res, false)
2091         .addUse(RHS)
2092         .setMIFlags(Flags);
2093 
2094       MI.eraseFromParent();
2095       return true;
2096     }
2097 
2098     // -1 / x -> RCP( FNEG(x) )
2099     if (CLHS->isExactlyValue(-1.0)) {
2100       auto FNeg = B.buildFNeg(ResTy, RHS, Flags);
2101       B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res, false)
2102         .addUse(FNeg.getReg(0))
2103         .setMIFlags(Flags);
2104 
2105       MI.eraseFromParent();
2106       return true;
2107     }
2108   }
2109 
2110   // x / y -> x * (1.0 / y)
2111   if (Unsafe) {
2112     auto RCP = B.buildIntrinsic(Intrinsic::amdgcn_rcp, {ResTy}, false)
2113       .addUse(RHS)
2114       .setMIFlags(Flags);
2115     B.buildFMul(Res, LHS, RCP, Flags);
2116 
2117     MI.eraseFromParent();
2118     return true;
2119   }
2120 
2121   return false;
2122 }
2123 
2124 bool AMDGPULegalizerInfo::legalizeFDIV16(MachineInstr &MI,
2125                                          MachineRegisterInfo &MRI,
2126                                          MachineIRBuilder &B) const {
2127   B.setInstr(MI);
2128   Register Res = MI.getOperand(0).getReg();
2129   Register LHS = MI.getOperand(1).getReg();
2130   Register RHS = MI.getOperand(2).getReg();
2131 
2132   uint16_t Flags = MI.getFlags();
2133 
2134   LLT S16 = LLT::scalar(16);
2135   LLT S32 = LLT::scalar(32);
2136 
2137   auto LHSExt = B.buildFPExt(S32, LHS, Flags);
2138   auto RHSExt = B.buildFPExt(S32, RHS, Flags);
2139 
2140   auto RCP = B.buildIntrinsic(Intrinsic::amdgcn_rcp, {S32}, false)
2141     .addUse(RHSExt.getReg(0))
2142     .setMIFlags(Flags);
2143 
2144   auto QUOT = B.buildFMul(S32, LHSExt, RCP, Flags);
2145   auto RDst = B.buildFPTrunc(S16, QUOT, Flags);
2146 
2147   B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res, false)
2148     .addUse(RDst.getReg(0))
2149     .addUse(RHS)
2150     .addUse(LHS)
2151     .setMIFlags(Flags);
2152 
2153   MI.eraseFromParent();
2154   return true;
2155 }
2156 
2157 // Enable or disable FP32 denorm mode. When 'Enable' is true, emit instructions
2158 // to enable denorm mode. When 'Enable' is false, disable denorm mode.
2159 static void toggleSPDenormMode(bool Enable,
2160                                MachineIRBuilder &B,
2161                                const GCNSubtarget &ST,
2162                                AMDGPU::SIModeRegisterDefaults Mode) {
2163   // Set SP denorm mode to this value.
2164   unsigned SPDenormMode =
2165     Enable ? FP_DENORM_FLUSH_NONE : FP_DENORM_FLUSH_IN_FLUSH_OUT;
2166 
2167   if (ST.hasDenormModeInst()) {
2168     // Preserve default FP64FP16 denorm mode while updating FP32 mode.
2169     unsigned DPDenormModeDefault = Mode.FP64FP16Denormals
2170                                    ? FP_DENORM_FLUSH_NONE
2171                                    : FP_DENORM_FLUSH_IN_FLUSH_OUT;
2172 
2173     unsigned NewDenormModeValue = SPDenormMode | (DPDenormModeDefault << 2);
2174     B.buildInstr(AMDGPU::S_DENORM_MODE)
2175       .addImm(NewDenormModeValue);
2176 
2177   } else {
2178     // Select FP32 bit field in mode register.
2179     unsigned SPDenormModeBitField = AMDGPU::Hwreg::ID_MODE |
2180                                     (4 << AMDGPU::Hwreg::OFFSET_SHIFT_) |
2181                                     (1 << AMDGPU::Hwreg::WIDTH_M1_SHIFT_);
2182 
2183     B.buildInstr(AMDGPU::S_SETREG_IMM32_B32)
2184       .addImm(SPDenormMode)
2185       .addImm(SPDenormModeBitField);
2186   }
2187 }
2188 
2189 bool AMDGPULegalizerInfo::legalizeFDIV32(MachineInstr &MI,
2190                                          MachineRegisterInfo &MRI,
2191                                          MachineIRBuilder &B) const {
2192   B.setInstr(MI);
2193   Register Res = MI.getOperand(0).getReg();
2194   Register LHS = MI.getOperand(1).getReg();
2195   Register RHS = MI.getOperand(2).getReg();
2196   const SIMachineFunctionInfo *MFI = B.getMF().getInfo<SIMachineFunctionInfo>();
2197   AMDGPU::SIModeRegisterDefaults Mode = MFI->getMode();
2198 
2199   uint16_t Flags = MI.getFlags();
2200 
2201   LLT S32 = LLT::scalar(32);
2202   LLT S1 = LLT::scalar(1);
2203 
2204   auto One = B.buildFConstant(S32, 1.0f);
2205 
2206   auto DenominatorScaled =
2207     B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {S32, S1}, false)
2208       .addUse(RHS)
2209       .addUse(LHS)
2210       .addImm(1)
2211       .setMIFlags(Flags);
2212   auto NumeratorScaled =
2213     B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {S32, S1}, false)
2214       .addUse(LHS)
2215       .addUse(RHS)
2216       .addImm(0)
2217       .setMIFlags(Flags);
2218 
2219   auto ApproxRcp = B.buildIntrinsic(Intrinsic::amdgcn_rcp, {S32}, false)
2220     .addUse(DenominatorScaled.getReg(0))
2221     .setMIFlags(Flags);
2222   auto NegDivScale0 = B.buildFNeg(S32, DenominatorScaled, Flags);
2223 
2224   // FIXME: Doesn't correctly model the FP mode switch, and the FP operations
2225   // aren't modeled as reading it.
2226   if (!Mode.FP32Denormals)
2227     toggleSPDenormMode(true, B, ST, Mode);
2228 
2229   auto Fma0 = B.buildFMA(S32, NegDivScale0, ApproxRcp, One, Flags);
2230   auto Fma1 = B.buildFMA(S32, Fma0, ApproxRcp, ApproxRcp, Flags);
2231   auto Mul = B.buildFMul(S32, NumeratorScaled, Fma1, Flags);
2232   auto Fma2 = B.buildFMA(S32, NegDivScale0, Mul, NumeratorScaled, Flags);
2233   auto Fma3 = B.buildFMA(S32, Fma2, Fma1, Mul, Flags);
2234   auto Fma4 = B.buildFMA(S32, NegDivScale0, Fma3, NumeratorScaled, Flags);
2235 
2236   if (!Mode.FP32Denormals)
2237     toggleSPDenormMode(false, B, ST, Mode);
2238 
2239   auto Fmas = B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {S32}, false)
2240     .addUse(Fma4.getReg(0))
2241     .addUse(Fma1.getReg(0))
2242     .addUse(Fma3.getReg(0))
2243     .addUse(NumeratorScaled.getReg(1))
2244     .setMIFlags(Flags);
2245 
2246   B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, Res, false)
2247     .addUse(Fmas.getReg(0))
2248     .addUse(RHS)
2249     .addUse(LHS)
2250     .setMIFlags(Flags);
2251 
2252   MI.eraseFromParent();
2253   return true;
2254 }
2255 
2256 bool AMDGPULegalizerInfo::legalizeFDIV64(MachineInstr &MI,
2257                                          MachineRegisterInfo &MRI,
2258                                          MachineIRBuilder &B) const {
2259   B.setInstr(MI);
2260   Register Res = MI.getOperand(0).getReg();
2261   Register LHS = MI.getOperand(1).getReg();
2262   Register RHS = MI.getOperand(2).getReg();
2263 
2264   uint16_t Flags = MI.getFlags();
2265 
2266   LLT S64 = LLT::scalar(64);
2267   LLT S1 = LLT::scalar(1);
2268 
2269   auto One = B.buildFConstant(S64, 1.0);
2270 
2271   auto DivScale0 = B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {S64, S1}, false)
2272     .addUse(LHS)
2273     .addUse(RHS)
2274     .addImm(1)
2275     .setMIFlags(Flags);
2276 
2277   auto NegDivScale0 = B.buildFNeg(S64, DivScale0.getReg(0), Flags);
2278 
2279   auto Rcp = B.buildIntrinsic(Intrinsic::amdgcn_rcp, {S64}, false)
2280     .addUse(DivScale0.getReg(0))
2281     .setMIFlags(Flags);
2282 
2283   auto Fma0 = B.buildFMA(S64, NegDivScale0, Rcp, One, Flags);
2284   auto Fma1 = B.buildFMA(S64, Rcp, Fma0, Rcp, Flags);
2285   auto Fma2 = B.buildFMA(S64, NegDivScale0, Fma1, One, Flags);
2286 
2287   auto DivScale1 = B.buildIntrinsic(Intrinsic::amdgcn_div_scale, {S64, S1}, false)
2288     .addUse(LHS)
2289     .addUse(RHS)
2290     .addImm(0)
2291     .setMIFlags(Flags);
2292 
2293   auto Fma3 = B.buildFMA(S64, Fma1, Fma2, Fma1, Flags);
2294   auto Mul = B.buildMul(S64, DivScale1.getReg(0), Fma3, Flags);
2295   auto Fma4 = B.buildFMA(S64, NegDivScale0, Mul, DivScale1.getReg(0), Flags);
2296 
2297   Register Scale;
2298   if (!ST.hasUsableDivScaleConditionOutput()) {
2299     // Workaround a hardware bug on SI where the condition output from div_scale
2300     // is not usable.
2301 
2302     LLT S32 = LLT::scalar(32);
2303 
2304     auto NumUnmerge = B.buildUnmerge(S32, LHS);
2305     auto DenUnmerge = B.buildUnmerge(S32, RHS);
2306     auto Scale0Unmerge = B.buildUnmerge(S32, DivScale0);
2307     auto Scale1Unmerge = B.buildUnmerge(S32, DivScale1);
2308 
2309     auto CmpNum = B.buildICmp(ICmpInst::ICMP_EQ, S1, NumUnmerge.getReg(1),
2310                               Scale1Unmerge.getReg(1));
2311     auto CmpDen = B.buildICmp(ICmpInst::ICMP_EQ, S1, DenUnmerge.getReg(1),
2312                               Scale0Unmerge.getReg(1));
2313     Scale = B.buildXor(S1, CmpNum, CmpDen).getReg(0);
2314   } else {
2315     Scale = DivScale1.getReg(1);
2316   }
2317 
2318   auto Fmas = B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {S64}, false)
2319     .addUse(Fma4.getReg(0))
2320     .addUse(Fma3.getReg(0))
2321     .addUse(Mul.getReg(0))
2322     .addUse(Scale)
2323     .setMIFlags(Flags);
2324 
2325   B.buildIntrinsic(Intrinsic::amdgcn_div_fixup, makeArrayRef(Res), false)
2326     .addUse(Fmas.getReg(0))
2327     .addUse(RHS)
2328     .addUse(LHS)
2329     .setMIFlags(Flags);
2330 
2331   MI.eraseFromParent();
2332   return true;
2333 }
2334 
2335 bool AMDGPULegalizerInfo::legalizeFDIVFastIntrin(MachineInstr &MI,
2336                                                  MachineRegisterInfo &MRI,
2337                                                  MachineIRBuilder &B) const {
2338   B.setInstr(MI);
2339   Register Res = MI.getOperand(0).getReg();
2340   Register LHS = MI.getOperand(2).getReg();
2341   Register RHS = MI.getOperand(3).getReg();
2342   uint16_t Flags = MI.getFlags();
2343 
2344   LLT S32 = LLT::scalar(32);
2345   LLT S1 = LLT::scalar(1);
2346 
2347   auto Abs = B.buildFAbs(S32, RHS, Flags);
2348   const APFloat C0Val(1.0f);
2349 
2350   auto C0 = B.buildConstant(S32, 0x6f800000);
2351   auto C1 = B.buildConstant(S32, 0x2f800000);
2352   auto C2 = B.buildConstant(S32, FloatToBits(1.0f));
2353 
2354   auto CmpRes = B.buildFCmp(CmpInst::FCMP_OGT, S1, Abs, C0, Flags);
2355   auto Sel = B.buildSelect(S32, CmpRes, C1, C2, Flags);
2356 
2357   auto Mul0 = B.buildFMul(S32, RHS, Sel, Flags);
2358 
2359   auto RCP = B.buildIntrinsic(Intrinsic::amdgcn_rcp, {S32}, false)
2360     .addUse(Mul0.getReg(0))
2361     .setMIFlags(Flags);
2362 
2363   auto Mul1 = B.buildFMul(S32, LHS, RCP, Flags);
2364 
2365   B.buildFMul(Res, Sel, Mul1, Flags);
2366 
2367   MI.eraseFromParent();
2368   return true;
2369 }
2370 
2371 bool AMDGPULegalizerInfo::legalizeImplicitArgPtr(MachineInstr &MI,
2372                                                  MachineRegisterInfo &MRI,
2373                                                  MachineIRBuilder &B) const {
2374   const SIMachineFunctionInfo *MFI = B.getMF().getInfo<SIMachineFunctionInfo>();
2375   if (!MFI->isEntryFunction()) {
2376     return legalizePreloadedArgIntrin(MI, MRI, B,
2377                                       AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR);
2378   }
2379 
2380   B.setInstr(MI);
2381 
2382   uint64_t Offset =
2383     ST.getTargetLowering()->getImplicitParameterOffset(
2384       B.getMF(), AMDGPUTargetLowering::FIRST_IMPLICIT);
2385   Register DstReg = MI.getOperand(0).getReg();
2386   LLT DstTy = MRI.getType(DstReg);
2387   LLT IdxTy = LLT::scalar(DstTy.getSizeInBits());
2388 
2389   const ArgDescriptor *Arg;
2390   const TargetRegisterClass *RC;
2391   std::tie(Arg, RC)
2392     = MFI->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
2393   if (!Arg)
2394     return false;
2395 
2396   Register KernargPtrReg = MRI.createGenericVirtualRegister(DstTy);
2397   if (!loadInputValue(KernargPtrReg, B, Arg))
2398     return false;
2399 
2400   B.buildPtrAdd(DstReg, KernargPtrReg, B.buildConstant(IdxTy, Offset).getReg(0));
2401   MI.eraseFromParent();
2402   return true;
2403 }
2404 
2405 bool AMDGPULegalizerInfo::legalizeIsAddrSpace(MachineInstr &MI,
2406                                               MachineRegisterInfo &MRI,
2407                                               MachineIRBuilder &B,
2408                                               unsigned AddrSpace) const {
2409   B.setInstr(MI);
2410   Register ApertureReg = getSegmentAperture(AddrSpace, MRI, B);
2411   auto Hi32 = B.buildExtract(LLT::scalar(32), MI.getOperand(2).getReg(), 32);
2412   B.buildICmp(ICmpInst::ICMP_EQ, MI.getOperand(0), Hi32, ApertureReg);
2413   MI.eraseFromParent();
2414   return true;
2415 }
2416 
2417 // The raw.(t)buffer and struct.(t)buffer intrinsics have two offset args:
2418 // offset (the offset that is included in bounds checking and swizzling, to be
2419 // split between the instruction's voffset and immoffset fields) and soffset
2420 // (the offset that is excluded from bounds checking and swizzling, to go in
2421 // the instruction's soffset field).  This function takes the first kind of
2422 // offset and figures out how to split it between voffset and immoffset.
2423 std::tuple<Register, unsigned, unsigned>
2424 AMDGPULegalizerInfo::splitBufferOffsets(MachineIRBuilder &B,
2425                                         Register OrigOffset) const {
2426   const unsigned MaxImm = 4095;
2427   Register BaseReg;
2428   unsigned TotalConstOffset;
2429   MachineInstr *OffsetDef;
2430   const LLT S32 = LLT::scalar(32);
2431 
2432   std::tie(BaseReg, TotalConstOffset, OffsetDef)
2433     = AMDGPU::getBaseWithConstantOffset(*B.getMRI(), OrigOffset);
2434 
2435   unsigned ImmOffset = TotalConstOffset;
2436 
2437   // If the immediate value is too big for the immoffset field, put the value
2438   // and -4096 into the immoffset field so that the value that is copied/added
2439   // for the voffset field is a multiple of 4096, and it stands more chance
2440   // of being CSEd with the copy/add for another similar load/store.
2441   // However, do not do that rounding down to a multiple of 4096 if that is a
2442   // negative number, as it appears to be illegal to have a negative offset
2443   // in the vgpr, even if adding the immediate offset makes it positive.
2444   unsigned Overflow = ImmOffset & ~MaxImm;
2445   ImmOffset -= Overflow;
2446   if ((int32_t)Overflow < 0) {
2447     Overflow += ImmOffset;
2448     ImmOffset = 0;
2449   }
2450 
2451   if (Overflow != 0) {
2452     if (!BaseReg) {
2453       BaseReg = B.buildConstant(S32, Overflow).getReg(0);
2454     } else {
2455       auto OverflowVal = B.buildConstant(S32, Overflow);
2456       BaseReg = B.buildAdd(S32, BaseReg, OverflowVal).getReg(0);
2457     }
2458   }
2459 
2460   if (!BaseReg)
2461     BaseReg = B.buildConstant(S32, 0).getReg(0);
2462 
2463   return std::make_tuple(BaseReg, ImmOffset, TotalConstOffset);
2464 }
2465 
2466 /// Handle register layout difference for f16 images for some subtargets.
2467 Register AMDGPULegalizerInfo::handleD16VData(MachineIRBuilder &B,
2468                                              MachineRegisterInfo &MRI,
2469                                              Register Reg) const {
2470   if (!ST.hasUnpackedD16VMem())
2471     return Reg;
2472 
2473   const LLT S16 = LLT::scalar(16);
2474   const LLT S32 = LLT::scalar(32);
2475   LLT StoreVT = MRI.getType(Reg);
2476   assert(StoreVT.isVector() && StoreVT.getElementType() == S16);
2477 
2478   auto Unmerge = B.buildUnmerge(S16, Reg);
2479 
2480   SmallVector<Register, 4> WideRegs;
2481   for (int I = 0, E = Unmerge->getNumOperands() - 1; I != E; ++I)
2482     WideRegs.push_back(B.buildAnyExt(S32, Unmerge.getReg(I)).getReg(0));
2483 
2484   int NumElts = StoreVT.getNumElements();
2485 
2486   return B.buildBuildVector(LLT::vector(NumElts, S32), WideRegs).getReg(0);
2487 }
2488 
2489 Register AMDGPULegalizerInfo::fixStoreSourceType(
2490   MachineIRBuilder &B, Register VData, bool IsFormat) const {
2491   MachineRegisterInfo *MRI = B.getMRI();
2492   LLT Ty = MRI->getType(VData);
2493 
2494   const LLT S16 = LLT::scalar(16);
2495 
2496   // Fixup illegal register types for i8 stores.
2497   if (Ty == LLT::scalar(8) || Ty == S16) {
2498     Register AnyExt = B.buildAnyExt(LLT::scalar(32), VData).getReg(0);
2499     return AnyExt;
2500   }
2501 
2502   if (Ty.isVector()) {
2503     if (Ty.getElementType() == S16 && Ty.getNumElements() <= 4) {
2504       if (IsFormat)
2505         return handleD16VData(B, *MRI, VData);
2506     }
2507   }
2508 
2509   return VData;
2510 }
2511 
2512 bool AMDGPULegalizerInfo::legalizeBufferStore(MachineInstr &MI,
2513                                               MachineRegisterInfo &MRI,
2514                                               MachineIRBuilder &B,
2515                                               bool IsTyped,
2516                                               bool IsFormat) const {
2517   B.setInstr(MI);
2518 
2519   Register VData = MI.getOperand(1).getReg();
2520   LLT Ty = MRI.getType(VData);
2521   LLT EltTy = Ty.getScalarType();
2522   const bool IsD16 = IsFormat && (EltTy.getSizeInBits() == 16);
2523   const LLT S32 = LLT::scalar(32);
2524 
2525   VData = fixStoreSourceType(B, VData, IsFormat);
2526   Register RSrc = MI.getOperand(2).getReg();
2527 
2528   MachineMemOperand *MMO = *MI.memoperands_begin();
2529   const int MemSize = MMO->getSize();
2530 
2531   unsigned ImmOffset;
2532   unsigned TotalOffset;
2533 
2534   // The typed intrinsics add an immediate after the registers.
2535   const unsigned NumVIndexOps = IsTyped ? 8 : 7;
2536 
2537   // The struct intrinsic variants add one additional operand over raw.
2538   const bool HasVIndex = MI.getNumOperands() == NumVIndexOps;
2539   Register VIndex;
2540   int OpOffset = 0;
2541   if (HasVIndex) {
2542     VIndex = MI.getOperand(3).getReg();
2543     OpOffset = 1;
2544   }
2545 
2546   Register VOffset = MI.getOperand(3 + OpOffset).getReg();
2547   Register SOffset = MI.getOperand(4 + OpOffset).getReg();
2548 
2549   unsigned Format = 0;
2550   if (IsTyped) {
2551     Format = MI.getOperand(5 + OpOffset).getImm();
2552     ++OpOffset;
2553   }
2554 
2555   unsigned AuxiliaryData = MI.getOperand(5 + OpOffset).getImm();
2556 
2557   std::tie(VOffset, ImmOffset, TotalOffset) = splitBufferOffsets(B, VOffset);
2558   if (TotalOffset != 0)
2559     MMO = B.getMF().getMachineMemOperand(MMO, TotalOffset, MemSize);
2560 
2561   unsigned Opc;
2562   if (IsTyped) {
2563     Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16 :
2564                   AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT;
2565   } else if (IsFormat) {
2566     Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16 :
2567                   AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT;
2568   } else {
2569     switch (MemSize) {
2570     case 1:
2571       Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE;
2572       break;
2573     case 2:
2574       Opc = AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT;
2575       break;
2576     default:
2577       Opc = AMDGPU::G_AMDGPU_BUFFER_STORE;
2578       break;
2579     }
2580   }
2581 
2582   if (!VIndex)
2583     VIndex = B.buildConstant(S32, 0).getReg(0);
2584 
2585   auto MIB = B.buildInstr(Opc)
2586     .addUse(VData)              // vdata
2587     .addUse(RSrc)               // rsrc
2588     .addUse(VIndex)             // vindex
2589     .addUse(VOffset)            // voffset
2590     .addUse(SOffset)            // soffset
2591     .addImm(ImmOffset);         // offset(imm)
2592 
2593   if (IsTyped)
2594     MIB.addImm(Format);
2595 
2596   MIB.addImm(AuxiliaryData)      // cachepolicy, swizzled buffer(imm)
2597      .addImm(HasVIndex ? -1 : 0) // idxen(imm)
2598      .addMemOperand(MMO);
2599 
2600   MI.eraseFromParent();
2601   return true;
2602 }
2603 
2604 bool AMDGPULegalizerInfo::legalizeBufferLoad(MachineInstr &MI,
2605                                              MachineRegisterInfo &MRI,
2606                                              MachineIRBuilder &B,
2607                                              bool IsFormat,
2608                                              bool IsTyped) const {
2609   B.setInstr(MI);
2610 
2611   // FIXME: Verifier should enforce 1 MMO for these intrinsics.
2612   MachineMemOperand *MMO = *MI.memoperands_begin();
2613   const int MemSize = MMO->getSize();
2614   const LLT S32 = LLT::scalar(32);
2615 
2616   Register Dst = MI.getOperand(0).getReg();
2617   Register RSrc = MI.getOperand(2).getReg();
2618 
2619   // The typed intrinsics add an immediate after the registers.
2620   const unsigned NumVIndexOps = IsTyped ? 8 : 7;
2621 
2622   // The struct intrinsic variants add one additional operand over raw.
2623   const bool HasVIndex = MI.getNumOperands() == NumVIndexOps;
2624   Register VIndex;
2625   int OpOffset = 0;
2626   if (HasVIndex) {
2627     VIndex = MI.getOperand(3).getReg();
2628     OpOffset = 1;
2629   }
2630 
2631   Register VOffset = MI.getOperand(3 + OpOffset).getReg();
2632   Register SOffset = MI.getOperand(4 + OpOffset).getReg();
2633 
2634   unsigned Format = 0;
2635   if (IsTyped) {
2636     Format = MI.getOperand(5 + OpOffset).getImm();
2637     ++OpOffset;
2638   }
2639 
2640   unsigned AuxiliaryData = MI.getOperand(5 + OpOffset).getImm();
2641   unsigned ImmOffset;
2642   unsigned TotalOffset;
2643 
2644   LLT Ty = MRI.getType(Dst);
2645   LLT EltTy = Ty.getScalarType();
2646   const bool IsD16 = IsFormat && (EltTy.getSizeInBits() == 16);
2647   const bool Unpacked = ST.hasUnpackedD16VMem();
2648 
2649   std::tie(VOffset, ImmOffset, TotalOffset) = splitBufferOffsets(B, VOffset);
2650   if (TotalOffset != 0)
2651     MMO = B.getMF().getMachineMemOperand(MMO, TotalOffset, MemSize);
2652 
2653   unsigned Opc;
2654 
2655   if (IsTyped) {
2656     Opc = IsD16 ? AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 :
2657                   AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT;
2658   } else if (IsFormat) {
2659     Opc = IsD16 ? AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16 :
2660                   AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT;
2661   } else {
2662     switch (MemSize) {
2663     case 1:
2664       Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
2665       break;
2666     case 2:
2667       Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
2668       break;
2669     default:
2670       Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD;
2671       break;
2672     }
2673   }
2674 
2675   Register LoadDstReg;
2676 
2677   bool IsExtLoad = (!IsD16 && MemSize < 4) || (IsD16 && !Ty.isVector());
2678   LLT UnpackedTy = Ty.changeElementSize(32);
2679 
2680   if (IsExtLoad)
2681     LoadDstReg = B.getMRI()->createGenericVirtualRegister(S32);
2682   else if (Unpacked && IsD16 && Ty.isVector())
2683     LoadDstReg = B.getMRI()->createGenericVirtualRegister(UnpackedTy);
2684   else
2685     LoadDstReg = Dst;
2686 
2687   if (!VIndex)
2688     VIndex = B.buildConstant(S32, 0).getReg(0);
2689 
2690   auto MIB = B.buildInstr(Opc)
2691     .addDef(LoadDstReg)         // vdata
2692     .addUse(RSrc)               // rsrc
2693     .addUse(VIndex)             // vindex
2694     .addUse(VOffset)            // voffset
2695     .addUse(SOffset)            // soffset
2696     .addImm(ImmOffset);         // offset(imm)
2697 
2698   if (IsTyped)
2699     MIB.addImm(Format);
2700 
2701   MIB.addImm(AuxiliaryData)      // cachepolicy, swizzled buffer(imm)
2702      .addImm(HasVIndex ? -1 : 0) // idxen(imm)
2703      .addMemOperand(MMO);
2704 
2705   if (LoadDstReg != Dst) {
2706     B.setInsertPt(B.getMBB(), ++B.getInsertPt());
2707 
2708     // Widen result for extending loads was widened.
2709     if (IsExtLoad)
2710       B.buildTrunc(Dst, LoadDstReg);
2711     else {
2712       // Repack to original 16-bit vector result
2713       // FIXME: G_TRUNC should work, but legalization currently fails
2714       auto Unmerge = B.buildUnmerge(S32, LoadDstReg);
2715       SmallVector<Register, 4> Repack;
2716       for (unsigned I = 0, N = Unmerge->getNumOperands() - 1; I != N; ++I)
2717         Repack.push_back(B.buildTrunc(EltTy, Unmerge.getReg(I)).getReg(0));
2718       B.buildMerge(Dst, Repack);
2719     }
2720   }
2721 
2722   MI.eraseFromParent();
2723   return true;
2724 }
2725 
2726 bool AMDGPULegalizerInfo::legalizeAtomicIncDec(MachineInstr &MI,
2727                                                MachineIRBuilder &B,
2728                                                bool IsInc) const {
2729   B.setInstr(MI);
2730   unsigned Opc = IsInc ? AMDGPU::G_AMDGPU_ATOMIC_INC :
2731                          AMDGPU::G_AMDGPU_ATOMIC_DEC;
2732   B.buildInstr(Opc)
2733     .addDef(MI.getOperand(0).getReg())
2734     .addUse(MI.getOperand(2).getReg())
2735     .addUse(MI.getOperand(3).getReg())
2736     .cloneMemRefs(MI);
2737   MI.eraseFromParent();
2738   return true;
2739 }
2740 
2741 static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID) {
2742   switch (IntrID) {
2743   case Intrinsic::amdgcn_raw_buffer_atomic_swap:
2744   case Intrinsic::amdgcn_struct_buffer_atomic_swap:
2745     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP;
2746   case Intrinsic::amdgcn_raw_buffer_atomic_add:
2747   case Intrinsic::amdgcn_struct_buffer_atomic_add:
2748     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD;
2749   case Intrinsic::amdgcn_raw_buffer_atomic_sub:
2750   case Intrinsic::amdgcn_struct_buffer_atomic_sub:
2751     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB;
2752   case Intrinsic::amdgcn_raw_buffer_atomic_smin:
2753   case Intrinsic::amdgcn_struct_buffer_atomic_smin:
2754     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN;
2755   case Intrinsic::amdgcn_raw_buffer_atomic_umin:
2756   case Intrinsic::amdgcn_struct_buffer_atomic_umin:
2757     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN;
2758   case Intrinsic::amdgcn_raw_buffer_atomic_smax:
2759   case Intrinsic::amdgcn_struct_buffer_atomic_smax:
2760     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX;
2761   case Intrinsic::amdgcn_raw_buffer_atomic_umax:
2762   case Intrinsic::amdgcn_struct_buffer_atomic_umax:
2763     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX;
2764   case Intrinsic::amdgcn_raw_buffer_atomic_and:
2765   case Intrinsic::amdgcn_struct_buffer_atomic_and:
2766     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND;
2767   case Intrinsic::amdgcn_raw_buffer_atomic_or:
2768   case Intrinsic::amdgcn_struct_buffer_atomic_or:
2769     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR;
2770   case Intrinsic::amdgcn_raw_buffer_atomic_xor:
2771   case Intrinsic::amdgcn_struct_buffer_atomic_xor:
2772     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR;
2773   case Intrinsic::amdgcn_raw_buffer_atomic_inc:
2774   case Intrinsic::amdgcn_struct_buffer_atomic_inc:
2775     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC;
2776   case Intrinsic::amdgcn_raw_buffer_atomic_dec:
2777   case Intrinsic::amdgcn_struct_buffer_atomic_dec:
2778     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC;
2779   case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
2780   case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
2781     return AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP;
2782   default:
2783     llvm_unreachable("unhandled atomic opcode");
2784   }
2785 }
2786 
2787 bool AMDGPULegalizerInfo::legalizeBufferAtomic(MachineInstr &MI,
2788                                                MachineIRBuilder &B,
2789                                                Intrinsic::ID IID) const {
2790   B.setInstr(MI);
2791 
2792   const bool IsCmpSwap = IID == Intrinsic::amdgcn_raw_buffer_atomic_cmpswap ||
2793                          IID == Intrinsic::amdgcn_struct_buffer_atomic_cmpswap;
2794 
2795   Register Dst = MI.getOperand(0).getReg();
2796   Register VData = MI.getOperand(2).getReg();
2797 
2798   Register CmpVal;
2799   int OpOffset = 0;
2800 
2801   if (IsCmpSwap) {
2802     CmpVal = MI.getOperand(3 + OpOffset).getReg();
2803     ++OpOffset;
2804   }
2805 
2806   Register RSrc = MI.getOperand(3 + OpOffset).getReg();
2807   const unsigned NumVIndexOps = IsCmpSwap ? 9 : 8;
2808 
2809   // The struct intrinsic variants add one additional operand over raw.
2810   const bool HasVIndex = MI.getNumOperands() == NumVIndexOps;
2811   Register VIndex;
2812   if (HasVIndex) {
2813     VIndex = MI.getOperand(4 + OpOffset).getReg();
2814     ++OpOffset;
2815   }
2816 
2817   Register VOffset = MI.getOperand(4 + OpOffset).getReg();
2818   Register SOffset = MI.getOperand(5 + OpOffset).getReg();
2819   unsigned AuxiliaryData = MI.getOperand(6 + OpOffset).getImm();
2820 
2821   MachineMemOperand *MMO = *MI.memoperands_begin();
2822 
2823   unsigned ImmOffset;
2824   unsigned TotalOffset;
2825   std::tie(VOffset, ImmOffset, TotalOffset) = splitBufferOffsets(B, VOffset);
2826   if (TotalOffset != 0)
2827     MMO = B.getMF().getMachineMemOperand(MMO, TotalOffset, MMO->getSize());
2828 
2829   if (!VIndex)
2830     VIndex = B.buildConstant(LLT::scalar(32), 0).getReg(0);
2831 
2832   auto MIB = B.buildInstr(getBufferAtomicPseudo(IID))
2833     .addDef(Dst)
2834     .addUse(VData); // vdata
2835 
2836   if (IsCmpSwap)
2837     MIB.addReg(CmpVal);
2838 
2839   MIB.addUse(RSrc)               // rsrc
2840      .addUse(VIndex)             // vindex
2841      .addUse(VOffset)            // voffset
2842      .addUse(SOffset)            // soffset
2843      .addImm(ImmOffset)          // offset(imm)
2844      .addImm(AuxiliaryData)      // cachepolicy, swizzled buffer(imm)
2845      .addImm(HasVIndex ? -1 : 0) // idxen(imm)
2846      .addMemOperand(MMO);
2847 
2848   MI.eraseFromParent();
2849   return true;
2850 }
2851 
2852 bool AMDGPULegalizerInfo::legalizeImageIntrinsic(
2853     MachineInstr &MI, MachineIRBuilder &B,
2854     GISelChangeObserver &Observer,
2855     const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr) const {
2856   // We are only processing the operands of d16 image operations on subtargets
2857   // that use the unpacked register layout.
2858   if (!ST.hasUnpackedD16VMem())
2859     return true;
2860 
2861   const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
2862     AMDGPU::getMIMGBaseOpcodeInfo(ImageDimIntr->BaseOpcode);
2863 
2864   if (BaseOpcode->Atomic) // No d16 atomics
2865     return true;
2866 
2867   MachineRegisterInfo *MRI = B.getMRI();
2868   const LLT S32 = LLT::scalar(32);
2869   const LLT S16 = LLT::scalar(16);
2870 
2871   if (BaseOpcode->Store) {
2872     Register VData = MI.getOperand(1).getReg();
2873     LLT Ty = MRI->getType(VData);
2874     if (!Ty.isVector() || Ty.getElementType() != S16)
2875       return true;
2876 
2877     B.setInstr(MI);
2878 
2879     Observer.changingInstr(MI);
2880     MI.getOperand(1).setReg(handleD16VData(B, *MRI, VData));
2881     Observer.changedInstr(MI);
2882     return true;
2883   }
2884 
2885   // Must be an image load.
2886   Register DstReg = MI.getOperand(0).getReg();
2887   LLT Ty = MRI->getType(DstReg);
2888   if (!Ty.isVector() || Ty.getElementType() != S16)
2889     return true;
2890 
2891   B.setInsertPt(*MI.getParent(), ++MI.getIterator());
2892 
2893   LLT WidenedTy = Ty.changeElementType(S32);
2894   Register WideDstReg = MRI->createGenericVirtualRegister(WidenedTy);
2895 
2896   Observer.changingInstr(MI);
2897   MI.getOperand(0).setReg(WideDstReg);
2898   Observer.changedInstr(MI);
2899 
2900   // FIXME: Just vector trunc should be sufficent, but legalization currently
2901   // broken.
2902   auto Unmerge = B.buildUnmerge(S32, WideDstReg);
2903 
2904   int NumOps = Unmerge->getNumOperands() - 1;
2905   SmallVector<Register, 4> RemergeParts(NumOps);
2906   for (int I = 0; I != NumOps; ++I)
2907     RemergeParts[I] = B.buildTrunc(S16, Unmerge.getReg(I)).getReg(0);
2908 
2909   B.buildBuildVector(DstReg, RemergeParts);
2910   return true;
2911 }
2912 
2913 bool AMDGPULegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
2914                                             MachineIRBuilder &B,
2915                                             GISelChangeObserver &Observer) const {
2916   MachineRegisterInfo &MRI = *B.getMRI();
2917 
2918   // Replace the use G_BRCOND with the exec manipulate and branch pseudos.
2919   auto IntrID = MI.getIntrinsicID();
2920   switch (IntrID) {
2921   case Intrinsic::amdgcn_if:
2922   case Intrinsic::amdgcn_else: {
2923     MachineInstr *Br = nullptr;
2924     if (MachineInstr *BrCond = verifyCFIntrinsic(MI, MRI, Br)) {
2925       const SIRegisterInfo *TRI
2926         = static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
2927 
2928       B.setInstr(*BrCond);
2929       Register Def = MI.getOperand(1).getReg();
2930       Register Use = MI.getOperand(3).getReg();
2931 
2932       MachineBasicBlock *BrTarget = BrCond->getOperand(1).getMBB();
2933       if (Br)
2934         BrTarget = Br->getOperand(0).getMBB();
2935 
2936       if (IntrID == Intrinsic::amdgcn_if) {
2937         B.buildInstr(AMDGPU::SI_IF)
2938           .addDef(Def)
2939           .addUse(Use)
2940           .addMBB(BrTarget);
2941       } else {
2942         B.buildInstr(AMDGPU::SI_ELSE)
2943           .addDef(Def)
2944           .addUse(Use)
2945           .addMBB(BrTarget)
2946           .addImm(0);
2947       }
2948 
2949       if (Br)
2950         Br->getOperand(0).setMBB(BrCond->getOperand(1).getMBB());
2951 
2952       MRI.setRegClass(Def, TRI->getWaveMaskRegClass());
2953       MRI.setRegClass(Use, TRI->getWaveMaskRegClass());
2954       MI.eraseFromParent();
2955       BrCond->eraseFromParent();
2956       return true;
2957     }
2958 
2959     return false;
2960   }
2961   case Intrinsic::amdgcn_loop: {
2962     MachineInstr *Br = nullptr;
2963     if (MachineInstr *BrCond = verifyCFIntrinsic(MI, MRI, Br)) {
2964       const SIRegisterInfo *TRI
2965         = static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
2966 
2967       B.setInstr(*BrCond);
2968 
2969       // FIXME: Need to adjust branch targets based on unconditional branch.
2970       Register Reg = MI.getOperand(2).getReg();
2971       B.buildInstr(AMDGPU::SI_LOOP)
2972         .addUse(Reg)
2973         .addMBB(BrCond->getOperand(1).getMBB());
2974       MI.eraseFromParent();
2975       BrCond->eraseFromParent();
2976       MRI.setRegClass(Reg, TRI->getWaveMaskRegClass());
2977       return true;
2978     }
2979 
2980     return false;
2981   }
2982   case Intrinsic::amdgcn_kernarg_segment_ptr:
2983     return legalizePreloadedArgIntrin(
2984       MI, MRI, B, AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
2985   case Intrinsic::amdgcn_implicitarg_ptr:
2986     return legalizeImplicitArgPtr(MI, MRI, B);
2987   case Intrinsic::amdgcn_workitem_id_x:
2988     return legalizePreloadedArgIntrin(MI, MRI, B,
2989                                       AMDGPUFunctionArgInfo::WORKITEM_ID_X);
2990   case Intrinsic::amdgcn_workitem_id_y:
2991     return legalizePreloadedArgIntrin(MI, MRI, B,
2992                                       AMDGPUFunctionArgInfo::WORKITEM_ID_Y);
2993   case Intrinsic::amdgcn_workitem_id_z:
2994     return legalizePreloadedArgIntrin(MI, MRI, B,
2995                                       AMDGPUFunctionArgInfo::WORKITEM_ID_Z);
2996   case Intrinsic::amdgcn_workgroup_id_x:
2997     return legalizePreloadedArgIntrin(MI, MRI, B,
2998                                       AMDGPUFunctionArgInfo::WORKGROUP_ID_X);
2999   case Intrinsic::amdgcn_workgroup_id_y:
3000     return legalizePreloadedArgIntrin(MI, MRI, B,
3001                                       AMDGPUFunctionArgInfo::WORKGROUP_ID_Y);
3002   case Intrinsic::amdgcn_workgroup_id_z:
3003     return legalizePreloadedArgIntrin(MI, MRI, B,
3004                                       AMDGPUFunctionArgInfo::WORKGROUP_ID_Z);
3005   case Intrinsic::amdgcn_dispatch_ptr:
3006     return legalizePreloadedArgIntrin(MI, MRI, B,
3007                                       AMDGPUFunctionArgInfo::DISPATCH_PTR);
3008   case Intrinsic::amdgcn_queue_ptr:
3009     return legalizePreloadedArgIntrin(MI, MRI, B,
3010                                       AMDGPUFunctionArgInfo::QUEUE_PTR);
3011   case Intrinsic::amdgcn_implicit_buffer_ptr:
3012     return legalizePreloadedArgIntrin(
3013       MI, MRI, B, AMDGPUFunctionArgInfo::IMPLICIT_BUFFER_PTR);
3014   case Intrinsic::amdgcn_dispatch_id:
3015     return legalizePreloadedArgIntrin(MI, MRI, B,
3016                                       AMDGPUFunctionArgInfo::DISPATCH_ID);
3017   case Intrinsic::amdgcn_fdiv_fast:
3018     return legalizeFDIVFastIntrin(MI, MRI, B);
3019   case Intrinsic::amdgcn_is_shared:
3020     return legalizeIsAddrSpace(MI, MRI, B, AMDGPUAS::LOCAL_ADDRESS);
3021   case Intrinsic::amdgcn_is_private:
3022     return legalizeIsAddrSpace(MI, MRI, B, AMDGPUAS::PRIVATE_ADDRESS);
3023   case Intrinsic::amdgcn_wavefrontsize: {
3024     B.setInstr(MI);
3025     B.buildConstant(MI.getOperand(0), ST.getWavefrontSize());
3026     MI.eraseFromParent();
3027     return true;
3028   }
3029   case Intrinsic::amdgcn_raw_buffer_store:
3030   case Intrinsic::amdgcn_struct_buffer_store:
3031     return legalizeBufferStore(MI, MRI, B, false, false);
3032   case Intrinsic::amdgcn_raw_buffer_store_format:
3033   case Intrinsic::amdgcn_struct_buffer_store_format:
3034     return legalizeBufferStore(MI, MRI, B, false, true);
3035   case Intrinsic::amdgcn_raw_tbuffer_store:
3036   case Intrinsic::amdgcn_struct_tbuffer_store:
3037     return legalizeBufferStore(MI, MRI, B, true, true);
3038   case Intrinsic::amdgcn_raw_buffer_load:
3039   case Intrinsic::amdgcn_struct_buffer_load:
3040     return legalizeBufferLoad(MI, MRI, B, false, false);
3041   case Intrinsic::amdgcn_raw_buffer_load_format:
3042   case Intrinsic::amdgcn_struct_buffer_load_format:
3043     return legalizeBufferLoad(MI, MRI, B, true, false);
3044   case Intrinsic::amdgcn_raw_tbuffer_load:
3045   case Intrinsic::amdgcn_struct_tbuffer_load:
3046     return legalizeBufferLoad(MI, MRI, B, true, true);
3047   case Intrinsic::amdgcn_raw_buffer_atomic_swap:
3048   case Intrinsic::amdgcn_struct_buffer_atomic_swap:
3049   case Intrinsic::amdgcn_raw_buffer_atomic_add:
3050   case Intrinsic::amdgcn_struct_buffer_atomic_add:
3051   case Intrinsic::amdgcn_raw_buffer_atomic_sub:
3052   case Intrinsic::amdgcn_struct_buffer_atomic_sub:
3053   case Intrinsic::amdgcn_raw_buffer_atomic_smin:
3054   case Intrinsic::amdgcn_struct_buffer_atomic_smin:
3055   case Intrinsic::amdgcn_raw_buffer_atomic_umin:
3056   case Intrinsic::amdgcn_struct_buffer_atomic_umin:
3057   case Intrinsic::amdgcn_raw_buffer_atomic_smax:
3058   case Intrinsic::amdgcn_struct_buffer_atomic_smax:
3059   case Intrinsic::amdgcn_raw_buffer_atomic_umax:
3060   case Intrinsic::amdgcn_struct_buffer_atomic_umax:
3061   case Intrinsic::amdgcn_raw_buffer_atomic_and:
3062   case Intrinsic::amdgcn_struct_buffer_atomic_and:
3063   case Intrinsic::amdgcn_raw_buffer_atomic_or:
3064   case Intrinsic::amdgcn_struct_buffer_atomic_or:
3065   case Intrinsic::amdgcn_raw_buffer_atomic_xor:
3066   case Intrinsic::amdgcn_struct_buffer_atomic_xor:
3067   case Intrinsic::amdgcn_raw_buffer_atomic_inc:
3068   case Intrinsic::amdgcn_struct_buffer_atomic_inc:
3069   case Intrinsic::amdgcn_raw_buffer_atomic_dec:
3070   case Intrinsic::amdgcn_struct_buffer_atomic_dec:
3071   case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
3072   case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
3073     return legalizeBufferAtomic(MI, B, IntrID);
3074   case Intrinsic::amdgcn_atomic_inc:
3075     return legalizeAtomicIncDec(MI, B, true);
3076   case Intrinsic::amdgcn_atomic_dec:
3077     return legalizeAtomicIncDec(MI, B, false);
3078   default: {
3079     if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
3080             AMDGPU::getImageDimIntrinsicInfo(IntrID))
3081       return legalizeImageIntrinsic(MI, B, Observer, ImageDimIntr);
3082     return true;
3083   }
3084   }
3085 
3086   return true;
3087 }
3088