1//===-- SIInstrInfo.td - SI Instruction Infos -------------*- 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//===----------------------------------------------------------------------===//
8def isCI : Predicate<"Subtarget->getGeneration() "
9                      ">= AMDGPUSubtarget::SEA_ISLANDS">;
10def isCIOnly : Predicate<"Subtarget->getGeneration() =="
11                         "AMDGPUSubtarget::SEA_ISLANDS">,
12  AssemblerPredicate <"FeatureSeaIslands">;
13def isVIOnly : Predicate<"Subtarget->getGeneration() =="
14                         "AMDGPUSubtarget::VOLCANIC_ISLANDS">,
15  AssemblerPredicate <"FeatureVolcanicIslands">;
16
17def DisableInst : Predicate <"false">, AssemblerPredicate<"FeatureDisable">;
18
19class GCNPredicateControl : PredicateControl {
20  Predicate SIAssemblerPredicate = isSICI;
21  Predicate VIAssemblerPredicate = isVI;
22}
23
24// Execpt for the NONE field, this must be kept in sync with the
25// SIEncodingFamily enum in AMDGPUInstrInfo.cpp
26def SIEncodingFamily {
27  int NONE = -1;
28  int SI = 0;
29  int VI = 1;
30  int SDWA = 2;
31  int SDWA9 = 3;
32  int GFX80 = 4;
33  int GFX9 = 5;
34}
35
36//===----------------------------------------------------------------------===//
37// SI DAG Nodes
38//===----------------------------------------------------------------------===//
39
40def AMDGPUclamp : SDNode<"AMDGPUISD::CLAMP", SDTFPUnaryOp>;
41
42def SIsbuffer_load : SDNode<"AMDGPUISD::SBUFFER_LOAD",
43  SDTypeProfile<1, 3, [SDTCisVT<1, v4i32>, SDTCisVT<2, i32>, SDTCisVT<3, i1>]>,
44  [SDNPMayLoad, SDNPMemOperand]
45>;
46
47def SIds_ordered_count : SDNode<"AMDGPUISD::DS_ORDERED_COUNT",
48  SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, SDTCisVT<2, i16>]>,
49  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain, SDNPInGlue]
50>;
51
52def SIatomic_inc : SDNode<"AMDGPUISD::ATOMIC_INC", SDTAtomic2,
53  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain]
54>;
55
56def SIatomic_dec : SDNode<"AMDGPUISD::ATOMIC_DEC", SDTAtomic2,
57  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain]
58>;
59
60def SDTAtomic2_f32 : SDTypeProfile<1, 2, [
61  SDTCisSameAs<0,2>, SDTCisFP<0>, SDTCisPtrTy<1>
62]>;
63
64def SIatomic_fmin : SDNode<"AMDGPUISD::ATOMIC_LOAD_FMIN", SDTAtomic2_f32,
65  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain]
66>;
67
68def SIatomic_fmax : SDNode<"AMDGPUISD::ATOMIC_LOAD_FMAX", SDTAtomic2_f32,
69  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain]
70>;
71
72// load_d16_{lo|hi} ptr, tied_input
73def SIload_d16 : SDTypeProfile<1, 2, [
74  SDTCisPtrTy<1>,
75  SDTCisSameAs<0, 2>
76]>;
77
78
79def SDTtbuffer_load : SDTypeProfile<1, 8,
80  [                     // vdata
81   SDTCisVT<1, v4i32>,  // rsrc
82   SDTCisVT<2, i32>,    // vindex(VGPR)
83   SDTCisVT<3, i32>,    // voffset(VGPR)
84   SDTCisVT<4, i32>,    // soffset(SGPR)
85   SDTCisVT<5, i32>,    // offset(imm)
86   SDTCisVT<6, i32>,    // format(imm)
87   SDTCisVT<7, i32>,    // cachecontrol(imm)
88   SDTCisVT<8, i1>      // idxen(imm)
89  ]>;
90
91def SItbuffer_load :   SDNode<"AMDGPUISD::TBUFFER_LOAD_FORMAT", SDTtbuffer_load,
92                              [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]>;
93def SItbuffer_load_d16 : SDNode<"AMDGPUISD::TBUFFER_LOAD_FORMAT_D16",
94                                SDTtbuffer_load,
95                                [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]>;
96
97def SDTtbuffer_store : SDTypeProfile<0, 9,
98    [                     // vdata
99     SDTCisVT<1, v4i32>,  // rsrc
100     SDTCisVT<2, i32>,    // vindex(VGPR)
101     SDTCisVT<3, i32>,    // voffset(VGPR)
102     SDTCisVT<4, i32>,    // soffset(SGPR)
103     SDTCisVT<5, i32>,    // offset(imm)
104     SDTCisVT<6, i32>,    // format(imm)
105     SDTCisVT<7, i32>,    // cachecontrol(imm)
106     SDTCisVT<8, i1>      // idxen(imm)
107    ]>;
108
109def SItbuffer_store : SDNode<"AMDGPUISD::TBUFFER_STORE_FORMAT", SDTtbuffer_store,
110                             [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
111def SItbuffer_store_d16 : SDNode<"AMDGPUISD::TBUFFER_STORE_FORMAT_D16",
112                                SDTtbuffer_store,
113                                [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
114
115def SDTBufferLoad : SDTypeProfile<1, 7,
116    [                    // vdata
117     SDTCisVT<1, v4i32>, // rsrc
118     SDTCisVT<2, i32>,   // vindex(VGPR)
119     SDTCisVT<3, i32>,   // voffset(VGPR)
120     SDTCisVT<4, i32>,   // soffset(SGPR)
121     SDTCisVT<5, i32>,   // offset(imm)
122     SDTCisVT<6, i32>,   // cachepolicy(imm)
123     SDTCisVT<7, i1>]>;  // idxen(imm)
124
125def SIbuffer_load : SDNode <"AMDGPUISD::BUFFER_LOAD", SDTBufferLoad,
126                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
127def SIbuffer_load_ubyte : SDNode <"AMDGPUISD::BUFFER_LOAD_UBYTE", SDTBufferLoad,
128                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
129def SIbuffer_load_ushort : SDNode <"AMDGPUISD::BUFFER_LOAD_USHORT", SDTBufferLoad,
130                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
131def SIbuffer_load_byte : SDNode <"AMDGPUISD::BUFFER_LOAD_BYTE", SDTBufferLoad,
132                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
133def SIbuffer_load_short: SDNode <"AMDGPUISD::BUFFER_LOAD_SHORT", SDTBufferLoad,
134                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
135def SIbuffer_load_format : SDNode <"AMDGPUISD::BUFFER_LOAD_FORMAT", SDTBufferLoad,
136                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
137def SIbuffer_load_format_d16 : SDNode <"AMDGPUISD::BUFFER_LOAD_FORMAT_D16",
138                                SDTBufferLoad,
139                                [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
140
141def SDTBufferStore : SDTypeProfile<0, 8,
142    [                    // vdata
143     SDTCisVT<1, v4i32>, // rsrc
144     SDTCisVT<2, i32>,   // vindex(VGPR)
145     SDTCisVT<3, i32>,   // voffset(VGPR)
146     SDTCisVT<4, i32>,   // soffset(SGPR)
147     SDTCisVT<5, i32>,   // offset(imm)
148     SDTCisVT<6, i32>,   // cachepolicy(imm)
149     SDTCisVT<7, i1>]>;  // idxen(imm)
150
151def SIbuffer_store : SDNode <"AMDGPUISD::BUFFER_STORE", SDTBufferStore,
152                             [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
153def SIbuffer_store_byte: SDNode <"AMDGPUISD::BUFFER_STORE_BYTE",
154                         SDTBufferStore,
155                         [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
156def SIbuffer_store_short : SDNode <"AMDGPUISD::BUFFER_STORE_SHORT",
157                           SDTBufferStore,
158                           [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
159def SIbuffer_store_format : SDNode <"AMDGPUISD::BUFFER_STORE_FORMAT",
160                            SDTBufferStore,
161                            [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
162def SIbuffer_store_format_d16 : SDNode <"AMDGPUISD::BUFFER_STORE_FORMAT_D16",
163                            SDTBufferStore,
164                            [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
165
166class SDBufferAtomic<string opcode> : SDNode <opcode,
167  SDTypeProfile<1, 8,
168       [SDTCisVT<2, v4i32>, // rsrc
169       SDTCisVT<3, i32>,   // vindex(VGPR)
170       SDTCisVT<4, i32>,   // voffset(VGPR)
171       SDTCisVT<5, i32>,   // soffset(SGPR)
172       SDTCisVT<6, i32>,   // offset(imm)
173       SDTCisVT<7, i32>,   // cachepolicy(imm)
174       SDTCisVT<8, i1>]>,  // idxen(imm)
175  [SDNPMemOperand, SDNPHasChain, SDNPMayLoad, SDNPMayStore]
176>;
177
178def SIbuffer_atomic_swap : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_SWAP">;
179def SIbuffer_atomic_add : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_ADD">;
180def SIbuffer_atomic_sub : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_SUB">;
181def SIbuffer_atomic_smin : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_SMIN">;
182def SIbuffer_atomic_umin : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_UMIN">;
183def SIbuffer_atomic_smax : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_SMAX">;
184def SIbuffer_atomic_umax : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_UMAX">;
185def SIbuffer_atomic_and : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_AND">;
186def SIbuffer_atomic_or : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_OR">;
187def SIbuffer_atomic_xor : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_XOR">;
188
189def SIbuffer_atomic_cmpswap : SDNode <"AMDGPUISD::BUFFER_ATOMIC_CMPSWAP",
190  SDTypeProfile<1, 9,
191    [SDTCisVT<0, i32>,   // dst
192     SDTCisVT<1, i32>,   // src
193     SDTCisVT<2, i32>,   // cmp
194     SDTCisVT<3, v4i32>, // rsrc
195     SDTCisVT<4, i32>,   // vindex(VGPR)
196     SDTCisVT<5, i32>,   // voffset(VGPR)
197     SDTCisVT<6, i32>,   // soffset(SGPR)
198     SDTCisVT<7, i32>,   // offset(imm)
199     SDTCisVT<8, i32>,   // cachepolicy(imm)
200     SDTCisVT<9, i1>]>,  // idxen(imm)
201  [SDNPMemOperand, SDNPHasChain, SDNPMayLoad, SDNPMayStore]
202>;
203
204def SIpc_add_rel_offset : SDNode<"AMDGPUISD::PC_ADD_REL_OFFSET",
205  SDTypeProfile<1, 2, [SDTCisVT<0, iPTR>, SDTCisSameAs<0,1>, SDTCisSameAs<0,2>]>
206>;
207
208def SIload_d16_lo : SDNode<"AMDGPUISD::LOAD_D16_LO",
209  SIload_d16,
210  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
211>;
212
213def SIload_d16_lo_u8 : SDNode<"AMDGPUISD::LOAD_D16_LO_U8",
214  SIload_d16,
215  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
216>;
217
218def SIload_d16_lo_i8 : SDNode<"AMDGPUISD::LOAD_D16_LO_I8",
219  SIload_d16,
220  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
221>;
222
223def SIload_d16_hi : SDNode<"AMDGPUISD::LOAD_D16_HI",
224  SIload_d16,
225  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
226>;
227
228def SIload_d16_hi_u8 : SDNode<"AMDGPUISD::LOAD_D16_HI_U8",
229  SIload_d16,
230  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
231>;
232
233def SIload_d16_hi_i8 : SDNode<"AMDGPUISD::LOAD_D16_HI_I8",
234  SIload_d16,
235  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
236>;
237
238//===----------------------------------------------------------------------===//
239// ValueType helpers
240//===----------------------------------------------------------------------===//
241
242// Returns 1 if the source arguments have modifiers, 0 if they do not.
243// XXX - do f16 instructions?
244class isFloatType<ValueType SrcVT> {
245  bit ret =
246    !if(!eq(SrcVT.Value, f16.Value), 1,
247    !if(!eq(SrcVT.Value, f32.Value), 1,
248    !if(!eq(SrcVT.Value, f64.Value), 1,
249    !if(!eq(SrcVT.Value, v2f16.Value), 1,
250    0))));
251}
252
253class isIntType<ValueType SrcVT> {
254  bit ret =
255    !if(!eq(SrcVT.Value, i16.Value), 1,
256    !if(!eq(SrcVT.Value, i32.Value), 1,
257    !if(!eq(SrcVT.Value, i64.Value), 1,
258    0)));
259}
260
261class isPackedType<ValueType SrcVT> {
262  bit ret =
263    !if(!eq(SrcVT.Value, v2i16.Value), 1,
264      !if(!eq(SrcVT.Value, v2f16.Value), 1, 0)
265    );
266}
267
268//===----------------------------------------------------------------------===//
269// PatFrags for global memory operations
270//===----------------------------------------------------------------------===//
271
272defm atomic_inc_global : global_binary_atomic_op<SIatomic_inc>;
273defm atomic_dec_global : global_binary_atomic_op<SIatomic_dec>;
274
275def atomic_inc_local : local_binary_atomic_op<SIatomic_inc>;
276def atomic_dec_local : local_binary_atomic_op<SIatomic_dec>;
277def atomic_load_fadd_local : local_binary_atomic_op<atomic_load_fadd>;
278def atomic_load_fmin_local : local_binary_atomic_op<SIatomic_fmin>;
279def atomic_load_fmax_local : local_binary_atomic_op<SIatomic_fmax>;
280
281//===----------------------------------------------------------------------===//
282// SDNodes PatFrags for loads/stores with a glue input.
283// This is for SDNodes and PatFrag for local loads and stores to
284// enable s_mov_b32 m0, -1 to be glued to the memory instructions.
285//
286// These mirror the regular load/store PatFrags and rely on special
287// processing during Select() to add the glued copy.
288//
289//===----------------------------------------------------------------------===//
290
291def AMDGPUld_glue : SDNode <"ISD::LOAD", SDTLoad,
292  [SDNPHasChain, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
293>;
294
295def AMDGPUatomic_ld_glue : SDNode <"ISD::ATOMIC_LOAD", SDTAtomicLoad,
296  [SDNPHasChain, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
297>;
298
299def unindexedload_glue : PatFrag <(ops node:$ptr), (AMDGPUld_glue node:$ptr), [{
300  return cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED;
301}]>;
302
303def load_glue : PatFrag <(ops node:$ptr), (unindexedload_glue node:$ptr), [{
304  return cast<LoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD;
305}]>;
306
307def atomic_load_32_glue : PatFrag<(ops node:$ptr),
308  (AMDGPUatomic_ld_glue node:$ptr)> {
309  let IsAtomic = 1;
310  let MemoryVT = i32;
311}
312
313def atomic_load_64_glue : PatFrag<(ops node:$ptr),
314  (AMDGPUatomic_ld_glue node:$ptr)> {
315  let IsAtomic = 1;
316  let MemoryVT = i64;
317}
318
319def extload_glue : PatFrag<(ops node:$ptr), (load_glue node:$ptr), [{
320  return cast<LoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD;
321}]>;
322
323def sextload_glue : PatFrag<(ops node:$ptr), (unindexedload_glue node:$ptr), [{
324  return cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD;
325}]>;
326
327def zextload_glue : PatFrag<(ops node:$ptr), (unindexedload_glue node:$ptr), [{
328  return cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD;
329}]>;
330
331def az_extload_glue : AZExtLoadBase <unindexedload_glue>;
332
333def az_extloadi8_glue : PatFrag<(ops node:$ptr), (az_extload_glue node:$ptr), [{
334  return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i8;
335}]>;
336
337def az_extloadi16_glue : PatFrag<(ops node:$ptr), (az_extload_glue node:$ptr), [{
338  return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i16;
339}]>;
340
341def sextloadi8_glue : PatFrag<(ops node:$ptr), (sextload_glue node:$ptr), [{
342  return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i8;
343}]>;
344
345def sextloadi16_glue : PatFrag<(ops node:$ptr), (sextload_glue node:$ptr), [{
346  return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i16;
347}]>;
348
349def load_glue_align8 : Aligned8Bytes <
350  (ops node:$ptr), (load_glue node:$ptr)
351>;
352def load_glue_align16 : Aligned16Bytes <
353  (ops node:$ptr), (load_glue node:$ptr)
354>;
355
356
357def load_local_m0 : LoadFrag<load_glue>, LocalAddress;
358def sextloadi8_local_m0 : LoadFrag<sextloadi8_glue>, LocalAddress;
359def sextloadi16_local_m0 : LoadFrag<sextloadi16_glue>, LocalAddress;
360def az_extloadi8_local_m0 : LoadFrag<az_extloadi8_glue>, LocalAddress;
361def az_extloadi16_local_m0 : LoadFrag<az_extloadi16_glue>, LocalAddress;
362def load_align8_local_m0 : LoadFrag <load_glue_align8>, LocalAddress;
363def load_align16_local_m0 : LoadFrag <load_glue_align16>, LocalAddress;
364def atomic_load_32_local_m0 : LoadFrag<atomic_load_32_glue>, LocalAddress;
365def atomic_load_64_local_m0 : LoadFrag<atomic_load_64_glue>, LocalAddress;
366
367
368def AMDGPUst_glue : SDNode <"ISD::STORE", SDTStore,
369  [SDNPHasChain, SDNPMayStore, SDNPMemOperand, SDNPInGlue]
370>;
371
372def AMDGPUatomic_st_glue : SDNode <"ISD::ATOMIC_STORE", SDTAtomicStore,
373  [SDNPHasChain, SDNPMayStore, SDNPMemOperand, SDNPInGlue]
374>;
375
376def atomic_store_glue : PatFrag<(ops node:$ptr, node:$val),
377  (AMDGPUatomic_st_glue node:$ptr, node:$val)> {
378}
379
380def unindexedstore_glue : PatFrag<(ops node:$val, node:$ptr),
381                                   (AMDGPUst_glue node:$val, node:$ptr), [{
382  return cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED;
383}]>;
384
385def store_glue : PatFrag<(ops node:$val, node:$ptr),
386                      (unindexedstore_glue node:$val, node:$ptr), [{
387  return !cast<StoreSDNode>(N)->isTruncatingStore();
388}]>;
389
390def truncstore_glue : PatFrag<(ops node:$val, node:$ptr),
391  (unindexedstore_glue node:$val, node:$ptr), [{
392  return cast<StoreSDNode>(N)->isTruncatingStore();
393}]>;
394
395def truncstorei8_glue : PatFrag<(ops node:$val, node:$ptr),
396                           (truncstore_glue node:$val, node:$ptr), [{
397  return cast<StoreSDNode>(N)->getMemoryVT() == MVT::i8;
398}]>;
399
400def truncstorei16_glue : PatFrag<(ops node:$val, node:$ptr),
401                           (truncstore_glue node:$val, node:$ptr), [{
402  return cast<StoreSDNode>(N)->getMemoryVT() == MVT::i16;
403}]>;
404
405def store_glue_align8 : Aligned8Bytes <
406  (ops node:$value, node:$ptr), (store_glue node:$value, node:$ptr)
407>;
408
409def store_glue_align16 : Aligned16Bytes <
410  (ops node:$value, node:$ptr), (store_glue node:$value, node:$ptr)
411>;
412
413def store_local_m0 : StoreFrag<store_glue>, LocalAddress;
414def truncstorei8_local_m0 : StoreFrag<truncstorei8_glue>, LocalAddress;
415def truncstorei16_local_m0 : StoreFrag<truncstorei16_glue>, LocalAddress;
416def atomic_store_local_m0 : StoreFrag<AMDGPUatomic_st_glue>, LocalAddress;
417
418def store_align8_local_m0 : StoreFrag<store_glue_align8>, LocalAddress;
419def store_align16_local_m0 : StoreFrag<store_glue_align16>, LocalAddress;
420
421def si_setcc_uniform : PatFrag <
422  (ops node:$lhs, node:$rhs, node:$cond),
423  (setcc node:$lhs, node:$rhs, node:$cond), [{
424  for (SDNode *Use : N->uses()) {
425    if (Use->isMachineOpcode() || Use->getOpcode() != ISD::CopyToReg)
426      return false;
427
428    unsigned Reg = cast<RegisterSDNode>(Use->getOperand(1))->getReg();
429    if (Reg != AMDGPU::SCC)
430      return false;
431  }
432  return true;
433}]>;
434
435//===----------------------------------------------------------------------===//
436// SDNodes PatFrags for d16 loads
437//===----------------------------------------------------------------------===//
438
439class LoadD16Frag <SDPatternOperator op> : PatFrag<(ops node:$ptr, node:$tied_in), (op node:$ptr, node:$tied_in)>;
440class LocalLoadD16 <SDPatternOperator op> : LoadD16Frag <op>, LocalAddress;
441class GlobalLoadD16 <SDPatternOperator op> : LoadD16Frag <op>, GlobalLoadAddress;
442class PrivateLoadD16 <SDPatternOperator op> : LoadD16Frag <op>, PrivateAddress;
443class FlatLoadD16 <SDPatternOperator op> : LoadD16Frag <op>, FlatLoadAddress;
444
445def load_d16_hi_local : LocalLoadD16 <SIload_d16_hi>;
446def az_extloadi8_d16_hi_local : LocalLoadD16 <SIload_d16_hi_u8>;
447def sextloadi8_d16_hi_local : LocalLoadD16 <SIload_d16_hi_i8>;
448
449def load_d16_hi_global : GlobalLoadD16 <SIload_d16_hi>;
450def az_extloadi8_d16_hi_global : GlobalLoadD16 <SIload_d16_hi_u8>;
451def sextloadi8_d16_hi_global : GlobalLoadD16 <SIload_d16_hi_i8>;
452
453def load_d16_hi_private : PrivateLoadD16 <SIload_d16_hi>;
454def az_extloadi8_d16_hi_private : PrivateLoadD16 <SIload_d16_hi_u8>;
455def sextloadi8_d16_hi_private : PrivateLoadD16 <SIload_d16_hi_i8>;
456
457def load_d16_hi_flat : FlatLoadD16 <SIload_d16_hi>;
458def az_extloadi8_d16_hi_flat : FlatLoadD16 <SIload_d16_hi_u8>;
459def sextloadi8_d16_hi_flat : FlatLoadD16 <SIload_d16_hi_i8>;
460
461
462def load_d16_lo_local : LocalLoadD16 <SIload_d16_lo>;
463def az_extloadi8_d16_lo_local : LocalLoadD16 <SIload_d16_lo_u8>;
464def sextloadi8_d16_lo_local : LocalLoadD16 <SIload_d16_lo_i8>;
465
466def load_d16_lo_global : GlobalLoadD16 <SIload_d16_lo>;
467def az_extloadi8_d16_lo_global : GlobalLoadD16 <SIload_d16_lo_u8>;
468def sextloadi8_d16_lo_global : GlobalLoadD16 <SIload_d16_lo_i8>;
469
470def load_d16_lo_private : PrivateLoadD16 <SIload_d16_lo>;
471def az_extloadi8_d16_lo_private : PrivateLoadD16 <SIload_d16_lo_u8>;
472def sextloadi8_d16_lo_private : PrivateLoadD16 <SIload_d16_lo_i8>;
473
474def load_d16_lo_flat : FlatLoadD16 <SIload_d16_lo>;
475def az_extloadi8_d16_lo_flat : FlatLoadD16 <SIload_d16_lo_u8>;
476def sextloadi8_d16_lo_flat : FlatLoadD16 <SIload_d16_lo_i8>;
477
478
479
480def lshr_rev : PatFrag <
481  (ops node:$src1, node:$src0),
482  (srl $src0, $src1)
483>;
484
485def ashr_rev : PatFrag <
486  (ops node:$src1, node:$src0),
487  (sra $src0, $src1)
488>;
489
490def lshl_rev : PatFrag <
491  (ops node:$src1, node:$src0),
492  (shl $src0, $src1)
493>;
494
495multiclass SIAtomicM0Glue2 <string op_name, bit is_amdgpu = 0,
496                            SDTypeProfile tc = SDTAtomic2> {
497
498  def _glue : SDNode <
499    !if(is_amdgpu, "AMDGPUISD", "ISD")#"::ATOMIC_"#op_name, tc,
500    [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
501  >;
502
503  def _local_m0 : local_binary_atomic_op <!cast<SDNode>(NAME#"_glue")>;
504}
505
506defm atomic_load_add : SIAtomicM0Glue2 <"LOAD_ADD">;
507defm atomic_load_sub : SIAtomicM0Glue2 <"LOAD_SUB">;
508defm atomic_inc : SIAtomicM0Glue2 <"INC", 1>;
509defm atomic_dec : SIAtomicM0Glue2 <"DEC", 1>;
510defm atomic_load_and : SIAtomicM0Glue2 <"LOAD_AND">;
511defm atomic_load_min : SIAtomicM0Glue2 <"LOAD_MIN">;
512defm atomic_load_max : SIAtomicM0Glue2 <"LOAD_MAX">;
513defm atomic_load_or : SIAtomicM0Glue2 <"LOAD_OR">;
514defm atomic_load_xor : SIAtomicM0Glue2 <"LOAD_XOR">;
515defm atomic_load_umin : SIAtomicM0Glue2 <"LOAD_UMIN">;
516defm atomic_load_umax : SIAtomicM0Glue2 <"LOAD_UMAX">;
517defm atomic_swap : SIAtomicM0Glue2 <"SWAP">;
518defm atomic_load_fadd : SIAtomicM0Glue2 <"LOAD_FADD", 0, SDTAtomic2_f32>;
519defm atomic_load_fmin : SIAtomicM0Glue2 <"LOAD_FMIN", 1, SDTAtomic2_f32>;
520defm atomic_load_fmax : SIAtomicM0Glue2 <"LOAD_FMAX", 1, SDTAtomic2_f32>;
521
522def atomic_cmp_swap_glue : SDNode <"ISD::ATOMIC_CMP_SWAP", SDTAtomic3,
523  [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
524>;
525
526def atomic_cmp_swap_local_m0 : AtomicCmpSwapLocal<atomic_cmp_swap_glue>;
527
528
529def as_i1imm : SDNodeXForm<imm, [{
530  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i1);
531}]>;
532
533def as_i8imm : SDNodeXForm<imm, [{
534  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i8);
535}]>;
536
537def as_i16imm : SDNodeXForm<imm, [{
538  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16);
539}]>;
540
541def as_i32imm: SDNodeXForm<imm, [{
542  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i32);
543}]>;
544
545def as_i64imm: SDNodeXForm<imm, [{
546  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i64);
547}]>;
548
549def cond_as_i32imm: SDNodeXForm<cond, [{
550  return CurDAG->getTargetConstant(N->get(), SDLoc(N), MVT::i32);
551}]>;
552
553// Copied from the AArch64 backend:
554def bitcast_fpimm_to_i32 : SDNodeXForm<fpimm, [{
555return CurDAG->getTargetConstant(
556  N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i32);
557}]>;
558
559def frameindex_to_targetframeindex : SDNodeXForm<frameindex, [{
560  auto FI = cast<FrameIndexSDNode>(N);
561  return CurDAG->getTargetFrameIndex(FI->getIndex(), MVT::i32);
562}]>;
563
564// Copied from the AArch64 backend:
565def bitcast_fpimm_to_i64 : SDNodeXForm<fpimm, [{
566return CurDAG->getTargetConstant(
567  N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i64);
568}]>;
569
570class bitextract_imm<int bitnum> : SDNodeXForm<imm, [{
571  uint64_t Imm = N->getZExtValue();
572  unsigned Bit = (Imm >> }] # bitnum # [{ ) & 1;
573  return CurDAG->getTargetConstant(Bit, SDLoc(N), MVT::i1);
574}]>;
575
576def SIMM16bit : PatLeaf <(imm),
577  [{return isInt<16>(N->getSExtValue());}]
578>;
579
580class InlineImm <ValueType vt> : PatLeaf <(vt imm), [{
581  return isInlineImmediate(N);
582}]>;
583
584class InlineFPImm <ValueType vt> : PatLeaf <(vt fpimm), [{
585  return isInlineImmediate(N);
586}]>;
587
588class VGPRImm <dag frag> : PatLeaf<frag, [{
589  return isVGPRImm(N);
590}]>;
591
592def NegateImm : SDNodeXForm<imm, [{
593  return CurDAG->getConstant(-N->getSExtValue(), SDLoc(N), MVT::i32);
594}]>;
595
596// TODO: When FP inline imm values work?
597def NegSubInlineConst32 : ImmLeaf<i32, [{
598  return Imm < -16 && Imm >= -64;
599}], NegateImm>;
600
601def NegSubInlineConst16 : ImmLeaf<i16, [{
602  return Imm < -16 && Imm >= -64;
603}], NegateImm>;
604
605def ShiftAmt32Imm : PatLeaf <(imm), [{
606  return N->getZExtValue() < 32;
607}]>;
608
609//===----------------------------------------------------------------------===//
610// Custom Operands
611//===----------------------------------------------------------------------===//
612
613def SoppBrTarget : AsmOperandClass {
614  let Name = "SoppBrTarget";
615  let ParserMethod = "parseSOppBrTarget";
616}
617
618def sopp_brtarget : Operand<OtherVT> {
619  let EncoderMethod = "getSOPPBrEncoding";
620  let DecoderMethod = "decodeSoppBrTarget";
621  let OperandType = "OPERAND_PCREL";
622  let ParserMatchClass = SoppBrTarget;
623}
624
625def si_ga : Operand<iPTR>;
626
627def InterpSlotMatchClass : AsmOperandClass {
628  let Name = "InterpSlot";
629  let PredicateMethod = "isInterpSlot";
630  let ParserMethod = "parseInterpSlot";
631  let RenderMethod = "addImmOperands";
632}
633
634def InterpSlot : Operand<i32> {
635  let PrintMethod = "printInterpSlot";
636  let ParserMatchClass = InterpSlotMatchClass;
637  let OperandType = "OPERAND_IMMEDIATE";
638}
639
640def AttrMatchClass : AsmOperandClass {
641  let Name = "Attr";
642  let PredicateMethod = "isInterpAttr";
643  let ParserMethod = "parseInterpAttr";
644  let RenderMethod = "addImmOperands";
645}
646
647// It appears to be necessary to create a separate operand for this to
648// be able to parse attr<num> with no space.
649def Attr : Operand<i32> {
650  let PrintMethod = "printInterpAttr";
651  let ParserMatchClass = AttrMatchClass;
652  let OperandType = "OPERAND_IMMEDIATE";
653}
654
655def AttrChanMatchClass : AsmOperandClass {
656  let Name = "AttrChan";
657  let PredicateMethod = "isAttrChan";
658  let RenderMethod = "addImmOperands";
659}
660
661def AttrChan : Operand<i32> {
662  let PrintMethod = "printInterpAttrChan";
663  let ParserMatchClass = AttrChanMatchClass;
664  let OperandType = "OPERAND_IMMEDIATE";
665}
666
667def SendMsgMatchClass : AsmOperandClass {
668  let Name = "SendMsg";
669  let PredicateMethod = "isSendMsg";
670  let ParserMethod = "parseSendMsgOp";
671  let RenderMethod = "addImmOperands";
672}
673
674def SwizzleMatchClass : AsmOperandClass {
675  let Name = "Swizzle";
676  let PredicateMethod = "isSwizzle";
677  let ParserMethod = "parseSwizzleOp";
678  let RenderMethod = "addImmOperands";
679  let IsOptional = 1;
680}
681
682def EndpgmMatchClass : AsmOperandClass {
683  let Name = "EndpgmImm";
684  let PredicateMethod = "isEndpgm";
685  let ParserMethod = "parseEndpgmOp";
686  let RenderMethod = "addImmOperands";
687  let IsOptional = 1;
688}
689
690def ExpTgtMatchClass : AsmOperandClass {
691  let Name = "ExpTgt";
692  let PredicateMethod = "isExpTgt";
693  let ParserMethod = "parseExpTgt";
694  let RenderMethod = "printExpTgt";
695}
696
697def SendMsgImm : Operand<i32> {
698  let PrintMethod = "printSendMsg";
699  let ParserMatchClass = SendMsgMatchClass;
700}
701
702def SwizzleImm : Operand<i16> {
703  let PrintMethod = "printSwizzle";
704  let ParserMatchClass = SwizzleMatchClass;
705}
706
707def EndpgmImm : Operand<i16> {
708  let PrintMethod = "printEndpgm";
709  let ParserMatchClass = EndpgmMatchClass;
710}
711
712def SWaitMatchClass : AsmOperandClass {
713  let Name = "SWaitCnt";
714  let RenderMethod = "addImmOperands";
715  let ParserMethod = "parseSWaitCntOps";
716}
717
718def VReg32OrOffClass : AsmOperandClass {
719  let Name = "VReg32OrOff";
720  let ParserMethod = "parseVReg32OrOff";
721}
722
723def WAIT_FLAG : Operand <i32> {
724  let ParserMatchClass = SWaitMatchClass;
725  let PrintMethod = "printWaitFlag";
726}
727
728include "SIInstrFormats.td"
729include "VIInstrFormats.td"
730
731// ===----------------------------------------------------------------------===//
732// ExpSrc* Special cases for exp src operands which are printed as
733// "off" depending on en operand.
734// ===----------------------------------------------------------------------===//
735
736def ExpSrc0 : RegisterOperand<VGPR_32> {
737  let PrintMethod = "printExpSrc0";
738  let ParserMatchClass = VReg32OrOffClass;
739}
740
741def ExpSrc1 : RegisterOperand<VGPR_32> {
742  let PrintMethod = "printExpSrc1";
743  let ParserMatchClass = VReg32OrOffClass;
744}
745
746def ExpSrc2 : RegisterOperand<VGPR_32> {
747  let PrintMethod = "printExpSrc2";
748  let ParserMatchClass = VReg32OrOffClass;
749}
750
751def ExpSrc3 : RegisterOperand<VGPR_32> {
752  let PrintMethod = "printExpSrc3";
753  let ParserMatchClass = VReg32OrOffClass;
754}
755
756class SDWASrc<ValueType vt> : RegisterOperand<VS_32> {
757  let OperandNamespace = "AMDGPU";
758  string Type = !if(isFloatType<vt>.ret, "FP", "INT");
759  let OperandType = "OPERAND_REG_INLINE_C_"#Type#vt.Size;
760  let DecoderMethod = "decodeSDWASrc"#vt.Size;
761  let EncoderMethod = "getSDWASrcEncoding";
762}
763
764def SDWASrc_i32 : SDWASrc<i32>;
765def SDWASrc_i16 : SDWASrc<i16>;
766def SDWASrc_f32 : SDWASrc<f32>;
767def SDWASrc_f16 : SDWASrc<f16>;
768
769def SDWAVopcDst : VOPDstOperand<SReg_64> {
770  let OperandNamespace = "AMDGPU";
771  let OperandType = "OPERAND_SDWA_VOPC_DST";
772  let EncoderMethod = "getSDWAVopcDstEncoding";
773  let DecoderMethod = "decodeSDWAVopcDst";
774}
775
776class NamedMatchClass<string CName, bit Optional = 1> : AsmOperandClass {
777  let Name = "Imm"#CName;
778  let PredicateMethod = "is"#CName;
779  let ParserMethod = !if(Optional, "parseOptionalOperand", "parse"#CName);
780  let RenderMethod = "addImmOperands";
781  let IsOptional = Optional;
782  let DefaultMethod = !if(Optional, "default"#CName, ?);
783}
784
785class NamedOperandBit<string Name, AsmOperandClass MatchClass> : Operand<i1> {
786  let PrintMethod = "print"#Name;
787  let ParserMatchClass = MatchClass;
788}
789
790class NamedOperandU8<string Name, AsmOperandClass MatchClass> : Operand<i8> {
791  let PrintMethod = "print"#Name;
792  let ParserMatchClass = MatchClass;
793}
794
795class NamedOperandU12<string Name, AsmOperandClass MatchClass> : Operand<i16> {
796  let PrintMethod = "print"#Name;
797  let ParserMatchClass = MatchClass;
798}
799
800class NamedOperandU16<string Name, AsmOperandClass MatchClass> : Operand<i16> {
801  let PrintMethod = "print"#Name;
802  let ParserMatchClass = MatchClass;
803}
804
805class NamedOperandS13<string Name, AsmOperandClass MatchClass> : Operand<i16> {
806  let PrintMethod = "print"#Name;
807  let ParserMatchClass = MatchClass;
808}
809
810class NamedOperandU32<string Name, AsmOperandClass MatchClass> : Operand<i32> {
811  let PrintMethod = "print"#Name;
812  let ParserMatchClass = MatchClass;
813}
814
815class NamedOperandU32Default0<string Name, AsmOperandClass MatchClass> :
816  OperandWithDefaultOps<i32, (ops (i32 0))> {
817  let PrintMethod = "print"#Name;
818  let ParserMatchClass = MatchClass;
819}
820
821let OperandType = "OPERAND_IMMEDIATE" in {
822
823def offen : NamedOperandBit<"Offen", NamedMatchClass<"Offen">>;
824def idxen : NamedOperandBit<"Idxen", NamedMatchClass<"Idxen">>;
825def addr64 : NamedOperandBit<"Addr64", NamedMatchClass<"Addr64">>;
826
827def offset_u12 : NamedOperandU12<"Offset", NamedMatchClass<"OffsetU12">>;
828def offset_s13 : NamedOperandS13<"OffsetS13", NamedMatchClass<"OffsetS13">>;
829def offset : NamedOperandU16<"Offset", NamedMatchClass<"Offset">>;
830def offset0 : NamedOperandU8<"Offset0", NamedMatchClass<"Offset0">>;
831def offset1 : NamedOperandU8<"Offset1", NamedMatchClass<"Offset1">>;
832
833def gds : NamedOperandBit<"GDS", NamedMatchClass<"GDS">>;
834
835def omod : NamedOperandU32<"OModSI", NamedMatchClass<"OModSI">>;
836def clampmod : NamedOperandBit<"ClampSI", NamedMatchClass<"ClampSI">>;
837def highmod : NamedOperandBit<"High", NamedMatchClass<"High">>;
838
839def GLC : NamedOperandBit<"GLC", NamedMatchClass<"GLC">>;
840def SLC : NamedOperandBit<"SLC", NamedMatchClass<"SLC">>;
841def TFE : NamedOperandBit<"TFE", NamedMatchClass<"TFE">>;
842def UNorm : NamedOperandBit<"UNorm", NamedMatchClass<"UNorm">>;
843def DA : NamedOperandBit<"DA", NamedMatchClass<"DA">>;
844def R128A16 : NamedOperandBit<"R128A16", NamedMatchClass<"R128A16">>;
845def D16 : NamedOperandBit<"D16", NamedMatchClass<"D16">>;
846def LWE : NamedOperandBit<"LWE", NamedMatchClass<"LWE">>;
847def exp_compr : NamedOperandBit<"ExpCompr", NamedMatchClass<"ExpCompr">>;
848def exp_vm : NamedOperandBit<"ExpVM", NamedMatchClass<"ExpVM">>;
849
850def FORMAT : NamedOperandU8<"FORMAT", NamedMatchClass<"FORMAT">>;
851
852def DMask : NamedOperandU16<"DMask", NamedMatchClass<"DMask">>;
853
854def dpp_ctrl : NamedOperandU32<"DPPCtrl", NamedMatchClass<"DPPCtrl", 0>>;
855def row_mask : NamedOperandU32<"RowMask", NamedMatchClass<"RowMask">>;
856def bank_mask : NamedOperandU32<"BankMask", NamedMatchClass<"BankMask">>;
857def bound_ctrl : NamedOperandBit<"BoundCtrl", NamedMatchClass<"BoundCtrl">>;
858
859def dst_sel : NamedOperandU32<"SDWADstSel", NamedMatchClass<"SDWADstSel">>;
860def src0_sel : NamedOperandU32<"SDWASrc0Sel", NamedMatchClass<"SDWASrc0Sel">>;
861def src1_sel : NamedOperandU32<"SDWASrc1Sel", NamedMatchClass<"SDWASrc1Sel">>;
862def dst_unused : NamedOperandU32<"SDWADstUnused", NamedMatchClass<"SDWADstUnused">>;
863
864def op_sel : NamedOperandU32Default0<"OpSel", NamedMatchClass<"OpSel">>;
865def op_sel_hi : NamedOperandU32Default0<"OpSelHi", NamedMatchClass<"OpSelHi">>;
866def neg_lo : NamedOperandU32Default0<"NegLo", NamedMatchClass<"NegLo">>;
867def neg_hi : NamedOperandU32Default0<"NegHi", NamedMatchClass<"NegHi">>;
868
869def hwreg : NamedOperandU16<"Hwreg", NamedMatchClass<"Hwreg", 0>>;
870
871def exp_tgt : NamedOperandU8<"ExpTgt", NamedMatchClass<"ExpTgt", 0>> {
872
873}
874
875} // End OperandType = "OPERAND_IMMEDIATE"
876
877class KImmMatchClass<int size> : AsmOperandClass {
878  let Name = "KImmFP"#size;
879  let PredicateMethod = "isKImmFP"#size;
880  let ParserMethod = "parseImm";
881  let RenderMethod = "addKImmFP"#size#"Operands";
882}
883
884class kimmOperand<ValueType vt> : Operand<vt> {
885  let OperandNamespace = "AMDGPU";
886  let OperandType = "OPERAND_KIMM"#vt.Size;
887  let PrintMethod = "printU"#vt.Size#"ImmOperand";
888  let ParserMatchClass = !cast<AsmOperandClass>("KImmFP"#vt.Size#"MatchClass");
889}
890
891// 32-bit VALU immediate operand that uses the constant bus.
892def KImmFP32MatchClass : KImmMatchClass<32>;
893def f32kimm : kimmOperand<i32>;
894
895// 32-bit VALU immediate operand with a 16-bit value that uses the
896// constant bus.
897def KImmFP16MatchClass : KImmMatchClass<16>;
898def f16kimm : kimmOperand<i16>;
899
900
901def VOPDstS64 : VOPDstOperand <SReg_64>;
902
903class FPInputModsMatchClass <int opSize> : AsmOperandClass {
904  let Name = "RegOrImmWithFP"#opSize#"InputMods";
905  let ParserMethod = "parseRegOrImmWithFPInputMods";
906  let PredicateMethod = "isRegOrImmWithFP"#opSize#"InputMods";
907}
908
909def FP16InputModsMatchClass : FPInputModsMatchClass<16>;
910def FP32InputModsMatchClass : FPInputModsMatchClass<32>;
911def FP64InputModsMatchClass : FPInputModsMatchClass<64>;
912
913class InputMods <AsmOperandClass matchClass> : Operand <i32> {
914  let OperandNamespace = "AMDGPU";
915  let OperandType = "OPERAND_INPUT_MODS";
916  let ParserMatchClass = matchClass;
917}
918
919class FPInputMods <FPInputModsMatchClass matchClass> : InputMods <matchClass> {
920  let PrintMethod = "printOperandAndFPInputMods";
921}
922
923def FP16InputMods : FPInputMods<FP16InputModsMatchClass>;
924def FP32InputMods : FPInputMods<FP32InputModsMatchClass>;
925def FP64InputMods : FPInputMods<FP64InputModsMatchClass>;
926
927class IntInputModsMatchClass <int opSize> : AsmOperandClass {
928  let Name = "RegOrImmWithInt"#opSize#"InputMods";
929  let ParserMethod = "parseRegOrImmWithIntInputMods";
930  let PredicateMethod = "isRegOrImmWithInt"#opSize#"InputMods";
931}
932def Int32InputModsMatchClass : IntInputModsMatchClass<32>;
933def Int64InputModsMatchClass : IntInputModsMatchClass<64>;
934
935class IntInputMods <IntInputModsMatchClass matchClass> : InputMods <matchClass> {
936  let PrintMethod = "printOperandAndIntInputMods";
937}
938def Int32InputMods : IntInputMods<Int32InputModsMatchClass>;
939def Int64InputMods : IntInputMods<Int64InputModsMatchClass>;
940
941class OpSelModsMatchClass : AsmOperandClass {
942  let Name = "OpSelMods";
943  let ParserMethod = "parseRegOrImm";
944  let PredicateMethod = "isRegOrImm";
945}
946
947def IntOpSelModsMatchClass : OpSelModsMatchClass;
948def IntOpSelMods : InputMods<IntOpSelModsMatchClass>;
949
950class FPSDWAInputModsMatchClass <int opSize> : AsmOperandClass {
951  let Name = "SDWAWithFP"#opSize#"InputMods";
952  let ParserMethod = "parseRegOrImmWithFPInputMods";
953  let PredicateMethod = "isSDWAFP"#opSize#"Operand";
954}
955
956def FP16SDWAInputModsMatchClass : FPSDWAInputModsMatchClass<16>;
957def FP32SDWAInputModsMatchClass : FPSDWAInputModsMatchClass<32>;
958
959class FPSDWAInputMods <FPSDWAInputModsMatchClass matchClass> :
960  InputMods <matchClass> {
961  let PrintMethod = "printOperandAndFPInputMods";
962}
963
964def FP16SDWAInputMods : FPSDWAInputMods<FP16SDWAInputModsMatchClass>;
965def FP32SDWAInputMods : FPSDWAInputMods<FP32SDWAInputModsMatchClass>;
966
967def FPVRegInputModsMatchClass : AsmOperandClass {
968  let Name = "VRegWithFPInputMods";
969  let ParserMethod = "parseRegWithFPInputMods";
970  let PredicateMethod = "isVReg32";
971}
972
973def FPVRegInputMods : InputMods <FPVRegInputModsMatchClass> {
974  let PrintMethod = "printOperandAndFPInputMods";
975}
976
977class IntSDWAInputModsMatchClass <int opSize> : AsmOperandClass {
978  let Name = "SDWAWithInt"#opSize#"InputMods";
979  let ParserMethod = "parseRegOrImmWithIntInputMods";
980  let PredicateMethod = "isSDWAInt"#opSize#"Operand";
981}
982
983def Int16SDWAInputModsMatchClass : IntSDWAInputModsMatchClass<16>;
984def Int32SDWAInputModsMatchClass : IntSDWAInputModsMatchClass<32>;
985
986class IntSDWAInputMods <IntSDWAInputModsMatchClass matchClass> :
987  InputMods <matchClass> {
988  let PrintMethod = "printOperandAndIntInputMods";
989}
990
991def Int16SDWAInputMods : IntSDWAInputMods<Int16SDWAInputModsMatchClass>;
992def Int32SDWAInputMods : IntSDWAInputMods<Int32SDWAInputModsMatchClass>;
993
994def IntVRegInputModsMatchClass : AsmOperandClass {
995  let Name = "VRegWithIntInputMods";
996  let ParserMethod = "parseRegWithIntInputMods";
997  let PredicateMethod = "isVReg32";
998}
999
1000def IntVRegInputMods : InputMods <IntVRegInputModsMatchClass> {
1001  let PrintMethod = "printOperandAndIntInputMods";
1002}
1003
1004class PackedFPInputModsMatchClass <int opSize> : AsmOperandClass {
1005  let Name = "PackedFP"#opSize#"InputMods";
1006  let ParserMethod = "parseRegOrImm";
1007  let PredicateMethod = "isRegOrImm";
1008//  let PredicateMethod = "isPackedFP"#opSize#"InputMods";
1009}
1010
1011class PackedIntInputModsMatchClass <int opSize> : AsmOperandClass {
1012  let Name = "PackedInt"#opSize#"InputMods";
1013  let ParserMethod = "parseRegOrImm";
1014  let PredicateMethod = "isRegOrImm";
1015//  let PredicateMethod = "isPackedInt"#opSize#"InputMods";
1016}
1017
1018def PackedF16InputModsMatchClass : PackedFPInputModsMatchClass<16>;
1019def PackedI16InputModsMatchClass : PackedIntInputModsMatchClass<16>;
1020
1021class PackedFPInputMods <PackedFPInputModsMatchClass matchClass> : InputMods <matchClass> {
1022//  let PrintMethod = "printPackedFPInputMods";
1023}
1024
1025class PackedIntInputMods <PackedIntInputModsMatchClass matchClass> : InputMods <matchClass> {
1026  //let PrintMethod = "printPackedIntInputMods";
1027}
1028
1029def PackedF16InputMods : PackedFPInputMods<PackedF16InputModsMatchClass>;
1030def PackedI16InputMods : PackedIntInputMods<PackedI16InputModsMatchClass>;
1031
1032//===----------------------------------------------------------------------===//
1033// Complex patterns
1034//===----------------------------------------------------------------------===//
1035
1036def DS1Addr1Offset : ComplexPattern<i32, 2, "SelectDS1Addr1Offset">;
1037def DS64Bit4ByteAligned : ComplexPattern<i32, 3, "SelectDS64Bit4ByteAligned">;
1038
1039def MOVRELOffset : ComplexPattern<i32, 2, "SelectMOVRELOffset">;
1040
1041def VOP3Mods0 : ComplexPattern<untyped, 4, "SelectVOP3Mods0">;
1042def VOP3Mods0Clamp : ComplexPattern<untyped, 3, "SelectVOP3Mods0Clamp">;
1043def VOP3Mods0Clamp0OMod : ComplexPattern<untyped, 4, "SelectVOP3Mods0Clamp0OMod">;
1044def VOP3Mods  : ComplexPattern<untyped, 2, "SelectVOP3Mods">;
1045def VOP3NoMods : ComplexPattern<untyped, 1, "SelectVOP3NoMods">;
1046// VOP3Mods, but the input source is known to never be NaN.
1047def VOP3Mods_nnan : ComplexPattern<fAny, 2, "SelectVOP3Mods_NNaN">;
1048
1049def VOP3OMods : ComplexPattern<untyped, 3, "SelectVOP3OMods">;
1050
1051def VOP3PMods  : ComplexPattern<untyped, 2, "SelectVOP3PMods">;
1052def VOP3PMods0 : ComplexPattern<untyped, 3, "SelectVOP3PMods0">;
1053
1054def VOP3OpSel  : ComplexPattern<untyped, 2, "SelectVOP3OpSel">;
1055def VOP3OpSel0 : ComplexPattern<untyped, 3, "SelectVOP3OpSel0">;
1056
1057def VOP3OpSelMods  : ComplexPattern<untyped, 2, "SelectVOP3OpSelMods">;
1058def VOP3OpSelMods0 : ComplexPattern<untyped, 3, "SelectVOP3OpSelMods0">;
1059
1060def VOP3PMadMixMods  : ComplexPattern<untyped, 2, "SelectVOP3PMadMixMods">;
1061
1062
1063def Hi16Elt  : ComplexPattern<untyped, 1, "SelectHi16Elt">;
1064
1065//===----------------------------------------------------------------------===//
1066// SI assembler operands
1067//===----------------------------------------------------------------------===//
1068
1069def SIOperand {
1070  int ZERO = 0x80;
1071  int VCC = 0x6A;
1072  int FLAT_SCR = 0x68;
1073}
1074
1075// This should be kept in sync with SISrcMods enum
1076def SRCMODS {
1077  int NONE = 0;
1078  int NEG = 1;
1079  int ABS = 2;
1080  int NEG_ABS = 3;
1081
1082  int NEG_HI = ABS;
1083  int OP_SEL_0 = 4;
1084  int OP_SEL_1 = 8;
1085  int DST_OP_SEL = 8;
1086}
1087
1088def DSTCLAMP {
1089  int NONE = 0;
1090  int ENABLE = 1;
1091}
1092
1093def DSTOMOD {
1094  int NONE = 0;
1095}
1096
1097def TRAPID{
1098  int LLVM_TRAP = 2;
1099  int LLVM_DEBUG_TRAP = 3;
1100}
1101
1102//===----------------------------------------------------------------------===//
1103//
1104// SI Instruction multiclass helpers.
1105//
1106// Instructions with _32 take 32-bit operands.
1107// Instructions with _64 take 64-bit operands.
1108//
1109// VOP_* instructions can use either a 32-bit or 64-bit encoding.  The 32-bit
1110// encoding is the standard encoding, but instruction that make use of
1111// any of the instruction modifiers must use the 64-bit encoding.
1112//
1113// Instructions with _e32 use the 32-bit encoding.
1114// Instructions with _e64 use the 64-bit encoding.
1115//
1116//===----------------------------------------------------------------------===//
1117
1118class SIMCInstr <string pseudo, int subtarget> {
1119  string PseudoInstr = pseudo;
1120  int Subtarget = subtarget;
1121}
1122
1123//===----------------------------------------------------------------------===//
1124// EXP classes
1125//===----------------------------------------------------------------------===//
1126
1127class EXP_Helper<bit done, SDPatternOperator node = null_frag> : EXPCommon<
1128  (outs),
1129  (ins exp_tgt:$tgt,
1130       ExpSrc0:$src0, ExpSrc1:$src1, ExpSrc2:$src2, ExpSrc3:$src3,
1131       exp_vm:$vm, exp_compr:$compr, i8imm:$en),
1132  "exp$tgt $src0, $src1, $src2, $src3"#!if(done, " done", "")#"$compr$vm",
1133  [(node (i8 timm:$tgt), (i8 timm:$en),
1134         f32:$src0, f32:$src1, f32:$src2, f32:$src3,
1135         (i1 timm:$compr), (i1 timm:$vm))]> {
1136  let AsmMatchConverter = "cvtExp";
1137}
1138
1139// Split EXP instruction into EXP and EXP_DONE so we can set
1140// mayLoad for done=1.
1141multiclass EXP_m<bit done, SDPatternOperator node> {
1142  let mayLoad = done, DisableWQM = 1 in {
1143    let isPseudo = 1, isCodeGenOnly = 1 in {
1144      def "" : EXP_Helper<done, node>,
1145               SIMCInstr <"exp"#!if(done, "_done", ""), SIEncodingFamily.NONE>;
1146    }
1147
1148    let done = done in {
1149      def _si : EXP_Helper<done>,
1150                SIMCInstr <"exp"#!if(done, "_done", ""), SIEncodingFamily.SI>,
1151                EXPe {
1152        let AssemblerPredicates = [isSICI];
1153        let DecoderNamespace = "SICI";
1154        let DisableDecoder = DisableSIDecoder;
1155      }
1156
1157      def _vi : EXP_Helper<done>,
1158                SIMCInstr <"exp"#!if(done, "_done", ""), SIEncodingFamily.VI>,
1159                EXPe_vi {
1160        let AssemblerPredicates = [isVI];
1161        let DecoderNamespace = "VI";
1162        let DisableDecoder = DisableVIDecoder;
1163      }
1164    }
1165  }
1166}
1167
1168//===----------------------------------------------------------------------===//
1169// Vector ALU classes
1170//===----------------------------------------------------------------------===//
1171
1172class getNumSrcArgs<ValueType Src0, ValueType Src1, ValueType Src2> {
1173  int ret =
1174    !if (!eq(Src0.Value, untyped.Value),      0,
1175      !if (!eq(Src1.Value, untyped.Value),    1,   // VOP1
1176         !if (!eq(Src2.Value, untyped.Value), 2,   // VOP2
1177                                              3))); // VOP3
1178}
1179
1180// Returns the register class to use for the destination of VOP[123C]
1181// instructions for the given VT.
1182class getVALUDstForVT<ValueType VT> {
1183  RegisterOperand ret = !if(!eq(VT.Size, 32), VOPDstOperand<VGPR_32>,
1184                          !if(!eq(VT.Size, 128), VOPDstOperand<VReg_128>,
1185                            !if(!eq(VT.Size, 64), VOPDstOperand<VReg_64>,
1186                              !if(!eq(VT.Size, 16), VOPDstOperand<VGPR_32>,
1187                              VOPDstOperand<SReg_64>)))); // else VT == i1
1188}
1189
1190// Returns the register class to use for the destination of VOP[12C]
1191// instructions with SDWA extension
1192class getSDWADstForVT<ValueType VT> {
1193  RegisterOperand ret = !if(!eq(VT.Size, 1),
1194                            SDWAVopcDst, // VOPC
1195                            VOPDstOperand<VGPR_32>); // VOP1/2 32-bit dst
1196}
1197
1198// Returns the register class to use for source 0 of VOP[12C]
1199// instructions for the given VT.
1200class getVOPSrc0ForVT<ValueType VT> {
1201  bit isFP = !if(!eq(VT.Value, f16.Value), 1,
1202             !if(!eq(VT.Value, v2f16.Value), 1,
1203             !if(!eq(VT.Value, f32.Value), 1,
1204             !if(!eq(VT.Value, f64.Value), 1,
1205             0))));
1206
1207  RegisterOperand ret =
1208    !if(isFP,
1209      !if(!eq(VT.Size, 64),
1210         VSrc_f64,
1211         !if(!eq(VT.Value, f16.Value),
1212            VSrc_f16,
1213            !if(!eq(VT.Value, v2f16.Value),
1214               VCSrc_v2f16,
1215               VSrc_f32
1216            )
1217         )
1218       ),
1219       !if(!eq(VT.Size, 64),
1220          VSrc_b64,
1221          !if(!eq(VT.Value, i16.Value),
1222             VSrc_b16,
1223             !if(!eq(VT.Value, v2i16.Value),
1224                VCSrc_v2b16,
1225                VSrc_b32
1226             )
1227          )
1228       )
1229    );
1230}
1231
1232// Returns the vreg register class to use for source operand given VT
1233class getVregSrcForVT<ValueType VT> {
1234  RegisterClass ret = !if(!eq(VT.Size, 128), VReg_128,
1235                        !if(!eq(VT.Size, 64), VReg_64, VGPR_32));
1236}
1237
1238class getSDWASrcForVT <ValueType VT> {
1239  bit isFP = !if(!eq(VT.Value, f16.Value), 1,
1240             !if(!eq(VT.Value, f32.Value), 1,
1241             0));
1242  RegisterOperand retFlt = !if(!eq(VT.Size, 16), SDWASrc_f16, SDWASrc_f32);
1243  RegisterOperand retInt = !if(!eq(VT.Size, 16), SDWASrc_i16, SDWASrc_i32);
1244  RegisterOperand ret = !if(isFP, retFlt, retInt);
1245}
1246
1247// Returns the register class to use for sources of VOP3 instructions for the
1248// given VT.
1249class getVOP3SrcForVT<ValueType VT> {
1250  bit isFP = !if(!eq(VT.Value, f16.Value), 1,
1251             !if(!eq(VT.Value, v2f16.Value), 1,
1252             !if(!eq(VT.Value, f32.Value), 1,
1253             !if(!eq(VT.Value, f64.Value), 1,
1254             0))));
1255  RegisterOperand ret =
1256  !if(!eq(VT.Size, 128),
1257     VSrc_128,
1258     !if(!eq(VT.Size, 64),
1259        !if(isFP,
1260           VCSrc_f64,
1261           VCSrc_b64),
1262        !if(!eq(VT.Value, i1.Value),
1263           SCSrc_i1,
1264           !if(isFP,
1265              !if(!eq(VT.Value, f16.Value),
1266                 VCSrc_f16,
1267                 !if(!eq(VT.Value, v2f16.Value),
1268                    VCSrc_v2f16,
1269                    VCSrc_f32
1270                 )
1271              ),
1272              !if(!eq(VT.Value, i16.Value),
1273                 VCSrc_b16,
1274                 !if(!eq(VT.Value, v2i16.Value),
1275                    VCSrc_v2b16,
1276                    VCSrc_b32
1277                 )
1278              )
1279           )
1280        )
1281     )
1282  );
1283}
1284
1285// Float or packed int
1286class isModifierType<ValueType SrcVT> {
1287  bit ret =
1288    !if(!eq(SrcVT.Value, f16.Value), 1,
1289    !if(!eq(SrcVT.Value, f32.Value), 1,
1290    !if(!eq(SrcVT.Value, f64.Value), 1,
1291    !if(!eq(SrcVT.Value, v2f16.Value), 1,
1292    !if(!eq(SrcVT.Value, v2i16.Value), 1,
1293    0)))));
1294}
1295
1296// Return type of input modifiers operand for specified input operand
1297class getSrcMod <ValueType VT, bit EnableF32SrcMods> {
1298  bit isFP = !if(!eq(VT.Value, f16.Value), 1,
1299               !if(!eq(VT.Value, f32.Value), 1,
1300               !if(!eq(VT.Value, f64.Value), 1,
1301               0)));
1302  bit isPacked = isPackedType<VT>.ret;
1303  Operand ret =  !if(!eq(VT.Size, 64),
1304                     !if(isFP, FP64InputMods, Int64InputMods),
1305                       !if(isFP,
1306                         !if(!eq(VT.Value, f16.Value),
1307                            FP16InputMods,
1308                            FP32InputMods
1309                          ),
1310                         !if(EnableF32SrcMods, FP32InputMods, Int32InputMods))
1311                     );
1312}
1313
1314class getOpSelMod <ValueType VT> {
1315  Operand ret = !if(!eq(VT.Value, f16.Value), FP16InputMods, IntOpSelMods);
1316}
1317
1318// Return type of input modifiers operand specified input operand for DPP
1319class getSrcModExt <ValueType VT> {
1320    bit isFP = !if(!eq(VT.Value, f16.Value), 1,
1321               !if(!eq(VT.Value, f32.Value), 1,
1322               !if(!eq(VT.Value, f64.Value), 1,
1323               0)));
1324  Operand ret = !if(isFP, FPVRegInputMods, IntVRegInputMods);
1325}
1326
1327// Return type of input modifiers operand specified input operand for SDWA
1328class getSrcModSDWA <ValueType VT> {
1329  Operand ret = !if(!eq(VT.Value, f16.Value), FP16SDWAInputMods,
1330                !if(!eq(VT.Value, f32.Value), FP32SDWAInputMods,
1331                !if(!eq(VT.Value, i16.Value), Int16SDWAInputMods,
1332                Int32SDWAInputMods)));
1333}
1334
1335// Returns the input arguments for VOP[12C] instructions for the given SrcVT.
1336class getIns32 <RegisterOperand Src0RC, RegisterClass Src1RC, int NumSrcArgs> {
1337  dag ret = !if(!eq(NumSrcArgs, 1), (ins Src0RC:$src0),               // VOP1
1338            !if(!eq(NumSrcArgs, 2), (ins Src0RC:$src0, Src1RC:$src1), // VOP2
1339                                    (ins)));
1340}
1341
1342// Returns the input arguments for VOP3 instructions for the given SrcVT.
1343class getIns64 <RegisterOperand Src0RC, RegisterOperand Src1RC,
1344                RegisterOperand Src2RC, int NumSrcArgs,
1345                bit HasIntClamp, bit HasModifiers, bit HasSrc2Mods, bit HasOMod,
1346                Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> {
1347
1348  dag ret =
1349    !if (!eq(NumSrcArgs, 0),
1350      // VOP1 without input operands (V_NOP, V_CLREXCP)
1351      (ins),
1352      /* else */
1353    !if (!eq(NumSrcArgs, 1),
1354      !if (!eq(HasModifiers, 1),
1355        // VOP1 with modifiers
1356        (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1357             clampmod:$clamp, omod:$omod)
1358      /* else */,
1359        // VOP1 without modifiers
1360        !if (!eq(HasIntClamp, 1),
1361          (ins Src0RC:$src0, clampmod:$clamp),
1362          (ins Src0RC:$src0))
1363      /* endif */ ),
1364    !if (!eq(NumSrcArgs, 2),
1365      !if (!eq(HasModifiers, 1),
1366        // VOP 2 with modifiers
1367        !if( !eq(HasOMod, 1),
1368          (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1369               Src1Mod:$src1_modifiers, Src1RC:$src1,
1370               clampmod:$clamp, omod:$omod),
1371           (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1372               Src1Mod:$src1_modifiers, Src1RC:$src1,
1373               clampmod:$clamp))
1374      /* else */,
1375        // VOP2 without modifiers
1376        !if (!eq(HasIntClamp, 1),
1377          (ins Src0RC:$src0, Src1RC:$src1, clampmod:$clamp),
1378          (ins Src0RC:$src0, Src1RC:$src1))
1379
1380      /* endif */ )
1381    /* NumSrcArgs == 3 */,
1382      !if (!eq(HasModifiers, 1),
1383        !if (!eq(HasSrc2Mods, 1),
1384          // VOP3 with modifiers
1385          !if (!eq(HasOMod, 1),
1386            (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1387                 Src1Mod:$src1_modifiers, Src1RC:$src1,
1388                 Src2Mod:$src2_modifiers, Src2RC:$src2,
1389                 clampmod:$clamp, omod:$omod),
1390            !if (!eq(HasIntClamp, 1),
1391              (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1392                   Src1Mod:$src1_modifiers, Src1RC:$src1,
1393                   Src2Mod:$src2_modifiers, Src2RC:$src2,
1394                   clampmod:$clamp),
1395              (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1396                   Src1Mod:$src1_modifiers, Src1RC:$src1,
1397                   Src2Mod:$src2_modifiers, Src2RC:$src2))),
1398          // VOP3 with modifiers except src2
1399          !if (!eq(HasOMod, 1),
1400            (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1401                 Src1Mod:$src1_modifiers, Src1RC:$src1,
1402                 Src2RC:$src2, clampmod:$clamp, omod:$omod),
1403            !if (!eq(HasIntClamp, 1),
1404              (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1405                   Src1Mod:$src1_modifiers, Src1RC:$src1,
1406                   Src2RC:$src2, clampmod:$clamp),
1407              (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1408                   Src1Mod:$src1_modifiers, Src1RC:$src1,
1409                   Src2RC:$src2))))
1410      /* else */,
1411        // VOP3 without modifiers
1412        !if (!eq(HasIntClamp, 1),
1413          (ins Src0RC:$src0, Src1RC:$src1, Src2RC:$src2, clampmod:$clamp),
1414          (ins Src0RC:$src0, Src1RC:$src1, Src2RC:$src2))
1415      /* endif */ ))));
1416}
1417
1418/// XXX - src1 may only allow VGPRs?
1419
1420// The modifiers (except clamp) are dummy operands for the benefit of
1421// printing and parsing. They defer their values to looking at the
1422// srcN_modifiers for what to print.
1423class getInsVOP3P <RegisterOperand Src0RC, RegisterOperand Src1RC,
1424                   RegisterOperand Src2RC, int NumSrcArgs,
1425                   bit HasClamp,
1426                   Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> {
1427  dag ret = !if (!eq(NumSrcArgs, 2),
1428    !if (HasClamp,
1429      (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1430           Src1Mod:$src1_modifiers, Src1RC:$src1,
1431           clampmod:$clamp,
1432           op_sel:$op_sel, op_sel_hi:$op_sel_hi,
1433           neg_lo:$neg_lo, neg_hi:$neg_hi),
1434      (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1435           Src1Mod:$src1_modifiers, Src1RC:$src1,
1436           op_sel:$op_sel, op_sel_hi:$op_sel_hi,
1437           neg_lo:$neg_lo, neg_hi:$neg_hi)),
1438    // else NumSrcArgs == 3
1439    !if (HasClamp,
1440      (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1441           Src1Mod:$src1_modifiers, Src1RC:$src1,
1442           Src2Mod:$src2_modifiers, Src2RC:$src2,
1443           clampmod:$clamp,
1444           op_sel:$op_sel, op_sel_hi:$op_sel_hi,
1445           neg_lo:$neg_lo, neg_hi:$neg_hi),
1446      (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1447           Src1Mod:$src1_modifiers, Src1RC:$src1,
1448           Src2Mod:$src2_modifiers, Src2RC:$src2,
1449           op_sel:$op_sel, op_sel_hi:$op_sel_hi,
1450           neg_lo:$neg_lo, neg_hi:$neg_hi))
1451  );
1452}
1453
1454class getInsVOP3OpSel <RegisterOperand Src0RC,
1455                       RegisterOperand Src1RC,
1456                       RegisterOperand Src2RC,
1457                       int NumSrcArgs,
1458                       bit HasClamp,
1459                       Operand Src0Mod,
1460                       Operand Src1Mod,
1461                       Operand Src2Mod> {
1462  dag ret = !if (!eq(NumSrcArgs, 2),
1463    !if (HasClamp,
1464      (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1465           Src1Mod:$src1_modifiers, Src1RC:$src1,
1466           clampmod:$clamp,
1467           op_sel:$op_sel),
1468      (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1469           Src1Mod:$src1_modifiers, Src1RC:$src1,
1470           op_sel:$op_sel)),
1471    // else NumSrcArgs == 3
1472    !if (HasClamp,
1473      (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1474           Src1Mod:$src1_modifiers, Src1RC:$src1,
1475           Src2Mod:$src2_modifiers, Src2RC:$src2,
1476           clampmod:$clamp,
1477           op_sel:$op_sel),
1478      (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1479           Src1Mod:$src1_modifiers, Src1RC:$src1,
1480           Src2Mod:$src2_modifiers, Src2RC:$src2,
1481           op_sel:$op_sel))
1482  );
1483}
1484
1485class getInsDPP <RegisterOperand DstRC, RegisterClass Src0RC, RegisterClass Src1RC,
1486                 int NumSrcArgs, bit HasModifiers,
1487                 Operand Src0Mod, Operand Src1Mod> {
1488
1489  dag ret = !if (!eq(NumSrcArgs, 0),
1490                // VOP1 without input operands (V_NOP)
1491                (ins dpp_ctrl:$dpp_ctrl, row_mask:$row_mask,
1492                     bank_mask:$bank_mask, bound_ctrl:$bound_ctrl),
1493            !if (!eq(NumSrcArgs, 1),
1494              !if (!eq(HasModifiers, 1),
1495                // VOP1_DPP with modifiers
1496                (ins DstRC:$old, Src0Mod:$src0_modifiers,
1497                     Src0RC:$src0, dpp_ctrl:$dpp_ctrl, row_mask:$row_mask,
1498                     bank_mask:$bank_mask, bound_ctrl:$bound_ctrl)
1499              /* else */,
1500                // VOP1_DPP without modifiers
1501                (ins DstRC:$old, Src0RC:$src0,
1502                     dpp_ctrl:$dpp_ctrl, row_mask:$row_mask,
1503                     bank_mask:$bank_mask, bound_ctrl:$bound_ctrl)
1504              /* endif */)
1505              /* NumSrcArgs == 2 */,
1506              !if (!eq(HasModifiers, 1),
1507                // VOP2_DPP with modifiers
1508                (ins DstRC:$old,
1509                     Src0Mod:$src0_modifiers, Src0RC:$src0,
1510                     Src1Mod:$src1_modifiers, Src1RC:$src1,
1511                     dpp_ctrl:$dpp_ctrl, row_mask:$row_mask,
1512                     bank_mask:$bank_mask, bound_ctrl:$bound_ctrl)
1513              /* else */,
1514                // VOP2_DPP without modifiers
1515                (ins DstRC:$old,
1516                     Src0RC:$src0, Src1RC:$src1, dpp_ctrl:$dpp_ctrl,
1517                     row_mask:$row_mask, bank_mask:$bank_mask,
1518                     bound_ctrl:$bound_ctrl)
1519             /* endif */)));
1520}
1521
1522
1523
1524// Ins for SDWA
1525class getInsSDWA <RegisterOperand Src0RC, RegisterOperand Src1RC, int NumSrcArgs,
1526                  bit HasSDWAOMod, Operand Src0Mod, Operand Src1Mod,
1527                  ValueType DstVT> {
1528
1529  dag ret = !if(!eq(NumSrcArgs, 0),
1530               // VOP1 without input operands (V_NOP)
1531               (ins),
1532            !if(!eq(NumSrcArgs, 1),
1533               // VOP1
1534               !if(!eq(HasSDWAOMod, 0),
1535                  // VOP1_SDWA without omod
1536                  (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1537                       clampmod:$clamp,
1538                       dst_sel:$dst_sel, dst_unused:$dst_unused,
1539                       src0_sel:$src0_sel),
1540                  // VOP1_SDWA with omod
1541                  (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1542                       clampmod:$clamp, omod:$omod,
1543                       dst_sel:$dst_sel, dst_unused:$dst_unused,
1544                       src0_sel:$src0_sel)),
1545            !if(!eq(NumSrcArgs, 2),
1546               !if(!eq(DstVT.Size, 1),
1547                  // VOPC_SDWA
1548                  (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1549                       Src1Mod:$src1_modifiers, Src1RC:$src1,
1550                       clampmod:$clamp, src0_sel:$src0_sel, src1_sel:$src1_sel),
1551                  // VOP2_SDWA
1552                  !if(!eq(HasSDWAOMod, 0),
1553                     // VOP2_SDWA without omod
1554                     (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1555                          Src1Mod:$src1_modifiers, Src1RC:$src1,
1556                          clampmod:$clamp,
1557                          dst_sel:$dst_sel, dst_unused:$dst_unused,
1558                          src0_sel:$src0_sel, src1_sel:$src1_sel),
1559                     // VOP2_SDWA with omod
1560                     (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1561                          Src1Mod:$src1_modifiers, Src1RC:$src1,
1562                          clampmod:$clamp, omod:$omod,
1563                          dst_sel:$dst_sel, dst_unused:$dst_unused,
1564                          src0_sel:$src0_sel, src1_sel:$src1_sel))),
1565            (ins)/* endif */)));
1566}
1567
1568// Outs for DPP and SDWA
1569class getOutsExt <bit HasDst, ValueType DstVT, RegisterOperand DstRCExt> {
1570  dag ret = !if(HasDst,
1571                !if(!eq(DstVT.Size, 1),
1572                    (outs), // no dst for VOPC, we use "vcc"-token as dst in SDWA VOPC instructions
1573                    (outs DstRCExt:$vdst)),
1574                (outs)); // V_NOP
1575}
1576
1577// Outs for SDWA
1578class getOutsSDWA <bit HasDst, ValueType DstVT, RegisterOperand DstRCSDWA> {
1579  dag ret = !if(HasDst,
1580                !if(!eq(DstVT.Size, 1),
1581                    (outs DstRCSDWA:$sdst),
1582                    (outs DstRCSDWA:$vdst)),
1583                (outs)); // V_NOP
1584}
1585
1586// Returns the assembly string for the inputs and outputs of a VOP[12C]
1587// instruction.  This does not add the _e32 suffix, so it can be reused
1588// by getAsm64.
1589class getAsm32 <bit HasDst, int NumSrcArgs, ValueType DstVT = i32> {
1590  string dst = !if(!eq(DstVT.Size, 1), "$sdst", "$vdst"); // use $sdst for VOPC
1591  string src0 = ", $src0";
1592  string src1 = ", $src1";
1593  string src2 = ", $src2";
1594  string ret = !if(HasDst, dst, "") #
1595               !if(!eq(NumSrcArgs, 1), src0, "") #
1596               !if(!eq(NumSrcArgs, 2), src0#src1, "") #
1597               !if(!eq(NumSrcArgs, 3), src0#src1#src2, "");
1598}
1599
1600// Returns the assembly string for the inputs and outputs of a VOP3
1601// instruction.
1602class getAsm64 <bit HasDst, int NumSrcArgs, bit HasIntClamp, bit HasModifiers,
1603                bit HasOMod, ValueType DstVT = i32> {
1604  string dst = !if(!eq(DstVT.Size, 1), "$sdst", "$vdst"); // use $sdst for VOPC
1605  string src0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,");
1606  string src1 = !if(!eq(NumSrcArgs, 1), "",
1607                   !if(!eq(NumSrcArgs, 2), " $src1_modifiers",
1608                                           " $src1_modifiers,"));
1609  string src2 = !if(!eq(NumSrcArgs, 3), " $src2_modifiers", "");
1610  string iclamp = !if(HasIntClamp, "$clamp", "");
1611  string ret =
1612  !if(!eq(HasModifiers, 0),
1613      getAsm32<HasDst, NumSrcArgs, DstVT>.ret # iclamp,
1614      dst#", "#src0#src1#src2#"$clamp"#!if(HasOMod, "$omod", ""));
1615}
1616
1617// Returns the assembly string for the inputs and outputs of a VOP3P
1618// instruction.
1619class getAsmVOP3P <bit HasDst, int NumSrcArgs, bit HasModifiers,
1620                   bit HasClamp, ValueType DstVT = i32> {
1621  string dst = " $vdst";
1622  string src0 = !if(!eq(NumSrcArgs, 1), "$src0", "$src0,");
1623  string src1 = !if(!eq(NumSrcArgs, 1), "",
1624                   !if(!eq(NumSrcArgs, 2), " $src1",
1625                                           " $src1,"));
1626  string src2 = !if(!eq(NumSrcArgs, 3), " $src2", "");
1627
1628  string mods = !if(HasModifiers, "$neg_lo$neg_hi", "");
1629  string clamp = !if(HasClamp, "$clamp", "");
1630
1631  // Each modifier is printed as an array of bits for each operand, so
1632  // all operands are printed as part of src0_modifiers.
1633  string ret = dst#", "#src0#src1#src2#"$op_sel$op_sel_hi"#mods#clamp;
1634}
1635
1636class getAsmVOP3OpSel <int NumSrcArgs,
1637                       bit HasClamp,
1638                       bit Src0HasMods,
1639                       bit Src1HasMods,
1640                       bit Src2HasMods> {
1641  string dst = " $vdst";
1642
1643  string isrc0 = !if(!eq(NumSrcArgs, 1), "$src0", "$src0,");
1644  string isrc1 = !if(!eq(NumSrcArgs, 1), "",
1645                     !if(!eq(NumSrcArgs, 2), " $src1",
1646                                             " $src1,"));
1647  string isrc2 = !if(!eq(NumSrcArgs, 3), " $src2", "");
1648
1649  string fsrc0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,");
1650  string fsrc1 = !if(!eq(NumSrcArgs, 1), "",
1651                     !if(!eq(NumSrcArgs, 2), " $src1_modifiers",
1652                                             " $src1_modifiers,"));
1653  string fsrc2 = !if(!eq(NumSrcArgs, 3), " $src2_modifiers", "");
1654
1655  string src0 = !if(Src0HasMods, fsrc0, isrc0);
1656  string src1 = !if(Src1HasMods, fsrc1, isrc1);
1657  string src2 = !if(Src2HasMods, fsrc2, isrc2);
1658
1659  string clamp = !if(HasClamp, "$clamp", "");
1660
1661  string ret = dst#", "#src0#src1#src2#"$op_sel"#clamp;
1662}
1663
1664class getAsmDPP <bit HasDst, int NumSrcArgs, bit HasModifiers, ValueType DstVT = i32> {
1665  string dst = !if(HasDst,
1666                   !if(!eq(DstVT.Size, 1),
1667                       "$sdst",
1668                       "$vdst"),
1669                    ""); // use $sdst for VOPC
1670  string src0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,");
1671  string src1 = !if(!eq(NumSrcArgs, 1), "",
1672                   !if(!eq(NumSrcArgs, 2), " $src1_modifiers",
1673                                           " $src1_modifiers,"));
1674  string args = !if(!eq(HasModifiers, 0),
1675                     getAsm32<0, NumSrcArgs, DstVT>.ret,
1676                     ", "#src0#src1);
1677  string ret = dst#args#" $dpp_ctrl$row_mask$bank_mask$bound_ctrl";
1678}
1679
1680class getAsmSDWA <bit HasDst, int NumSrcArgs, ValueType DstVT = i32> {
1681  string dst = !if(HasDst,
1682                   !if(!eq(DstVT.Size, 1),
1683                       " vcc", // use vcc token as dst for VOPC instructioins
1684                       "$vdst"),
1685                    "");
1686  string src0 = "$src0_modifiers";
1687  string src1 = "$src1_modifiers";
1688  string args = !if(!eq(NumSrcArgs, 0),
1689                    "",
1690                    !if(!eq(NumSrcArgs, 1),
1691                        ", "#src0#"$clamp",
1692                        ", "#src0#", "#src1#"$clamp"
1693                     )
1694                );
1695  string sdwa = !if(!eq(NumSrcArgs, 0),
1696                    "",
1697                    !if(!eq(NumSrcArgs, 1),
1698                        " $dst_sel $dst_unused $src0_sel",
1699                        !if(!eq(DstVT.Size, 1),
1700                            " $src0_sel $src1_sel", // No dst_sel and dst_unused for VOPC
1701                            " $dst_sel $dst_unused $src0_sel $src1_sel"
1702                        )
1703                    )
1704                );
1705  string ret = dst#args#sdwa;
1706}
1707
1708class getAsmSDWA9 <bit HasDst, bit HasOMod, int NumSrcArgs,
1709                   ValueType DstVT = i32> {
1710  string dst = !if(HasDst,
1711                   !if(!eq(DstVT.Size, 1),
1712                       "$sdst", // VOPC
1713                       "$vdst"), // VOP1/2
1714                    "");
1715  string src0 = "$src0_modifiers";
1716  string src1 = "$src1_modifiers";
1717  string out_mods = !if(!eq(HasOMod, 0), "$clamp", "$clamp$omod");
1718  string args = !if(!eq(NumSrcArgs, 0), "",
1719                    !if(!eq(NumSrcArgs, 1),
1720                        ", "#src0,
1721                        ", "#src0#", "#src1
1722                     )
1723                );
1724  string sdwa = !if(!eq(NumSrcArgs, 0), "",
1725                    !if(!eq(NumSrcArgs, 1),
1726                        out_mods#" $dst_sel $dst_unused $src0_sel",
1727                        !if(!eq(DstVT.Size, 1),
1728                            " $src0_sel $src1_sel", // No dst_sel, dst_unused and output modifiers for VOPC
1729                            out_mods#" $dst_sel $dst_unused $src0_sel $src1_sel"
1730                        )
1731                    )
1732                );
1733  string ret = dst#args#sdwa;
1734}
1735
1736
1737// Function that checks if instruction supports DPP and SDWA
1738class getHasExt <int NumSrcArgs, ValueType DstVT = i32, ValueType Src0VT = i32,
1739                 ValueType Src1VT = i32> {
1740  bit ret = !if(!eq(NumSrcArgs, 3),
1741                0, // NumSrcArgs == 3 - No DPP or SDWA for VOP3
1742                !if(!eq(DstVT.Size, 64),
1743                    0, // 64-bit dst - No DPP or SDWA for 64-bit operands
1744                    !if(!eq(Src0VT.Size, 64),
1745                        0, // 64-bit src0
1746                        !if(!eq(Src1VT.Size, 64),
1747                            0, // 64-bit src2
1748                            1
1749                        )
1750                    )
1751                )
1752            );
1753}
1754
1755class getHasDPP <int NumSrcArgs, ValueType DstVT = i32, ValueType Src0VT = i32,
1756                 ValueType Src1VT = i32> {
1757  bit ret = !if(!eq(NumSrcArgs, 0), 0,
1758                getHasExt<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret);
1759}
1760
1761class BitOr<bit a, bit b> {
1762  bit ret = !if(a, 1, !if(b, 1, 0));
1763}
1764
1765class BitAnd<bit a, bit b> {
1766  bit ret = !if(a, !if(b, 1, 0), 0);
1767}
1768
1769def PatGenMode {
1770  int NoPattern = 0;
1771  int Pattern   = 1;
1772}
1773
1774class VOPProfile <list<ValueType> _ArgVT, bit _EnableF32SrcMods = 0,
1775                  bit _EnableClamp = 0> {
1776
1777  field list<ValueType> ArgVT = _ArgVT;
1778  field bit EnableF32SrcMods = _EnableF32SrcMods;
1779  field bit EnableClamp = _EnableClamp;
1780
1781  field ValueType DstVT = ArgVT[0];
1782  field ValueType Src0VT = ArgVT[1];
1783  field ValueType Src1VT = ArgVT[2];
1784  field ValueType Src2VT = ArgVT[3];
1785  field RegisterOperand DstRC = getVALUDstForVT<DstVT>.ret;
1786  field RegisterOperand DstRCDPP = getVALUDstForVT<DstVT>.ret;
1787  field RegisterOperand DstRCSDWA = getSDWADstForVT<DstVT>.ret;
1788  field RegisterOperand Src0RC32 = getVOPSrc0ForVT<Src0VT>.ret;
1789  field RegisterClass Src1RC32 = getVregSrcForVT<Src1VT>.ret;
1790  field RegisterOperand Src0RC64 = getVOP3SrcForVT<Src0VT>.ret;
1791  field RegisterOperand Src1RC64 = getVOP3SrcForVT<Src1VT>.ret;
1792  field RegisterOperand Src2RC64 = getVOP3SrcForVT<Src2VT>.ret;
1793  field RegisterClass Src0DPP = getVregSrcForVT<Src0VT>.ret;
1794  field RegisterClass Src1DPP = getVregSrcForVT<Src1VT>.ret;
1795  field RegisterOperand Src0SDWA = getSDWASrcForVT<Src0VT>.ret;
1796  field RegisterOperand Src1SDWA = getSDWASrcForVT<Src0VT>.ret;
1797  field Operand Src0Mod = getSrcMod<Src0VT, EnableF32SrcMods>.ret;
1798  field Operand Src1Mod = getSrcMod<Src1VT, EnableF32SrcMods>.ret;
1799  field Operand Src2Mod = getSrcMod<Src2VT, EnableF32SrcMods>.ret;
1800  field Operand Src0ModDPP = getSrcModExt<Src0VT>.ret;
1801  field Operand Src1ModDPP = getSrcModExt<Src1VT>.ret;
1802  field Operand Src0ModSDWA = getSrcModSDWA<Src0VT>.ret;
1803  field Operand Src1ModSDWA = getSrcModSDWA<Src1VT>.ret;
1804
1805
1806  field bit HasDst = !if(!eq(DstVT.Value, untyped.Value), 0, 1);
1807  field bit HasDst32 = HasDst;
1808  field bit EmitDst = HasDst; // force dst encoding, see v_movreld_b32 special case
1809  field int NumSrcArgs = getNumSrcArgs<Src0VT, Src1VT, Src2VT>.ret;
1810  field bit HasSrc0 = !if(!eq(Src0VT.Value, untyped.Value), 0, 1);
1811  field bit HasSrc1 = !if(!eq(Src1VT.Value, untyped.Value), 0, 1);
1812  field bit HasSrc2 = !if(!eq(Src2VT.Value, untyped.Value), 0, 1);
1813
1814  // TODO: Modifiers logic is somewhat adhoc here, to be refined later
1815  // HasModifiers affects the normal and DPP encodings. We take note of EnableF32SrcMods, which
1816  // enables modifiers for i32 type.
1817  field bit HasModifiers = BitOr<isModifierType<Src0VT>.ret, EnableF32SrcMods>.ret;
1818
1819  // HasSrc*FloatMods affects the SDWA encoding. We ignore EnableF32SrcMods.
1820  field bit HasSrc0FloatMods = isFloatType<Src0VT>.ret;
1821  field bit HasSrc1FloatMods = isFloatType<Src1VT>.ret;
1822  field bit HasSrc2FloatMods = isFloatType<Src2VT>.ret;
1823
1824  // HasSrc*IntMods affects the SDWA encoding. We ignore EnableF32SrcMods.
1825  field bit HasSrc0IntMods = isIntType<Src0VT>.ret;
1826  field bit HasSrc1IntMods = isIntType<Src1VT>.ret;
1827  field bit HasSrc2IntMods = isIntType<Src2VT>.ret;
1828
1829  field bit HasSrc0Mods = HasModifiers;
1830  field bit HasSrc1Mods = !if(HasModifiers, BitOr<HasSrc1FloatMods, HasSrc1IntMods>.ret, 0);
1831  field bit HasSrc2Mods = !if(HasModifiers, BitOr<HasSrc2FloatMods, HasSrc2IntMods>.ret, 0);
1832
1833  field bit HasClamp = BitOr<isModifierType<Src0VT>.ret, EnableClamp>.ret;
1834  field bit HasSDWAClamp = EmitDst;
1835  field bit HasFPClamp = BitAnd<isFloatType<DstVT>.ret, HasClamp>.ret;
1836  field bit HasIntClamp = !if(isFloatType<DstVT>.ret, 0, HasClamp);
1837  field bit HasClampLo = HasClamp;
1838  field bit HasClampHi = BitAnd<isPackedType<DstVT>.ret, HasClamp>.ret;
1839  field bit HasHigh = 0;
1840
1841  field bit IsPacked = isPackedType<Src0VT>.ret;
1842  field bit HasOpSel = IsPacked;
1843  field bit HasOMod = !if(HasOpSel, 0, isFloatType<DstVT>.ret);
1844  field bit HasSDWAOMod = isFloatType<DstVT>.ret;
1845
1846  field bit HasExt = getHasExt<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret;
1847  field bit HasExtDPP = getHasDPP<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret;
1848  field bit HasExtSDWA = HasExt;
1849  field bit HasExtSDWA9 = HasExt;
1850  field int NeedPatGen = PatGenMode.NoPattern;
1851
1852  field Operand Src0PackedMod = !if(HasSrc0FloatMods, PackedF16InputMods, PackedI16InputMods);
1853  field Operand Src1PackedMod = !if(HasSrc1FloatMods, PackedF16InputMods, PackedI16InputMods);
1854  field Operand Src2PackedMod = !if(HasSrc2FloatMods, PackedF16InputMods, PackedI16InputMods);
1855
1856  field dag Outs = !if(HasDst,(outs DstRC:$vdst),(outs));
1857
1858  // VOP3b instructions are a special case with a second explicit
1859  // output. This is manually overridden for them.
1860  field dag Outs32 = Outs;
1861  field dag Outs64 = Outs;
1862  field dag OutsDPP = getOutsExt<HasDst, DstVT, DstRCDPP>.ret;
1863  field dag OutsSDWA = getOutsSDWA<HasDst, DstVT, DstRCSDWA>.ret;
1864
1865  field dag Ins32 = getIns32<Src0RC32, Src1RC32, NumSrcArgs>.ret;
1866  field dag Ins64 = getIns64<Src0RC64, Src1RC64, Src2RC64, NumSrcArgs,
1867                             HasIntClamp, HasModifiers, HasSrc2Mods,
1868                             HasOMod, Src0Mod, Src1Mod, Src2Mod>.ret;
1869  field dag InsVOP3P = getInsVOP3P<Src0RC64, Src1RC64, Src2RC64,
1870                                   NumSrcArgs, HasClamp,
1871                                   Src0PackedMod, Src1PackedMod, Src2PackedMod>.ret;
1872  field dag InsVOP3OpSel = getInsVOP3OpSel<Src0RC64, Src1RC64, Src2RC64,
1873                                           NumSrcArgs,
1874                                           HasClamp,
1875                                           getOpSelMod<Src0VT>.ret,
1876                                           getOpSelMod<Src1VT>.ret,
1877                                           getOpSelMod<Src2VT>.ret>.ret;
1878  field dag InsDPP = !if(HasExtDPP,
1879                         getInsDPP<DstRCDPP, Src0DPP, Src1DPP, NumSrcArgs,
1880                                   HasModifiers, Src0ModDPP, Src1ModDPP>.ret,
1881                         (ins));
1882  field dag InsSDWA = getInsSDWA<Src0SDWA, Src1SDWA, NumSrcArgs,
1883                                 HasSDWAOMod, Src0ModSDWA, Src1ModSDWA,
1884                                 DstVT>.ret;
1885
1886
1887  field string Asm32 = getAsm32<HasDst, NumSrcArgs, DstVT>.ret;
1888  field string Asm64 = getAsm64<HasDst, NumSrcArgs, HasIntClamp, HasModifiers, HasOMod, DstVT>.ret;
1889  field string AsmVOP3P = getAsmVOP3P<HasDst, NumSrcArgs, HasModifiers, HasClamp, DstVT>.ret;
1890  field string AsmVOP3OpSel = getAsmVOP3OpSel<NumSrcArgs,
1891                                              HasClamp,
1892                                              HasSrc0FloatMods,
1893                                              HasSrc1FloatMods,
1894                                              HasSrc2FloatMods>.ret;
1895  field string AsmDPP = !if(HasExtDPP,
1896                            getAsmDPP<HasDst, NumSrcArgs, HasModifiers, DstVT>.ret, "");
1897  field string AsmSDWA = getAsmSDWA<HasDst, NumSrcArgs, DstVT>.ret;
1898  field string AsmSDWA9 = getAsmSDWA9<HasDst, HasSDWAOMod, NumSrcArgs, DstVT>.ret;
1899}
1900
1901class VOP_NO_EXT <VOPProfile p> : VOPProfile <p.ArgVT> {
1902  let HasExt = 0;
1903  let HasExtDPP = 0;
1904  let HasExtSDWA = 0;
1905  let HasExtSDWA9 = 0;
1906}
1907
1908class VOP_PAT_GEN <VOPProfile p, int mode=PatGenMode.Pattern> : VOPProfile <p.ArgVT> {
1909  let NeedPatGen = mode;
1910}
1911
1912def VOP_F16_F16 : VOPProfile <[f16, f16, untyped, untyped]>;
1913def VOP_F16_I16 : VOPProfile <[f16, i16, untyped, untyped]>;
1914def VOP_I16_F16 : VOPProfile <[i16, f16, untyped, untyped]>;
1915
1916def VOP_F16_F16_F16 : VOPProfile <[f16, f16, f16, untyped]>;
1917def VOP_F16_F16_I16 : VOPProfile <[f16, f16, i16, untyped]>;
1918def VOP_F16_F16_I32 : VOPProfile <[f16, f16, i32, untyped]>;
1919def VOP_I16_I16_I16 : VOPProfile <[i16, i16, i16, untyped]>;
1920
1921def VOP_I16_I16_I16_I16 : VOPProfile <[i16, i16, i16, i16, untyped]>;
1922def VOP_F16_F16_F16_F16 : VOPProfile <[f16, f16, f16, f16, untyped]>;
1923
1924def VOP_I32_I16_I16_I32 : VOPProfile <[i32, i16, i16, i32, untyped]>;
1925
1926def VOP_V2F16_V2F16_V2F16 : VOPProfile <[v2f16, v2f16, v2f16, untyped]>;
1927def VOP_V2I16_V2I16_V2I16 : VOPProfile <[v2i16, v2i16, v2i16, untyped]>;
1928def VOP_B32_F16_F16 : VOPProfile <[i32, f16, f16, untyped]>;
1929
1930def VOP_V2F16_V2F16_V2F16_V2F16 : VOPProfile <[v2f16, v2f16, v2f16, v2f16]>;
1931def VOP_V2I16_V2I16_V2I16_V2I16 : VOPProfile <[v2i16, v2i16, v2i16, v2i16]>;
1932def VOP_V2I16_F32_F32 : VOPProfile <[v2i16, f32, f32, untyped]>;
1933def VOP_V2I16_I32_I32 : VOPProfile <[v2i16, i32, i32, untyped]>;
1934
1935def VOP_F32_V2F16_V2F16_V2F16 : VOPProfile <[f32, v2f16, v2f16, v2f16]>;
1936
1937def VOP_NONE : VOPProfile <[untyped, untyped, untyped, untyped]>;
1938
1939def VOP_F32_F32 : VOPProfile <[f32, f32, untyped, untyped]>;
1940def VOP_F32_F64 : VOPProfile <[f32, f64, untyped, untyped]>;
1941def VOP_F32_I32 : VOPProfile <[f32, i32, untyped, untyped]>;
1942def VOP_F64_F32 : VOPProfile <[f64, f32, untyped, untyped]>;
1943def VOP_F64_F64 : VOPProfile <[f64, f64, untyped, untyped]>;
1944def VOP_F64_I32 : VOPProfile <[f64, i32, untyped, untyped]>;
1945def VOP_I32_F32 : VOPProfile <[i32, f32, untyped, untyped]>;
1946def VOP_I32_F64 : VOPProfile <[i32, f64, untyped, untyped]>;
1947def VOP_I32_I32 : VOPProfile <[i32, i32, untyped, untyped]>;
1948def VOP_F16_F32 : VOPProfile <[f16, f32, untyped, untyped]>;
1949def VOP_F32_F16 : VOPProfile <[f32, f16, untyped, untyped]>;
1950
1951def VOP_F32_F32_F16 : VOPProfile <[f32, f32, f16, untyped]>;
1952def VOP_F32_F32_F32 : VOPProfile <[f32, f32, f32, untyped]>;
1953def VOP_F32_F32_I32 : VOPProfile <[f32, f32, i32, untyped]>;
1954def VOP_F64_F64_F64 : VOPProfile <[f64, f64, f64, untyped]>;
1955def VOP_F64_F64_I32 : VOPProfile <[f64, f64, i32, untyped]>;
1956def VOP_I32_F32_F32 : VOPProfile <[i32, f32, f32, untyped]>;
1957def VOP_I32_F32_I32 : VOPProfile <[i32, f32, i32, untyped]>;
1958def VOP_I32_I32_I32 : VOPProfile <[i32, i32, i32, untyped]>;
1959def VOP_I32_I32_I32_ARITH : VOPProfile <[i32, i32, i32, untyped], 0, /*EnableClamp=*/1>;
1960def VOP_V2F16_F32_F32 : VOPProfile <[v2f16, f32, f32, untyped]>;
1961def VOP_F32_F16_F16_F16 : VOPProfile <[f32, f16, f16, f16]>;
1962
1963def VOP_I64_I64_I32 : VOPProfile <[i64, i64, i32, untyped]>;
1964def VOP_I64_I32_I64 : VOPProfile <[i64, i32, i64, untyped]>;
1965def VOP_I64_I64_I64 : VOPProfile <[i64, i64, i64, untyped]>;
1966
1967def VOP_F16_F32_F16_F32 : VOPProfile <[f16, f32, f16, f32]>;
1968def VOP_F32_F32_F16_F16 : VOPProfile <[f32, f32, f16, f16]>;
1969def VOP_F32_F32_F32_F32 : VOPProfile <[f32, f32, f32, f32]>;
1970def VOP_F64_F64_F64_F64 : VOPProfile <[f64, f64, f64, f64]>;
1971def VOP_I32_I32_I32_I32 : VOPProfile <[i32, i32, i32, i32]>;
1972def VOP_I64_I32_I32_I64 : VOPProfile <[i64, i32, i32, i64]>;
1973def VOP_I32_F32_I32_I32 : VOPProfile <[i32, f32, i32, i32]>;
1974def VOP_I64_I64_I32_I64 : VOPProfile <[i64, i64, i32, i64]>;
1975def VOP_V4I32_I64_I32_V4I32 : VOPProfile <[v4i32, i64, i32, v4i32]>;
1976
1977def VOP_F32_V2F16_V2F16_F32 : VOPProfile <[f32, v2f16, v2f16, f32]>;
1978def VOP_I32_V2I16_V2I16_I32 : VOPProfile <[i32, v2i16, v2i16, i32]>;
1979
1980class Commutable_REV <string revOp, bit isOrig> {
1981  string RevOp = revOp;
1982  bit IsOrig = isOrig;
1983}
1984
1985class AtomicNoRet <string noRetOp, bit isRet> {
1986  string NoRetOp = noRetOp;
1987  bit IsRet = isRet;
1988}
1989
1990//===----------------------------------------------------------------------===//
1991// Interpolation opcodes
1992//===----------------------------------------------------------------------===//
1993
1994class VINTRPDstOperand <RegisterClass rc> : RegisterOperand <rc, "printVINTRPDst">;
1995
1996class VINTRP_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
1997  VINTRPCommon <outs, ins, "", pattern>,
1998  SIMCInstr<opName, SIEncodingFamily.NONE> {
1999  let isPseudo = 1;
2000  let isCodeGenOnly = 1;
2001}
2002
2003class VINTRP_Real_si <bits <2> op, string opName, dag outs, dag ins,
2004                      string asm> :
2005  VINTRPCommon <outs, ins, asm, []>,
2006  VINTRPe <op>,
2007  SIMCInstr<opName, SIEncodingFamily.SI> {
2008  let AssemblerPredicate = SIAssemblerPredicate;
2009  let DecoderNamespace = "SICI";
2010  let DisableDecoder = DisableSIDecoder;
2011}
2012
2013class VINTRP_Real_vi <bits <2> op, string opName, dag outs, dag ins,
2014                      string asm> :
2015  VINTRPCommon <outs, ins, asm, []>,
2016  VINTRPe_vi <op>,
2017  SIMCInstr<opName, SIEncodingFamily.VI> {
2018  let AssemblerPredicate = VIAssemblerPredicate;
2019  let DecoderNamespace = "VI";
2020  let DisableDecoder = DisableVIDecoder;
2021}
2022
2023multiclass VINTRP_m <bits <2> op, dag outs, dag ins, string asm,
2024                     list<dag> pattern = []> {
2025  def "" : VINTRP_Pseudo <NAME, outs, ins, pattern>;
2026
2027  def _si : VINTRP_Real_si <op, NAME, outs, ins, asm>;
2028
2029  def _vi : VINTRP_Real_vi <op, NAME, outs, ins, asm>;
2030}
2031
2032//===----------------------------------------------------------------------===//
2033// Vector instruction mappings
2034//===----------------------------------------------------------------------===//
2035
2036// Maps an opcode in e32 form to its e64 equivalent
2037def getVOPe64 : InstrMapping {
2038  let FilterClass = "VOP";
2039  let RowFields = ["OpName"];
2040  let ColFields = ["Size", "VOP3"];
2041  let KeyCol = ["4", "0"];
2042  let ValueCols = [["8", "1"]];
2043}
2044
2045// Maps an opcode in e64 form to its e32 equivalent
2046def getVOPe32 : InstrMapping {
2047  let FilterClass = "VOP";
2048  let RowFields = ["OpName"];
2049  let ColFields = ["Size", "VOP3"];
2050  let KeyCol = ["8", "1"];
2051  let ValueCols = [["4", "0"]];
2052}
2053
2054// Maps ordinary instructions to their SDWA counterparts
2055def getSDWAOp : InstrMapping {
2056  let FilterClass = "VOP";
2057  let RowFields = ["OpName"];
2058  let ColFields = ["AsmVariantName"];
2059  let KeyCol = ["Default"];
2060  let ValueCols = [["SDWA"]];
2061}
2062
2063// Maps SDWA instructions to their ordinary counterparts
2064def getBasicFromSDWAOp : InstrMapping {
2065  let FilterClass = "VOP";
2066  let RowFields = ["OpName"];
2067  let ColFields = ["AsmVariantName"];
2068  let KeyCol = ["SDWA"];
2069  let ValueCols = [["Default"]];
2070}
2071
2072// Maps ordinary instructions to their DPP counterparts
2073def getDPPOp32 : InstrMapping {
2074  let FilterClass = "VOP";
2075  let RowFields = ["OpName"];
2076  let ColFields = ["AsmVariantName"];
2077  let KeyCol = ["Default"];
2078  let ValueCols = [["DPP"]];
2079}
2080
2081// Maps an commuted opcode to its original version
2082def getCommuteOrig : InstrMapping {
2083  let FilterClass = "Commutable_REV";
2084  let RowFields = ["RevOp"];
2085  let ColFields = ["IsOrig"];
2086  let KeyCol = ["0"];
2087  let ValueCols = [["1"]];
2088}
2089
2090// Maps an original opcode to its commuted version
2091def getCommuteRev : InstrMapping {
2092  let FilterClass = "Commutable_REV";
2093  let RowFields = ["RevOp"];
2094  let ColFields = ["IsOrig"];
2095  let KeyCol = ["1"];
2096  let ValueCols = [["0"]];
2097}
2098
2099def getMCOpcodeGen : InstrMapping {
2100  let FilterClass = "SIMCInstr";
2101  let RowFields = ["PseudoInstr"];
2102  let ColFields = ["Subtarget"];
2103  let KeyCol = [!cast<string>(SIEncodingFamily.NONE)];
2104  let ValueCols = [[!cast<string>(SIEncodingFamily.SI)],
2105                   [!cast<string>(SIEncodingFamily.VI)],
2106                   [!cast<string>(SIEncodingFamily.SDWA)],
2107                   [!cast<string>(SIEncodingFamily.SDWA9)],
2108                   // GFX80 encoding is added to work around a multiple matching
2109                   // issue for buffer instructions with unpacked d16 data. This
2110                   // does not actually change the encoding, and thus may be
2111                   // removed later.
2112                   [!cast<string>(SIEncodingFamily.GFX80)],
2113                   [!cast<string>(SIEncodingFamily.GFX9)]];
2114}
2115
2116// Get equivalent SOPK instruction.
2117def getSOPKOp : InstrMapping {
2118  let FilterClass = "SOPKInstTable";
2119  let RowFields = ["BaseCmpOp"];
2120  let ColFields = ["IsSOPK"];
2121  let KeyCol = ["0"];
2122  let ValueCols = [["1"]];
2123}
2124
2125def getAddr64Inst : InstrMapping {
2126  let FilterClass = "MUBUFAddr64Table";
2127  let RowFields = ["OpName"];
2128  let ColFields = ["IsAddr64"];
2129  let KeyCol = ["0"];
2130  let ValueCols = [["1"]];
2131}
2132
2133def getIfAddr64Inst : InstrMapping {
2134  let FilterClass = "MUBUFAddr64Table";
2135  let RowFields = ["OpName"];
2136  let ColFields = ["IsAddr64"];
2137  let KeyCol = ["1"];
2138  let ValueCols = [["1"]];
2139}
2140
2141def getMUBUFNoLdsInst : InstrMapping {
2142  let FilterClass = "MUBUFLdsTable";
2143  let RowFields = ["OpName"];
2144  let ColFields = ["IsLds"];
2145  let KeyCol = ["1"];
2146  let ValueCols = [["0"]];
2147}
2148
2149// Maps an atomic opcode to its version with a return value.
2150def getAtomicRetOp : InstrMapping {
2151  let FilterClass = "AtomicNoRet";
2152  let RowFields = ["NoRetOp"];
2153  let ColFields = ["IsRet"];
2154  let KeyCol = ["0"];
2155  let ValueCols = [["1"]];
2156}
2157
2158// Maps an atomic opcode to its returnless version.
2159def getAtomicNoRetOp : InstrMapping {
2160  let FilterClass = "AtomicNoRet";
2161  let RowFields = ["NoRetOp"];
2162  let ColFields = ["IsRet"];
2163  let KeyCol = ["1"];
2164  let ValueCols = [["0"]];
2165}
2166
2167// Maps a GLOBAL to its SADDR form.
2168def getGlobalSaddrOp : InstrMapping {
2169  let FilterClass = "GlobalSaddrTable";
2170  let RowFields = ["SaddrOp"];
2171  let ColFields = ["IsSaddr"];
2172  let KeyCol = ["0"];
2173  let ValueCols = [["1"]];
2174}
2175
2176include "SIInstructions.td"
2177
2178include "DSInstructions.td"
2179include "MIMGInstructions.td"
2180