1//===-- AMDGPUInstructions.td - Common instruction defs ---*- tablegen -*-===//
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//
9// This file contains instruction defs that are common to all hw codegen
10// targets.
11//
12//===----------------------------------------------------------------------===//
13
14class AddressSpacesImpl {
15  int Flat = 0;
16  int Global = 1;
17  int Region = 2;
18  int Local = 3;
19  int Constant = 4;
20  int Private = 5;
21}
22
23def AddrSpaces : AddressSpacesImpl;
24
25
26class AMDGPUInst <dag outs, dag ins, string asm = "",
27  list<dag> pattern = []> : Instruction {
28  field bit isRegisterLoad = 0;
29  field bit isRegisterStore = 0;
30
31  let Namespace = "AMDGPU";
32  let OutOperandList = outs;
33  let InOperandList = ins;
34  let AsmString = asm;
35  let Pattern = pattern;
36  let Itinerary = NullALU;
37
38  // SoftFail is a field the disassembler can use to provide a way for
39  // instructions to not match without killing the whole decode process. It is
40  // mainly used for ARM, but Tablegen expects this field to exist or it fails
41  // to build the decode table.
42  field bits<64> SoftFail = 0;
43
44  let DecoderNamespace = Namespace;
45
46  let TSFlags{63} = isRegisterLoad;
47  let TSFlags{62} = isRegisterStore;
48}
49
50class AMDGPUShaderInst <dag outs, dag ins, string asm = "",
51  list<dag> pattern = []> : AMDGPUInst<outs, ins, asm, pattern> {
52
53  field bits<32> Inst = 0xffffffff;
54}
55
56//===---------------------------------------------------------------------===//
57// Return instruction
58//===---------------------------------------------------------------------===//
59
60class ILFormat<dag outs, dag ins, string asmstr, list<dag> pattern>
61: Instruction {
62
63     let Namespace = "AMDGPU";
64     dag OutOperandList = outs;
65     dag InOperandList = ins;
66     let Pattern = pattern;
67     let AsmString = !strconcat(asmstr, "\n");
68     let isPseudo = 1;
69     let Itinerary = NullALU;
70     bit hasIEEEFlag = 0;
71     bit hasZeroOpFlag = 0;
72     let mayLoad = 0;
73     let mayStore = 0;
74     let hasSideEffects = 0;
75     let isCodeGenOnly = 1;
76}
77
78def TruePredicate : Predicate<"">;
79
80// Add a predicate to the list if does not already exist to deduplicate it.
81class PredConcat<list<Predicate> lst, Predicate pred> {
82  list<Predicate> ret =
83    !foldl([pred], lst, acc, cur,
84           !listconcat(acc, !if(!eq(!cast<string>(cur),!cast<string>(pred)),
85                                [], [cur])));
86}
87
88class PredicateControl {
89  Predicate SubtargetPredicate = TruePredicate;
90  Predicate AssemblerPredicate = TruePredicate;
91  Predicate WaveSizePredicate = TruePredicate;
92  list<Predicate> OtherPredicates = [];
93  list<Predicate> Predicates = PredConcat<
94                                 PredConcat<PredConcat<OtherPredicates,
95                                                       SubtargetPredicate>.ret,
96                                            AssemblerPredicate>.ret,
97                                 WaveSizePredicate>.ret;
98}
99
100class AMDGPUPat<dag pattern, dag result> : Pat<pattern, result>,
101      PredicateControl;
102
103def FP16Denormals : Predicate<"Subtarget->hasFP16Denormals()">;
104def FP32Denormals : Predicate<"Subtarget->hasFP32Denormals()">;
105def FP64Denormals : Predicate<"Subtarget->hasFP64Denormals()">;
106def NoFP16Denormals : Predicate<"!Subtarget->hasFP16Denormals()">;
107def NoFP32Denormals : Predicate<"!Subtarget->hasFP32Denormals()">;
108def NoFP64Denormals : Predicate<"!Subtarget->hasFP64Denormals()">;
109def UnsafeFPMath : Predicate<"TM.Options.UnsafeFPMath">;
110def FMA : Predicate<"Subtarget->hasFMA()">;
111
112def InstFlag : OperandWithDefaultOps <i32, (ops (i32 0))>;
113
114def u16ImmTarget : AsmOperandClass {
115  let Name = "U16Imm";
116  let RenderMethod = "addImmOperands";
117}
118
119def s16ImmTarget : AsmOperandClass {
120  let Name = "S16Imm";
121  let RenderMethod = "addImmOperands";
122}
123
124let OperandType = "OPERAND_IMMEDIATE" in {
125
126def u32imm : Operand<i32> {
127  let PrintMethod = "printU32ImmOperand";
128}
129
130def u16imm : Operand<i16> {
131  let PrintMethod = "printU16ImmOperand";
132  let ParserMatchClass = u16ImmTarget;
133}
134
135def s16imm : Operand<i16> {
136  let PrintMethod = "printU16ImmOperand";
137  let ParserMatchClass = s16ImmTarget;
138}
139
140def u8imm : Operand<i8> {
141  let PrintMethod = "printU8ImmOperand";
142}
143
144} // End OperandType = "OPERAND_IMMEDIATE"
145
146//===--------------------------------------------------------------------===//
147// Custom Operands
148//===--------------------------------------------------------------------===//
149def brtarget   : Operand<OtherVT>;
150
151//===----------------------------------------------------------------------===//
152// Misc. PatFrags
153//===----------------------------------------------------------------------===//
154
155class HasOneUseUnaryOp<SDPatternOperator op> : PatFrag<
156  (ops node:$src0),
157  (op $src0),
158  [{ return N->hasOneUse(); }]
159>;
160
161class HasOneUseBinOp<SDPatternOperator op> : PatFrag<
162  (ops node:$src0, node:$src1),
163  (op $src0, $src1),
164  [{ return N->hasOneUse(); }]
165>;
166
167class HasOneUseTernaryOp<SDPatternOperator op> : PatFrag<
168  (ops node:$src0, node:$src1, node:$src2),
169  (op $src0, $src1, $src2),
170  [{ return N->hasOneUse(); }]
171>;
172
173let Properties = [SDNPCommutative, SDNPAssociative] in {
174def smax_oneuse : HasOneUseBinOp<smax>;
175def smin_oneuse : HasOneUseBinOp<smin>;
176def umax_oneuse : HasOneUseBinOp<umax>;
177def umin_oneuse : HasOneUseBinOp<umin>;
178
179def fminnum_oneuse : HasOneUseBinOp<fminnum>;
180def fmaxnum_oneuse : HasOneUseBinOp<fmaxnum>;
181
182def fminnum_ieee_oneuse : HasOneUseBinOp<fminnum_ieee>;
183def fmaxnum_ieee_oneuse : HasOneUseBinOp<fmaxnum_ieee>;
184
185
186def and_oneuse : HasOneUseBinOp<and>;
187def or_oneuse : HasOneUseBinOp<or>;
188def xor_oneuse : HasOneUseBinOp<xor>;
189} // Properties = [SDNPCommutative, SDNPAssociative]
190
191def not_oneuse : HasOneUseUnaryOp<not>;
192
193def add_oneuse : HasOneUseBinOp<add>;
194def sub_oneuse : HasOneUseBinOp<sub>;
195
196def srl_oneuse : HasOneUseBinOp<srl>;
197def shl_oneuse : HasOneUseBinOp<shl>;
198
199def select_oneuse : HasOneUseTernaryOp<select>;
200
201def AMDGPUmul_u24_oneuse : HasOneUseBinOp<AMDGPUmul_u24>;
202def AMDGPUmul_i24_oneuse : HasOneUseBinOp<AMDGPUmul_i24>;
203
204def srl_16 : PatFrag<
205  (ops node:$src0), (srl_oneuse node:$src0, (i32 16))
206>;
207
208
209def hi_i16_elt : PatFrag<
210  (ops node:$src0), (i16 (trunc (i32 (srl_16 node:$src0))))
211>;
212
213
214def hi_f16_elt : PatLeaf<
215  (vt), [{
216  if (N->getOpcode() != ISD::BITCAST)
217    return false;
218  SDValue Tmp = N->getOperand(0);
219
220  if (Tmp.getOpcode() != ISD::SRL)
221    return false;
222    if (const auto *RHS = dyn_cast<ConstantSDNode>(Tmp.getOperand(1))
223      return RHS->getZExtValue() == 16;
224    return false;
225}]>;
226
227//===----------------------------------------------------------------------===//
228// PatLeafs for floating-point comparisons
229//===----------------------------------------------------------------------===//
230
231def COND_OEQ : PatFrags<(ops), [(OtherVT SETOEQ), (OtherVT SETEQ)]>;
232def COND_ONE : PatFrags<(ops), [(OtherVT SETONE), (OtherVT SETNE)]>;
233def COND_OGT : PatFrags<(ops), [(OtherVT SETOGT), (OtherVT SETGT)]>;
234def COND_OGE : PatFrags<(ops), [(OtherVT SETOGE), (OtherVT SETGE)]>;
235def COND_OLT : PatFrags<(ops), [(OtherVT SETOLT), (OtherVT SETLT)]>;
236def COND_OLE : PatFrags<(ops), [(OtherVT SETOLE), (OtherVT SETLE)]>;
237def COND_O   : PatFrags<(ops), [(OtherVT SETO)]>;
238def COND_UO  : PatFrags<(ops), [(OtherVT SETUO)]>;
239
240//===----------------------------------------------------------------------===//
241// PatLeafs for unsigned / unordered comparisons
242//===----------------------------------------------------------------------===//
243
244def COND_UEQ : PatFrag<(ops), (OtherVT SETUEQ)>;
245def COND_UNE : PatFrag<(ops), (OtherVT SETUNE)>;
246def COND_UGT : PatFrag<(ops), (OtherVT SETUGT)>;
247def COND_UGE : PatFrag<(ops), (OtherVT SETUGE)>;
248def COND_ULT : PatFrag<(ops), (OtherVT SETULT)>;
249def COND_ULE : PatFrag<(ops), (OtherVT SETULE)>;
250
251// XXX - For some reason R600 version is preferring to use unordered
252// for setne?
253def COND_UNE_NE  : PatFrags<(ops), [(OtherVT SETUNE), (OtherVT SETNE)]>;
254
255//===----------------------------------------------------------------------===//
256// PatLeafs for signed comparisons
257//===----------------------------------------------------------------------===//
258
259def COND_SGT : PatFrag<(ops), (OtherVT SETGT)>;
260def COND_SGE : PatFrag<(ops), (OtherVT SETGE)>;
261def COND_SLT : PatFrag<(ops), (OtherVT SETLT)>;
262def COND_SLE : PatFrag<(ops), (OtherVT SETLE)>;
263
264//===----------------------------------------------------------------------===//
265// PatLeafs for integer equality
266//===----------------------------------------------------------------------===//
267
268def COND_EQ : PatFrags<(ops), [(OtherVT SETEQ), (OtherVT SETUEQ)]>;
269def COND_NE : PatFrags<(ops), [(OtherVT SETNE), (OtherVT SETUNE)]>;
270
271// FIXME: Should not need code predicate
272//def COND_NULL : PatLeaf<(OtherVT null_frag)>;
273def COND_NULL : PatLeaf <
274  (cond),
275  [{(void)N; return false;}]
276>;
277
278//===----------------------------------------------------------------------===//
279// PatLeafs for Texture Constants
280//===----------------------------------------------------------------------===//
281
282def TEX_ARRAY : PatLeaf<
283  (imm),
284  [{uint32_t TType = (uint32_t)N->getZExtValue();
285    return TType == 9 || TType == 10 || TType == 16;
286  }]
287>;
288
289def TEX_RECT : PatLeaf<
290  (imm),
291  [{uint32_t TType = (uint32_t)N->getZExtValue();
292    return TType == 5;
293  }]
294>;
295
296def TEX_SHADOW : PatLeaf<
297  (imm),
298  [{uint32_t TType = (uint32_t)N->getZExtValue();
299    return (TType >= 6 && TType <= 8) || TType == 13;
300  }]
301>;
302
303def TEX_SHADOW_ARRAY : PatLeaf<
304  (imm),
305  [{uint32_t TType = (uint32_t)N->getZExtValue();
306    return TType == 11 || TType == 12 || TType == 17;
307  }]
308>;
309
310//===----------------------------------------------------------------------===//
311// Load/Store Pattern Fragments
312//===----------------------------------------------------------------------===//
313
314def atomic_cmp_swap_glue : SDNode <"ISD::ATOMIC_CMP_SWAP", SDTAtomic3,
315  [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
316>;
317
318class AddressSpaceList<list<int> AS> {
319  list<int> AddrSpaces = AS;
320}
321
322class Aligned<int Bytes> {
323  int MinAlignment = Bytes;
324}
325
326class LoadFrag <SDPatternOperator op> : PatFrag<(ops node:$ptr), (op node:$ptr)>;
327
328class StoreFrag<SDPatternOperator op> : PatFrag <
329  (ops node:$value, node:$ptr), (op node:$value, node:$ptr)
330>;
331
332class StoreHi16<SDPatternOperator op> : PatFrag <
333  (ops node:$value, node:$ptr), (op (srl node:$value, (i32 16)), node:$ptr)
334>;
335
336def LoadAddress_constant : AddressSpaceList<[  AddrSpaces.Constant ]>;
337def LoadAddress_global : AddressSpaceList<[  AddrSpaces.Global, AddrSpaces.Constant ]>;
338def StoreAddress_global : AddressSpaceList<[ AddrSpaces.Global ]>;
339
340def LoadAddress_flat : AddressSpaceList<[  AddrSpaces.Flat,
341                                           AddrSpaces.Global,
342                                           AddrSpaces.Constant ]>;
343def StoreAddress_flat : AddressSpaceList<[ AddrSpaces.Flat, AddrSpaces.Global ]>;
344
345def LoadAddress_private : AddressSpaceList<[ AddrSpaces.Private ]>;
346def StoreAddress_private : AddressSpaceList<[ AddrSpaces.Private ]>;
347
348def LoadAddress_local : AddressSpaceList<[ AddrSpaces.Local ]>;
349def StoreAddress_local : AddressSpaceList<[ AddrSpaces.Local ]>;
350
351def LoadAddress_region : AddressSpaceList<[ AddrSpaces.Region ]>;
352def StoreAddress_region : AddressSpaceList<[ AddrSpaces.Region ]>;
353
354
355
356class GlobalLoadAddress : CodePatPred<[{
357  auto AS = cast<MemSDNode>(N)->getAddressSpace();
358  return AS == AMDGPUAS::GLOBAL_ADDRESS || AS == AMDGPUAS::CONSTANT_ADDRESS;
359}]>;
360
361class FlatLoadAddress : CodePatPred<[{
362  const auto AS = cast<MemSDNode>(N)->getAddressSpace();
363  return AS == AMDGPUAS::FLAT_ADDRESS ||
364         AS == AMDGPUAS::GLOBAL_ADDRESS ||
365         AS == AMDGPUAS::CONSTANT_ADDRESS;
366}]>;
367
368class GlobalAddress : CodePatPred<[{
369  return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS;
370}]>;
371
372class PrivateAddress : CodePatPred<[{
373  return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS;
374}]>;
375
376class LocalAddress : CodePatPred<[{
377  return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS;
378}]>;
379
380class RegionAddress : CodePatPred<[{
381  return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUAS::REGION_ADDRESS;
382}]>;
383
384class FlatStoreAddress : CodePatPred<[{
385  const auto AS = cast<MemSDNode>(N)->getAddressSpace();
386  return AS == AMDGPUAS::FLAT_ADDRESS ||
387         AS == AMDGPUAS::GLOBAL_ADDRESS;
388}]>;
389
390// TODO: Remove these when stores to new PatFrag format.
391class PrivateStore <SDPatternOperator op> : StoreFrag <op>, PrivateAddress;
392class LocalStore <SDPatternOperator op> : StoreFrag <op>, LocalAddress;
393class RegionStore <SDPatternOperator op> : StoreFrag <op>, RegionAddress;
394class GlobalStore <SDPatternOperator op> : StoreFrag<op>, GlobalAddress;
395class FlatStore <SDPatternOperator op> : StoreFrag <op>, FlatStoreAddress;
396
397
398foreach as = [ "global", "flat", "constant", "local", "private", "region" ] in {
399let AddressSpaces = !cast<AddressSpaceList>("LoadAddress_"#as).AddrSpaces in {
400
401def load_#as : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> {
402  let IsLoad = 1;
403  let IsNonExtLoad = 1;
404}
405
406def extloadi8_#as  : PatFrag<(ops node:$ptr), (extload node:$ptr)> {
407  let IsLoad = 1;
408  let MemoryVT = i8;
409}
410
411def extloadi16_#as : PatFrag<(ops node:$ptr), (extload node:$ptr)> {
412  let IsLoad = 1;
413  let MemoryVT = i16;
414}
415
416def sextloadi8_#as  : PatFrag<(ops node:$ptr), (sextload node:$ptr)> {
417  let IsLoad = 1;
418  let MemoryVT = i8;
419}
420
421def sextloadi16_#as : PatFrag<(ops node:$ptr), (sextload node:$ptr)> {
422  let IsLoad = 1;
423  let MemoryVT = i16;
424}
425
426def zextloadi8_#as  : PatFrag<(ops node:$ptr), (zextload node:$ptr)> {
427  let IsLoad = 1;
428  let MemoryVT = i8;
429}
430
431def zextloadi16_#as : PatFrag<(ops node:$ptr), (zextload node:$ptr)> {
432  let IsLoad = 1;
433  let MemoryVT = i16;
434}
435
436def atomic_load_32_#as : PatFrag<(ops node:$ptr), (atomic_load_32 node:$ptr)> {
437  let IsAtomic = 1;
438  let MemoryVT = i32;
439}
440
441def atomic_load_64_#as : PatFrag<(ops node:$ptr), (atomic_load_64 node:$ptr)> {
442  let IsAtomic = 1;
443  let MemoryVT = i64;
444}
445
446def store_#as : PatFrag<(ops node:$val, node:$ptr),
447                    (unindexedstore node:$val, node:$ptr)> {
448  let IsStore = 1;
449  let IsTruncStore = 0;
450}
451
452// truncstore fragments.
453def truncstore_#as : PatFrag<(ops node:$val, node:$ptr),
454                             (unindexedstore node:$val, node:$ptr)> {
455  let IsStore = 1;
456  let IsTruncStore = 1;
457}
458
459// TODO: We don't really need the truncstore here. We can use
460// unindexedstore with MemoryVT directly, which will save an
461// unnecessary check that the memory size is less than the value type
462// in the generated matcher table.
463def truncstorei8_#as : PatFrag<(ops node:$val, node:$ptr),
464                               (truncstore node:$val, node:$ptr)> {
465  let IsStore = 1;
466  let MemoryVT = i8;
467}
468
469def truncstorei16_#as : PatFrag<(ops node:$val, node:$ptr),
470                                (truncstore node:$val, node:$ptr)> {
471  let IsStore = 1;
472  let MemoryVT = i16;
473}
474
475defm atomic_store_#as : binary_atomic_op<atomic_store>;
476
477} // End let AddressSpaces = ...
478} // End foreach AddrSpace
479
480
481multiclass ret_noret_binary_atomic_op<SDNode atomic_op, bit IsInt = 1> {
482  foreach as = [ "global", "flat", "constant", "local", "private", "region" ] in {
483    let AddressSpaces = !cast<AddressSpaceList>("LoadAddress_"#as).AddrSpaces in {
484      defm "_"#as : binary_atomic_op<atomic_op, IsInt>;
485
486      let PredicateCode = [{return (SDValue(N, 0).use_empty());}] in {
487        defm "_"#as#"_noret" : binary_atomic_op<atomic_op, IsInt>;
488      }
489
490      let PredicateCode = [{return !(SDValue(N, 0).use_empty());}] in {
491        defm "_"#as#"_ret" : binary_atomic_op<atomic_op, IsInt>;
492      }
493    }
494  }
495}
496
497defm atomic_swap : ret_noret_binary_atomic_op<atomic_swap>;
498defm atomic_load_add : ret_noret_binary_atomic_op<atomic_load_add>;
499defm atomic_load_and : ret_noret_binary_atomic_op<atomic_load_and>;
500defm atomic_load_max : ret_noret_binary_atomic_op<atomic_load_max>;
501defm atomic_load_min : ret_noret_binary_atomic_op<atomic_load_min>;
502defm atomic_load_or : ret_noret_binary_atomic_op<atomic_load_or>;
503defm atomic_load_sub : ret_noret_binary_atomic_op<atomic_load_sub>;
504defm atomic_load_umax : ret_noret_binary_atomic_op<atomic_load_umax>;
505defm atomic_load_umin : ret_noret_binary_atomic_op<atomic_load_umin>;
506defm atomic_load_xor : ret_noret_binary_atomic_op<atomic_load_xor>;
507defm atomic_load_fadd : ret_noret_binary_atomic_op<atomic_load_fadd, 0>;
508defm AMDGPUatomic_cmp_swap : ret_noret_binary_atomic_op<AMDGPUatomic_cmp_swap>;
509
510
511def store_hi16_private : StoreHi16 <truncstorei16>, PrivateAddress;
512def truncstorei8_hi16_private : StoreHi16<truncstorei8>, PrivateAddress;
513
514def store_atomic_global : GlobalStore<atomic_store>;
515def truncstorei8_hi16_global : StoreHi16 <truncstorei8>, GlobalAddress;
516def truncstorei16_hi16_global : StoreHi16 <truncstorei16>, GlobalAddress;
517
518def store_local_hi16 : StoreHi16 <truncstorei16>, LocalAddress;
519def truncstorei8_local_hi16 : StoreHi16<truncstorei8>, LocalAddress;
520def atomic_store_local : LocalStore <atomic_store>;
521
522
523def load_align8_local : PatFrag <(ops node:$ptr), (load_local node:$ptr)> {
524  let IsLoad = 1;
525  let IsNonExtLoad = 1;
526  let MinAlignment = 8;
527}
528
529def load_align16_local : PatFrag <(ops node:$ptr), (load_local node:$ptr)> {
530  let IsLoad = 1;
531  let IsNonExtLoad = 1;
532  let MinAlignment = 16;
533}
534
535def store_align8_local: PatFrag<(ops node:$val, node:$ptr),
536                                (store_local node:$val, node:$ptr)>, Aligned<8> {
537  let IsStore = 1;
538  let IsTruncStore = 0;
539}
540
541def store_align16_local: PatFrag<(ops node:$val, node:$ptr),
542                                (store_local node:$val, node:$ptr)>, Aligned<16> {
543  let IsStore = 1;
544  let IsTruncStore = 0;
545}
546
547
548def atomic_store_flat  : FlatStore <atomic_store>;
549def truncstorei8_hi16_flat  : StoreHi16<truncstorei8>, FlatStoreAddress;
550def truncstorei16_hi16_flat : StoreHi16<truncstorei16>, FlatStoreAddress;
551
552
553class local_binary_atomic_op<SDNode atomic_op> :
554  PatFrag<(ops node:$ptr, node:$value),
555    (atomic_op node:$ptr, node:$value), [{
556  return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS;
557}]>;
558
559class region_binary_atomic_op<SDNode atomic_op> :
560  PatFrag<(ops node:$ptr, node:$value),
561    (atomic_op node:$ptr, node:$value), [{
562  return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUAS::REGION_ADDRESS;
563}]>;
564
565
566def mskor_global : PatFrag<(ops node:$val, node:$ptr),
567                            (AMDGPUstore_mskor node:$val, node:$ptr), [{
568  return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS;
569}]>;
570
571let AddressSpaces = StoreAddress_local.AddrSpaces in {
572defm atomic_cmp_swap_local : ternary_atomic_op<atomic_cmp_swap>;
573defm atomic_cmp_swap_local_m0 : ternary_atomic_op<atomic_cmp_swap_glue>;
574}
575
576let AddressSpaces = StoreAddress_region.AddrSpaces in {
577defm atomic_cmp_swap_region : ternary_atomic_op<atomic_cmp_swap>;
578defm atomic_cmp_swap_region_m0 : ternary_atomic_op<atomic_cmp_swap_glue>;
579}
580
581// Legacy.
582def atomic_cmp_swap_global_noret : PatFrag<
583  (ops node:$ptr, node:$cmp, node:$value),
584  (atomic_cmp_swap node:$ptr, node:$cmp, node:$value),
585  [{return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS && (SDValue(N, 0).use_empty());}]>;
586
587def atomic_cmp_swap_global_ret : PatFrag<
588  (ops node:$ptr, node:$cmp, node:$value),
589  (atomic_cmp_swap node:$ptr, node:$cmp, node:$value),
590  [{return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS && (!SDValue(N, 0).use_empty());}]>;
591
592//===----------------------------------------------------------------------===//
593// Misc Pattern Fragments
594//===----------------------------------------------------------------------===//
595
596class Constants {
597int TWO_PI = 0x40c90fdb;
598int PI = 0x40490fdb;
599int TWO_PI_INV = 0x3e22f983;
600int FP_UINT_MAX_PLUS_1 = 0x4f800000;    // 1 << 32 in floating point encoding
601int FP16_ONE = 0x3C00;
602int FP16_NEG_ONE = 0xBC00;
603int FP32_ONE = 0x3f800000;
604int FP32_NEG_ONE = 0xbf800000;
605int FP64_ONE = 0x3ff0000000000000;
606int FP64_NEG_ONE = 0xbff0000000000000;
607}
608def CONST : Constants;
609
610def FP_ZERO : PatLeaf <
611  (fpimm),
612  [{return N->getValueAPF().isZero();}]
613>;
614
615def FP_ONE : PatLeaf <
616  (fpimm),
617  [{return N->isExactlyValue(1.0);}]
618>;
619
620def FP_HALF : PatLeaf <
621  (fpimm),
622  [{return N->isExactlyValue(0.5);}]
623>;
624
625/* Generic helper patterns for intrinsics */
626/* -------------------------------------- */
627
628class POW_Common <AMDGPUInst log_ieee, AMDGPUInst exp_ieee, AMDGPUInst mul>
629  : AMDGPUPat <
630  (fpow f32:$src0, f32:$src1),
631  (exp_ieee (mul f32:$src1, (log_ieee f32:$src0)))
632>;
633
634/* Other helper patterns */
635/* --------------------- */
636
637/* Extract element pattern */
638class Extract_Element <ValueType sub_type, ValueType vec_type, int sub_idx,
639                       SubRegIndex sub_reg>
640  : AMDGPUPat<
641  (sub_type (extractelt vec_type:$src, sub_idx)),
642  (EXTRACT_SUBREG $src, sub_reg)
643>;
644
645/* Insert element pattern */
646class Insert_Element <ValueType elem_type, ValueType vec_type,
647                      int sub_idx, SubRegIndex sub_reg>
648  : AMDGPUPat <
649  (insertelt vec_type:$vec, elem_type:$elem, sub_idx),
650  (INSERT_SUBREG $vec, $elem, sub_reg)
651>;
652
653// XXX: Convert to new syntax and use COPY_TO_REG, once the DFAPacketizer
654// can handle COPY instructions.
655// bitconvert pattern
656class BitConvert <ValueType dt, ValueType st, RegisterClass rc> : AMDGPUPat <
657  (dt (bitconvert (st rc:$src0))),
658  (dt rc:$src0)
659>;
660
661// XXX: Convert to new syntax and use COPY_TO_REG, once the DFAPacketizer
662// can handle COPY instructions.
663class DwordAddrPat<ValueType vt, RegisterClass rc> : AMDGPUPat <
664  (vt (AMDGPUdwordaddr (vt rc:$addr))),
665  (vt rc:$addr)
666>;
667
668// BFI_INT patterns
669
670multiclass BFIPatterns <Instruction BFI_INT,
671                        Instruction LoadImm32,
672                        RegisterClass RC64> {
673  // Definition from ISA doc:
674  // (y & x) | (z & ~x)
675  def : AMDGPUPat <
676    (or (and i32:$y, i32:$x), (and i32:$z, (not i32:$x))),
677    (BFI_INT $x, $y, $z)
678  >;
679
680  // 64-bit version
681  def : AMDGPUPat <
682    (or (and i64:$y, i64:$x), (and i64:$z, (not i64:$x))),
683    (REG_SEQUENCE RC64,
684      (BFI_INT (i32 (EXTRACT_SUBREG $x, sub0)),
685               (i32 (EXTRACT_SUBREG $y, sub0)),
686               (i32 (EXTRACT_SUBREG $z, sub0))), sub0,
687      (BFI_INT (i32 (EXTRACT_SUBREG $x, sub1)),
688               (i32 (EXTRACT_SUBREG $y, sub1)),
689               (i32 (EXTRACT_SUBREG $z, sub1))), sub1)
690  >;
691
692  // SHA-256 Ch function
693  // z ^ (x & (y ^ z))
694  def : AMDGPUPat <
695    (xor i32:$z, (and i32:$x, (xor i32:$y, i32:$z))),
696    (BFI_INT $x, $y, $z)
697  >;
698
699  // 64-bit version
700  def : AMDGPUPat <
701    (xor i64:$z, (and i64:$x, (xor i64:$y, i64:$z))),
702    (REG_SEQUENCE RC64,
703      (BFI_INT (i32 (EXTRACT_SUBREG $x, sub0)),
704               (i32 (EXTRACT_SUBREG $y, sub0)),
705               (i32 (EXTRACT_SUBREG $z, sub0))), sub0,
706      (BFI_INT (i32 (EXTRACT_SUBREG $x, sub1)),
707               (i32 (EXTRACT_SUBREG $y, sub1)),
708               (i32 (EXTRACT_SUBREG $z, sub1))), sub1)
709  >;
710
711  def : AMDGPUPat <
712    (fcopysign f32:$src0, f32:$src1),
713    (BFI_INT (LoadImm32 (i32 0x7fffffff)), $src0, $src1)
714  >;
715
716  def : AMDGPUPat <
717    (f32 (fcopysign f32:$src0, f64:$src1)),
718    (BFI_INT (LoadImm32 (i32 0x7fffffff)), $src0,
719             (i32 (EXTRACT_SUBREG $src1, sub1)))
720  >;
721
722  def : AMDGPUPat <
723    (f64 (fcopysign f64:$src0, f64:$src1)),
724    (REG_SEQUENCE RC64,
725      (i32 (EXTRACT_SUBREG $src0, sub0)), sub0,
726      (BFI_INT (LoadImm32 (i32 0x7fffffff)),
727               (i32 (EXTRACT_SUBREG $src0, sub1)),
728               (i32 (EXTRACT_SUBREG $src1, sub1))), sub1)
729  >;
730
731  def : AMDGPUPat <
732    (f64 (fcopysign f64:$src0, f32:$src1)),
733    (REG_SEQUENCE RC64,
734      (i32 (EXTRACT_SUBREG $src0, sub0)), sub0,
735      (BFI_INT (LoadImm32 (i32 0x7fffffff)),
736               (i32 (EXTRACT_SUBREG $src0, sub1)),
737               $src1), sub1)
738  >;
739}
740
741// SHA-256 Ma patterns
742
743// ((x & z) | (y & (x | z))) -> BFI_INT (XOR x, y), z, y
744multiclass SHA256MaPattern <Instruction BFI_INT, Instruction XOR, RegisterClass RC64> {
745  def : AMDGPUPat <
746    (or (and i32:$x, i32:$z), (and i32:$y, (or i32:$x, i32:$z))),
747    (BFI_INT (XOR i32:$x, i32:$y), i32:$z, i32:$y)
748  >;
749
750  def : AMDGPUPat <
751    (or (and i64:$x, i64:$z), (and i64:$y, (or i64:$x, i64:$z))),
752    (REG_SEQUENCE RC64,
753      (BFI_INT (XOR (i32 (EXTRACT_SUBREG $x, sub0)),
754                    (i32 (EXTRACT_SUBREG $y, sub0))),
755               (i32 (EXTRACT_SUBREG $z, sub0)),
756               (i32 (EXTRACT_SUBREG $y, sub0))), sub0,
757      (BFI_INT (XOR (i32 (EXTRACT_SUBREG $x, sub1)),
758                    (i32 (EXTRACT_SUBREG $y, sub1))),
759               (i32 (EXTRACT_SUBREG $z, sub1)),
760               (i32 (EXTRACT_SUBREG $y, sub1))), sub1)
761  >;
762}
763
764// Bitfield extract patterns
765
766def IMMZeroBasedBitfieldMask : PatLeaf <(imm), [{
767  return isMask_32(N->getZExtValue());
768}]>;
769
770def IMMPopCount : SDNodeXForm<imm, [{
771  return CurDAG->getTargetConstant(countPopulation(N->getZExtValue()), SDLoc(N),
772                                   MVT::i32);
773}]>;
774
775multiclass BFEPattern <Instruction UBFE, Instruction SBFE, Instruction MOV> {
776  def : AMDGPUPat <
777    (i32 (and (i32 (srl i32:$src, i32:$rshift)), IMMZeroBasedBitfieldMask:$mask)),
778    (UBFE $src, $rshift, (MOV (i32 (IMMPopCount $mask))))
779  >;
780
781  // x & ((1 << y) - 1)
782  def : AMDGPUPat <
783    (and i32:$src, (add_oneuse (shl_oneuse 1, i32:$width), -1)),
784    (UBFE $src, (MOV (i32 0)), $width)
785  >;
786
787  // x & ~(-1 << y)
788  def : AMDGPUPat <
789    (and i32:$src, (xor_oneuse (shl_oneuse -1, i32:$width), -1)),
790    (UBFE $src, (MOV (i32 0)), $width)
791  >;
792
793  // x & (-1 >> (bitwidth - y))
794  def : AMDGPUPat <
795    (and i32:$src, (srl_oneuse -1, (sub 32, i32:$width))),
796    (UBFE $src, (MOV (i32 0)), $width)
797  >;
798
799  // x << (bitwidth - y) >> (bitwidth - y)
800  def : AMDGPUPat <
801    (srl (shl_oneuse i32:$src, (sub 32, i32:$width)), (sub 32, i32:$width)),
802    (UBFE $src, (MOV (i32 0)), $width)
803  >;
804
805  def : AMDGPUPat <
806    (sra (shl_oneuse i32:$src, (sub 32, i32:$width)), (sub 32, i32:$width)),
807    (SBFE $src, (MOV (i32 0)), $width)
808  >;
809}
810
811// rotr pattern
812class ROTRPattern <Instruction BIT_ALIGN> : AMDGPUPat <
813  (rotr i32:$src0, i32:$src1),
814  (BIT_ALIGN $src0, $src0, $src1)
815>;
816
817multiclass IntMed3Pat<Instruction med3Inst,
818                 SDPatternOperator min,
819                 SDPatternOperator max,
820                 SDPatternOperator min_oneuse,
821                 SDPatternOperator max_oneuse,
822                 ValueType vt = i32> {
823
824  // This matches 16 permutations of
825  // min(max(a, b), max(min(a, b), c))
826  def : AMDGPUPat <
827  (min (max_oneuse vt:$src0, vt:$src1),
828       (max_oneuse (min_oneuse vt:$src0, vt:$src1), vt:$src2)),
829  (med3Inst vt:$src0, vt:$src1, vt:$src2)
830>;
831
832  // This matches 16 permutations of
833  // max(min(x, y), min(max(x, y), z))
834  def : AMDGPUPat <
835  (max (min_oneuse vt:$src0, vt:$src1),
836       (min_oneuse (max_oneuse vt:$src0, vt:$src1), vt:$src2)),
837  (med3Inst $src0, $src1, $src2)
838>;
839}
840
841// Special conversion patterns
842
843def cvt_rpi_i32_f32 : PatFrag <
844  (ops node:$src),
845  (fp_to_sint (ffloor (fadd $src, FP_HALF))),
846  [{ (void) N; return TM.Options.NoNaNsFPMath; }]
847>;
848
849def cvt_flr_i32_f32 : PatFrag <
850  (ops node:$src),
851  (fp_to_sint (ffloor $src)),
852  [{ (void)N; return TM.Options.NoNaNsFPMath; }]
853>;
854
855let AddedComplexity = 2 in {
856class IMad24Pat<Instruction Inst, bit HasClamp = 0> : AMDGPUPat <
857  (add (AMDGPUmul_i24 i32:$src0, i32:$src1), i32:$src2),
858  !if(HasClamp, (Inst $src0, $src1, $src2, (i1 0)),
859                (Inst $src0, $src1, $src2))
860>;
861
862class UMad24Pat<Instruction Inst, bit HasClamp = 0> : AMDGPUPat <
863  (add (AMDGPUmul_u24 i32:$src0, i32:$src1), i32:$src2),
864  !if(HasClamp, (Inst $src0, $src1, $src2, (i1 0)),
865                (Inst $src0, $src1, $src2))
866>;
867} // AddedComplexity.
868
869class RcpPat<Instruction RcpInst, ValueType vt> : AMDGPUPat <
870  (fdiv FP_ONE, vt:$src),
871  (RcpInst $src)
872>;
873
874class RsqPat<Instruction RsqInst, ValueType vt> : AMDGPUPat <
875  (AMDGPUrcp (fsqrt vt:$src)),
876  (RsqInst $src)
877>;
878
879// Instructions which select to the same v_min_f*
880def fminnum_like : PatFrags<(ops node:$src0, node:$src1),
881  [(fminnum_ieee node:$src0, node:$src1),
882   (fminnum node:$src0, node:$src1)]
883>;
884
885// Instructions which select to the same v_max_f*
886def fmaxnum_like : PatFrags<(ops node:$src0, node:$src1),
887  [(fmaxnum_ieee node:$src0, node:$src1),
888   (fmaxnum node:$src0, node:$src1)]
889>;
890
891def fminnum_like_oneuse : PatFrags<(ops node:$src0, node:$src1),
892  [(fminnum_ieee_oneuse node:$src0, node:$src1),
893   (fminnum_oneuse node:$src0, node:$src1)]
894>;
895
896def fmaxnum_like_oneuse : PatFrags<(ops node:$src0, node:$src1),
897  [(fmaxnum_ieee_oneuse node:$src0, node:$src1),
898   (fmaxnum_oneuse node:$src0, node:$src1)]
899>;
900