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