1//===-- SIInstrInfo.td -----------------------------------------------------===//
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
9def isWave32 : Predicate<"Subtarget->getWavefrontSize() == 32">,
10  AssemblerPredicate <(all_of FeatureWavefrontSize32)>;
11def isWave64 : Predicate<"Subtarget->getWavefrontSize() == 64">,
12  AssemblerPredicate <(all_of FeatureWavefrontSize64)>;
13
14class GCNPredicateControl : PredicateControl {
15  Predicate SIAssemblerPredicate = isGFX6GFX7;
16  Predicate VIAssemblerPredicate = isGFX8GFX9;
17}
18
19// Except for the NONE field, this must be kept in sync with the
20// SIEncodingFamily enum in SIInstrInfo.cpp and the columns of the
21// getMCOpcodeGen table.
22def SIEncodingFamily {
23  int NONE = -1;
24  int SI = 0;
25  int VI = 1;
26  int SDWA = 2;
27  int SDWA9 = 3;
28  int GFX80 = 4;
29  int GFX9 = 5;
30  int GFX10 = 6;
31  int SDWA10 = 7;
32  int GFX90A = 8;
33  int GFX940 = 9;
34  int GFX11 = 10;
35}
36
37//===----------------------------------------------------------------------===//
38// SI DAG Nodes
39//===----------------------------------------------------------------------===//
40
41def AMDGPUclamp : SDNode<"AMDGPUISD::CLAMP", SDTFPUnaryOp>;
42
43def SIsbuffer_load : SDNode<"AMDGPUISD::SBUFFER_LOAD",
44  SDTypeProfile<1, 3, [SDTCisVT<1, v4i32>, SDTCisVT<2, i32>, SDTCisVT<3, i32>]>,
45  [SDNPMayLoad, SDNPMemOperand]
46>;
47
48def SIds_ordered_count : SDNode<"AMDGPUISD::DS_ORDERED_COUNT",
49  SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, SDTCisVT<2, i16>]>,
50  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain, SDNPInGlue]
51>;
52
53def SIatomic_inc : SDNode<"AMDGPUISD::ATOMIC_INC", SDTAtomic2,
54  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain]
55>;
56
57def SIatomic_dec : SDNode<"AMDGPUISD::ATOMIC_DEC", SDTAtomic2,
58  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain]
59>;
60
61def SDTAtomic2_f32 : SDTypeProfile<1, 2, [
62  SDTCisSameAs<0,2>, SDTCisFP<0>, SDTCisPtrTy<1>
63]>;
64
65def SIatomic_fmin : SDNode<"AMDGPUISD::ATOMIC_LOAD_FMIN", SDTAtomic2_f32,
66  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain]
67>;
68
69def SIatomic_fmax : SDNode<"AMDGPUISD::ATOMIC_LOAD_FMAX", SDTAtomic2_f32,
70  [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain]
71>;
72
73// load_d16_{lo|hi} ptr, tied_input
74def SIload_d16 : SDTypeProfile<1, 2, [
75  SDTCisPtrTy<1>,
76  SDTCisSameAs<0, 2>
77]>;
78
79
80def SDTtbuffer_load : SDTypeProfile<1, 8,
81  [                     // vdata
82   SDTCisVT<1, v4i32>,  // rsrc
83   SDTCisVT<2, i32>,    // vindex(VGPR)
84   SDTCisVT<3, i32>,    // voffset(VGPR)
85   SDTCisVT<4, i32>,    // soffset(SGPR)
86   SDTCisVT<5, i32>,    // offset(imm)
87   SDTCisVT<6, i32>,    // format(imm)
88   SDTCisVT<7, i32>,    // cachepolicy, swizzled buffer(imm)
89   SDTCisVT<8, i1>      // idxen(imm)
90  ]>;
91
92def SItbuffer_load :   SDNode<"AMDGPUISD::TBUFFER_LOAD_FORMAT", SDTtbuffer_load,
93                              [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]>;
94def SItbuffer_load_d16 : SDNode<"AMDGPUISD::TBUFFER_LOAD_FORMAT_D16",
95                                SDTtbuffer_load,
96                                [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]>;
97
98def SDTtbuffer_store : SDTypeProfile<0, 9,
99    [                     // vdata
100     SDTCisVT<1, v4i32>,  // rsrc
101     SDTCisVT<2, i32>,    // vindex(VGPR)
102     SDTCisVT<3, i32>,    // voffset(VGPR)
103     SDTCisVT<4, i32>,    // soffset(SGPR)
104     SDTCisVT<5, i32>,    // offset(imm)
105     SDTCisVT<6, i32>,    // format(imm)
106     SDTCisVT<7, i32>,    // cachepolicy, swizzled buffer(imm)
107     SDTCisVT<8, i1>      // idxen(imm)
108    ]>;
109
110def SItbuffer_store : SDNode<"AMDGPUISD::TBUFFER_STORE_FORMAT", SDTtbuffer_store,
111                             [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
112def SItbuffer_store_d16 : SDNode<"AMDGPUISD::TBUFFER_STORE_FORMAT_D16",
113                                SDTtbuffer_store,
114                                [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
115
116def SDTBufferLoad : SDTypeProfile<1, 7,
117    [                    // vdata
118     SDTCisVT<1, v4i32>, // rsrc
119     SDTCisVT<2, i32>,   // vindex(VGPR)
120     SDTCisVT<3, i32>,   // voffset(VGPR)
121     SDTCisVT<4, i32>,   // soffset(SGPR)
122     SDTCisVT<5, i32>,   // offset(imm)
123     SDTCisVT<6, i32>,   // cachepolicy, swizzled buffer(imm)
124     SDTCisVT<7, i1>]>;  // idxen(imm)
125
126def SIbuffer_load : SDNode <"AMDGPUISD::BUFFER_LOAD", SDTBufferLoad,
127                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
128def SIbuffer_load_ubyte : SDNode <"AMDGPUISD::BUFFER_LOAD_UBYTE", SDTBufferLoad,
129                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
130def SIbuffer_load_ushort : SDNode <"AMDGPUISD::BUFFER_LOAD_USHORT", SDTBufferLoad,
131                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
132def SIbuffer_load_byte : SDNode <"AMDGPUISD::BUFFER_LOAD_BYTE", SDTBufferLoad,
133                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
134def SIbuffer_load_short: SDNode <"AMDGPUISD::BUFFER_LOAD_SHORT", SDTBufferLoad,
135                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
136def SIbuffer_load_format : SDNode <"AMDGPUISD::BUFFER_LOAD_FORMAT", SDTBufferLoad,
137                            [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
138def SIbuffer_load_format_d16 : SDNode <"AMDGPUISD::BUFFER_LOAD_FORMAT_D16",
139                                SDTBufferLoad,
140                                [SDNPMemOperand, SDNPHasChain, SDNPMayLoad]>;
141
142def SDTBufferStore : SDTypeProfile<0, 8,
143    [                    // vdata
144     SDTCisVT<1, v4i32>, // rsrc
145     SDTCisVT<2, i32>,   // vindex(VGPR)
146     SDTCisVT<3, i32>,   // voffset(VGPR)
147     SDTCisVT<4, i32>,   // soffset(SGPR)
148     SDTCisVT<5, i32>,   // offset(imm)
149     SDTCisVT<6, i32>,   // cachepolicy, swizzled buffer(imm)
150     SDTCisVT<7, i1>]>;  // idxen(imm)
151
152def SIbuffer_store : SDNode <"AMDGPUISD::BUFFER_STORE", SDTBufferStore,
153                             [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
154def SIbuffer_store_byte: SDNode <"AMDGPUISD::BUFFER_STORE_BYTE",
155                         SDTBufferStore,
156                         [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
157def SIbuffer_store_short : SDNode <"AMDGPUISD::BUFFER_STORE_SHORT",
158                           SDTBufferStore,
159                           [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
160def SIbuffer_store_format : SDNode <"AMDGPUISD::BUFFER_STORE_FORMAT",
161                            SDTBufferStore,
162                            [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
163def SIbuffer_store_format_d16 : SDNode <"AMDGPUISD::BUFFER_STORE_FORMAT_D16",
164                            SDTBufferStore,
165                            [SDNPMayStore, SDNPMemOperand, SDNPHasChain]>;
166
167class SDBufferAtomic<string opcode> : SDNode <opcode,
168  SDTypeProfile<1, 8,
169       [SDTCisVT<2, v4i32>, // rsrc
170       SDTCisVT<3, i32>,   // vindex(VGPR)
171       SDTCisVT<4, i32>,   // voffset(VGPR)
172       SDTCisVT<5, i32>,   // soffset(SGPR)
173       SDTCisVT<6, i32>,   // offset(imm)
174       SDTCisVT<7, i32>,   // cachepolicy(imm)
175       SDTCisVT<8, i1>]>,  // idxen(imm)
176  [SDNPMemOperand, SDNPHasChain, SDNPMayLoad, SDNPMayStore]
177>;
178
179def SIbuffer_atomic_swap : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_SWAP">;
180def SIbuffer_atomic_add : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_ADD">;
181def SIbuffer_atomic_sub : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_SUB">;
182def SIbuffer_atomic_smin : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_SMIN">;
183def SIbuffer_atomic_umin : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_UMIN">;
184def SIbuffer_atomic_smax : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_SMAX">;
185def SIbuffer_atomic_umax : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_UMAX">;
186def SIbuffer_atomic_and : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_AND">;
187def SIbuffer_atomic_or : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_OR">;
188def SIbuffer_atomic_xor : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_XOR">;
189def SIbuffer_atomic_inc : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_INC">;
190def SIbuffer_atomic_dec : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_DEC">;
191def SIbuffer_atomic_csub : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_CSUB">;
192def SIbuffer_atomic_fadd : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_FADD">;
193def SIbuffer_atomic_fmin : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_FMIN">;
194def SIbuffer_atomic_fmax : SDBufferAtomic <"AMDGPUISD::BUFFER_ATOMIC_FMAX">;
195
196multiclass SDBufferAtomicNoRet {
197  def "_noret" : PatFrag<
198    (ops node:$vdata_in, node:$rsrc, node:$vindex, node:$voffset, node:$soffset,
199      node:$offset, node:$cachepolicy, node:$idxen),
200    (!cast<SDNode>(NAME) node:$vdata_in, node:$rsrc, node:$vindex,
201      node:$voffset, node:$soffset, node:$offset, node:$cachepolicy,
202      node:$idxen)> {
203    let HasNoUse = true;
204  }
205}
206
207defm SIbuffer_atomic_swap : SDBufferAtomicNoRet;
208defm SIbuffer_atomic_add : SDBufferAtomicNoRet;
209defm SIbuffer_atomic_sub : SDBufferAtomicNoRet;
210defm SIbuffer_atomic_smin : SDBufferAtomicNoRet;
211defm SIbuffer_atomic_umin : SDBufferAtomicNoRet;
212defm SIbuffer_atomic_smax : SDBufferAtomicNoRet;
213defm SIbuffer_atomic_umax : SDBufferAtomicNoRet;
214defm SIbuffer_atomic_and : SDBufferAtomicNoRet;
215defm SIbuffer_atomic_or : SDBufferAtomicNoRet;
216defm SIbuffer_atomic_xor : SDBufferAtomicNoRet;
217defm SIbuffer_atomic_inc : SDBufferAtomicNoRet;
218defm SIbuffer_atomic_dec : SDBufferAtomicNoRet;
219defm SIbuffer_atomic_fadd : SDBufferAtomicNoRet;
220defm SIbuffer_atomic_fmin : SDBufferAtomicNoRet;
221defm SIbuffer_atomic_fmax : SDBufferAtomicNoRet;
222
223def SIbuffer_atomic_cmpswap : SDNode <"AMDGPUISD::BUFFER_ATOMIC_CMPSWAP",
224  SDTypeProfile<1, 9,
225    [SDTCisVT<0, i32>,   // dst
226     SDTCisVT<1, i32>,   // src
227     SDTCisVT<2, i32>,   // cmp
228     SDTCisVT<3, v4i32>, // rsrc
229     SDTCisVT<4, i32>,   // vindex(VGPR)
230     SDTCisVT<5, i32>,   // voffset(VGPR)
231     SDTCisVT<6, i32>,   // soffset(SGPR)
232     SDTCisVT<7, i32>,   // offset(imm)
233     SDTCisVT<8, i32>,   // cachepolicy(imm)
234     SDTCisVT<9, i1>]>,  // idxen(imm)
235  [SDNPMemOperand, SDNPHasChain, SDNPMayLoad, SDNPMayStore]
236>;
237
238def SIbuffer_atomic_cmpswap_noret : PatFrag<
239  (ops node:$src, node:$cmp, node:$rsrc, node:$vindex, node:$voffset,
240    node:$soffset, node:$offset, node:$cachepolicy, node:$idxen),
241  (SIbuffer_atomic_cmpswap node:$src, node:$cmp, node:$rsrc, node:$vindex,
242    node:$voffset, node:$soffset, node:$offset, node:$cachepolicy,
243    node:$idxen)> {
244  let HasNoUse = true;
245}
246
247class SDGlobalAtomicNoRtn<string opcode, ValueType ty> : SDNode <opcode,
248  SDTypeProfile<0, 2,
249      [SDTCisPtrTy<0>,     // vaddr
250       SDTCisVT<1, ty>]>,  // vdata
251  [SDNPMemOperand, SDNPHasChain, SDNPMayLoad, SDNPMayStore]
252>;
253
254def SIpc_add_rel_offset : SDNode<"AMDGPUISD::PC_ADD_REL_OFFSET",
255  SDTypeProfile<1, 2, [SDTCisVT<0, iPTR>, SDTCisSameAs<0,1>, SDTCisSameAs<0,2>]>
256>;
257
258def SIlds : SDNode<"AMDGPUISD::LDS",
259  SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisSameAs<0,1>]>
260>;
261
262def SIload_d16_lo : SDNode<"AMDGPUISD::LOAD_D16_LO",
263  SIload_d16,
264  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
265>;
266
267def SIload_d16_lo_u8 : SDNode<"AMDGPUISD::LOAD_D16_LO_U8",
268  SIload_d16,
269  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
270>;
271
272def SIload_d16_lo_i8 : SDNode<"AMDGPUISD::LOAD_D16_LO_I8",
273  SIload_d16,
274  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
275>;
276
277def SIload_d16_hi : SDNode<"AMDGPUISD::LOAD_D16_HI",
278  SIload_d16,
279  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
280>;
281
282def SIload_d16_hi_u8 : SDNode<"AMDGPUISD::LOAD_D16_HI_U8",
283  SIload_d16,
284  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
285>;
286
287def SIload_d16_hi_i8 : SDNode<"AMDGPUISD::LOAD_D16_HI_I8",
288  SIload_d16,
289  [SDNPMayLoad, SDNPMemOperand, SDNPHasChain]
290>;
291
292def SIdenorm_mode : SDNode<"AMDGPUISD::DENORM_MODE",
293  SDTypeProfile<0 ,1, [SDTCisInt<0>]>,
294  [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]
295>;
296
297def SIfptrunc_round_upward : SDNode<"AMDGPUISD::FPTRUNC_ROUND_UPWARD",
298  SDTFPRoundOp
299>;
300
301def SIfptrunc_round_downward : SDNode<"AMDGPUISD::FPTRUNC_ROUND_DOWNWARD",
302  SDTFPRoundOp
303>;
304
305//===----------------------------------------------------------------------===//
306// ValueType helpers
307//===----------------------------------------------------------------------===//
308
309// Returns 1 if the source arguments have modifiers, 0 if they do not.
310class isFloatType<ValueType SrcVT> {
311  bit ret = !or(!eq(SrcVT.Value, f16.Value),
312                !eq(SrcVT.Value, f32.Value),
313                !eq(SrcVT.Value, f64.Value),
314                !eq(SrcVT.Value, v2f16.Value),
315                !eq(SrcVT.Value, v4f16.Value),
316                !eq(SrcVT.Value, v8f16.Value),
317                !eq(SrcVT.Value, v16f16.Value),
318                !eq(SrcVT.Value, v2f32.Value),
319                !eq(SrcVT.Value, v4f32.Value),
320                !eq(SrcVT.Value, v8f32.Value),
321                !eq(SrcVT.Value, v2f64.Value),
322                !eq(SrcVT.Value, v4f64.Value));
323}
324
325// XXX - do v2i16 instructions?
326class isIntType<ValueType SrcVT> {
327  bit ret = !or(!eq(SrcVT.Value, i16.Value),
328                !eq(SrcVT.Value, i32.Value),
329                !eq(SrcVT.Value, i64.Value),
330                !eq(SrcVT.Value, v4i16.Value),
331                !eq(SrcVT.Value, v8i16.Value),
332                !eq(SrcVT.Value, v16i16.Value),
333                !eq(SrcVT.Value, v2i32.Value),
334                !eq(SrcVT.Value, v4i32.Value),
335                !eq(SrcVT.Value, v8i32.Value));
336}
337
338class isPackedType<ValueType SrcVT> {
339  bit ret = !or(!eq(SrcVT.Value, v2i16.Value),
340                !eq(SrcVT.Value, v2f16.Value),
341                !eq(SrcVT.Value, v4f16.Value),
342                !eq(SrcVT.Value, v2i32.Value),
343                !eq(SrcVT.Value, v2f32.Value),
344                !eq(SrcVT.Value, v4i32.Value),
345                !eq(SrcVT.Value, v4f32.Value),
346                !eq(SrcVT.Value, v8i32.Value),
347                !eq(SrcVT.Value, v8f32.Value));
348}
349
350
351//===----------------------------------------------------------------------===//
352// PatFrags for global memory operations
353//===----------------------------------------------------------------------===//
354
355defm atomic_inc : binary_atomic_op_all_as<SIatomic_inc>;
356defm atomic_dec : binary_atomic_op_all_as<SIatomic_dec>;
357defm atomic_load_fmin : binary_atomic_op_all_as<SIatomic_fmin, 0>;
358defm atomic_load_fmax : binary_atomic_op_all_as<SIatomic_fmax, 0>;
359
360//===----------------------------------------------------------------------===//
361// SDNodes PatFrags for loads/stores with a glue input.
362// This is for SDNodes and PatFrag for local loads and stores to
363// enable s_mov_b32 m0, -1 to be glued to the memory instructions.
364//
365// These mirror the regular load/store PatFrags and rely on special
366// processing during Select() to add the glued copy.
367//
368//===----------------------------------------------------------------------===//
369
370def AMDGPUld_glue : SDNode <"ISD::LOAD", SDTLoad,
371  [SDNPHasChain, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
372>;
373
374def AMDGPUatomic_ld_glue : SDNode <"ISD::ATOMIC_LOAD", SDTAtomicLoad,
375  [SDNPHasChain, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
376>;
377
378def unindexedload_glue : PatFrag <(ops node:$ptr), (AMDGPUld_glue node:$ptr)> {
379  let IsLoad = 1;
380  let IsUnindexed = 1;
381}
382
383def load_glue : PatFrag <(ops node:$ptr), (unindexedload_glue node:$ptr)> {
384  let IsLoad = 1;
385  let IsNonExtLoad = 1;
386}
387
388def atomic_load_8_glue : PatFrag<(ops node:$ptr),
389  (AMDGPUatomic_ld_glue node:$ptr)> {
390  let IsAtomic = 1;
391  let MemoryVT = i8;
392}
393
394def atomic_load_16_glue : PatFrag<(ops node:$ptr),
395  (AMDGPUatomic_ld_glue node:$ptr)> {
396  let IsAtomic = 1;
397  let MemoryVT = i16;
398}
399
400def atomic_load_32_glue : PatFrag<(ops node:$ptr),
401  (AMDGPUatomic_ld_glue node:$ptr)> {
402  let IsAtomic = 1;
403  let MemoryVT = i32;
404}
405
406def atomic_load_64_glue : PatFrag<(ops node:$ptr),
407  (AMDGPUatomic_ld_glue node:$ptr)> {
408  let IsAtomic = 1;
409  let MemoryVT = i64;
410}
411
412def extload_glue : PatFrag<(ops node:$ptr), (unindexedload_glue node:$ptr)> {
413  let IsLoad = 1;
414  let IsAnyExtLoad = 1;
415}
416
417def sextload_glue : PatFrag<(ops node:$ptr), (unindexedload_glue node:$ptr)> {
418  let IsLoad = 1;
419  let IsSignExtLoad = 1;
420}
421
422def zextload_glue : PatFrag<(ops node:$ptr), (unindexedload_glue node:$ptr)> {
423  let IsLoad = 1;
424  let IsZeroExtLoad = 1;
425}
426
427def extloadi8_glue : PatFrag<(ops node:$ptr), (extload_glue node:$ptr)> {
428  let IsLoad = 1;
429  let MemoryVT = i8;
430}
431
432def zextloadi8_glue : PatFrag<(ops node:$ptr), (zextload_glue node:$ptr)> {
433  let IsLoad = 1;
434  let MemoryVT = i8;
435}
436
437def extloadi16_glue : PatFrag<(ops node:$ptr), (extload_glue node:$ptr)> {
438  let IsLoad = 1;
439  let MemoryVT = i16;
440}
441
442def zextloadi16_glue : PatFrag<(ops node:$ptr), (zextload_glue node:$ptr)> {
443  let IsLoad = 1;
444  let MemoryVT = i16;
445}
446
447def sextloadi8_glue : PatFrag<(ops node:$ptr), (sextload_glue node:$ptr)> {
448  let IsLoad = 1;
449  let MemoryVT = i8;
450}
451
452def sextloadi16_glue : PatFrag<(ops node:$ptr), (sextload_glue node:$ptr)> {
453  let IsLoad = 1;
454  let MemoryVT = i16;
455}
456
457
458let IsLoad = 1, AddressSpaces = LoadAddress_local.AddrSpaces in {
459def load_local_m0 : PatFrag<(ops node:$ptr), (load_glue node:$ptr)> {
460  let IsNonExtLoad = 1;
461}
462
463def extloadi8_local_m0 : PatFrag<(ops node:$ptr), (extloadi8_glue node:$ptr)>;
464def sextloadi8_local_m0 : PatFrag<(ops node:$ptr), (sextloadi8_glue node:$ptr)>;
465def zextloadi8_local_m0 : PatFrag<(ops node:$ptr), (zextloadi8_glue node:$ptr)>;
466
467def extloadi16_local_m0 : PatFrag<(ops node:$ptr), (extloadi16_glue node:$ptr)>;
468def sextloadi16_local_m0 : PatFrag<(ops node:$ptr), (sextloadi16_glue node:$ptr)>;
469def zextloadi16_local_m0 : PatFrag<(ops node:$ptr), (zextloadi16_glue node:$ptr)>;
470} // End IsLoad = 1, , AddressSpaces = LoadAddress_local.AddrSpaces
471
472def load_align8_local_m0 : PatFrag<(ops node:$ptr),
473                                   (load_local_m0 node:$ptr)> {
474  let IsLoad = 1;
475  int MinAlignment = 8;
476}
477
478def load_align16_local_m0 : PatFrag<(ops node:$ptr),
479                                   (load_local_m0 node:$ptr)> {
480  let IsLoad = 1;
481  int MinAlignment = 16;
482}
483
484let IsAtomic = 1, AddressSpaces = LoadAddress_local.AddrSpaces in {
485def atomic_load_8_local_m0 : PatFrag<(ops node:$ptr),
486                                      (atomic_load_8_glue node:$ptr)>;
487def atomic_load_16_local_m0 : PatFrag<(ops node:$ptr),
488                                      (atomic_load_16_glue node:$ptr)>;
489def atomic_load_32_local_m0 : PatFrag<(ops node:$ptr),
490                                      (atomic_load_32_glue node:$ptr)>;
491def atomic_load_64_local_m0 : PatFrag<(ops node:$ptr),
492                                       (atomic_load_64_glue node:$ptr)>;
493} // End let AddressSpaces = LoadAddress_local.AddrSpaces
494
495
496def AMDGPUst_glue : SDNode <"ISD::STORE", SDTStore,
497  [SDNPHasChain, SDNPMayStore, SDNPMemOperand, SDNPInGlue]
498>;
499
500def AMDGPUatomic_st_glue : SDNode <"ISD::ATOMIC_STORE", SDTAtomicStore,
501  [SDNPHasChain, SDNPMayStore, SDNPMemOperand, SDNPInGlue]
502>;
503
504def unindexedstore_glue : PatFrag<(ops node:$val, node:$ptr),
505                                   (AMDGPUst_glue node:$val, node:$ptr)> {
506  let IsStore = 1;
507  let IsUnindexed = 1;
508}
509
510def store_glue : PatFrag<(ops node:$val, node:$ptr),
511                         (unindexedstore_glue node:$val, node:$ptr)> {
512  let IsStore = 1;
513  let IsTruncStore = 0;
514}
515
516def truncstore_glue : PatFrag<(ops node:$val, node:$ptr),
517  (unindexedstore_glue node:$val, node:$ptr)> {
518  let IsStore = 1;
519  let IsTruncStore = 1;
520}
521
522def truncstorei8_glue : PatFrag<(ops node:$val, node:$ptr),
523                           (truncstore_glue node:$val, node:$ptr)> {
524  let IsStore = 1;
525  let MemoryVT = i8;
526  let IsTruncStore = 1;
527}
528
529def truncstorei16_glue : PatFrag<(ops node:$val, node:$ptr),
530                           (truncstore_glue node:$val, node:$ptr)> {
531  let IsStore = 1;
532  let MemoryVT = i16;
533  let IsTruncStore = 1;
534}
535
536let IsStore = 1, AddressSpaces = StoreAddress_local.AddrSpaces in {
537def store_local_m0 : PatFrag<(ops node:$val, node:$ptr),
538                             (store_glue node:$val, node:$ptr)>;
539def truncstorei8_local_m0 : PatFrag<(ops node:$val, node:$ptr),
540                                    (truncstorei8_glue node:$val, node:$ptr)>;
541def truncstorei16_local_m0 : PatFrag<(ops node:$val, node:$ptr),
542                                    (truncstorei16_glue node:$val, node:$ptr)>;
543}
544
545def store_align8_local_m0 : PatFrag <(ops node:$value, node:$ptr),
546                                     (store_local_m0 node:$value, node:$ptr)>,
547                            Aligned<8> {
548  let IsStore = 1;
549}
550
551def store_align16_local_m0 : PatFrag <(ops node:$value, node:$ptr),
552                                     (store_local_m0 node:$value, node:$ptr)>,
553                            Aligned<16> {
554  let IsStore = 1;
555}
556
557let PredicateCode = [{return cast<MemSDNode>(N)->getAlignment() < 4;}],
558    GISelPredicateCode = [{return (*MI.memoperands_begin())->getAlign() < 4;}],
559    AddressSpaces = [ AddrSpaces.Local ] in {
560def load_align_less_than_4_local : PatFrag<(ops node:$ptr),
561                                           (load_local node:$ptr)> {
562  let IsLoad = 1;
563  let IsNonExtLoad = 1;
564}
565
566def load_align_less_than_4_local_m0 : PatFrag<(ops node:$ptr),
567                                              (load_local_m0 node:$ptr)> {
568  let IsLoad = 1;
569  let IsNonExtLoad = 1;
570}
571
572def store_align_less_than_4_local : PatFrag <(ops node:$value, node:$ptr),
573                                             (store_local node:$value, node:$ptr)> {
574  let IsStore = 1;
575  let IsTruncStore = 0;
576}
577
578def store_align_less_than_4_local_m0 : PatFrag <(ops node:$value, node:$ptr),
579                                                (store_local_m0 node:$value, node:$ptr)> {
580  let IsStore = 1;
581  let IsTruncStore = 0;
582}
583}
584
585def atomic_store_8_glue : PatFrag <
586  (ops node:$ptr, node:$value),
587  (AMDGPUatomic_st_glue node:$ptr, node:$value)> {
588  let IsAtomic = 1;
589  let MemoryVT = i8;
590}
591
592def atomic_store_16_glue : PatFrag <
593  (ops node:$ptr, node:$value),
594  (AMDGPUatomic_st_glue node:$ptr, node:$value)> {
595  let IsAtomic = 1;
596  let MemoryVT = i16;
597}
598
599def atomic_store_32_glue : PatFrag <
600  (ops node:$ptr, node:$value),
601  (AMDGPUatomic_st_glue node:$ptr, node:$value)> {
602  let IsAtomic = 1;
603  let MemoryVT = i32;
604}
605
606def atomic_store_64_glue : PatFrag <
607  (ops node:$ptr, node:$value),
608  (AMDGPUatomic_st_glue node:$ptr, node:$value)> {
609  let IsAtomic = 1;
610  let MemoryVT = i64;
611}
612
613let IsAtomic = 1, AddressSpaces = StoreAddress_local.AddrSpaces in {
614def atomic_store_8_local_m0 : PatFrag<(ops node:$ptr, node:$val),
615                                       (atomic_store_8_glue node:$ptr, node:$val)>;
616def atomic_store_16_local_m0 : PatFrag<(ops node:$ptr, node:$val),
617                                       (atomic_store_16_glue node:$ptr, node:$val)>;
618def atomic_store_32_local_m0 : PatFrag<(ops node:$ptr, node:$val),
619                                       (atomic_store_32_glue node:$ptr, node:$val)>;
620def atomic_store_64_local_m0 : PatFrag<(ops node:$ptr, node:$val),
621                                       (atomic_store_64_glue node:$ptr, node:$val)>;
622} // End let IsAtomic = 1, AddressSpaces = StoreAddress_local.AddrSpaces
623
624
625def si_setcc_uniform : PatFrag <
626  (ops node:$lhs, node:$rhs, node:$cond),
627  (setcc node:$lhs, node:$rhs, node:$cond), [{
628  return !N->isDivergent();
629}]>;
630
631//===----------------------------------------------------------------------===//
632// SDNodes PatFrags for a16 loads and stores with 3 components.
633// v3f16/v3i16 is widened to v4f16/v4i16, so we need to match on the memory
634// load/store size.
635//===----------------------------------------------------------------------===//
636
637class mubuf_intrinsic_load<SDPatternOperator name, ValueType vt> : PatFrag <
638  (ops node:$rsrc, node:$vindex, node:$voffset, node:$soffset, node:$offset,
639            node:$auxiliary, node:$idxen),
640  (name node:$rsrc, node:$vindex, node:$voffset, node:$soffset, node:$offset,
641            node:$auxiliary, node:$idxen)> {
642  let IsLoad = 1;
643  let MemoryVT = vt;
644}
645
646class mubuf_intrinsic_store<SDPatternOperator name, ValueType vt> : PatFrag <
647  (ops node:$vdata, node:$rsrc, node:$vindex, node:$voffset, node:$soffset, node:$offset,
648            node:$auxiliary, node:$idxen),
649  (name node:$vdata, node:$rsrc, node:$vindex, node:$voffset, node:$soffset, node:$offset,
650            node:$auxiliary, node:$idxen)> {
651  let IsStore = 1;
652  let MemoryVT = vt;
653}
654
655class mtbuf_intrinsic_load<SDPatternOperator name, ValueType vt> : PatFrag <
656  (ops node:$rsrc, node:$vindex, node:$voffset, node:$soffset, node:$offset,
657            node:$format, node:$auxiliary, node:$idxen),
658  (name node:$rsrc, node:$vindex, node:$voffset, node:$soffset, node:$offset,
659            node:$format, node:$auxiliary, node:$idxen)> {
660  let IsLoad = 1;
661  let MemoryVT = vt;
662}
663
664class mtbuf_intrinsic_store<SDPatternOperator name, ValueType vt> : PatFrag <
665  (ops node:$vdata, node:$rsrc, node:$vindex, node:$voffset, node:$soffset, node:$offset,
666            node:$format, node:$auxiliary, node:$idxen),
667  (name node:$vdata, node:$rsrc, node:$vindex, node:$voffset, node:$soffset, node:$offset,
668            node:$format, node:$auxiliary, node:$idxen)> {
669  let IsStore = 1;
670  let MemoryVT = vt;
671}
672
673//===----------------------------------------------------------------------===//
674// SDNodes PatFrags for d16 loads
675//===----------------------------------------------------------------------===//
676
677class LoadD16Frag <SDPatternOperator op> : PatFrag<
678  (ops node:$ptr, node:$tied_in),
679  (op node:$ptr, node:$tied_in)> {
680  let IsLoad = 1;
681}
682
683foreach as = [ "global", "flat", "constant", "local", "private", "region" ] in {
684let AddressSpaces = !cast<AddressSpaceList>("LoadAddress_"#as).AddrSpaces in {
685
686def load_d16_hi_#as : LoadD16Frag <SIload_d16_hi>;
687
688def az_extloadi8_d16_hi_#as : LoadD16Frag <SIload_d16_hi_u8> {
689  let MemoryVT = i8;
690}
691
692def sextloadi8_d16_hi_#as : LoadD16Frag <SIload_d16_hi_i8> {
693  let MemoryVT = i8;
694}
695
696def load_d16_lo_#as : LoadD16Frag <SIload_d16_lo>;
697
698def az_extloadi8_d16_lo_#as : LoadD16Frag <SIload_d16_lo_u8> {
699  let MemoryVT = i8;
700}
701
702def sextloadi8_d16_lo_#as : LoadD16Frag <SIload_d16_lo_i8> {
703  let MemoryVT = i8;
704}
705
706} // End let AddressSpaces = ...
707} // End foreach AddrSpace
708
709def lshr_rev : PatFrag <
710  (ops node:$src1, node:$src0),
711  (srl $src0, $src1)
712>;
713
714def ashr_rev : PatFrag <
715  (ops node:$src1, node:$src0),
716  (sra $src0, $src1)
717>;
718
719def lshl_rev : PatFrag <
720  (ops node:$src1, node:$src0),
721  (shl $src0, $src1)
722>;
723
724def add_ctpop : PatFrag <
725  (ops node:$src0, node:$src1),
726  (add (ctpop $src0), $src1)
727>;
728
729def xnor : PatFrag <
730  (ops node:$src0, node:$src1),
731  (not (xor $src0, $src1))
732>;
733
734foreach I = 1-4 in {
735def shl#I#_add : PatFrag <
736  (ops node:$src0, node:$src1),
737  (add (shl_oneuse $src0, (i32 I)), $src1)> {
738  // FIXME: Poor substitute for disabling pattern in SelectionDAG
739  let PredicateCode = [{return false;}];
740  let GISelPredicateCode = [{return true;}];
741}
742}
743
744multiclass SIAtomicM0Glue2 <string op_name, bit is_amdgpu = 0,
745                            SDTypeProfile tc = SDTAtomic2,
746                            bit IsInt = 1> {
747
748  def _glue : SDNode <
749    !if(is_amdgpu, "AMDGPUISD", "ISD")#"::ATOMIC_"#op_name, tc,
750    [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand, SDNPInGlue]
751  >;
752
753  let AddressSpaces = StoreAddress_local.AddrSpaces in {
754    defm _local_m0 : binary_atomic_op <!cast<SDNode>(NAME#"_glue"), IsInt>;
755    defm _local_m0 : noret_binary_atomic_op <!cast<SDNode>(NAME#"_glue"),
756                                                 IsInt>;
757  }
758
759  let AddressSpaces = StoreAddress_region.AddrSpaces in {
760    defm _region_m0 : binary_atomic_op <!cast<SDNode>(NAME#"_glue"), IsInt>;
761    defm _region_m0 : noret_binary_atomic_op <!cast<SDNode>(NAME#"_glue"),
762                                                  IsInt>;
763  }
764}
765
766defm atomic_load_add : SIAtomicM0Glue2 <"LOAD_ADD">;
767defm atomic_load_sub : SIAtomicM0Glue2 <"LOAD_SUB">;
768defm atomic_inc : SIAtomicM0Glue2 <"INC", 1>;
769defm atomic_dec : SIAtomicM0Glue2 <"DEC", 1>;
770defm atomic_load_and : SIAtomicM0Glue2 <"LOAD_AND">;
771defm atomic_load_min : SIAtomicM0Glue2 <"LOAD_MIN">;
772defm atomic_load_max : SIAtomicM0Glue2 <"LOAD_MAX">;
773defm atomic_load_or : SIAtomicM0Glue2 <"LOAD_OR">;
774defm atomic_load_xor : SIAtomicM0Glue2 <"LOAD_XOR">;
775defm atomic_load_umin : SIAtomicM0Glue2 <"LOAD_UMIN">;
776defm atomic_load_umax : SIAtomicM0Glue2 <"LOAD_UMAX">;
777defm atomic_swap : SIAtomicM0Glue2 <"SWAP">;
778defm atomic_load_fadd : SIAtomicM0Glue2 <"LOAD_FADD", 0, SDTAtomic2_f32, 0>;
779defm atomic_load_fmin : SIAtomicM0Glue2 <"LOAD_FMIN", 1, SDTAtomic2_f32, 0>;
780defm atomic_load_fmax : SIAtomicM0Glue2 <"LOAD_FMAX", 1, SDTAtomic2_f32, 0>;
781
782def as_i1timm : SDNodeXForm<timm, [{
783  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i1);
784}]>;
785
786def as_i8imm : SDNodeXForm<imm, [{
787  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i8);
788}]>;
789
790def as_i8timm : SDNodeXForm<timm, [{
791  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16);
792}]>;
793
794def as_i16imm : SDNodeXForm<imm, [{
795  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16);
796}]>;
797
798def as_i16timm : SDNodeXForm<timm, [{
799  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16);
800}]>;
801
802def as_i32imm: SDNodeXForm<imm, [{
803  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i32);
804}]>;
805
806def as_i32timm: SDNodeXForm<timm, [{
807  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i32);
808}]>;
809
810def as_i64imm: SDNodeXForm<imm, [{
811  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i64);
812}]>;
813
814def cond_as_i32imm: SDNodeXForm<cond, [{
815  return CurDAG->getTargetConstant(N->get(), SDLoc(N), MVT::i32);
816}]>;
817
818// Copied from the AArch64 backend:
819def bitcast_fpimm_to_i32 : SDNodeXForm<fpimm, [{
820return CurDAG->getTargetConstant(
821  N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i32);
822}]>;
823
824def frameindex_to_targetframeindex : SDNodeXForm<frameindex, [{
825  auto FI = cast<FrameIndexSDNode>(N);
826  return CurDAG->getTargetFrameIndex(FI->getIndex(), MVT::i32);
827}]>;
828
829// Copied from the AArch64 backend:
830def bitcast_fpimm_to_i64 : SDNodeXForm<fpimm, [{
831return CurDAG->getTargetConstant(
832  N->getValueAPF().bitcastToAPInt().getZExtValue(), SDLoc(N), MVT::i64);
833}]>;
834
835class bitextract_imm<int bitnum> : SDNodeXForm<imm, [{
836  uint64_t Imm = N->getZExtValue();
837  unsigned Bit = (Imm >> }] # bitnum # [{ ) & 1;
838  return CurDAG->getTargetConstant(Bit, SDLoc(N), MVT::i1);
839}]>;
840
841def SIMM16bit : ImmLeaf <i32,
842  [{return isInt<16>(Imm);}]
843>;
844
845def UIMM16bit : ImmLeaf <i32,
846  [{return isUInt<16>(Imm);}]
847>;
848
849def i64imm_32bit : ImmLeaf<i64, [{
850  return (Imm & 0xffffffffULL) == static_cast<uint64_t>(Imm);
851}]>;
852
853def InlineImm16 : ImmLeaf<i16, [{
854  return isInlineImmediate16(Imm);
855}]>;
856
857def InlineImm32 : ImmLeaf<i32, [{
858  return isInlineImmediate32(Imm);
859}]>;
860
861def InlineImm64 : ImmLeaf<i64, [{
862  return isInlineImmediate64(Imm);
863}]>;
864
865def InlineImmFP32 : FPImmLeaf<f32, [{
866  return isInlineImmediate(Imm);
867}]>;
868
869def InlineImmFP64 : FPImmLeaf<f64, [{
870  return isInlineImmediate(Imm);
871}]>;
872
873
874class VGPRImm <dag frag> : PatLeaf<frag, [{
875  return isVGPRImm(N);
876}]>;
877
878def NegateImm : SDNodeXForm<imm, [{
879  return CurDAG->getConstant(-N->getSExtValue(), SDLoc(N), MVT::i32);
880}]>;
881
882// TODO: When FP inline imm values work?
883def NegSubInlineConst32 : ImmLeaf<i32, [{
884  return Imm < -16 && Imm >= -64;
885}], NegateImm>;
886
887def NegSubInlineIntConst16 : ImmLeaf<i16, [{
888  return Imm < -16 && Imm >= -64;
889}], NegateImm>;
890
891def ShiftAmt32Imm : ImmLeaf <i32, [{
892  return Imm < 32;
893}]>;
894
895def getNegV2I16Imm : SDNodeXForm<build_vector, [{
896  return SDValue(packNegConstantV2I16(N, *CurDAG), 0);
897}]>;
898
899def NegSubInlineConstV216 : PatLeaf<(build_vector), [{
900  assert(N->getNumOperands() == 2);
901  assert(N->getOperand(0).getValueType().getSizeInBits() == 16);
902  SDValue Src0 = N->getOperand(0);
903  SDValue Src1 = N->getOperand(1);
904  if (Src0 == Src1)
905    return isNegInlineImmediate(Src0.getNode());
906
907  return (isNullConstantOrUndef(Src0) && isNegInlineImmediate(Src1.getNode())) ||
908         (isNullConstantOrUndef(Src1) && isNegInlineImmediate(Src0.getNode()));
909}], getNegV2I16Imm>;
910
911
912def fp16_zeros_high_16bits : PatLeaf<(f16 VGPR_32:$src), [{
913  return fp16SrcZerosHighBits(N->getOpcode());
914}]>;
915
916
917//===----------------------------------------------------------------------===//
918// MUBUF/SMEM Patterns
919//===----------------------------------------------------------------------===//
920
921def extract_cpol : SDNodeXForm<timm, [{
922  return CurDAG->getTargetConstant(N->getZExtValue() & AMDGPU::CPol::ALL, SDLoc(N), MVT::i8);
923}]>;
924
925def extract_swz : SDNodeXForm<timm, [{
926  return CurDAG->getTargetConstant((N->getZExtValue() >> 3) & 1, SDLoc(N), MVT::i8);
927}]>;
928
929def set_glc : SDNodeXForm<timm, [{
930  return CurDAG->getTargetConstant(N->getZExtValue() | AMDGPU::CPol::GLC, SDLoc(N), MVT::i8);
931}]>;
932
933//===----------------------------------------------------------------------===//
934// Custom Operands
935//===----------------------------------------------------------------------===//
936
937def SoppBrTarget : AsmOperandClass {
938  let Name = "SoppBrTarget";
939  let ParserMethod = "parseSOppBrTarget";
940}
941
942def sopp_brtarget : Operand<OtherVT> {
943  let EncoderMethod = "getSOPPBrEncoding";
944  let DecoderMethod = "decodeSoppBrTarget";
945  let OperandType = "OPERAND_PCREL";
946  let ParserMatchClass = SoppBrTarget;
947}
948
949def si_ga : Operand<iPTR>;
950
951def InterpSlotMatchClass : AsmOperandClass {
952  let Name = "InterpSlot";
953  let PredicateMethod = "isInterpSlot";
954  let ParserMethod = "parseInterpSlot";
955  let RenderMethod = "addImmOperands";
956}
957
958def InterpSlot : Operand<i32> {
959  let PrintMethod = "printInterpSlot";
960  let ParserMatchClass = InterpSlotMatchClass;
961  let OperandType = "OPERAND_IMMEDIATE";
962}
963
964def AttrMatchClass : AsmOperandClass {
965  let Name = "Attr";
966  let PredicateMethod = "isInterpAttr";
967  let ParserMethod = "parseInterpAttr";
968  let RenderMethod = "addImmOperands";
969}
970
971// It appears to be necessary to create a separate operand for this to
972// be able to parse attr<num> with no space.
973def Attr : Operand<i32> {
974  let PrintMethod = "printInterpAttr";
975  let ParserMatchClass = AttrMatchClass;
976  let OperandType = "OPERAND_IMMEDIATE";
977}
978
979def AttrChanMatchClass : AsmOperandClass {
980  let Name = "AttrChan";
981  let PredicateMethod = "isAttrChan";
982  let RenderMethod = "addImmOperands";
983}
984
985def AttrChan : Operand<i32> {
986  let PrintMethod = "printInterpAttrChan";
987  let ParserMatchClass = AttrChanMatchClass;
988  let OperandType = "OPERAND_IMMEDIATE";
989}
990
991def SendMsgMatchClass : AsmOperandClass {
992  let Name = "SendMsg";
993  let PredicateMethod = "isSendMsg";
994  let ParserMethod = "parseSendMsgOp";
995  let RenderMethod = "addImmOperands";
996}
997
998def SwizzleMatchClass : AsmOperandClass {
999  let Name = "Swizzle";
1000  let PredicateMethod = "isSwizzle";
1001  let ParserMethod = "parseSwizzleOp";
1002  let RenderMethod = "addImmOperands";
1003  let IsOptional = 1;
1004}
1005
1006def EndpgmMatchClass : AsmOperandClass {
1007  let Name = "EndpgmImm";
1008  let PredicateMethod = "isEndpgm";
1009  let ParserMethod = "parseEndpgmOp";
1010  let RenderMethod = "addImmOperands";
1011  let IsOptional = 1;
1012}
1013
1014def ExpTgtMatchClass : AsmOperandClass {
1015  let Name = "ExpTgt";
1016  let PredicateMethod = "isExpTgt";
1017  let ParserMethod = "parseExpTgt";
1018  let RenderMethod = "printExpTgt";
1019}
1020
1021def SWaitMatchClass : AsmOperandClass {
1022  let Name = "SWaitCnt";
1023  let RenderMethod = "addImmOperands";
1024  let ParserMethod = "parseSWaitCntOps";
1025}
1026
1027def DepCtrMatchClass : AsmOperandClass {
1028  let Name = "DepCtr";
1029  let RenderMethod = "addImmOperands";
1030  let ParserMethod = "parseDepCtrOps";
1031}
1032
1033def SDelayMatchClass : AsmOperandClass {
1034  let Name = "SDelayAlu";
1035  let RenderMethod = "addImmOperands";
1036  let ParserMethod = "parseSDelayAluOps";
1037}
1038
1039def VReg32OrOffClass : AsmOperandClass {
1040  let Name = "VReg32OrOff";
1041  let ParserMethod = "parseVReg32OrOff";
1042}
1043
1044let OperandType = "OPERAND_IMMEDIATE" in {
1045def SendMsgImm : Operand<i32> {
1046  let PrintMethod = "printSendMsg";
1047  let ParserMatchClass = SendMsgMatchClass;
1048}
1049
1050def SwizzleImm : Operand<i16> {
1051  let PrintMethod = "printSwizzle";
1052  let ParserMatchClass = SwizzleMatchClass;
1053}
1054
1055def EndpgmImm : Operand<i16> {
1056  let PrintMethod = "printEndpgm";
1057  let ParserMatchClass = EndpgmMatchClass;
1058}
1059
1060def WAIT_FLAG : Operand <i32> {
1061  let ParserMatchClass = SWaitMatchClass;
1062  let PrintMethod = "printWaitFlag";
1063}
1064
1065def DepCtrImm : Operand <i32> {
1066  let ParserMatchClass = DepCtrMatchClass;
1067  let PrintMethod = "printDepCtr";
1068}
1069
1070def DELAY_FLAG : Operand <i32> {
1071  let ParserMatchClass = SDelayMatchClass;
1072  let PrintMethod = "printDelayFlag";
1073}
1074} // End OperandType = "OPERAND_IMMEDIATE"
1075
1076include "SIInstrFormats.td"
1077include "VIInstrFormats.td"
1078
1079def BoolReg : AsmOperandClass {
1080  let Name = "BoolReg";
1081  let ParserMethod = "parseBoolReg";
1082  let RenderMethod = "addRegOperands";
1083}
1084
1085class BoolRC : RegisterOperand<SReg_1> {
1086  let ParserMatchClass = BoolReg;
1087  let DecoderMethod = "decodeBoolReg";
1088}
1089
1090def SSrc_i1 : RegisterOperand<SReg_1_XEXEC> {
1091  let ParserMatchClass = BoolReg;
1092  let DecoderMethod = "decodeBoolReg";
1093}
1094
1095def VOPDstS64orS32 : BoolRC {
1096  let PrintMethod = "printVOPDst";
1097}
1098
1099// SCSrc_i1 is the operand for pseudo instructions only.
1100// Boolean immediates shall not be exposed to codegen instructions.
1101def SCSrc_i1 : RegisterOperand<SReg_1_XEXEC> {
1102  let OperandNamespace = "AMDGPU";
1103  let OperandType = "OPERAND_REG_IMM_INT32";
1104  let ParserMatchClass = BoolReg;
1105  let DecoderMethod = "decodeBoolReg";
1106}
1107
1108// ===----------------------------------------------------------------------===//
1109// ExpSrc* Special cases for exp src operands which are printed as
1110// "off" depending on en operand.
1111// ===----------------------------------------------------------------------===//
1112
1113def ExpSrc0 : RegisterOperand<VGPR_32> {
1114  let PrintMethod = "printExpSrc0";
1115  let ParserMatchClass = VReg32OrOffClass;
1116}
1117
1118def ExpSrc1 : RegisterOperand<VGPR_32> {
1119  let PrintMethod = "printExpSrc1";
1120  let ParserMatchClass = VReg32OrOffClass;
1121}
1122
1123def ExpSrc2 : RegisterOperand<VGPR_32> {
1124  let PrintMethod = "printExpSrc2";
1125  let ParserMatchClass = VReg32OrOffClass;
1126}
1127
1128def ExpSrc3 : RegisterOperand<VGPR_32> {
1129  let PrintMethod = "printExpSrc3";
1130  let ParserMatchClass = VReg32OrOffClass;
1131}
1132
1133class SDWASrc<ValueType vt> : RegisterOperand<VS_32> {
1134  let OperandNamespace = "AMDGPU";
1135  string Type = !if(isFloatType<vt>.ret, "FP", "INT");
1136  let OperandType = "OPERAND_REG_INLINE_C_"#Type#vt.Size;
1137  let DecoderMethod = "decodeSDWASrc"#vt.Size;
1138  let EncoderMethod = "getSDWASrcEncoding";
1139}
1140
1141def SDWASrc_i32 : SDWASrc<i32>;
1142def SDWASrc_i16 : SDWASrc<i16>;
1143def SDWASrc_f32 : SDWASrc<f32>;
1144def SDWASrc_f16 : SDWASrc<f16>;
1145
1146def SDWAVopcDst : BoolRC {
1147  let OperandNamespace = "AMDGPU";
1148  let OperandType = "OPERAND_SDWA_VOPC_DST";
1149  let EncoderMethod = "getSDWAVopcDstEncoding";
1150  let DecoderMethod = "decodeSDWAVopcDst";
1151  let PrintMethod = "printVOPDst";
1152}
1153
1154class NamedMatchClass<string CName, bit Optional = 1> : AsmOperandClass {
1155  let Name = "Imm"#CName;
1156  let PredicateMethod = "is"#CName;
1157  let ParserMethod = !if(Optional, "parseOptionalOperand", "parse"#CName);
1158  let RenderMethod = "addImmOperands";
1159  let IsOptional = Optional;
1160  let DefaultMethod = !if(Optional, "default"#CName, ?);
1161}
1162
1163class NamedOperandBit<string Name, AsmOperandClass MatchClass> : Operand<i1> {
1164  let PrintMethod = "print"#Name;
1165  let ParserMatchClass = MatchClass;
1166}
1167
1168class NamedOperandBit_0<string Name, AsmOperandClass MatchClass> :
1169  OperandWithDefaultOps<i1, (ops (i1 0))> {
1170  let PrintMethod = "print"#Name;
1171  let ParserMatchClass = MatchClass;
1172}
1173
1174class NamedOperandBit_1<string Name, AsmOperandClass MatchClass> :
1175  OperandWithDefaultOps<i1, (ops (i1 1))> {
1176  let PrintMethod = "print"#Name;
1177  let ParserMatchClass = MatchClass;
1178}
1179
1180class NamedOperandU8<string Name, AsmOperandClass MatchClass> : Operand<i8> {
1181  let PrintMethod = "print"#Name;
1182  let ParserMatchClass = MatchClass;
1183}
1184
1185class NamedOperandU16<string Name, AsmOperandClass MatchClass> : Operand<i16> {
1186  let PrintMethod = "print"#Name;
1187  let ParserMatchClass = MatchClass;
1188}
1189
1190class NamedOperandU32<string Name, AsmOperandClass MatchClass> : Operand<i32> {
1191  let PrintMethod = "print"#Name;
1192  let ParserMatchClass = MatchClass;
1193}
1194
1195class NamedOperandU32_0<string Name, AsmOperandClass MatchClass> :
1196  OperandWithDefaultOps<i32, (ops (i32 0))> {
1197  let PrintMethod = "print"#Name;
1198  let ParserMatchClass = MatchClass;
1199}
1200
1201class NamedOperandU32Default0<string Name, AsmOperandClass MatchClass> :
1202  OperandWithDefaultOps<i32, (ops (i32 0))> {
1203  let PrintMethod = "print"#Name;
1204  let ParserMatchClass = MatchClass;
1205}
1206
1207class NamedOperandU32Default1<string Name, AsmOperandClass MatchClass> :
1208  OperandWithDefaultOps<i32, (ops (i32 1))> {
1209  let PrintMethod = "print"#Name;
1210  let ParserMatchClass = MatchClass;
1211}
1212
1213let OperandType = "OPERAND_IMMEDIATE" in {
1214
1215def offen : NamedOperandBit<"Offen", NamedMatchClass<"Offen">>;
1216def idxen : NamedOperandBit<"Idxen", NamedMatchClass<"Idxen">>;
1217def addr64 : NamedOperandBit<"Addr64", NamedMatchClass<"Addr64">>;
1218
1219def flat_offset : NamedOperandU16<"FlatOffset", NamedMatchClass<"FlatOffset">>;
1220def offset : NamedOperandU16<"Offset", NamedMatchClass<"Offset">>;
1221def offset0 : NamedOperandU8<"Offset0", NamedMatchClass<"Offset0">>;
1222def offset1 : NamedOperandU8<"Offset1", NamedMatchClass<"Offset1">>;
1223
1224def gds : NamedOperandBit<"GDS", NamedMatchClass<"GDS">>;
1225
1226def omod : NamedOperandU32<"OModSI", NamedMatchClass<"OModSI">>;
1227def omod0 : NamedOperandU32_0<"OModSI", NamedMatchClass<"OModSI">>;
1228
1229// We need to make the cases with a default of 0 distinct from no
1230// default to help deal with some cases where the operand appears
1231// before a mandatory operand.
1232def clampmod : NamedOperandBit<"ClampSI", NamedMatchClass<"ClampSI">>;
1233def clampmod0 : NamedOperandBit_0<"ClampSI", NamedMatchClass<"ClampSI">>;
1234def highmod : NamedOperandBit<"High", NamedMatchClass<"High">>;
1235
1236def CPol : NamedOperandU32<"CPol", NamedMatchClass<"CPol">>;
1237def CPol_0 : NamedOperandU32Default0<"CPol", NamedMatchClass<"CPol">>;
1238def CPol_GLC1 : NamedOperandU32Default1<"CPol", NamedMatchClass<"CPol">>;
1239
1240def TFE : NamedOperandBit<"TFE", NamedMatchClass<"TFE">>;
1241def TFE_0 : NamedOperandBit_0<"TFE", NamedMatchClass<"TFE">>;
1242def SWZ : NamedOperandBit<"SWZ", NamedMatchClass<"SWZ">>;
1243def SWZ_0 : NamedOperandBit_0<"SWZ", NamedMatchClass<"SWZ">>;
1244def UNorm : NamedOperandBit<"UNorm", NamedMatchClass<"UNorm">>;
1245def DA : NamedOperandBit<"DA", NamedMatchClass<"DA">>;
1246def R128A16 : NamedOperandBit<"R128A16", NamedMatchClass<"R128A16">>;
1247def GFX10A16 : NamedOperandBit<"GFX10A16", NamedMatchClass<"GFX10A16">>;
1248def D16 : NamedOperandBit<"D16", NamedMatchClass<"D16">>;
1249def LWE : NamedOperandBit<"LWE", NamedMatchClass<"LWE">>;
1250def exp_compr : NamedOperandBit<"ExpCompr", NamedMatchClass<"ExpCompr">>;
1251def exp_vm : NamedOperandBit<"ExpVM", NamedMatchClass<"ExpVM">>;
1252
1253def FORMAT : NamedOperandU8<"FORMAT", NamedMatchClass<"FORMAT", 0>>;
1254
1255def DMask : NamedOperandU16<"DMask", NamedMatchClass<"DMask">>;
1256def Dim : NamedOperandU8<"Dim", NamedMatchClass<"Dim", 0>>;
1257
1258def dst_sel : NamedOperandU32<"SDWADstSel", NamedMatchClass<"SDWADstSel">>;
1259def src0_sel : NamedOperandU32<"SDWASrc0Sel", NamedMatchClass<"SDWASrc0Sel">>;
1260def src1_sel : NamedOperandU32<"SDWASrc1Sel", NamedMatchClass<"SDWASrc1Sel">>;
1261def dst_unused : NamedOperandU32<"SDWADstUnused", NamedMatchClass<"SDWADstUnused">>;
1262
1263def op_sel0 : NamedOperandU32Default0<"OpSel", NamedMatchClass<"OpSel">>;
1264def op_sel_hi0 : NamedOperandU32Default0<"OpSelHi", NamedMatchClass<"OpSelHi">>;
1265def neg_lo0 : NamedOperandU32Default0<"NegLo", NamedMatchClass<"NegLo">>;
1266def neg_hi0 : NamedOperandU32Default0<"NegHi", NamedMatchClass<"NegHi">>;
1267
1268def dpp8 : NamedOperandU32<"DPP8", NamedMatchClass<"DPP8", 0>>;
1269def dpp_ctrl : NamedOperandU32<"DPPCtrl", NamedMatchClass<"DPPCtrl", 0>>;
1270
1271def row_mask : NamedOperandU32<"RowMask", NamedMatchClass<"RowMask">>;
1272def bank_mask : NamedOperandU32<"BankMask", NamedMatchClass<"BankMask">>;
1273def bound_ctrl : NamedOperandBit<"BoundCtrl", NamedMatchClass<"BoundCtrl">>;
1274def FI : NamedOperandU32<"FI", NamedMatchClass<"FI">>;
1275
1276def blgp : NamedOperandU32<"BLGP", NamedMatchClass<"BLGP">>;
1277def cbsz : NamedOperandU32<"CBSZ", NamedMatchClass<"CBSZ">>;
1278def abid : NamedOperandU32<"ABID", NamedMatchClass<"ABID">>;
1279
1280def hwreg : NamedOperandU32<"Hwreg", NamedMatchClass<"Hwreg", 0>>;
1281
1282def exp_tgt : NamedOperandU32<"ExpTgt", NamedMatchClass<"ExpTgt", 0>> {
1283
1284}
1285
1286def wait_vdst : NamedOperandU8<"WaitVDST", NamedMatchClass<"WaitVDST">>;
1287def wait_exp : NamedOperandU8<"WaitEXP", NamedMatchClass<"WaitEXP">>;
1288
1289} // End OperandType = "OPERAND_IMMEDIATE"
1290
1291class KImmMatchClass<int size> : AsmOperandClass {
1292  let Name = "KImmFP"#size;
1293  let PredicateMethod = "isKImmFP"#size;
1294  let ParserMethod = "parseImm";
1295  let RenderMethod = "addKImmFP"#size#"Operands";
1296}
1297
1298class kimmOperand<ValueType vt> : Operand<vt> {
1299  let OperandNamespace = "AMDGPU";
1300  let OperandType = "OPERAND_KIMM"#vt.Size;
1301  let PrintMethod = "printU"#vt.Size#"ImmOperand";
1302  let ParserMatchClass = !cast<AsmOperandClass>("KImmFP"#vt.Size#"MatchClass");
1303  let DecoderMethod = "decodeOperand_f"#vt.Size#"kimm";
1304}
1305
1306// 32-bit VALU immediate operand that uses the constant bus.
1307def KImmFP32MatchClass : KImmMatchClass<32>;
1308def f32kimm : kimmOperand<i32>;
1309
1310// 32-bit VALU immediate operand with a 16-bit value that uses the
1311// constant bus.
1312def KImmFP16MatchClass : KImmMatchClass<16>;
1313def f16kimm : kimmOperand<i16>;
1314
1315class FPInputModsMatchClass <int opSize> : AsmOperandClass {
1316  let Name = "RegOrImmWithFP"#opSize#"InputMods";
1317  let ParserMethod = "parseRegOrImmWithFPInputMods";
1318  let PredicateMethod = "isRegOrImmWithFP"#opSize#"InputMods";
1319}
1320
1321class FPVCSrcInputModsMatchClass <int opSize> : FPInputModsMatchClass <opSize> {
1322  let Name = "RegOrInlineImmWithFP"#opSize#"InputMods";
1323  let PredicateMethod = "isRegOrInlineImmWithFP"#opSize#"InputMods";
1324}
1325
1326def FP16InputModsMatchClass : FPInputModsMatchClass<16>;
1327def FP32InputModsMatchClass : FPInputModsMatchClass<32>;
1328def FP64InputModsMatchClass : FPInputModsMatchClass<64>;
1329
1330def FP16VCSrcInputModsMatchClass : FPVCSrcInputModsMatchClass<16>;
1331def FP32VCSrcInputModsMatchClass : FPVCSrcInputModsMatchClass<32>;
1332
1333class InputMods <AsmOperandClass matchClass> : Operand <i32> {
1334  let OperandNamespace = "AMDGPU";
1335  let OperandType = "OPERAND_INPUT_MODS";
1336  let ParserMatchClass = matchClass;
1337}
1338
1339class FPInputMods <FPInputModsMatchClass matchClass> : InputMods <matchClass> {
1340  let PrintMethod = "printOperandAndFPInputMods";
1341}
1342
1343def FP16InputMods : FPInputMods<FP16InputModsMatchClass>;
1344def FP32InputMods : FPInputMods<FP32InputModsMatchClass>;
1345def FP64InputMods : FPInputMods<FP64InputModsMatchClass>;
1346
1347def FP16VCSrcInputMods : FPInputMods<FP16VCSrcInputModsMatchClass>;
1348def FP32VCSrcInputMods : FPInputMods<FP32VCSrcInputModsMatchClass>;
1349
1350class IntInputModsMatchClass <int opSize> : AsmOperandClass {
1351  let Name = "RegOrImmWithInt"#opSize#"InputMods";
1352  let ParserMethod = "parseRegOrImmWithIntInputMods";
1353  let PredicateMethod = "isRegOrImmWithInt"#opSize#"InputMods";
1354}
1355class IntVCSrcInputModsMatchClass <int opSize> : IntInputModsMatchClass <opSize> {
1356  let Name = "RegOrInlineImmWithInt"#opSize#"InputMods";
1357  let PredicateMethod = "isRegOrInlineImmWithInt"#opSize#"InputMods";
1358}
1359def Int32InputModsMatchClass : IntInputModsMatchClass<32>;
1360def Int64InputModsMatchClass : IntInputModsMatchClass<64>;
1361def Int32VCSrcInputModsMatchClass : IntVCSrcInputModsMatchClass<32>;
1362
1363class IntInputMods <IntInputModsMatchClass matchClass> : InputMods <matchClass> {
1364  let PrintMethod = "printOperandAndIntInputMods";
1365}
1366def Int32InputMods : IntInputMods<Int32InputModsMatchClass>;
1367def Int64InputMods : IntInputMods<Int64InputModsMatchClass>;
1368def Int32VCSrcInputMods : IntInputMods<Int32VCSrcInputModsMatchClass>;
1369
1370class OpSelModsMatchClass : AsmOperandClass {
1371  let Name = "OpSelMods";
1372  let ParserMethod = "parseRegOrImm";
1373  let PredicateMethod = "isRegOrImm";
1374}
1375
1376def IntOpSelModsMatchClass : OpSelModsMatchClass;
1377def IntOpSelMods : InputMods<IntOpSelModsMatchClass>;
1378
1379class FPSDWAInputModsMatchClass <int opSize> : AsmOperandClass {
1380  let Name = "SDWAWithFP"#opSize#"InputMods";
1381  let ParserMethod = "parseRegOrImmWithFPInputMods";
1382  let PredicateMethod = "isSDWAFP"#opSize#"Operand";
1383}
1384
1385def FP16SDWAInputModsMatchClass : FPSDWAInputModsMatchClass<16>;
1386def FP32SDWAInputModsMatchClass : FPSDWAInputModsMatchClass<32>;
1387
1388class FPSDWAInputMods <FPSDWAInputModsMatchClass matchClass> :
1389  InputMods <matchClass> {
1390  let PrintMethod = "printOperandAndFPInputMods";
1391}
1392
1393def FP16SDWAInputMods : FPSDWAInputMods<FP16SDWAInputModsMatchClass>;
1394def FP32SDWAInputMods : FPSDWAInputMods<FP32SDWAInputModsMatchClass>;
1395
1396def FPVRegInputModsMatchClass : AsmOperandClass {
1397  let Name = "VRegWithFPInputMods";
1398  let ParserMethod = "parseRegWithFPInputMods";
1399  let PredicateMethod = "isVRegWithInputMods";
1400}
1401
1402def FPVRegInputMods : InputMods <FPVRegInputModsMatchClass> {
1403  let PrintMethod = "printOperandAndFPInputMods";
1404}
1405
1406class IntSDWAInputModsMatchClass <int opSize> : AsmOperandClass {
1407  let Name = "SDWAWithInt"#opSize#"InputMods";
1408  let ParserMethod = "parseRegOrImmWithIntInputMods";
1409  let PredicateMethod = "isSDWAInt"#opSize#"Operand";
1410}
1411
1412def Int16SDWAInputModsMatchClass : IntSDWAInputModsMatchClass<16>;
1413def Int32SDWAInputModsMatchClass : IntSDWAInputModsMatchClass<32>;
1414
1415class IntSDWAInputMods <IntSDWAInputModsMatchClass matchClass> :
1416  InputMods <matchClass> {
1417  let PrintMethod = "printOperandAndIntInputMods";
1418}
1419
1420def Int16SDWAInputMods : IntSDWAInputMods<Int16SDWAInputModsMatchClass>;
1421def Int32SDWAInputMods : IntSDWAInputMods<Int32SDWAInputModsMatchClass>;
1422
1423def IntVRegInputModsMatchClass : AsmOperandClass {
1424  let Name = "VRegWithIntInputMods";
1425  let ParserMethod = "parseRegWithIntInputMods";
1426  let PredicateMethod = "isVRegWithInputMods";
1427}
1428
1429def IntVRegInputMods : InputMods <IntVRegInputModsMatchClass> {
1430  let PrintMethod = "printOperandAndIntInputMods";
1431}
1432
1433class PackedFPInputModsMatchClass <int opSize> : AsmOperandClass {
1434  let Name = "PackedFP"#opSize#"InputMods";
1435  let ParserMethod = "parseRegOrImm";
1436  let PredicateMethod = "isRegOrImm";
1437//  let PredicateMethod = "isPackedFP"#opSize#"InputMods";
1438}
1439
1440class PackedIntInputModsMatchClass <int opSize> : AsmOperandClass {
1441  let Name = "PackedInt"#opSize#"InputMods";
1442  let ParserMethod = "parseRegOrImm";
1443  let PredicateMethod = "isRegOrImm";
1444//  let PredicateMethod = "isPackedInt"#opSize#"InputMods";
1445}
1446
1447def PackedF16InputModsMatchClass : PackedFPInputModsMatchClass<16>;
1448def PackedI16InputModsMatchClass : PackedIntInputModsMatchClass<16>;
1449
1450class PackedFPInputMods <PackedFPInputModsMatchClass matchClass> : InputMods <matchClass> {
1451//  let PrintMethod = "printPackedFPInputMods";
1452}
1453
1454class PackedIntInputMods <PackedIntInputModsMatchClass matchClass> : InputMods <matchClass> {
1455  //let PrintMethod = "printPackedIntInputMods";
1456}
1457
1458def PackedF16InputMods : PackedFPInputMods<PackedF16InputModsMatchClass>;
1459def PackedI16InputMods : PackedIntInputMods<PackedI16InputModsMatchClass>;
1460
1461//===----------------------------------------------------------------------===//
1462// Complex patterns
1463//===----------------------------------------------------------------------===//
1464
1465def DS1Addr1Offset : ComplexPattern<iPTR, 2, "SelectDS1Addr1Offset">;
1466def DS64Bit4ByteAligned : ComplexPattern<iPTR, 3, "SelectDS64Bit4ByteAligned">;
1467def DS128Bit8ByteAligned : ComplexPattern<iPTR, 3, "SelectDS128Bit8ByteAligned">;
1468
1469def MOVRELOffset : ComplexPattern<iPTR, 2, "SelectMOVRELOffset">;
1470
1471def VOP3Mods0 : ComplexPattern<untyped, 4, "SelectVOP3Mods0">;
1472def VOP3Mods  : ComplexPattern<untyped, 2, "SelectVOP3Mods">;
1473def VOP3NoMods : ComplexPattern<untyped, 1, "SelectVOP3NoMods">;
1474// VOP3Mods, but the input source is known to never be NaN.
1475def VOP3Mods_nnan : ComplexPattern<fAny, 2, "SelectVOP3Mods_NNaN">;
1476
1477def VOP3OMods : ComplexPattern<untyped, 3, "SelectVOP3OMods">;
1478
1479def VOP3PMods  : ComplexPattern<untyped, 2, "SelectVOP3PMods">;
1480
1481def VOP3PModsDOT  : ComplexPattern<untyped, 2, "SelectVOP3PModsDOT">;
1482def DotIUVOP3PMods  : ComplexPattern<untyped, 1, "SelectDotIUVOP3PMods">;
1483def WMMAOpSelVOP3PMods  : ComplexPattern<untyped, 1, "SelectWMMAOpSelVOP3PMods">;
1484
1485def VOP3OpSel  : ComplexPattern<untyped, 2, "SelectVOP3OpSel">;
1486
1487def VOP3OpSelMods  : ComplexPattern<untyped, 2, "SelectVOP3OpSelMods">;
1488
1489def VOP3PMadMixMods  : ComplexPattern<untyped, 2, "SelectVOP3PMadMixMods">;
1490
1491def VINTERPMods  : ComplexPattern<untyped, 2, "SelectVINTERPMods">;
1492def VINTERPModsHi  : ComplexPattern<untyped, 2, "SelectVINTERPModsHi">;
1493
1494//===----------------------------------------------------------------------===//
1495// SI assembler operands
1496//===----------------------------------------------------------------------===//
1497
1498def SIOperand {
1499  int ZERO = 0x80;
1500  int VCC = 0x6A;
1501  int FLAT_SCR = 0x68;
1502}
1503
1504// This should be kept in sync with SISrcMods enum
1505def SRCMODS {
1506  int NONE = 0;
1507  int NEG = 1;
1508  int ABS = 2;
1509  int NEG_ABS = 3;
1510
1511  int NEG_HI = ABS;
1512  int OP_SEL_0 = 4;
1513  int OP_SEL_1 = 8;
1514  int DST_OP_SEL = 8;
1515}
1516
1517def DSTCLAMP {
1518  int NONE = 0;
1519  int ENABLE = 1;
1520}
1521
1522def DSTOMOD {
1523  int NONE = 0;
1524}
1525
1526def HWREG {
1527  int MODE = 1;
1528  int STATUS = 2;
1529  int TRAPSTS = 3;
1530  int HW_ID = 4;
1531  int GPR_ALLOC = 5;
1532  int LDS_ALLOC = 6;
1533  int IB_STS = 7;
1534  int MEM_BASES = 15;
1535  int TBA_LO = 16;
1536  int TBA_HI = 17;
1537  int TMA_LO = 18;
1538  int TMA_HI = 19;
1539  int FLAT_SCR_LO = 20;
1540  int FLAT_SCR_HI = 21;
1541  int XNACK_MASK = 22;
1542  int POPS_PACKER = 25;
1543  int SHADER_CYCLES = 29;
1544}
1545
1546class getHwRegImm<int Reg, int Offset = 0, int Size = 32> {
1547  int ret = !and(!or(Reg,
1548                     !shl(Offset, 6),
1549                     !shl(!add(Size, -1), 11)), 65535);
1550}
1551
1552//===----------------------------------------------------------------------===//
1553//
1554// SI Instruction multiclass helpers.
1555//
1556// Instructions with _32 take 32-bit operands.
1557// Instructions with _64 take 64-bit operands.
1558//
1559// VOP_* instructions can use either a 32-bit or 64-bit encoding.  The 32-bit
1560// encoding is the standard encoding, but instruction that make use of
1561// any of the instruction modifiers must use the 64-bit encoding.
1562//
1563// Instructions with _e32 use the 32-bit encoding.
1564// Instructions with _e64 use the 64-bit encoding.
1565//
1566//===----------------------------------------------------------------------===//
1567
1568class SIMCInstr <string pseudo, int subtarget> {
1569  string PseudoInstr = pseudo;
1570  int Subtarget = subtarget;
1571}
1572
1573//===----------------------------------------------------------------------===//
1574// Vector ALU classes
1575//===----------------------------------------------------------------------===//
1576
1577class getNumSrcArgs<ValueType Src0, ValueType Src1, ValueType Src2> {
1578  int ret =
1579    !if (!eq(Src0.Value, untyped.Value),      0,
1580      !if (!eq(Src1.Value, untyped.Value),    1,   // VOP1
1581         !if (!eq(Src2.Value, untyped.Value), 2,   // VOP2
1582                                              3))); // VOP3
1583}
1584
1585// Returns the register class to use for the destination of VOP[123C]
1586// instructions for the given VT.
1587class getVALUDstForVT<ValueType VT> {
1588  RegisterOperand ret = !if(!eq(VT.Size, 32), VOPDstOperand<VGPR_32>,
1589                          !if(!eq(VT.Size, 128), VOPDstOperand<VReg_128>,
1590                            !if(!eq(VT.Size, 64), VOPDstOperand<VReg_64>,
1591                              !if(!eq(VT.Size, 16), VOPDstOperand<VGPR_32>,
1592                              VOPDstS64orS32)))); // else VT == i1
1593}
1594
1595// Returns the register class to use for the destination of VOP[12C]
1596// instructions with SDWA extension
1597class getSDWADstForVT<ValueType VT> {
1598  RegisterOperand ret = !if(!eq(VT.Size, 1),
1599                            SDWAVopcDst, // VOPC
1600                            VOPDstOperand<VGPR_32>); // VOP1/2 32-bit dst
1601}
1602
1603// Returns the register class to use for source 0 of VOP[12C]
1604// instructions for the given VT.
1605class getVOPSrc0ForVT<ValueType VT> {
1606  bit isFP = isFloatType<VT>.ret;
1607
1608  RegisterOperand ret =
1609    !if(isFP,
1610      !if(!eq(VT.Size, 64),
1611         VSrc_f64,
1612         !if(!eq(VT.Value, f16.Value),
1613            VSrc_f16,
1614            !if(!eq(VT.Value, v2f16.Value),
1615               VSrc_v2f16,
1616               !if(!eq(VT.Value, v4f16.Value),
1617                 AVSrc_64,
1618                 VSrc_f32
1619               )
1620            )
1621         )
1622       ),
1623       !if(!eq(VT.Size, 64),
1624          VSrc_b64,
1625          !if(!eq(VT.Value, i16.Value),
1626             VSrc_b16,
1627             !if(!eq(VT.Value, v2i16.Value),
1628                VSrc_v2b16,
1629                VSrc_b32
1630             )
1631          )
1632       )
1633    );
1634}
1635
1636class getSOPSrcForVT<ValueType VT> {
1637  RegisterOperand ret = !if(!eq(VT.Size, 64), SSrc_b64, SSrc_b32);
1638}
1639
1640// Returns the vreg register class to use for source operand given VT
1641class getVregSrcForVT<ValueType VT> {
1642  RegisterClass ret = !if(!eq(VT.Size, 128), VReg_128,
1643                        !if(!eq(VT.Size, 96), VReg_96,
1644                          !if(!eq(VT.Size, 64), VReg_64,
1645                            !if(!eq(VT.Size, 48), VReg_64,
1646                              VGPR_32))));
1647}
1648
1649class getSDWASrcForVT <ValueType VT> {
1650  bit isFP = isFloatType<VT>.ret;
1651  RegisterOperand retFlt = !if(!eq(VT.Size, 16), SDWASrc_f16, SDWASrc_f32);
1652  RegisterOperand retInt = !if(!eq(VT.Size, 16), SDWASrc_i16, SDWASrc_i32);
1653  RegisterOperand ret = !if(isFP, retFlt, retInt);
1654}
1655
1656// Returns the register class to use for sources of VOP3 instructions for the
1657// given VT.
1658class getVOP3SrcForVT<ValueType VT> {
1659  bit isFP = isFloatType<VT>.ret;
1660  RegisterOperand ret =
1661  !if(!eq(VT.Size, 128),
1662     VSrc_128,
1663     !if(!eq(VT.Size, 64),
1664        !if(isFP,
1665           !if(!eq(VT.Value, v2f32.Value),
1666               VSrc_v2f32,
1667               VSrc_f64),
1668           !if(!eq(VT.Value, v2i32.Value),
1669               VSrc_v2b32,
1670           VSrc_b64)),
1671        !if(!eq(VT.Value, i1.Value),
1672           SSrc_i1,
1673           !if(isFP,
1674              !if(!eq(VT.Value, f16.Value),
1675                 VSrc_f16,
1676                 !if(!eq(VT.Value, v2f16.Value),
1677                    VSrc_v2f16,
1678                    !if(!eq(VT.Value, v4f16.Value),
1679                      AVSrc_64,
1680                      VSrc_f32
1681                    )
1682                 )
1683              ),
1684              !if(!eq(VT.Value, i16.Value),
1685                 VSrc_b16,
1686                 !if(!eq(VT.Value, v2i16.Value),
1687                    VSrc_v2b16,
1688                    VSrc_b32
1689                 )
1690              )
1691           )
1692        )
1693     )
1694  );
1695}
1696
1697// Src2 of VOP3 DPP instructions cannot be a literal
1698class getVOP3DPPSrcForVT<ValueType VT> {
1699  bit isFP = isFloatType<VT>.ret;
1700  RegisterOperand ret =
1701      !if (!eq(VT.Value, i1.Value), SSrc_i1,
1702           !if (isFP,
1703                !if (!eq(VT.Value, f16.Value), VCSrc_f16,
1704                     !if (!eq(VT.Value, v2f16.Value), VCSrc_v2f16, VCSrc_f32)),
1705                !if (!eq(VT.Value, i16.Value), VCSrc_b16,
1706                     !if (!eq(VT.Value, v2i16.Value), VCSrc_v2b16,
1707                          VCSrc_b32))));
1708}
1709
1710// Float or packed int
1711class isModifierType<ValueType SrcVT> {
1712  bit ret = !or(!eq(SrcVT.Value, f16.Value),
1713                !eq(SrcVT.Value, f32.Value),
1714                !eq(SrcVT.Value, f64.Value),
1715                !eq(SrcVT.Value, v2f16.Value),
1716                !eq(SrcVT.Value, v2i16.Value),
1717                !eq(SrcVT.Value, v2f32.Value),
1718                !eq(SrcVT.Value, v2i32.Value),
1719                !eq(SrcVT.Value, v4f16.Value),
1720                !eq(SrcVT.Value, v4i16.Value),
1721                !eq(SrcVT.Value, v4f32.Value),
1722                !eq(SrcVT.Value, v4i32.Value),
1723                !eq(SrcVT.Value, v8f16.Value),
1724                !eq(SrcVT.Value, v8i16.Value),
1725                !eq(SrcVT.Value, v8f32.Value),
1726                !eq(SrcVT.Value, v8i32.Value),
1727                !eq(SrcVT.Value, v16f16.Value),
1728                !eq(SrcVT.Value, v16i16.Value));
1729}
1730
1731// Return type of input modifiers operand for specified input operand
1732class getSrcMod <ValueType VT, bit EnableF32SrcMods> {
1733  bit isFP = isFloatType<VT>.ret;
1734  bit isPacked = isPackedType<VT>.ret;
1735  Operand ret =  !if(!eq(VT.Size, 64),
1736                     !if(isFP, FP64InputMods, Int64InputMods),
1737                       !if(isFP,
1738                         !if(!eq(VT.Value, f16.Value),
1739                            FP16InputMods,
1740                            FP32InputMods
1741                          ),
1742                         !if(EnableF32SrcMods, FP32InputMods, Int32InputMods))
1743                     );
1744}
1745
1746class getOpSelMod <ValueType VT> {
1747  Operand ret = !if(!eq(VT.Value, f16.Value), FP16InputMods, IntOpSelMods);
1748}
1749
1750// Return type of input modifiers operand specified input operand for DPP
1751class getSrcModDPP <ValueType VT> {
1752  bit isFP = isFloatType<VT>.ret;
1753  Operand ret = !if(isFP, FPVRegInputMods, IntVRegInputMods);
1754}
1755
1756// Return type of input modifiers operand for specified input operand for DPP
1757class getSrcModVOP3DPP <ValueType VT, bit EnableF32SrcMods> {
1758  bit isFP = isFloatType<VT>.ret;
1759  bit isPacked = isPackedType<VT>.ret;
1760  Operand ret =
1761      !if (isFP,
1762           !if (!eq(VT.Value, f16.Value), FP16VCSrcInputMods,
1763                FP32VCSrcInputMods),
1764           !if (EnableF32SrcMods, FP32VCSrcInputMods, Int32VCSrcInputMods));
1765}
1766
1767// Return type of input modifiers operand specified input operand for SDWA
1768class getSrcModSDWA <ValueType VT> {
1769  Operand ret = !if(!eq(VT.Value, f16.Value), FP16SDWAInputMods,
1770                !if(!eq(VT.Value, f32.Value), FP32SDWAInputMods,
1771                !if(!eq(VT.Value, i16.Value), Int16SDWAInputMods,
1772                Int32SDWAInputMods)));
1773}
1774
1775// Returns the input arguments for VOP[12C] instructions for the given SrcVT.
1776class getIns32 <RegisterOperand Src0RC, RegisterOperand Src1RC, int NumSrcArgs> {
1777  dag ret = !if(!eq(NumSrcArgs, 1), (ins Src0RC:$src0),               // VOP1
1778            !if(!eq(NumSrcArgs, 2), (ins Src0RC:$src0, Src1RC:$src1), // VOP2
1779                                    (ins)));
1780}
1781
1782// Returns the input arguments for VOP3 instructions for the given SrcVT.
1783class getIns64 <RegisterOperand Src0RC, RegisterOperand Src1RC,
1784                RegisterOperand Src2RC, int NumSrcArgs,
1785                bit HasClamp, bit HasModifiers, bit HasSrc2Mods, bit HasOMod,
1786                Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> {
1787
1788  dag ret =
1789    !if (!eq(NumSrcArgs, 0),
1790      // VOP1 without input operands (V_NOP, V_CLREXCP)
1791      (ins),
1792      /* else */
1793    !if (!eq(NumSrcArgs, 1),
1794      !if (HasModifiers,
1795        // VOP1 with modifiers
1796        !if(HasOMod,
1797          (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1798               clampmod0:$clamp, omod0:$omod),
1799          (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1800               clampmod0:$clamp))
1801      /* else */,
1802        // VOP1 without modifiers
1803        !if (HasClamp,
1804          (ins Src0RC:$src0, clampmod0:$clamp),
1805          (ins Src0RC:$src0))
1806      /* endif */ ),
1807    !if (!eq(NumSrcArgs, 2),
1808      !if (HasModifiers,
1809        // VOP 2 with modifiers
1810        !if(HasOMod,
1811          (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1812               Src1Mod:$src1_modifiers, Src1RC:$src1,
1813               clampmod0:$clamp, omod0:$omod),
1814           (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1815               Src1Mod:$src1_modifiers, Src1RC:$src1,
1816               clampmod0:$clamp))
1817      /* else */,
1818        // VOP2 without modifiers
1819        !if (HasClamp,
1820          (ins Src0RC:$src0, Src1RC:$src1, clampmod0:$clamp),
1821          (ins Src0RC:$src0, Src1RC:$src1))
1822
1823      /* endif */ )
1824    /* NumSrcArgs == 3 */,
1825      !if (HasModifiers,
1826        !if (HasSrc2Mods,
1827          // VOP3 with modifiers
1828          !if (HasOMod,
1829            (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1830                 Src1Mod:$src1_modifiers, Src1RC:$src1,
1831                 Src2Mod:$src2_modifiers, Src2RC:$src2,
1832                 clampmod0:$clamp, omod0:$omod),
1833            !if (HasClamp,
1834              (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1835                   Src1Mod:$src1_modifiers, Src1RC:$src1,
1836                   Src2Mod:$src2_modifiers, Src2RC:$src2,
1837                   clampmod0:$clamp),
1838              (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1839                   Src1Mod:$src1_modifiers, Src1RC:$src1,
1840                   Src2Mod:$src2_modifiers, Src2RC:$src2))),
1841          // VOP3 with modifiers except src2
1842          !if (HasOMod,
1843            (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1844                 Src1Mod:$src1_modifiers, Src1RC:$src1,
1845                 Src2RC:$src2, clampmod0:$clamp, omod0:$omod),
1846            !if (HasClamp,
1847              (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1848                   Src1Mod:$src1_modifiers, Src1RC:$src1,
1849                   Src2RC:$src2, clampmod0:$clamp),
1850              (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
1851                   Src1Mod:$src1_modifiers, Src1RC:$src1,
1852                   Src2RC:$src2))))
1853      /* else */,
1854        // VOP3 without modifiers
1855        !if (HasClamp,
1856          (ins Src0RC:$src0, Src1RC:$src1, Src2RC:$src2, clampmod0:$clamp),
1857          (ins Src0RC:$src0, Src1RC:$src1, Src2RC:$src2))
1858      /* endif */ ))));
1859}
1860
1861class getInsVOP3Base<RegisterOperand Src0RC, RegisterOperand Src1RC,
1862                RegisterOperand Src2RC, int NumSrcArgs,
1863                bit HasClamp, bit HasModifiers, bit HasSrc2Mods, bit HasOMod,
1864                Operand Src0Mod, Operand Src1Mod, Operand Src2Mod, bit HasOpSel,
1865                bit IsVOP3P> {
1866  // getInst64 handles clamp and omod. implicit mutex between vop3p and omod
1867  dag base = getIns64 <Src0RC, Src1RC, Src2RC, NumSrcArgs,
1868                HasClamp, HasModifiers, HasSrc2Mods, HasOMod,
1869                Src0Mod, Src1Mod, Src2Mod>.ret;
1870  dag opsel = (ins op_sel0:$op_sel);
1871  dag vop3pOpsel = (ins op_sel_hi0:$op_sel_hi);
1872  dag vop3pFields = !con(!if(HasOpSel, vop3pOpsel, (ins)), (ins neg_lo0:$neg_lo, neg_hi0:$neg_hi));
1873
1874  dag ret = !con(base,
1875                 !if(HasOpSel, opsel,(ins)),
1876                 !if(IsVOP3P, vop3pFields,(ins)));
1877}
1878
1879class getInsVOP3P <RegisterOperand Src0RC, RegisterOperand Src1RC,
1880                   RegisterOperand Src2RC, int NumSrcArgs, bit HasClamp, bit HasOpSel,
1881                   Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> {
1882  dag ret = getInsVOP3Base<Src0RC, Src1RC, Src2RC, NumSrcArgs,
1883                    HasClamp, 1/*HasModifiers*/, 1/*HasSrc2Mods*/,
1884                    0/*HasOMod*/, Src0Mod, Src1Mod, Src2Mod,
1885                    HasOpSel, 1/*IsVOP3P*/>.ret;
1886}
1887
1888class getInsVOP3OpSel <RegisterOperand Src0RC, RegisterOperand Src1RC,
1889                       RegisterOperand Src2RC, int NumSrcArgs,
1890                       bit HasClamp, bit HasOMod,
1891                       Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> {
1892  dag ret = getInsVOP3Base<Src0RC, Src1RC,
1893                    Src2RC, NumSrcArgs,
1894                    HasClamp, 1/*HasModifiers*/, 1/*HasSrc2Mods*/, HasOMod,
1895                    Src0Mod, Src1Mod, Src2Mod, 1/*HasOpSel*/, 0>.ret;
1896}
1897
1898class getInsDPPBase <RegisterOperand OldRC, RegisterClass Src0RC, RegisterClass Src1RC,
1899                 RegisterClass Src2RC, int NumSrcArgs, bit HasModifiers,
1900                 Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> {
1901
1902  dag ret = !if (!eq(NumSrcArgs, 0),
1903                // VOP1 without input operands (V_NOP)
1904                (ins ),
1905            !if (!eq(NumSrcArgs, 1),
1906              !if (HasModifiers,
1907                // VOP1_DPP with modifiers
1908                (ins OldRC:$old, Src0Mod:$src0_modifiers,
1909                     Src0RC:$src0)
1910              /* else */,
1911                // VOP1_DPP without modifiers
1912                (ins OldRC:$old, Src0RC:$src0)
1913              /* endif */),
1914            !if (!eq(NumSrcArgs, 2),
1915              !if (HasModifiers,
1916                // VOP2_DPP with modifiers
1917                (ins OldRC:$old,
1918                     Src0Mod:$src0_modifiers, Src0RC:$src0,
1919                     Src1Mod:$src1_modifiers, Src1RC:$src1)
1920              /* else */,
1921                // VOP2_DPP without modifiers
1922                (ins OldRC:$old,
1923                     Src0RC:$src0, Src1RC:$src1)
1924                )
1925              /* NumSrcArgs == 3, VOP3 */,
1926              !if (HasModifiers,
1927                // VOP3_DPP with modifiers
1928                (ins OldRC:$old,
1929                     Src0Mod:$src0_modifiers, Src0RC:$src0,
1930                     Src1Mod:$src1_modifiers, Src1RC:$src1,
1931                     Src2Mod:$src2_modifiers, Src2RC:$src2)
1932              /* else */,
1933                // VOP3_DPP without modifiers
1934                (ins OldRC:$old,
1935                     Src0RC:$src0, Src1RC:$src1,
1936                     Src2RC:$src2)
1937                )
1938             /* endif */)));
1939}
1940
1941class getInsDPP <RegisterOperand OldRC, RegisterClass Src0RC, RegisterClass Src1RC,
1942                 RegisterClass Src2RC, int NumSrcArgs, bit HasModifiers,
1943                 Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> {
1944  dag ret = !con(getInsDPPBase<OldRC, Src0RC, Src1RC, Src2RC, NumSrcArgs,
1945                           HasModifiers, Src0Mod, Src1Mod, Src2Mod>.ret,
1946                 (ins dpp_ctrl:$dpp_ctrl, row_mask:$row_mask,
1947                     bank_mask:$bank_mask, bound_ctrl:$bound_ctrl));
1948}
1949
1950class getInsDPP16 <RegisterOperand OldRC, RegisterClass Src0RC, RegisterClass Src1RC,
1951                 RegisterClass Src2RC, int NumSrcArgs, bit HasModifiers,
1952                 Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> {
1953  dag ret = !con(getInsDPP<OldRC, Src0RC, Src1RC, Src2RC, NumSrcArgs,
1954                           HasModifiers, Src0Mod, Src1Mod, Src2Mod>.ret,
1955                 (ins FI:$fi));
1956}
1957
1958class getInsDPP8 <RegisterOperand OldRC, RegisterClass Src0RC, RegisterClass Src1RC,
1959                 RegisterClass Src2RC, int NumSrcArgs, bit HasModifiers,
1960                 Operand Src0Mod, Operand Src1Mod, Operand Src2Mod> {
1961  dag ret = !con(getInsDPPBase<OldRC, Src0RC, Src1RC, Src2RC, NumSrcArgs,
1962                           HasModifiers, Src0Mod, Src1Mod, Src2Mod>.ret,
1963                 (ins dpp8:$dpp8, FI:$fi));
1964}
1965
1966class getInsVOP3DPPBase<dag VOP3Base, RegisterOperand OldRC, int NumSrcArgs> {
1967  dag old = ( ins OldRC:$old );
1968  dag base = VOP3Base;
1969  dag ret =  !con(
1970                !if(!ne(NumSrcArgs, 0), old, (ins)),
1971                base
1972              );
1973}
1974
1975class getInsVOP3DPP<dag VOP3Base, RegisterOperand OldRC, int NumSrcArgs> {
1976  dag ret = !con(getInsVOP3DPPBase<VOP3Base,OldRC,NumSrcArgs>.ret,
1977                 (ins dpp_ctrl:$dpp_ctrl, row_mask:$row_mask,
1978                     bank_mask:$bank_mask, bound_ctrl:$bound_ctrl));
1979}
1980
1981class getInsVOP3DPP16<dag VOP3Base, RegisterOperand OldRC, int NumSrcArgs> {
1982  dag ret = !con(getInsVOP3DPP<VOP3Base,OldRC,NumSrcArgs>.ret,
1983                 (ins FI:$fi));
1984}
1985
1986class getInsVOP3DPP8<dag VOP3Base, RegisterOperand OldRC, int NumSrcArgs> {
1987  dag ret = !con(getInsVOP3DPPBase<VOP3Base,OldRC,NumSrcArgs>.ret,
1988                 (ins dpp8:$dpp8, FI:$fi));
1989}
1990
1991// Ins for SDWA
1992class getInsSDWA <RegisterOperand Src0RC, RegisterOperand Src1RC, int NumSrcArgs,
1993                  bit HasSDWAOMod, Operand Src0Mod, Operand Src1Mod,
1994                  ValueType DstVT> {
1995
1996  dag ret = !if(!eq(NumSrcArgs, 0),
1997               // VOP1 without input operands (V_NOP)
1998               (ins),
1999            !if(!eq(NumSrcArgs, 1),
2000               // VOP1
2001               !if(!not(HasSDWAOMod),
2002                  // VOP1_SDWA without omod
2003                  (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
2004                       clampmod:$clamp,
2005                       dst_sel:$dst_sel, dst_unused:$dst_unused,
2006                       src0_sel:$src0_sel),
2007                  // VOP1_SDWA with omod
2008                  (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
2009                       clampmod:$clamp, omod:$omod,
2010                       dst_sel:$dst_sel, dst_unused:$dst_unused,
2011                       src0_sel:$src0_sel)),
2012            !if(!eq(NumSrcArgs, 2),
2013               !if(!eq(DstVT.Size, 1),
2014                  // VOPC_SDWA
2015                  (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
2016                       Src1Mod:$src1_modifiers, Src1RC:$src1,
2017                       clampmod:$clamp, src0_sel:$src0_sel, src1_sel:$src1_sel),
2018                  // VOP2_SDWA
2019                  !if(!not(HasSDWAOMod),
2020                     // VOP2_SDWA without omod
2021                     (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
2022                          Src1Mod:$src1_modifiers, Src1RC:$src1,
2023                          clampmod:$clamp,
2024                          dst_sel:$dst_sel, dst_unused:$dst_unused,
2025                          src0_sel:$src0_sel, src1_sel:$src1_sel),
2026                     // VOP2_SDWA with omod
2027                     (ins Src0Mod:$src0_modifiers, Src0RC:$src0,
2028                          Src1Mod:$src1_modifiers, Src1RC:$src1,
2029                          clampmod:$clamp, omod:$omod,
2030                          dst_sel:$dst_sel, dst_unused:$dst_unused,
2031                          src0_sel:$src0_sel, src1_sel:$src1_sel))),
2032            (ins)/* endif */)));
2033}
2034
2035// Outs for DPP
2036class getOutsDPP <bit HasDst, ValueType DstVT, RegisterOperand DstRCDPP> {
2037  dag ret = !if(HasDst,
2038                !if(!eq(DstVT.Size, 1),
2039                    (outs), // no dst for VOPC, we use "vcc"-token as dst in SDWA VOPC instructions
2040                    (outs DstRCDPP:$vdst)),
2041                (outs)); // V_NOP
2042}
2043
2044// Outs for SDWA
2045class getOutsSDWA <bit HasDst, ValueType DstVT, RegisterOperand DstRCSDWA> {
2046  dag ret = !if(HasDst,
2047                !if(!eq(DstVT.Size, 1),
2048                    (outs DstRCSDWA:$sdst),
2049                    (outs DstRCSDWA:$vdst)),
2050                (outs)); // V_NOP
2051}
2052
2053// Returns the assembly string for the inputs and outputs of a VOP[12C]
2054// instruction.  This does not add the _e32 suffix, so it can be reused
2055// by getAsm64.
2056class getAsm32 <bit HasDst, int NumSrcArgs, ValueType DstVT = i32> {
2057  string dst = !if(!eq(DstVT.Size, 1), "$sdst", "$vdst"); // use $sdst for VOPC
2058  string src0 = ", $src0";
2059  string src1 = ", $src1";
2060  string src2 = ", $src2";
2061  string ret = !if(HasDst, dst, "") #
2062               !if(!eq(NumSrcArgs, 1), src0, "") #
2063               !if(!eq(NumSrcArgs, 2), src0#src1, "") #
2064               !if(!eq(NumSrcArgs, 3), src0#src1#src2, "");
2065}
2066
2067class getAsmVOPDPart <int NumSrcArgs, string XorY> {
2068  string dst = "$vdst" # XorY;
2069  string src0 = ", $src0" # XorY;
2070  string src1 = ", $vsrc1" # XorY;
2071  string ret = dst #
2072               !if(!ge(NumSrcArgs, 1), src0, "") #
2073               !if(!ge(NumSrcArgs, 2), src1, "");
2074}
2075
2076// Returns the assembly string for the inputs and outputs of a VOP3
2077// instruction.
2078class getAsm64 <bit HasDst, int NumSrcArgs, bit HasIntClamp, bit HasModifiers,
2079                bit HasOMod, ValueType DstVT = i32> {
2080  string dst = !if(!eq(DstVT.Size, 1), "$sdst", "$vdst"); // use $sdst for VOPC
2081  string src0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,");
2082  string src1 = !if(!eq(NumSrcArgs, 1), "",
2083                   !if(!eq(NumSrcArgs, 2), " $src1_modifiers",
2084                                           " $src1_modifiers,"));
2085  string src2 = !if(!eq(NumSrcArgs, 3), " $src2_modifiers", "");
2086  string iclamp = !if(HasIntClamp, "$clamp", "");
2087  string ret =
2088  !if(!not(HasModifiers),
2089      getAsm32<HasDst, NumSrcArgs, DstVT>.ret # iclamp,
2090      dst#", "#src0#src1#src2#"$clamp"#!if(HasOMod, "$omod", ""));
2091}
2092
2093// Returns the assembly string for the inputs and outputs of a VOP3P
2094// instruction.
2095class getAsmVOP3P <int NumSrcArgs, bit HasModifiers,
2096                   bit HasClamp, bit HasOpSel> {
2097  string dst = "$vdst";
2098  string src0 = !if(!eq(NumSrcArgs, 1), "$src0", "$src0,");
2099  string src1 = !if(!eq(NumSrcArgs, 1), "",
2100                   !if(!eq(NumSrcArgs, 2), " $src1",
2101                                           " $src1,"));
2102  string src2 = !if(!eq(NumSrcArgs, 3), " $src2", "");
2103
2104  string mods = !if(HasModifiers, "$neg_lo$neg_hi", "");
2105  string clamp = !if(HasClamp, "$clamp", "");
2106  string opsel = !if(HasOpSel, "$op_sel$op_sel_hi", "");
2107
2108  // Each modifier is printed as an array of bits for each operand, so
2109  // all operands are printed as part of src0_modifiers.
2110  string ret = dst#", "#src0#src1#src2#opsel#mods#clamp;
2111}
2112
2113class getAsmVOP3OpSel <int NumSrcArgs,
2114                       bit HasClamp,
2115                       bit Src0HasMods,
2116                       bit Src1HasMods,
2117                       bit Src2HasMods> {
2118  string dst = "$vdst";
2119
2120  string isrc0 = !if(!eq(NumSrcArgs, 1), "$src0", "$src0,");
2121  string isrc1 = !if(!eq(NumSrcArgs, 1), "",
2122                     !if(!eq(NumSrcArgs, 2), " $src1",
2123                                             " $src1,"));
2124  string isrc2 = !if(!eq(NumSrcArgs, 3), " $src2", "");
2125
2126  string fsrc0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,");
2127  string fsrc1 = !if(!eq(NumSrcArgs, 1), "",
2128                     !if(!eq(NumSrcArgs, 2), " $src1_modifiers",
2129                                             " $src1_modifiers,"));
2130  string fsrc2 = !if(!eq(NumSrcArgs, 3), " $src2_modifiers", "");
2131
2132  string src0 = !if(Src0HasMods, fsrc0, isrc0);
2133  string src1 = !if(Src1HasMods, fsrc1, isrc1);
2134  string src2 = !if(Src2HasMods, fsrc2, isrc2);
2135
2136  string clamp = !if(HasClamp, "$clamp", "");
2137  string omod = "";
2138  string ret = dst#", "#src0#src1#src2#"$op_sel"#clamp#omod;
2139}
2140
2141class getAsmDPP <bit HasDst, int NumSrcArgs, bit HasModifiers, ValueType DstVT = i32> {
2142  string dst = !if(HasDst,
2143                   !if(!eq(DstVT.Size, 1),
2144                       "$sdst",
2145                       "$vdst"),
2146                    ""); // use $sdst for VOPC
2147  string src0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,");
2148  string src1 = !if(!eq(NumSrcArgs, 1), "",
2149                   !if(!eq(NumSrcArgs, 2), " $src1_modifiers",
2150                                           " $src1_modifiers,"));
2151  string args = !if(!not(HasModifiers),
2152                     getAsm32<0, NumSrcArgs, DstVT>.ret,
2153                     ", "#src0#src1);
2154  string ret = dst#args#" $dpp_ctrl$row_mask$bank_mask$bound_ctrl";
2155}
2156
2157class getAsmDPP16 <bit HasDst, int NumSrcArgs, bit HasModifiers, ValueType DstVT = i32> {
2158  string ret = getAsmDPP<HasDst, NumSrcArgs, HasModifiers, DstVT>.ret#"$fi";
2159}
2160
2161class getAsmDPP8 <bit HasDst, int NumSrcArgs, bit HasModifiers, ValueType DstVT = i32>
2162  : getAsmDPP<HasDst, NumSrcArgs, HasModifiers, DstVT>{
2163  let ret = dst#args#" $dpp8$fi";
2164}
2165
2166class getAsmVOP3DPPBase <int NumSrcArgs, bit HasDst, bit HasClamp,
2167                       bit HasOpSel, bit HasOMod, bit IsVOP3P,
2168                       bit HasModifiers, bit Src0HasMods,
2169                       bit Src1HasMods, bit Src2HasMods, ValueType DstVT = i32> {
2170  string dst = !if(HasDst,
2171                   !if(!eq(DstVT.Size, 1),
2172                       "$sdst",
2173                       "$vdst"),
2174                    ""); // use $sdst for VOPC
2175  string src0nomods = !if(!eq(NumSrcArgs, 1), "$src0", "$src0,");
2176  string src1nomods = !if(!eq(NumSrcArgs, 1), "",
2177                    !if(!eq(NumSrcArgs, 2), " $src1",
2178                                            " $src1,"));
2179  string src2nomods = !if(!eq(NumSrcArgs, 3), " $src2", "");
2180
2181  string src0mods = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,");
2182  string src1mods = !if(!eq(NumSrcArgs, 1), "",
2183                    !if(!eq(NumSrcArgs, 2), " $src1_modifiers",
2184                                            " $src1_modifiers,"));
2185  string src2mods = !if(!eq(NumSrcArgs, 3), " $src2_modifiers", "");
2186
2187  string src0 = !if(Src0HasMods, src0mods, src0nomods);
2188  string src1 = !if(Src1HasMods, src1mods, src1nomods);
2189  string src2 = !if(Src2HasMods, src2mods, src2nomods);
2190  string opsel = !if(HasOpSel, "$op_sel", "");
2191  string 3PMods = !if(IsVOP3P,
2192                      !if(HasOpSel, "$op_sel_hi", "")
2193                        #!if(HasModifiers, "$neg_lo$neg_hi", ""),
2194                      "");
2195  string clamp = !if(HasClamp, "$clamp", "");
2196  string omod = !if(HasOMod, "$omod", "");
2197
2198  string ret = dst#", "#src0#src1#src2#opsel#3PMods#clamp#omod;
2199
2200}
2201
2202class getAsmVOP3DPP<string base> {
2203  string ret = base # " $dpp_ctrl$row_mask$bank_mask$bound_ctrl";
2204}
2205
2206class getAsmVOP3DPP16<string base> {
2207  string ret = getAsmVOP3DPP<base>.ret # "$fi";
2208}
2209
2210class getAsmVOP3DPP8<string base> {
2211  string ret = base # " $dpp8$fi";
2212}
2213
2214
2215class getAsmSDWA <bit HasDst, int NumSrcArgs, ValueType DstVT = i32> {
2216  string dst = !if(HasDst,
2217                   !if(!eq(DstVT.Size, 1),
2218                       " vcc", // use vcc token as dst for VOPC instructions
2219                       "$vdst"),
2220                    "");
2221  string src0 = "$src0_modifiers";
2222  string src1 = "$src1_modifiers";
2223  string args = !if(!eq(NumSrcArgs, 0),
2224                    "",
2225                    !if(!eq(NumSrcArgs, 1),
2226                        ", "#src0#"$clamp",
2227                        ", "#src0#", "#src1#"$clamp"
2228                     )
2229                );
2230  string sdwa = !if(!eq(NumSrcArgs, 0),
2231                    "",
2232                    !if(!eq(NumSrcArgs, 1),
2233                        " $dst_sel $dst_unused $src0_sel",
2234                        !if(!eq(DstVT.Size, 1),
2235                            " $src0_sel $src1_sel", // No dst_sel and dst_unused for VOPC
2236                            " $dst_sel $dst_unused $src0_sel $src1_sel"
2237                        )
2238                    )
2239                );
2240  string ret = dst#args#sdwa;
2241}
2242
2243class getAsmSDWA9 <bit HasDst, bit HasOMod, int NumSrcArgs,
2244                   ValueType DstVT = i32> {
2245  string dst = !if(HasDst,
2246                   !if(!eq(DstVT.Size, 1),
2247                       "$sdst", // VOPC
2248                       "$vdst"), // VOP1/2
2249                    "");
2250  string src0 = "$src0_modifiers";
2251  string src1 = "$src1_modifiers";
2252  string out_mods = !if(!not(HasOMod), "$clamp", "$clamp$omod");
2253  string args = !if(!eq(NumSrcArgs, 0), "",
2254                    !if(!eq(NumSrcArgs, 1),
2255                        ", "#src0,
2256                        ", "#src0#", "#src1
2257                     )
2258                );
2259  string sdwa = !if(!eq(NumSrcArgs, 0), "",
2260                    !if(!eq(NumSrcArgs, 1),
2261                        out_mods#" $dst_sel $dst_unused $src0_sel",
2262                        !if(!eq(DstVT.Size, 1),
2263                            " $src0_sel $src1_sel", // No dst_sel, dst_unused and output modifiers for VOPC
2264                            out_mods#" $dst_sel $dst_unused $src0_sel $src1_sel"
2265                        )
2266                    )
2267                );
2268  string ret = dst#args#sdwa;
2269}
2270
2271class getHas64BitOps <int NumSrcArgs, ValueType DstVT, ValueType Src0VT,
2272                      ValueType Src1VT> {
2273  bit ret = !if(!eq(NumSrcArgs, 3),
2274                0,
2275                !if(!eq(DstVT.Size, 64),
2276                    1,
2277                    !if(!eq(Src0VT.Size, 64),
2278                        1,
2279                        !if(!eq(Src1VT.Size, 64),
2280                            1,
2281                            0
2282                        )
2283                    )
2284                )
2285            );
2286}
2287
2288class getHasSDWA <int NumSrcArgs, ValueType DstVT = i32, ValueType Src0VT = i32,
2289                  ValueType Src1VT = i32> {
2290  bit ret = !if(!eq(NumSrcArgs, 3),
2291                0, // NumSrcArgs == 3 - No SDWA for VOP3
2292                !if(!eq(DstVT.Size, 64),
2293                    0, // 64-bit dst - No SDWA for 64-bit operands
2294                    !if(!eq(Src0VT.Size, 64),
2295                        0, // 64-bit src0
2296                        !if(!eq(Src1VT.Size, 64),
2297                            0, // 64-bit src2
2298                            1
2299                        )
2300                    )
2301                )
2302            );
2303}
2304
2305class getHasDPP <int NumSrcArgs> {
2306  bit ret = !if(!eq(NumSrcArgs, 3),
2307                0, // NumSrcArgs == 3 - No DPP for VOP3
2308                1);
2309}
2310
2311class getHasExt32BitDPP <int NumSrcArgs, ValueType DstVT = i32, ValueType Src0VT = i32,
2312                 ValueType Src1VT = i32> {
2313  bit ret = !and(getHasDPP<NumSrcArgs>.ret,
2314                 !not(getHas64BitOps<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret));
2315}
2316
2317class getHasExt64BitDPP <int NumSrcArgs, ValueType DstVT = i32, ValueType Src0VT = i32,
2318                 ValueType Src1VT = i32> {
2319  bit ret = !and(getHasDPP<NumSrcArgs>.ret,
2320                 getHas64BitOps<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret);
2321}
2322
2323// Function that checks if instruction supports DPP and SDWA
2324class getHasExt <int NumSrcArgs, ValueType DstVT = i32, ValueType Src0VT = i32,
2325                 ValueType Src1VT = i32> {
2326  bit ret = !or(getHasDPP<NumSrcArgs>.ret,
2327                getHasSDWA<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret);
2328}
2329
2330// Return an AGPR+VGPR operand class for the given VGPR register class.
2331class getLdStRegisterOperand<RegisterClass RC> {
2332  RegisterOperand ret =
2333    !if(!eq(RC.Size, 32), AVLdSt_32,
2334      !if(!eq(RC.Size, 64), AVLdSt_64,
2335        !if(!eq(RC.Size, 96), AVLdSt_96,
2336          !if(!eq(RC.Size, 128), AVLdSt_128,
2337            !if(!eq(RC.Size, 160), AVLdSt_160,
2338              RegisterOperand<VReg_1> // invalid register
2339    )))));
2340}
2341
2342class BitOr<bit a, bit b> {
2343  bit ret = !if(a, 1, !if(b, 1, 0));
2344}
2345
2346class BitAnd<bit a, bit b> {
2347  bit ret = !if(a, !if(b, 1, 0), 0);
2348}
2349
2350class getHasVOP3DPP <ValueType DstVT = i32, ValueType Src0VT = i32,
2351                 ValueType Src1VT = i32, ValueType Src2VT = i32> {
2352  bit ret =    !if(!eq(DstVT.Size, 64),
2353                    0, // 64-bit dst No DPP for 64-bit operands
2354                    !if(!eq(Src0VT.Size, 64),
2355                        0, // 64-bit src0
2356                        !if(!eq(Src1VT.Size, 64),
2357                            0, // 64-bit src1
2358                            !if(!eq(Src2VT.Size, 64),
2359                                0, // 64-bit src2
2360                                1
2361                            )
2362                        )
2363                    )
2364                );
2365}
2366
2367
2368def PatGenMode {
2369  int NoPattern = 0;
2370  int Pattern   = 1;
2371}
2372
2373class VOPProfile <list<ValueType> _ArgVT, bit _EnableF32SrcMods = 0,
2374                  bit _EnableClamp = 0> {
2375
2376  field list<ValueType> ArgVT = _ArgVT;
2377  field bit EnableF32SrcMods = _EnableF32SrcMods;
2378  field bit EnableClamp = _EnableClamp;
2379
2380  field ValueType DstVT = ArgVT[0];
2381  field ValueType Src0VT = ArgVT[1];
2382  field ValueType Src1VT = ArgVT[2];
2383  field ValueType Src2VT = ArgVT[3];
2384  field RegisterOperand DstRC = getVALUDstForVT<DstVT>.ret;
2385  field RegisterOperand DstRC64 = DstRC;
2386  field RegisterOperand DstRCDPP = getVALUDstForVT<DstVT>.ret;
2387  field RegisterOperand DstRCSDWA = getSDWADstForVT<DstVT>.ret;
2388  field RegisterOperand Src0RC32 = getVOPSrc0ForVT<Src0VT>.ret;
2389  field RegisterOperand Src1RC32 = RegisterOperand<getVregSrcForVT<Src1VT>.ret>;
2390  field RegisterOperand Src0RC64 = getVOP3SrcForVT<Src0VT>.ret;
2391  field RegisterOperand Src1RC64 = getVOP3SrcForVT<Src1VT>.ret;
2392  field RegisterOperand Src2RC64 = getVOP3SrcForVT<Src2VT>.ret;
2393  field RegisterClass Src0DPP = getVregSrcForVT<Src0VT>.ret;
2394  field RegisterClass Src1DPP = getVregSrcForVT<Src1VT>.ret;
2395  field RegisterClass Src2DPP = getVregSrcForVT<Src2VT>.ret;
2396  field RegisterOperand Src0VOP3DPP = VGPRSrc_32;
2397  field RegisterOperand Src1VOP3DPP = VGPRSrc_32;
2398  field RegisterOperand Src2VOP3DPP = getVOP3DPPSrcForVT<Src2VT>.ret;
2399  field RegisterOperand Src0SDWA = getSDWASrcForVT<Src0VT>.ret;
2400  field RegisterOperand Src1SDWA = getSDWASrcForVT<Src0VT>.ret;
2401  field Operand Src0Mod = getSrcMod<Src0VT, EnableF32SrcMods>.ret;
2402  field Operand Src1Mod = getSrcMod<Src1VT, EnableF32SrcMods>.ret;
2403  field Operand Src2Mod = getSrcMod<Src2VT, EnableF32SrcMods>.ret;
2404  field Operand Src0ModDPP = getSrcModDPP<Src0VT>.ret;
2405  field Operand Src1ModDPP = getSrcModDPP<Src1VT>.ret;
2406  field Operand Src2ModDPP = getSrcModDPP<Src2VT>.ret;
2407  field Operand Src2ModVOP3DPP = getSrcModVOP3DPP<Src2VT, EnableF32SrcMods>.ret;
2408  field Operand Src0ModSDWA = getSrcModSDWA<Src0VT>.ret;
2409  field Operand Src1ModSDWA = getSrcModSDWA<Src1VT>.ret;
2410
2411
2412  field bit HasDst = !ne(DstVT.Value, untyped.Value);
2413  field bit HasDst32 = HasDst;
2414  field bit EmitDst = HasDst; // force dst encoding, see v_movreld_b32 special case
2415  field bit EmitDstSel = EmitDst;
2416  field int NumSrcArgs = getNumSrcArgs<Src0VT, Src1VT, Src2VT>.ret;
2417  field bit HasSrc0 = !ne(Src0VT.Value, untyped.Value);
2418  field bit HasSrc1 = !ne(Src1VT.Value, untyped.Value);
2419  field bit HasSrc2 = !ne(Src2VT.Value, untyped.Value);
2420
2421  // HasSrc*FloatMods affects the SDWA encoding. We ignore EnableF32SrcMods.
2422  field bit HasSrc0FloatMods = isFloatType<Src0VT>.ret;
2423  field bit HasSrc1FloatMods = isFloatType<Src1VT>.ret;
2424  field bit HasSrc2FloatMods = isFloatType<Src2VT>.ret;
2425
2426  // HasSrc*IntMods affects the SDWA encoding. We ignore EnableF32SrcMods.
2427  field bit HasSrc0IntMods = isIntType<Src0VT>.ret;
2428  field bit HasSrc1IntMods = isIntType<Src1VT>.ret;
2429  field bit HasSrc2IntMods = isIntType<Src2VT>.ret;
2430
2431  field bit HasClamp = !or(isModifierType<Src0VT>.ret, EnableClamp);
2432  field bit HasSDWAClamp = EmitDst;
2433  field bit HasFPClamp = !and(isFloatType<DstVT>.ret, HasClamp);
2434  field bit HasIntClamp = !if(isFloatType<DstVT>.ret, 0, HasClamp);
2435  field bit HasClampLo = HasClamp;
2436  field bit HasClampHi = !and(isPackedType<DstVT>.ret, HasClamp);
2437  field bit HasHigh = 0;
2438
2439  field bit IsPacked = isPackedType<Src0VT>.ret;
2440  field bit HasOpSel = IsPacked;
2441  field bit HasOMod = !if(HasOpSel, 0, isFloatType<DstVT>.ret);
2442  field bit HasSDWAOMod = isFloatType<DstVT>.ret;
2443
2444  field bit HasModifiers = !or(isModifierType<Src0VT>.ret,
2445                               isModifierType<Src1VT>.ret,
2446                               isModifierType<Src2VT>.ret,
2447                               HasOMod,
2448                               EnableF32SrcMods);
2449
2450  field bit HasSrc0Mods = HasModifiers;
2451  field bit HasSrc1Mods = !if(HasModifiers, !or(HasSrc1FloatMods, HasSrc1IntMods), 0);
2452  field bit HasSrc2Mods = !if(HasModifiers, !or(HasSrc2FloatMods, HasSrc2IntMods), 0);
2453
2454  field bit HasExt = getHasExt<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret;
2455  field bit HasExtVOP3DPP = getHasVOP3DPP<DstVT, Src0VT, Src1VT, Src2VT>.ret;
2456  field bit HasExtDPP = !if(!or(getHasDPP<NumSrcArgs>.ret,
2457                HasExtVOP3DPP), 1, 0);
2458  field bit HasExt32BitDPP = getHasExt32BitDPP<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret;
2459  field bit HasExt64BitDPP = getHasExt64BitDPP<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret;
2460  field bit HasExtSDWA = getHasSDWA<NumSrcArgs, DstVT, Src0VT, Src1VT>.ret;
2461  field bit HasExtSDWA9 = HasExtSDWA;
2462  field int NeedPatGen = PatGenMode.NoPattern;
2463
2464  field bit IsMAI = 0;
2465  field bit IsVOP3P = 0;
2466  field bit IsDOT = 0;
2467  field bit IsSingle = 0;
2468  field bit IsWMMA = 0;
2469
2470  field Operand Src0PackedMod = !if(HasSrc0FloatMods, PackedF16InputMods, PackedI16InputMods);
2471  field Operand Src1PackedMod = !if(HasSrc1FloatMods, PackedF16InputMods, PackedI16InputMods);
2472  field Operand Src2PackedMod = !if(HasSrc2FloatMods, PackedF16InputMods, PackedI16InputMods);
2473
2474  field dag Outs = !if(HasDst,(outs DstRC:$vdst),(outs));
2475
2476  // VOP3b instructions are a special case with a second explicit
2477  // output. This is manually overridden for them.
2478  field dag Outs32 = Outs;
2479  field dag Outs64 = !if(HasDst,(outs DstRC64:$vdst),(outs));
2480  field dag OutsDPP = getOutsDPP<HasDst, DstVT, DstRCDPP>.ret;
2481  field dag OutsDPP8 = getOutsDPP<HasDst, DstVT, DstRCDPP>.ret;
2482  field dag OutsVOP3DPP = OutsDPP;
2483  field dag OutsVOP3DPP8 = OutsDPP8;
2484  field dag OutsSDWA = getOutsSDWA<HasDst, DstVT, DstRCSDWA>.ret;
2485
2486  field dag Ins32 = getIns32<Src0RC32, Src1RC32, NumSrcArgs>.ret;
2487  field dag Ins64 = getIns64<Src0RC64, Src1RC64, Src2RC64, NumSrcArgs,
2488                             HasIntClamp, HasModifiers, HasSrc2Mods,
2489                             HasOMod, Src0Mod, Src1Mod, Src2Mod>.ret;
2490  field dag InsVOP3P = getInsVOP3P<Src0RC64, Src1RC64, Src2RC64,
2491                                   NumSrcArgs, HasClamp, HasOpSel,
2492                                   Src0PackedMod, Src1PackedMod, Src2PackedMod>.ret;
2493  field dag InsVOP3OpSel = getInsVOP3OpSel<Src0RC64, Src1RC64, Src2RC64,
2494                                NumSrcArgs, HasClamp, HasOMod,
2495                                getOpSelMod<Src0VT>.ret,
2496                                getOpSelMod<Src1VT>.ret,
2497                                getOpSelMod<Src2VT>.ret>.ret;
2498  field dag InsDPP = !if(HasExtDPP,
2499                         getInsDPP<DstRCDPP, Src0DPP, Src1DPP, Src2DPP, NumSrcArgs,
2500                                   HasModifiers, Src0ModDPP, Src1ModDPP, Src2ModDPP>.ret,
2501                         (ins));
2502  field dag InsDPP16 = getInsDPP16<DstRCDPP, Src0DPP, Src1DPP, Src2DPP, NumSrcArgs,
2503                                   HasModifiers, Src0ModDPP, Src1ModDPP, Src2ModDPP>.ret;
2504  field dag InsDPP8 = getInsDPP8<DstRCDPP, Src0DPP, Src1DPP, Src2DPP,
2505                                 NumSrcArgs, HasModifiers,
2506                                 Src0ModDPP, Src1ModDPP, Src2ModDPP>.ret;
2507  field dag InsVOP3Base = getInsVOP3Base<Src0VOP3DPP, Src1VOP3DPP,
2508                  Src2VOP3DPP, NumSrcArgs, HasClamp, HasModifiers, HasSrc2Mods, HasOMod,
2509                  Src0ModDPP, Src1ModDPP, Src2ModVOP3DPP, HasOpSel, IsVOP3P>.ret;
2510  field dag InsVOP3DPP = getInsVOP3DPP<InsVOP3Base, DstRCDPP, NumSrcArgs>.ret;
2511  field dag InsVOP3DPP16 = getInsVOP3DPP16<InsVOP3Base, DstRCDPP, NumSrcArgs>.ret;
2512  field dag InsVOP3DPP8 = getInsVOP3DPP8<InsVOP3Base, DstRCDPP, NumSrcArgs>.ret;
2513  field dag InsSDWA = getInsSDWA<Src0SDWA, Src1SDWA, NumSrcArgs,
2514                                 HasSDWAOMod, Src0ModSDWA, Src1ModSDWA,
2515                                 DstVT>.ret;
2516  field dag InsVOPDX = (ins Src0RC32:$src0X, Src1RC32:$vsrc1X);
2517  // It is a slight misnomer to use the deferred f32 operand type for non-float
2518  // operands, but this operand type will only be used if the other dual
2519  // component is FMAAK or FMAMK
2520  field dag InsVOPDXDeferred = (ins !if(!eq(Src0VT.Size, 32), VSrc_f32_Deferred, VSrc_f16_Deferred):$src0X, VGPR_32:$vsrc1X);
2521  field dag InsVOPDY = (ins Src0RC32:$src0Y, Src1RC32:$vsrc1Y);
2522  field dag InsVOPDYDeferred = (ins !if(!eq(Src1VT.Size, 32), VSrc_f32_Deferred, VSrc_f16_Deferred):$src0Y, VGPR_32:$vsrc1Y);
2523
2524
2525  field string Asm32 = getAsm32<HasDst, NumSrcArgs, DstVT>.ret;
2526  field string Asm64 = getAsm64<HasDst, NumSrcArgs, HasIntClamp, HasModifiers, HasOMod, DstVT>.ret;
2527  field string AsmVOP3P = getAsmVOP3P<NumSrcArgs, HasModifiers, HasClamp, HasOpSel>.ret;
2528  field string AsmVOP3OpSel = getAsmVOP3OpSel<NumSrcArgs,
2529                                              HasClamp,
2530                                              HasSrc0FloatMods,
2531                                              HasSrc1FloatMods,
2532                                              HasSrc2FloatMods>.ret;
2533  field string AsmDPP = !if(HasExtDPP,
2534                            getAsmDPP<HasDst, NumSrcArgs, HasModifiers, DstVT>.ret, "");
2535  field string AsmDPP16 = getAsmDPP16<HasDst, NumSrcArgs, HasModifiers, DstVT>.ret;
2536  // DPP8 encoding has no fields for modifiers, and it is enforced by setting
2537  // the asm operand name via this HasModifiers flag
2538  field string AsmDPP8 = getAsmDPP8<HasDst, NumSrcArgs, 0 /*HasModifiers*/, DstVT>.ret;
2539  field string AsmVOP3DPPBase = getAsmVOP3DPPBase<NumSrcArgs, HasDst, HasClamp,
2540   HasOpSel, HasOMod, IsVOP3P, HasModifiers, HasModifiers, HasModifiers,
2541   HasModifiers, DstVT>.ret;
2542  field string AsmVOP3DPP = getAsmVOP3DPP<AsmVOP3DPPBase>.ret;
2543  field string AsmVOP3DPP16 = getAsmVOP3DPP16<AsmVOP3DPPBase>.ret;
2544  field string AsmVOP3DPP8 = getAsmVOP3DPP8<AsmVOP3DPPBase>.ret;
2545  field string AsmSDWA = getAsmSDWA<HasDst, NumSrcArgs, DstVT>.ret;
2546  field string AsmSDWA9 = getAsmSDWA9<HasDst, HasSDWAOMod, NumSrcArgs, DstVT>.ret;
2547  field string AsmVOPDX = getAsmVOPDPart<NumSrcArgs, "X">.ret;
2548  field string AsmVOPDY = getAsmVOPDPart<NumSrcArgs, "Y">.ret;
2549  field string TieRegDPP = "$old";
2550}
2551
2552  class VOP_NO_EXT <VOPProfile p> : VOPProfile <p.ArgVT> {
2553  let HasExt = 0;
2554  let HasExtDPP = 0;
2555  let HasExtVOP3DPP = 0;
2556  let HasExt32BitDPP = 0;
2557  let HasExt64BitDPP = 0;
2558  let HasExtSDWA = 0;
2559  let HasExtSDWA9 = 0;
2560}
2561
2562class VOP_PAT_GEN <VOPProfile p, int mode=PatGenMode.NoPattern> : VOPProfile <p.ArgVT> {
2563  let NeedPatGen = mode;
2564}
2565def VOP_F16_F16 : VOPProfile <[f16, f16, untyped, untyped]>;
2566def VOP_F16_I16 : VOPProfile <[f16, i16, untyped, untyped]>;
2567def VOP_I16_F16 : VOPProfile <[i16, f16, untyped, untyped]>;
2568def VOP_I16_I16 : VOPProfile <[i16, i16, untyped, untyped]>;
2569
2570def VOP_F16_F16_F16 : VOPProfile <[f16, f16, f16, untyped]>;
2571def VOP_F16_F16_I16 : VOPProfile <[f16, f16, i16, untyped]>;
2572def VOP_F16_F16_I32 : VOPProfile <[f16, f16, i32, untyped]>;
2573def VOP_I16_I16_I16 : VOPProfile <[i16, i16, i16, untyped]>;
2574def VOP_I16_I16_I16_ARITH : VOPProfile <[i16, i16, i16, untyped], 0, /*EnableClamp=*/1>;
2575
2576def VOP_I16_I16_I16_I16 : VOPProfile <[i16, i16, i16, i16, untyped]>;
2577def VOP_F16_F16_F16_F16 : VOPProfile <[f16, f16, f16, f16, untyped]>;
2578
2579def VOP_I32_I16_I16_I32 : VOPProfile <[i32, i16, i16, i32, untyped]>;
2580def VOP_I32_I16 : VOPProfile <[i32, i16, untyped, untyped]>;
2581
2582def VOP_V2F16_V2F16_V2F16 : VOPProfile <[v2f16, v2f16, v2f16, untyped]>;
2583def VOP_V2I16_V2I16_V2I16 : VOPProfile <[v2i16, v2i16, v2i16, untyped]>;
2584def VOP_B32_F16_F16 : VOPProfile <[i32, f16, f16, untyped]>;
2585
2586def VOP_V2F16_V2F16_V2F16_V2F16 : VOPProfile <[v2f16, v2f16, v2f16, v2f16]>;
2587def VOP_V2I16_V2I16_V2I16_V2I16 : VOPProfile <[v2i16, v2i16, v2i16, v2i16]>;
2588def VOP_V2I16_F32_F32 : VOPProfile <[v2i16, f32, f32, untyped]>;
2589def VOP_V2I16_I32_I32 : VOPProfile <[v2i16, i32, i32, untyped]>;
2590
2591def VOP_F16_V2F16_V2F16_F16 : VOPProfile <[f16, v2f16, v2f16, f16]>;
2592def VOP_I16_V2I16_V2I16_I16 : VOPProfile <[i16, v2i16, v2i16, i16]>;
2593def VOP_F32_V2I16_V2I16_F32 : VOPProfile <[f32, v2i16, v2i16, f32]>;
2594
2595def VOP_F32_V2F16_V2F16_V2F16 : VOPProfile <[f32, v2f16, v2f16, v2f16]>;
2596
2597def VOP_NONE : VOPProfile <[untyped, untyped, untyped, untyped]>;
2598
2599def VOP_F32_F32 : VOPProfile <[f32, f32, untyped, untyped]>;
2600def VOP_F32_F64 : VOPProfile <[f32, f64, untyped, untyped]>;
2601def VOP_F32_I32 : VOPProfile <[f32, i32, untyped, untyped]>;
2602def VOP_F64_F32 : VOPProfile <[f64, f32, untyped, untyped]>;
2603def VOP_F64_F64 : VOPProfile <[f64, f64, untyped, untyped]>;
2604def VOP_F64_I32 : VOPProfile <[f64, i32, untyped, untyped]>;
2605def VOP_I32_F32 : VOPProfile <[i32, f32, untyped, untyped]>;
2606def VOP_I32_F64 : VOPProfile <[i32, f64, untyped, untyped]>;
2607def VOP_I32_I32 : VOPProfile <[i32, i32, untyped, untyped]>;
2608def VOP_F16_F32 : VOPProfile <[f16, f32, untyped, untyped]>;
2609def VOP_F32_F16 : VOPProfile <[f32, f16, untyped, untyped]>;
2610def VOP_I64_I64 : VOPProfile <[i64, i64, untyped, untyped]>;
2611
2612def VOP_F32_F32_F16 : VOPProfile <[f32, f32, f16, untyped]>;
2613def VOP_F32_F32_F32 : VOPProfile <[f32, f32, f32, untyped]>;
2614def VOP_F32_F32_I32 : VOPProfile <[f32, f32, i32, untyped]>;
2615def VOP_F64_F64_F64 : VOPProfile <[f64, f64, f64, untyped]>;
2616def VOP_F64_F64_I32 : VOPProfile <[f64, f64, i32, untyped]>;
2617def VOP_I32_F32_F32 : VOPProfile <[i32, f32, f32, untyped]>;
2618def VOP_I32_F32_I32 : VOPProfile <[i32, f32, i32, untyped]>;
2619def VOP_I32_I32_I32 : VOPProfile <[i32, i32, i32, untyped]>;
2620def VOP_I32_I32_I32_ARITH : VOPProfile <[i32, i32, i32, untyped], 0, /*EnableClamp=*/1>;
2621def VOP_V2F16_F32_F32 : VOPProfile <[v2f16, f32, f32, untyped]>;
2622def VOP_F32_F16_F16_F16 : VOPProfile <[f32, f16, f16, f16]>;
2623
2624def VOP_I64_I64_I32 : VOPProfile <[i64, i64, i32, untyped]>;
2625def VOP_I64_I32_I64 : VOPProfile <[i64, i32, i64, untyped]>;
2626def VOP_I64_I64_I64 : VOPProfile <[i64, i64, i64, untyped]>;
2627
2628def VOP_F16_F32_F16_F32 : VOPProfile <[f16, f32, f16, f32]>;
2629def VOP_F32_F32_F16_F16 : VOPProfile <[f32, f32, f16, f16]>;
2630def VOP_F32_F32_F32_F32 : VOPProfile <[f32, f32, f32, f32]>;
2631def VOP_F64_F64_F64_F64 : VOPProfile <[f64, f64, f64, f64]>;
2632def VOP_I32_I32_I32_I32 : VOPProfile <[i32, i32, i32, i32]>;
2633def VOP_I64_I32_I32_I64 : VOPProfile <[i64, i32, i32, i64]>;
2634def VOP_I32_F32_I32_I32 : VOPProfile <[i32, f32, i32, i32]>;
2635def VOP_I64_I64_I32_I64 : VOPProfile <[i64, i64, i32, i64]>;
2636def VOP_V4I32_I64_I32_V4I32 : VOPProfile <[v4i32, i64, i32, v4i32]>;
2637
2638def VOP_F32_V2F16_V2F16_F32 : VOPProfile <[f32, v2f16, v2f16, f32]>;
2639def VOP_I32_V2I16_V2I16_I32 : VOPProfile <[i32, v2i16, v2i16, i32]>;
2640
2641def VOP_V4F32_F32_F32_V4F32       : VOPProfile <[v4f32,  f32,   f32,   v4f32]>;
2642def VOP_V16F32_F32_F32_V16F32     : VOPProfile <[v16f32, f32,   f32,   v16f32]>;
2643def VOP_V32F32_F32_F32_V32F32     : VOPProfile <[v32f32, f32,   f32,   v32f32]>;
2644def VOP_V4F32_V4F16_V4F16_V4F32   : VOPProfile <[v4f32,  v4f16, v4f16, v4f32]>;
2645def VOP_V16F32_V4F16_V4F16_V16F32 : VOPProfile <[v16f32, v4f16, v4f16, v16f32]>;
2646def VOP_V32F32_V4F16_V4F16_V32F32 : VOPProfile <[v32f32, v4f16, v4f16, v32f32]>;
2647def VOP_V4F32_V2I16_V2I16_V4F32   : VOPProfile <[v4f32,  v2i16, v2i16, v4f32]>;
2648def VOP_V16F32_V2I16_V2I16_V16F32 : VOPProfile <[v16f32, v2i16, v2i16, v16f32]>;
2649def VOP_V32F32_V2I16_V2I16_V32F32 : VOPProfile <[v32f32, v2i16, v2i16, v32f32]>;
2650def VOP_V4I32_I32_I32_V4I32       : VOPProfile <[v4i32,  i32,   i32,   v4i32]>;
2651def VOP_V16I32_I32_I32_V16I32     : VOPProfile <[v16i32, i32,   i32,   v16i32]>;
2652def VOP_V32I32_I32_I32_V32I32     : VOPProfile <[v32i32, i32,   i32,   v32i32]>;
2653
2654def VOP_V4F64_F64_F64_V4F64 : VOPProfile <[v4f64, f64, f64, v4f64]>;
2655def VOP_V1F64_F64_F64_V1F64 : VOPProfile <[v1f64, f64, f64, v1f64]>;
2656
2657def VOP_V2F32_V2F32_V2F32_V2F32   : VOPProfile <[v2f32,  v2f32, v2f32, v2f32]>;
2658def VOP_V2F32_V2F32_V2F32         : VOPProfile <[v2f32,  v2f32, v2f32, untyped]>;
2659def VOP_V2I32_V2I32_V2I32         : VOPProfile <[v2i32,  v2i32, v2i32, untyped]>;
2660def VOP_V4F32_V4I16_V4I16_V4F32   : VOPProfile <[v4f32,  v4i16, v4i16, v4f32]>;
2661def VOP_V16F32_V4I16_V4I16_V16F32 : VOPProfile <[v16f32, v4i16, v4i16, v16f32]>;
2662def VOP_V32F32_V4I16_V4I16_V32F32 : VOPProfile <[v32f32, v4i16, v4i16, v32f32]>;
2663
2664def VOP_V4I32_I64_I64_V4I32       : VOPProfile <[v4i32,  i64,   i64,   v4i32]>;
2665def VOP_V16I32_I64_I64_V16I32     : VOPProfile <[v16i32, i64,   i64,   v16i32]>;
2666def VOP_V4F32_V2F32_V2F32_V4F32   : VOPProfile <[v4f32,  v2f32, v2f32, v4f32]>;
2667def VOP_V16F32_V2F32_V2F32_V16F32 : VOPProfile <[v16f32, v2f32, v2f32, v16f32]>;
2668
2669def VOP_V4F32_V4F16_V8F16_I32     : VOPProfile <[v4f32,  v4f16, v8f16, i32]>;
2670def VOP_V16F32_V4F16_V8F16_I32    : VOPProfile <[v16f32, v4f16, v8f16, i32]>;
2671def VOP_V4F32_V4I16_V8I16_I32     : VOPProfile <[v4f32,  v4i16, v8i16, i32]>;
2672def VOP_V16F32_V4I16_V8I16_I32    : VOPProfile <[v16f32, v4i16, v8i16, i32]>;
2673def VOP_V4I32_V2I32_V4I32_I32     : VOPProfile <[v4i32,  v2i32, v4i32, i32]>;
2674def VOP_V16I32_V2I32_V4I32_I32    : VOPProfile <[v16i32, v2i32, v4i32, i32]>;
2675
2676class Commutable_REV <string revOp, bit isOrig> {
2677  string RevOp = revOp;
2678  bit IsOrig = isOrig;
2679}
2680
2681class AtomicNoRet <string noRetOp, bit isRet> {
2682  string NoRetOp = noRetOp;
2683  bit IsRet = isRet;
2684}
2685
2686//===----------------------------------------------------------------------===//
2687// Interpolation opcodes
2688//===----------------------------------------------------------------------===//
2689
2690class VINTRPDstOperand <RegisterClass rc> : RegisterOperand <rc, "printVINTRPDst">;
2691
2692class VINTRP_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
2693  VINTRPCommon <outs, ins, "", pattern>,
2694  SIMCInstr<opName, SIEncodingFamily.NONE> {
2695  let isPseudo = 1;
2696  let isCodeGenOnly = 1;
2697}
2698
2699// FIXME-GFX10: WIP.
2700class VINTRP_Real_si <bits <2> op, string opName, dag outs, dag ins,
2701                      string asm, int encodingFamily> :
2702  VINTRPCommon <outs, ins, asm, []>,
2703  VINTRPe <op>,
2704  SIMCInstr<opName, encodingFamily> {
2705}
2706
2707class VINTRP_Real_vi <bits <2> op, string opName, dag outs, dag ins,
2708                      string asm> :
2709  VINTRPCommon <outs, ins, asm, []>,
2710  VINTRPe_vi <op>,
2711  SIMCInstr<opName, SIEncodingFamily.VI> {
2712  let AssemblerPredicate = VIAssemblerPredicate;
2713  let DecoderNamespace = "GFX8";
2714}
2715
2716// FIXME-GFX10: WIP.
2717multiclass VINTRP_m <bits <2> op, dag outs, dag ins, string asm,
2718                     list<dag> pattern = []> {
2719  def "" : VINTRP_Pseudo <NAME, outs, ins, pattern>;
2720
2721  let AssemblerPredicate = isGFX6GFX7, DecoderNamespace = "GFX6GFX7" in {
2722    def _si : VINTRP_Real_si <op, NAME, outs, ins, asm, SIEncodingFamily.SI>;
2723  } // End AssemblerPredicate = isGFX6GFX7, DecoderNamespace = "GFX6GFX7"
2724
2725  def _vi : VINTRP_Real_vi <op, NAME, outs, ins, asm>;
2726
2727  let AssemblerPredicate = isGFX10Only, DecoderNamespace = "GFX10" in {
2728    def _gfx10 : VINTRP_Real_si<op, NAME, outs, ins, asm, SIEncodingFamily.GFX10>;
2729  } // End AssemblerPredicate = isGFX10Only, DecoderNamespace = "GFX10"
2730}
2731
2732//===----------------------------------------------------------------------===//
2733// Vector instruction mappings
2734//===----------------------------------------------------------------------===//
2735
2736// Maps an opcode in e32 form to its e64 equivalent
2737def getVOPe64 : InstrMapping {
2738  let FilterClass = "VOP";
2739  let RowFields = ["OpName"];
2740  let ColFields = ["Size", "VOP3"];
2741  let KeyCol = ["4", "0"];
2742  let ValueCols = [["8", "1"]];
2743}
2744
2745// Maps an opcode in e64 form to its e32 equivalent
2746def getVOPe32 : InstrMapping {
2747  let FilterClass = "VOP";
2748  let RowFields = ["OpName"];
2749  let ColFields = ["Size", "VOP3"];
2750  let KeyCol = ["8", "1"];
2751  let ValueCols = [["4", "0"]];
2752}
2753
2754// Maps ordinary instructions to their SDWA counterparts
2755def getSDWAOp : InstrMapping {
2756  let FilterClass = "VOP";
2757  let RowFields = ["OpName"];
2758  let ColFields = ["AsmVariantName"];
2759  let KeyCol = ["Default"];
2760  let ValueCols = [["SDWA"]];
2761}
2762
2763// Maps SDWA instructions to their ordinary counterparts
2764def getBasicFromSDWAOp : InstrMapping {
2765  let FilterClass = "VOP";
2766  let RowFields = ["OpName"];
2767  let ColFields = ["AsmVariantName"];
2768  let KeyCol = ["SDWA"];
2769  let ValueCols = [["Default"]];
2770}
2771
2772// Maps ordinary instructions to their DPP counterparts
2773def getDPPOp32 : InstrMapping {
2774  let FilterClass = "VOP";
2775  let RowFields = ["OpName"];
2776  let ColFields = ["AsmVariantName"];
2777  let KeyCol = ["Default"];
2778  let ValueCols = [["DPP"]];
2779}
2780
2781def getDPPOp64 : InstrMapping {
2782  let FilterClass = "VOP";
2783  let RowFields = ["OpName"];
2784  let ColFields = ["AsmVariantName"];
2785  let KeyCol = ["VOP3"];
2786  let ValueCols = [["VOP3_DPP"]];
2787}
2788
2789// Maps an commuted opcode to its original version
2790def getCommuteOrig : InstrMapping {
2791  let FilterClass = "Commutable_REV";
2792  let RowFields = ["RevOp"];
2793  let ColFields = ["IsOrig"];
2794  let KeyCol = ["0"];
2795  let ValueCols = [["1"]];
2796}
2797
2798// Maps an original opcode to its commuted version
2799def getCommuteRev : InstrMapping {
2800  let FilterClass = "Commutable_REV";
2801  let RowFields = ["RevOp"];
2802  let ColFields = ["IsOrig"];
2803  let KeyCol = ["1"];
2804  let ValueCols = [["0"]];
2805}
2806
2807def getMCOpcodeGen : InstrMapping {
2808  let FilterClass = "SIMCInstr";
2809  let RowFields = ["PseudoInstr"];
2810  let ColFields = ["Subtarget"];
2811  let KeyCol = [!cast<string>(SIEncodingFamily.NONE)];
2812  // These columns must be kept in sync with the SIEncodingFamily enumeration.
2813  let ValueCols = [[!cast<string>(SIEncodingFamily.SI)],
2814                   [!cast<string>(SIEncodingFamily.VI)],
2815                   [!cast<string>(SIEncodingFamily.SDWA)],
2816                   [!cast<string>(SIEncodingFamily.SDWA9)],
2817                   // GFX80 encoding is added to work around a multiple matching
2818                   // issue for buffer instructions with unpacked d16 data. This
2819                   // does not actually change the encoding, and thus may be
2820                   // removed later.
2821                   [!cast<string>(SIEncodingFamily.GFX80)],
2822                   [!cast<string>(SIEncodingFamily.GFX9)],
2823                   [!cast<string>(SIEncodingFamily.GFX10)],
2824                   [!cast<string>(SIEncodingFamily.SDWA10)],
2825                   [!cast<string>(SIEncodingFamily.GFX90A)],
2826                   [!cast<string>(SIEncodingFamily.GFX940)],
2827                   [!cast<string>(SIEncodingFamily.GFX11)]];
2828}
2829
2830// Get equivalent SOPK instruction.
2831def getSOPKOp : InstrMapping {
2832  let FilterClass = "SOPKInstTable";
2833  let RowFields = ["BaseCmpOp"];
2834  let ColFields = ["IsSOPK"];
2835  let KeyCol = ["0"];
2836  let ValueCols = [["1"]];
2837}
2838
2839def getAddr64Inst : InstrMapping {
2840  let FilterClass = "MUBUFAddr64Table";
2841  let RowFields = ["OpName"];
2842  let ColFields = ["IsAddr64"];
2843  let KeyCol = ["0"];
2844  let ValueCols = [["1"]];
2845}
2846
2847def getIfAddr64Inst : InstrMapping {
2848  let FilterClass = "MUBUFAddr64Table";
2849  let RowFields = ["OpName"];
2850  let ColFields = ["IsAddr64"];
2851  let KeyCol = ["1"];
2852  let ValueCols = [["1"]];
2853}
2854
2855// Maps an atomic opcode to its returnless version.
2856def getAtomicNoRetOp : InstrMapping {
2857  let FilterClass = "AtomicNoRet";
2858  let RowFields = ["NoRetOp"];
2859  let ColFields = ["IsRet"];
2860  let KeyCol = ["1"];
2861  let ValueCols = [["0"]];
2862}
2863
2864// Maps a GLOBAL to its SADDR form.
2865def getGlobalSaddrOp : InstrMapping {
2866  let FilterClass = "GlobalSaddrTable";
2867  let RowFields = ["SaddrOp"];
2868  let ColFields = ["IsSaddr"];
2869  let KeyCol = ["0"];
2870  let ValueCols = [["1"]];
2871}
2872
2873// Maps a GLOBAL SADDR to its VADDR form.
2874def getGlobalVaddrOp : InstrMapping {
2875  let FilterClass = "GlobalSaddrTable";
2876  let RowFields = ["SaddrOp"];
2877  let ColFields = ["IsSaddr"];
2878  let KeyCol = ["1"];
2879  let ValueCols = [["0"]];
2880}
2881
2882// Maps a v_cmpx opcode with sdst to opcode without sdst.
2883def getVCMPXNoSDstOp : InstrMapping {
2884  let FilterClass = "VCMPXNoSDstTable";
2885  let RowFields = ["NoSDstOp"];
2886  let ColFields = ["HasSDst"];
2887  let KeyCol = ["1"];
2888  let ValueCols = [["0"]];
2889}
2890
2891// Maps a SOPP to a SOPP with S_NOP
2892def getSOPPWithRelaxation : InstrMapping {
2893  let FilterClass = "SOPPRelaxTable";
2894  let RowFields = ["KeyName"];
2895  let ColFields = ["IsRelaxed"];
2896  let KeyCol = ["0"];
2897  let ValueCols = [["1"]];
2898}
2899
2900// Maps flat scratch opcodes by addressing modes
2901def getFlatScratchInstSTfromSS : InstrMapping {
2902  let FilterClass = "FlatScratchInst";
2903  let RowFields = ["SVOp"];
2904  let ColFields = ["Mode"];
2905  let KeyCol = ["SS"];
2906  let ValueCols = [["ST"]];
2907}
2908
2909def getFlatScratchInstSSfromSV : InstrMapping {
2910  let FilterClass = "FlatScratchInst";
2911  let RowFields = ["SVOp"];
2912  let ColFields = ["Mode"];
2913  let KeyCol = ["SV"];
2914  let ValueCols = [["SS"]];
2915}
2916
2917def getFlatScratchInstSVfromSVS : InstrMapping {
2918  let FilterClass = "FlatScratchInst";
2919  let RowFields = ["SVOp"];
2920  let ColFields = ["Mode"];
2921  let KeyCol = ["SVS"];
2922  let ValueCols = [["SV"]];
2923}
2924
2925def getFlatScratchInstSVfromSS : InstrMapping {
2926  let FilterClass = "FlatScratchInst";
2927  let RowFields = ["SVOp"];
2928  let ColFields = ["Mode"];
2929  let KeyCol = ["SS"];
2930  let ValueCols = [["SV"]];
2931}
2932
2933def getMFMAEarlyClobberOp : InstrMapping {
2934  let FilterClass = "MFMATable";
2935  let RowFields = ["FMAOp"];
2936  let ColFields = ["IsMac"];
2937  let KeyCol = ["1"];
2938  let ValueCols = [["0"]];
2939}
2940
2941// Maps an v_cmp instruction to its v_cmpx equivalent.
2942def getVCMPXOpFromVCMP : InstrMapping {
2943  let FilterClass = "VCMPVCMPXTable";
2944  let RowFields = ["VCMPOp"];
2945  let ColFields = ["IsVCMPX"];
2946  let KeyCol = ["0"];
2947  let ValueCols = [["1"]];
2948}
2949
2950def VOPDComponentTable : GenericTable {
2951  let FilterClass = "VOPD_Component";
2952  let CppTypeName = "VOPDComponentInfo";
2953  let Fields = ["BaseVOP", "VOPDOp", "CanBeVOPDX"];
2954  let PrimaryKey = ["BaseVOP"];
2955  let PrimaryKeyName = "getVOPDComponentHelper";
2956}
2957
2958def VOPDPairs : GenericTable {
2959  let FilterClass = "VOPD_Base";
2960  let CppTypeName = "VOPDInfo";
2961  let Fields = ["Opcode", "OpX", "OpY"];
2962  let PrimaryKey = ["Opcode"];
2963  let PrimaryKeyName = "getVOPDOpcodeHelper";
2964}
2965
2966def getVOPDInfoFromComponentOpcodes : SearchIndex {
2967  let Table = VOPDPairs;
2968  let Key = ["OpX", "OpY"];
2969}
2970
2971include "SIInstructions.td"
2972
2973include "DSInstructions.td"
2974include "MIMGInstructions.td"
2975