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