1//===---- SMInstructions.td - Scalar Memory Instruction Definitions -------===//
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 smrd_offset_8 : NamedOperandU32<"SMRDOffset8",
10                                  NamedMatchClass<"SMRDOffset8">> {
11  let OperandType = "OPERAND_IMMEDIATE";
12}
13
14class SMEMOffset : NamedOperandU32<"SMEMOffset",
15                                   NamedMatchClass<"SMEMOffset">> {
16  let OperandType = "OPERAND_IMMEDIATE";
17  let EncoderMethod = "getSMEMOffsetEncoding";
18  let DecoderMethod = "decodeSMEMOffset";
19}
20
21def smem_offset : SMEMOffset;
22
23def smem_offset_mod : SMEMOffset {
24  let PrintMethod = "printSMEMOffsetMod";
25}
26
27//===----------------------------------------------------------------------===//
28// Scalar Memory classes
29//===----------------------------------------------------------------------===//
30
31class SM_Pseudo <string opName, dag outs, dag ins, string asmOps, list<dag> pattern=[]> :
32  InstSI <outs, ins, "", pattern>,
33  SIMCInstr<opName, SIEncodingFamily.NONE> {
34  let isPseudo = 1;
35  let isCodeGenOnly = 1;
36
37  let LGKM_CNT = 1;
38  let SMRD = 1;
39  let mayStore = 0;
40  let mayLoad = 1;
41  let hasSideEffects = 0;
42  let UseNamedOperandTable = 1;
43  let SchedRW = [WriteSMEM];
44
45  string Mnemonic = opName;
46  string AsmOperands = asmOps;
47
48  bits<1> has_sbase = 1;
49  bits<1> has_sdst = 1;
50  bit has_glc = 0;
51  bit has_dlc = 0;
52  bit has_offset = 0;
53  bit has_soffset = 0;
54  bit is_buffer = 0;
55}
56
57class SM_Real <SM_Pseudo ps>
58  : InstSI<ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands, []> {
59
60  let isPseudo = 0;
61  let isCodeGenOnly = 0;
62
63  Instruction Opcode = !cast<Instruction>(NAME);
64
65  // copy relevant pseudo op flags
66  let LGKM_CNT             = ps.LGKM_CNT;
67  let SMRD                 = ps.SMRD;
68  let mayStore             = ps.mayStore;
69  let mayLoad              = ps.mayLoad;
70  let hasSideEffects       = ps.hasSideEffects;
71  let UseNamedOperandTable = ps.UseNamedOperandTable;
72  let SchedRW              = ps.SchedRW;
73  let SubtargetPredicate   = ps.SubtargetPredicate;
74  let AsmMatchConverter    = ps.AsmMatchConverter;
75  let IsAtomicRet          = ps.IsAtomicRet;
76  let IsAtomicNoRet        = ps.IsAtomicNoRet;
77
78  let TSFlags = ps.TSFlags;
79
80  bit is_buffer = ps.is_buffer;
81
82  // encoding
83  bits<7>  sbase;
84  bits<7>  sdst;
85  bits<32> offset;
86  bits<8>  soffset;
87  bits<5> cpol;
88}
89
90class SM_Probe_Pseudo <string opName, dag ins, bit isImm>
91  : SM_Pseudo<opName, (outs), ins,
92              " $sdata, $sbase, " # !if(isImm, "$offset", "$soffset")> {
93  let mayLoad = 0;
94  let mayStore = 0;
95  let has_glc = 0;
96  let LGKM_CNT = 0;
97  let ScalarStore = 0;
98  let hasSideEffects = 1;
99  let has_offset = isImm;
100  let has_soffset = !not(isImm);
101  let PseudoInstr = opName # !if(isImm, "_IMM", "_SGPR");
102}
103
104class SM_Load_Pseudo <string opName, dag outs, dag ins, string asmOps, list<dag> pattern=[]>
105  : SM_Pseudo<opName, outs, ins, asmOps, pattern> {
106  RegisterClass BaseClass;
107  let mayLoad = 1;
108  let mayStore = 0;
109  let has_glc = 1;
110  let has_dlc = 1;
111}
112
113class SM_Store_Pseudo <string opName, RegisterClass baseClass,
114                       RegisterClass srcClass, dag ins, string asmOps>
115  : SM_Pseudo<opName, (outs), ins, asmOps, []> {
116  RegisterClass BaseClass = baseClass;
117  RegisterClass SrcClass = srcClass;
118  let mayLoad = 0;
119  let mayStore = 1;
120  let has_glc = 1;
121  let has_dlc = 1;
122  let ScalarStore = 1;
123}
124
125class SM_Discard_Pseudo <string opName, dag ins, bit isImm>
126  : SM_Pseudo<opName, (outs), ins,
127              " $sbase, " # !if(isImm, "$offset", "$soffset")> {
128  let mayLoad = 0;
129  let mayStore = 0;
130  let has_glc = 0;
131  let has_sdst = 0;
132  let ScalarStore = 0;
133  let hasSideEffects = 1;
134  let has_offset = isImm;
135  let has_soffset = !not(isImm);
136  let PseudoInstr = opName # !if(isImm, "_IMM", "_SGPR");
137}
138
139multiclass SM_Pseudo_Loads<string opName,
140                           RegisterClass baseClass,
141                           RegisterClass dstClass> {
142  def _IMM  : SM_Load_Pseudo <opName,
143                              (outs dstClass:$sdst),
144                              (ins baseClass:$sbase, i32imm:$offset, CPol:$cpol),
145                              " $sdst, $sbase, $offset$cpol", []> {
146    let has_offset = 1;
147    let BaseClass = baseClass;
148    let PseudoInstr = opName # "_IMM";
149    let has_glc = 1;
150    let has_dlc = 1;
151  }
152
153  def _SGPR  : SM_Load_Pseudo <opName,
154                              (outs dstClass:$sdst),
155                              (ins baseClass:$sbase, SReg_32:$soffset, CPol:$cpol),
156                              " $sdst, $sbase, $soffset$cpol", []> {
157    let has_soffset = 1;
158    let BaseClass = baseClass;
159    let PseudoInstr = opName # "_SGPR";
160    let has_glc = 1;
161    let has_dlc = 1;
162  }
163
164  def _SGPR_IMM  : SM_Load_Pseudo <opName,
165                                   (outs dstClass:$sdst),
166                                   (ins baseClass:$sbase, SReg_32:$soffset,
167                                        i32imm:$offset, CPol:$cpol),
168                                   " $sdst, $sbase, $soffset$offset$cpol", []> {
169    let has_offset = 1;
170    let has_soffset = 1;
171    let BaseClass = baseClass;
172    let PseudoInstr = opName # "_SGPR_IMM";
173    let has_glc = 1;
174    let has_dlc = 1;
175  }
176}
177
178multiclass SM_Pseudo_Stores<string opName,
179                           RegisterClass baseClass,
180                           RegisterClass srcClass> {
181  def _IMM : SM_Store_Pseudo <opName, baseClass, srcClass,
182    (ins srcClass:$sdata, baseClass:$sbase, i32imm:$offset, CPol:$cpol),
183    " $sdata, $sbase, $offset$cpol"> {
184    let has_offset = 1;
185    let PseudoInstr = opName # "_IMM";
186  }
187
188  def _SGPR : SM_Store_Pseudo <opName, baseClass, srcClass,
189    (ins srcClass:$sdata, baseClass:$sbase, SReg_32:$soffset, CPol:$cpol),
190    " $sdata, $sbase, $soffset$cpol"> {
191    let has_soffset = 1;
192    let PseudoInstr = opName # "_SGPR";
193  }
194
195  def _SGPR_IMM : SM_Store_Pseudo <opName, baseClass, srcClass,
196    (ins srcClass:$sdata, baseClass:$sbase, SReg_32:$soffset, i32imm:$offset,
197     CPol:$cpol),
198    " $sdata, $sbase, $soffset$offset$cpol"> {
199    let has_offset = 1;
200    let has_soffset = 1;
201    let PseudoInstr = opName # "_SGPR_IMM";
202  }
203}
204
205multiclass SM_Pseudo_Discards<string opName> {
206  def _IMM  : SM_Discard_Pseudo <opName, (ins SReg_64:$sbase, smem_offset:$offset), 1>;
207  def _SGPR : SM_Discard_Pseudo <opName, (ins SReg_64:$sbase, SReg_32:$soffset), 0>;
208}
209
210class SM_Time_Pseudo<string opName, SDPatternOperator node = null_frag> : SM_Pseudo<
211  opName, (outs SReg_64_XEXEC:$sdst), (ins),
212  " $sdst", [(set i64:$sdst, (node))]> {
213  let hasSideEffects = 1;
214
215  let mayStore = 0;
216  let mayLoad = 0;
217  let has_sbase = 0;
218}
219
220class SM_Inval_Pseudo <string opName, SDPatternOperator node = null_frag> : SM_Pseudo<
221  opName, (outs), (ins), "", [(node)]> {
222  let hasSideEffects = 1;
223  let mayStore = 0;
224  let has_sdst = 0;
225  let has_sbase = 0;
226}
227
228multiclass SM_Pseudo_Probe<string opName, RegisterClass baseClass> {
229  def _IMM  : SM_Probe_Pseudo <opName, (ins i8imm:$sdata, baseClass:$sbase, smem_offset:$offset), 1>;
230  def _SGPR : SM_Probe_Pseudo <opName, (ins i8imm:$sdata, baseClass:$sbase, SReg_32:$soffset), 0>;
231}
232
233class SM_WaveId_Pseudo<string opName, SDPatternOperator node> : SM_Pseudo<
234  opName, (outs SReg_32_XM0_XEXEC:$sdst), (ins),
235  " $sdst", [(set i32:$sdst, (node))]> {
236  let hasSideEffects = 1;
237  let mayStore = 0;
238  let mayLoad = 1;
239  let has_sbase = 0;
240}
241
242//===----------------------------------------------------------------------===//
243// Scalar Atomic Memory Classes
244//===----------------------------------------------------------------------===//
245
246class SM_Atomic_Pseudo <string opName,
247                        dag outs, dag ins, string asmOps, bit isRet>
248  : SM_Pseudo<opName, outs, ins, asmOps, []> {
249
250  bit glc = isRet;
251
252  let mayLoad = 1;
253  let mayStore = 1;
254  let has_glc = 1;
255  let has_dlc = 1;
256  let has_soffset = 1;
257
258  // Should these be set?
259  let ScalarStore = 1;
260  let hasSideEffects = 1;
261  let maybeAtomic = 1;
262
263  let IsAtomicNoRet = !not(isRet);
264  let IsAtomicRet = isRet;
265
266  let AsmMatchConverter = "cvtSMEMAtomic";
267}
268
269class SM_Pseudo_Atomic<string opName,
270                       RegisterClass baseClass,
271                       RegisterClass dataClass,
272                       bit isImm,
273                       bit isRet,
274                       string opNameWithSuffix = opName # !if(isImm,
275                                 !if(isRet, "_IMM_RTN", "_IMM"),
276                                 !if(isRet, "_SGPR_RTN", "_SGPR")),
277                       Operand CPolTy = !if(isRet, CPol_GLC1, CPol)> :
278  SM_Atomic_Pseudo<opName,
279                   !if(isRet, (outs dataClass:$sdst), (outs)),
280                   !if(isImm,
281                       (ins dataClass:$sdata, baseClass:$sbase, smem_offset:$offset, CPolTy:$cpol),
282                       (ins dataClass:$sdata, baseClass:$sbase, SReg_32:$soffset, CPolTy:$cpol)),
283                   !if(isRet, " $sdst", " $sdata") # ", $sbase, " #
284                     !if(isImm, "$offset", "$soffset") # "$cpol",
285                   isRet>,
286  AtomicNoRet <opNameWithSuffix, isRet> {
287  let has_offset = isImm;
288  let has_soffset = !not(isImm);
289  let PseudoInstr = opNameWithSuffix;
290
291  let Constraints = !if(isRet, "$sdst = $sdata", "");
292  let DisableEncoding = !if(isRet, "$sdata", "");
293}
294
295multiclass SM_Pseudo_Atomics<string opName,
296                             RegisterClass baseClass,
297                             RegisterClass dataClass> {
298  def _IMM      : SM_Pseudo_Atomic <opName, baseClass, dataClass, 1, 0>;
299  def _SGPR     : SM_Pseudo_Atomic <opName, baseClass, dataClass, 0, 0>;
300  def _IMM_RTN  : SM_Pseudo_Atomic <opName, baseClass, dataClass, 1, 1>;
301  def _SGPR_RTN : SM_Pseudo_Atomic <opName, baseClass, dataClass, 0, 1>;
302}
303
304//===----------------------------------------------------------------------===//
305// Scalar Memory Instructions
306//===----------------------------------------------------------------------===//
307
308// We are using the SReg_32_XM0 and not the SReg_32 register class for 32-bit
309// SMRD instructions, because the SReg_32_XM0 register class does not include M0
310// and writing to M0 from an SMRD instruction will hang the GPU.
311
312// XXX - SMEM instructions do not allow exec for data operand, but
313// does sdst for SMRD on SI/CI?
314defm S_LOAD_DWORD    : SM_Pseudo_Loads <"s_load_dword", SReg_64, SReg_32_XM0_XEXEC>;
315defm S_LOAD_DWORDX2  : SM_Pseudo_Loads <"s_load_dwordx2", SReg_64, SReg_64_XEXEC>;
316defm S_LOAD_DWORDX4  : SM_Pseudo_Loads <"s_load_dwordx4", SReg_64, SReg_128>;
317defm S_LOAD_DWORDX8  : SM_Pseudo_Loads <"s_load_dwordx8", SReg_64, SReg_256>;
318defm S_LOAD_DWORDX16 : SM_Pseudo_Loads <"s_load_dwordx16", SReg_64, SReg_512>;
319
320let is_buffer = 1 in {
321defm S_BUFFER_LOAD_DWORD : SM_Pseudo_Loads <
322  "s_buffer_load_dword", SReg_128, SReg_32_XM0_XEXEC
323>;
324
325// FIXME: exec_lo/exec_hi appear to be allowed for SMRD loads on
326// SI/CI, bit disallowed for SMEM on VI.
327defm S_BUFFER_LOAD_DWORDX2 : SM_Pseudo_Loads <
328  "s_buffer_load_dwordx2", SReg_128, SReg_64_XEXEC
329>;
330
331defm S_BUFFER_LOAD_DWORDX4 : SM_Pseudo_Loads <
332  "s_buffer_load_dwordx4", SReg_128, SReg_128
333>;
334
335defm S_BUFFER_LOAD_DWORDX8 : SM_Pseudo_Loads <
336  "s_buffer_load_dwordx8", SReg_128, SReg_256
337>;
338
339defm S_BUFFER_LOAD_DWORDX16 : SM_Pseudo_Loads <
340  "s_buffer_load_dwordx16", SReg_128, SReg_512
341>;
342}
343
344let SubtargetPredicate = HasScalarStores in {
345defm S_STORE_DWORD : SM_Pseudo_Stores <"s_store_dword", SReg_64, SReg_32_XM0_XEXEC>;
346defm S_STORE_DWORDX2 : SM_Pseudo_Stores <"s_store_dwordx2", SReg_64, SReg_64_XEXEC>;
347defm S_STORE_DWORDX4 : SM_Pseudo_Stores <"s_store_dwordx4", SReg_64, SReg_128>;
348
349let is_buffer = 1 in {
350defm S_BUFFER_STORE_DWORD : SM_Pseudo_Stores <
351  "s_buffer_store_dword", SReg_128, SReg_32_XM0_XEXEC
352>;
353
354defm S_BUFFER_STORE_DWORDX2 : SM_Pseudo_Stores <
355  "s_buffer_store_dwordx2", SReg_128, SReg_64_XEXEC
356>;
357
358defm S_BUFFER_STORE_DWORDX4 : SM_Pseudo_Stores <
359  "s_buffer_store_dwordx4", SReg_128, SReg_128
360>;
361}
362} // End SubtargetPredicate = HasScalarStores
363
364let SubtargetPredicate = HasSMemTimeInst in
365def S_MEMTIME : SM_Time_Pseudo <"s_memtime", int_amdgcn_s_memtime>;
366def S_DCACHE_INV : SM_Inval_Pseudo <"s_dcache_inv", int_amdgcn_s_dcache_inv>;
367
368let SubtargetPredicate = isGFX7GFX8GFX9 in {
369def S_DCACHE_INV_VOL : SM_Inval_Pseudo <"s_dcache_inv_vol", int_amdgcn_s_dcache_inv_vol>;
370} // let SubtargetPredicate = isGFX7GFX8GFX9
371
372let SubtargetPredicate = isGFX8Plus in {
373let OtherPredicates = [HasScalarStores] in {
374def S_DCACHE_WB     : SM_Inval_Pseudo <"s_dcache_wb", int_amdgcn_s_dcache_wb>;
375def S_DCACHE_WB_VOL : SM_Inval_Pseudo <"s_dcache_wb_vol", int_amdgcn_s_dcache_wb_vol>;
376} // End OtherPredicates = [HasScalarStores]
377
378defm S_ATC_PROBE        : SM_Pseudo_Probe <"s_atc_probe", SReg_64>;
379let is_buffer = 1 in {
380defm S_ATC_PROBE_BUFFER : SM_Pseudo_Probe <"s_atc_probe_buffer", SReg_128>;
381}
382} // SubtargetPredicate = isGFX8Plus
383
384let SubtargetPredicate = HasSMemRealTime in
385def S_MEMREALTIME   : SM_Time_Pseudo <"s_memrealtime", int_amdgcn_s_memrealtime>;
386
387let SubtargetPredicate = isGFX10Plus in
388def S_GL1_INV : SM_Inval_Pseudo<"s_gl1_inv">;
389let SubtargetPredicate = HasGetWaveIdInst in
390def S_GET_WAVEID_IN_WORKGROUP : SM_WaveId_Pseudo <"s_get_waveid_in_workgroup", int_amdgcn_s_get_waveid_in_workgroup>;
391
392
393let SubtargetPredicate = HasScalarFlatScratchInsts, Uses = [FLAT_SCR] in {
394defm S_SCRATCH_LOAD_DWORD    : SM_Pseudo_Loads <"s_scratch_load_dword",   SReg_64, SReg_32_XM0_XEXEC>;
395defm S_SCRATCH_LOAD_DWORDX2  : SM_Pseudo_Loads <"s_scratch_load_dwordx2", SReg_64, SReg_64_XEXEC>;
396defm S_SCRATCH_LOAD_DWORDX4  : SM_Pseudo_Loads <"s_scratch_load_dwordx4", SReg_64, SReg_128>;
397
398defm S_SCRATCH_STORE_DWORD   : SM_Pseudo_Stores <"s_scratch_store_dword",   SReg_64, SReg_32_XM0_XEXEC>;
399defm S_SCRATCH_STORE_DWORDX2 : SM_Pseudo_Stores <"s_scratch_store_dwordx2", SReg_64, SReg_64_XEXEC>;
400defm S_SCRATCH_STORE_DWORDX4 : SM_Pseudo_Stores <"s_scratch_store_dwordx4", SReg_64, SReg_128>;
401} // SubtargetPredicate = HasScalarFlatScratchInsts
402
403let SubtargetPredicate = HasScalarAtomics in {
404
405let is_buffer = 1 in {
406defm S_BUFFER_ATOMIC_SWAP         : SM_Pseudo_Atomics <"s_buffer_atomic_swap", SReg_128, SReg_32_XM0_XEXEC>;
407defm S_BUFFER_ATOMIC_CMPSWAP      : SM_Pseudo_Atomics <"s_buffer_atomic_cmpswap", SReg_128, SReg_64_XEXEC>;
408defm S_BUFFER_ATOMIC_ADD          : SM_Pseudo_Atomics <"s_buffer_atomic_add", SReg_128, SReg_32_XM0_XEXEC>;
409defm S_BUFFER_ATOMIC_SUB          : SM_Pseudo_Atomics <"s_buffer_atomic_sub", SReg_128, SReg_32_XM0_XEXEC>;
410defm S_BUFFER_ATOMIC_SMIN         : SM_Pseudo_Atomics <"s_buffer_atomic_smin", SReg_128, SReg_32_XM0_XEXEC>;
411defm S_BUFFER_ATOMIC_UMIN         : SM_Pseudo_Atomics <"s_buffer_atomic_umin", SReg_128, SReg_32_XM0_XEXEC>;
412defm S_BUFFER_ATOMIC_SMAX         : SM_Pseudo_Atomics <"s_buffer_atomic_smax", SReg_128, SReg_32_XM0_XEXEC>;
413defm S_BUFFER_ATOMIC_UMAX         : SM_Pseudo_Atomics <"s_buffer_atomic_umax", SReg_128, SReg_32_XM0_XEXEC>;
414defm S_BUFFER_ATOMIC_AND          : SM_Pseudo_Atomics <"s_buffer_atomic_and", SReg_128, SReg_32_XM0_XEXEC>;
415defm S_BUFFER_ATOMIC_OR           : SM_Pseudo_Atomics <"s_buffer_atomic_or", SReg_128, SReg_32_XM0_XEXEC>;
416defm S_BUFFER_ATOMIC_XOR          : SM_Pseudo_Atomics <"s_buffer_atomic_xor", SReg_128, SReg_32_XM0_XEXEC>;
417defm S_BUFFER_ATOMIC_INC          : SM_Pseudo_Atomics <"s_buffer_atomic_inc", SReg_128, SReg_32_XM0_XEXEC>;
418defm S_BUFFER_ATOMIC_DEC          : SM_Pseudo_Atomics <"s_buffer_atomic_dec", SReg_128, SReg_32_XM0_XEXEC>;
419
420defm S_BUFFER_ATOMIC_SWAP_X2      : SM_Pseudo_Atomics <"s_buffer_atomic_swap_x2", SReg_128, SReg_64_XEXEC>;
421defm S_BUFFER_ATOMIC_CMPSWAP_X2   : SM_Pseudo_Atomics <"s_buffer_atomic_cmpswap_x2", SReg_128, SReg_128>;
422defm S_BUFFER_ATOMIC_ADD_X2       : SM_Pseudo_Atomics <"s_buffer_atomic_add_x2", SReg_128, SReg_64_XEXEC>;
423defm S_BUFFER_ATOMIC_SUB_X2       : SM_Pseudo_Atomics <"s_buffer_atomic_sub_x2", SReg_128, SReg_64_XEXEC>;
424defm S_BUFFER_ATOMIC_SMIN_X2      : SM_Pseudo_Atomics <"s_buffer_atomic_smin_x2", SReg_128, SReg_64_XEXEC>;
425defm S_BUFFER_ATOMIC_UMIN_X2      : SM_Pseudo_Atomics <"s_buffer_atomic_umin_x2", SReg_128, SReg_64_XEXEC>;
426defm S_BUFFER_ATOMIC_SMAX_X2      : SM_Pseudo_Atomics <"s_buffer_atomic_smax_x2", SReg_128, SReg_64_XEXEC>;
427defm S_BUFFER_ATOMIC_UMAX_X2      : SM_Pseudo_Atomics <"s_buffer_atomic_umax_x2", SReg_128, SReg_64_XEXEC>;
428defm S_BUFFER_ATOMIC_AND_X2       : SM_Pseudo_Atomics <"s_buffer_atomic_and_x2", SReg_128, SReg_64_XEXEC>;
429defm S_BUFFER_ATOMIC_OR_X2        : SM_Pseudo_Atomics <"s_buffer_atomic_or_x2", SReg_128, SReg_64_XEXEC>;
430defm S_BUFFER_ATOMIC_XOR_X2       : SM_Pseudo_Atomics <"s_buffer_atomic_xor_x2", SReg_128, SReg_64_XEXEC>;
431defm S_BUFFER_ATOMIC_INC_X2       : SM_Pseudo_Atomics <"s_buffer_atomic_inc_x2", SReg_128, SReg_64_XEXEC>;
432defm S_BUFFER_ATOMIC_DEC_X2       : SM_Pseudo_Atomics <"s_buffer_atomic_dec_x2", SReg_128, SReg_64_XEXEC>;
433}
434
435defm S_ATOMIC_SWAP                : SM_Pseudo_Atomics <"s_atomic_swap", SReg_64, SReg_32_XM0_XEXEC>;
436defm S_ATOMIC_CMPSWAP             : SM_Pseudo_Atomics <"s_atomic_cmpswap", SReg_64, SReg_64_XEXEC>;
437defm S_ATOMIC_ADD                 : SM_Pseudo_Atomics <"s_atomic_add", SReg_64, SReg_32_XM0_XEXEC>;
438defm S_ATOMIC_SUB                 : SM_Pseudo_Atomics <"s_atomic_sub", SReg_64, SReg_32_XM0_XEXEC>;
439defm S_ATOMIC_SMIN                : SM_Pseudo_Atomics <"s_atomic_smin", SReg_64, SReg_32_XM0_XEXEC>;
440defm S_ATOMIC_UMIN                : SM_Pseudo_Atomics <"s_atomic_umin", SReg_64, SReg_32_XM0_XEXEC>;
441defm S_ATOMIC_SMAX                : SM_Pseudo_Atomics <"s_atomic_smax", SReg_64, SReg_32_XM0_XEXEC>;
442defm S_ATOMIC_UMAX                : SM_Pseudo_Atomics <"s_atomic_umax", SReg_64, SReg_32_XM0_XEXEC>;
443defm S_ATOMIC_AND                 : SM_Pseudo_Atomics <"s_atomic_and", SReg_64, SReg_32_XM0_XEXEC>;
444defm S_ATOMIC_OR                  : SM_Pseudo_Atomics <"s_atomic_or", SReg_64, SReg_32_XM0_XEXEC>;
445defm S_ATOMIC_XOR                 : SM_Pseudo_Atomics <"s_atomic_xor", SReg_64, SReg_32_XM0_XEXEC>;
446defm S_ATOMIC_INC                 : SM_Pseudo_Atomics <"s_atomic_inc", SReg_64, SReg_32_XM0_XEXEC>;
447defm S_ATOMIC_DEC                 : SM_Pseudo_Atomics <"s_atomic_dec", SReg_64, SReg_32_XM0_XEXEC>;
448
449defm S_ATOMIC_SWAP_X2             : SM_Pseudo_Atomics <"s_atomic_swap_x2", SReg_64, SReg_64_XEXEC>;
450defm S_ATOMIC_CMPSWAP_X2          : SM_Pseudo_Atomics <"s_atomic_cmpswap_x2", SReg_64, SReg_128>;
451defm S_ATOMIC_ADD_X2              : SM_Pseudo_Atomics <"s_atomic_add_x2", SReg_64, SReg_64_XEXEC>;
452defm S_ATOMIC_SUB_X2              : SM_Pseudo_Atomics <"s_atomic_sub_x2", SReg_64, SReg_64_XEXEC>;
453defm S_ATOMIC_SMIN_X2             : SM_Pseudo_Atomics <"s_atomic_smin_x2", SReg_64, SReg_64_XEXEC>;
454defm S_ATOMIC_UMIN_X2             : SM_Pseudo_Atomics <"s_atomic_umin_x2", SReg_64, SReg_64_XEXEC>;
455defm S_ATOMIC_SMAX_X2             : SM_Pseudo_Atomics <"s_atomic_smax_x2", SReg_64, SReg_64_XEXEC>;
456defm S_ATOMIC_UMAX_X2             : SM_Pseudo_Atomics <"s_atomic_umax_x2", SReg_64, SReg_64_XEXEC>;
457defm S_ATOMIC_AND_X2              : SM_Pseudo_Atomics <"s_atomic_and_x2", SReg_64, SReg_64_XEXEC>;
458defm S_ATOMIC_OR_X2               : SM_Pseudo_Atomics <"s_atomic_or_x2", SReg_64, SReg_64_XEXEC>;
459defm S_ATOMIC_XOR_X2              : SM_Pseudo_Atomics <"s_atomic_xor_x2", SReg_64, SReg_64_XEXEC>;
460defm S_ATOMIC_INC_X2              : SM_Pseudo_Atomics <"s_atomic_inc_x2", SReg_64, SReg_64_XEXEC>;
461defm S_ATOMIC_DEC_X2              : SM_Pseudo_Atomics <"s_atomic_dec_x2", SReg_64, SReg_64_XEXEC>;
462
463} // let SubtargetPredicate = HasScalarAtomics
464
465let SubtargetPredicate = HasScalarAtomics in {
466defm S_DCACHE_DISCARD    : SM_Pseudo_Discards <"s_dcache_discard">;
467defm S_DCACHE_DISCARD_X2 : SM_Pseudo_Discards <"s_dcache_discard_x2">;
468}
469
470//===----------------------------------------------------------------------===//
471// Targets
472//===----------------------------------------------------------------------===//
473
474//===----------------------------------------------------------------------===//
475// SI
476//===----------------------------------------------------------------------===//
477
478class SMRD_Real_si <bits<5> op, SM_Pseudo ps>
479  : SM_Real<ps>
480  , SIMCInstr<ps.PseudoInstr, SIEncodingFamily.SI>
481  , Enc32 {
482
483  let AssemblerPredicate = isGFX6GFX7;
484  let DecoderNamespace = "GFX6GFX7";
485
486  let Inst{7-0}   = !if(ps.has_offset, offset{7-0}, !if(ps.has_soffset, soffset, ?));
487  let Inst{8}     = ps.has_offset;
488  let Inst{14-9}  = !if(ps.has_sbase, sbase{6-1}, ?);
489  let Inst{21-15} = !if(ps.has_sdst, sdst{6-0}, ?);
490  let Inst{26-22} = op;
491  let Inst{31-27} = 0x18; //encoding
492}
493
494// FIXME: Assembler should reject trying to use glc on SMRD
495// instructions on SI.
496multiclass SM_Real_Loads_si<bits<5> op, string ps,
497                            SM_Load_Pseudo immPs = !cast<SM_Load_Pseudo>(ps#_IMM),
498                            SM_Load_Pseudo sgprPs = !cast<SM_Load_Pseudo>(ps#_SGPR)> {
499
500  def _IMM_si : SMRD_Real_si <op, immPs> {
501    let InOperandList = (ins immPs.BaseClass:$sbase, smrd_offset_8:$offset, CPol:$cpol);
502  }
503
504  def _SGPR_si : SMRD_Real_si <op, sgprPs> {
505    let InOperandList = (ins sgprPs.BaseClass:$sbase, SReg_32:$soffset, CPol:$cpol);
506  }
507
508}
509
510defm S_LOAD_DWORD           : SM_Real_Loads_si <0x00, "S_LOAD_DWORD">;
511defm S_LOAD_DWORDX2         : SM_Real_Loads_si <0x01, "S_LOAD_DWORDX2">;
512defm S_LOAD_DWORDX4         : SM_Real_Loads_si <0x02, "S_LOAD_DWORDX4">;
513defm S_LOAD_DWORDX8         : SM_Real_Loads_si <0x03, "S_LOAD_DWORDX8">;
514defm S_LOAD_DWORDX16        : SM_Real_Loads_si <0x04, "S_LOAD_DWORDX16">;
515defm S_BUFFER_LOAD_DWORD    : SM_Real_Loads_si <0x08, "S_BUFFER_LOAD_DWORD">;
516defm S_BUFFER_LOAD_DWORDX2  : SM_Real_Loads_si <0x09, "S_BUFFER_LOAD_DWORDX2">;
517defm S_BUFFER_LOAD_DWORDX4  : SM_Real_Loads_si <0x0a, "S_BUFFER_LOAD_DWORDX4">;
518defm S_BUFFER_LOAD_DWORDX8  : SM_Real_Loads_si <0x0b, "S_BUFFER_LOAD_DWORDX8">;
519defm S_BUFFER_LOAD_DWORDX16 : SM_Real_Loads_si <0x0c, "S_BUFFER_LOAD_DWORDX16">;
520
521def S_MEMTIME_si    : SMRD_Real_si <0x1e, S_MEMTIME>;
522def S_DCACHE_INV_si : SMRD_Real_si <0x1f, S_DCACHE_INV>;
523
524
525//===----------------------------------------------------------------------===//
526// VI
527//===----------------------------------------------------------------------===//
528
529class SMEM_Real_vi <bits<8> op, SM_Pseudo ps>
530  : SM_Real<ps>
531  , SIMCInstr<ps.PseudoInstr, SIEncodingFamily.VI>
532  , Enc64 {
533  let AssemblerPredicate = isGFX8GFX9;
534  let DecoderNamespace = "GFX8";
535
536  let Inst{5-0}   = !if(ps.has_sbase, sbase{6-1}, ?);
537  let Inst{12-6}  = !if(ps.has_sdst, sdst{6-0}, ?);
538
539  let Inst{16} = !if(ps.has_glc, cpol{CPolBit.GLC}, ?);
540  let Inst{17} = ps.has_offset;
541  let Inst{25-18} = op;
542  let Inst{31-26} = 0x30; //encoding
543
544  // VI supports 20-bit unsigned offsets while GFX9+ supports 21-bit signed.
545  // Offset value is corrected accordingly when offset is encoded/decoded.
546  let Inst{38-32} = !if(ps.has_offset, offset{6-0}, !if(ps.has_soffset, soffset{6-0}, ?));
547  let Inst{52-39} = !if(ps.has_offset, offset{20-7}, ?);
548}
549
550multiclass SM_Real_Loads_vi<bits<8> op, string ps,
551                            SM_Load_Pseudo immPs = !cast<SM_Load_Pseudo>(ps#_IMM),
552                            SM_Load_Pseudo sgprPs = !cast<SM_Load_Pseudo>(ps#_SGPR)> {
553  def _IMM_vi : SMEM_Real_vi <op, immPs> {
554    let InOperandList = (ins immPs.BaseClass:$sbase, smem_offset:$offset, CPol:$cpol);
555  }
556  def _SGPR_vi : SMEM_Real_vi <op, sgprPs> {
557    let InOperandList = (ins sgprPs.BaseClass:$sbase, SReg_32:$soffset, CPol:$cpol);
558  }
559}
560
561class SMEM_Real_Store_vi <bits<8> op, SM_Pseudo ps> : SMEM_Real_vi <op, ps> {
562  // encoding
563  bits<7> sdata;
564
565  let sdst = ?;
566  let Inst{12-6}  = !if(ps.has_sdst, sdata{6-0}, ?);
567}
568
569multiclass SM_Real_Stores_vi<bits<8> op, string ps,
570                            SM_Store_Pseudo immPs = !cast<SM_Store_Pseudo>(ps#_IMM),
571                            SM_Store_Pseudo sgprPs = !cast<SM_Store_Pseudo>(ps#_SGPR)> {
572  def _IMM_vi : SMEM_Real_Store_vi <op, immPs> {
573    let InOperandList = (ins immPs.SrcClass:$sdata, immPs.BaseClass:$sbase, smem_offset:$offset, CPol:$cpol);
574  }
575
576  def _SGPR_vi : SMEM_Real_Store_vi <op, sgprPs> {
577    let InOperandList = (ins sgprPs.SrcClass:$sdata, sgprPs.BaseClass:$sbase, SReg_32:$soffset, CPol:$cpol);
578  }
579}
580
581multiclass SM_Real_Probe_vi<bits<8> op, string ps> {
582  def _IMM_vi  : SMEM_Real_Store_vi <op, !cast<SM_Probe_Pseudo>(ps#_IMM)>;
583  def _SGPR_vi : SMEM_Real_Store_vi <op, !cast<SM_Probe_Pseudo>(ps#_SGPR)>;
584}
585
586defm S_LOAD_DWORD           : SM_Real_Loads_vi <0x00, "S_LOAD_DWORD">;
587defm S_LOAD_DWORDX2         : SM_Real_Loads_vi <0x01, "S_LOAD_DWORDX2">;
588defm S_LOAD_DWORDX4         : SM_Real_Loads_vi <0x02, "S_LOAD_DWORDX4">;
589defm S_LOAD_DWORDX8         : SM_Real_Loads_vi <0x03, "S_LOAD_DWORDX8">;
590defm S_LOAD_DWORDX16        : SM_Real_Loads_vi <0x04, "S_LOAD_DWORDX16">;
591defm S_BUFFER_LOAD_DWORD    : SM_Real_Loads_vi <0x08, "S_BUFFER_LOAD_DWORD">;
592defm S_BUFFER_LOAD_DWORDX2  : SM_Real_Loads_vi <0x09, "S_BUFFER_LOAD_DWORDX2">;
593defm S_BUFFER_LOAD_DWORDX4  : SM_Real_Loads_vi <0x0a, "S_BUFFER_LOAD_DWORDX4">;
594defm S_BUFFER_LOAD_DWORDX8  : SM_Real_Loads_vi <0x0b, "S_BUFFER_LOAD_DWORDX8">;
595defm S_BUFFER_LOAD_DWORDX16 : SM_Real_Loads_vi <0x0c, "S_BUFFER_LOAD_DWORDX16">;
596
597defm S_STORE_DWORD : SM_Real_Stores_vi <0x10, "S_STORE_DWORD">;
598defm S_STORE_DWORDX2 : SM_Real_Stores_vi <0x11, "S_STORE_DWORDX2">;
599defm S_STORE_DWORDX4 : SM_Real_Stores_vi <0x12, "S_STORE_DWORDX4">;
600
601defm S_BUFFER_STORE_DWORD    : SM_Real_Stores_vi <0x18, "S_BUFFER_STORE_DWORD">;
602defm S_BUFFER_STORE_DWORDX2  : SM_Real_Stores_vi <0x19, "S_BUFFER_STORE_DWORDX2">;
603defm S_BUFFER_STORE_DWORDX4  : SM_Real_Stores_vi <0x1a, "S_BUFFER_STORE_DWORDX4">;
604
605// These instructions use same encoding
606def S_DCACHE_INV_vi         : SMEM_Real_vi <0x20, S_DCACHE_INV>;
607def S_DCACHE_WB_vi          : SMEM_Real_vi <0x21, S_DCACHE_WB>;
608def S_DCACHE_INV_VOL_vi     : SMEM_Real_vi <0x22, S_DCACHE_INV_VOL>;
609def S_DCACHE_WB_VOL_vi      : SMEM_Real_vi <0x23, S_DCACHE_WB_VOL>;
610def S_MEMTIME_vi            : SMEM_Real_vi <0x24, S_MEMTIME>;
611def S_MEMREALTIME_vi        : SMEM_Real_vi <0x25, S_MEMREALTIME>;
612
613defm S_SCRATCH_LOAD_DWORD    : SM_Real_Loads_vi <0x05, "S_SCRATCH_LOAD_DWORD">;
614defm S_SCRATCH_LOAD_DWORDX2  : SM_Real_Loads_vi <0x06, "S_SCRATCH_LOAD_DWORDX2">;
615defm S_SCRATCH_LOAD_DWORDX4  : SM_Real_Loads_vi <0x07, "S_SCRATCH_LOAD_DWORDX4">;
616
617defm S_SCRATCH_STORE_DWORD   : SM_Real_Stores_vi <0x15, "S_SCRATCH_STORE_DWORD">;
618defm S_SCRATCH_STORE_DWORDX2 : SM_Real_Stores_vi <0x16, "S_SCRATCH_STORE_DWORDX2">;
619defm S_SCRATCH_STORE_DWORDX4 : SM_Real_Stores_vi <0x17, "S_SCRATCH_STORE_DWORDX4">;
620
621defm S_ATC_PROBE        : SM_Real_Probe_vi <0x26, "S_ATC_PROBE">;
622defm S_ATC_PROBE_BUFFER : SM_Real_Probe_vi <0x27, "S_ATC_PROBE_BUFFER">;
623
624//===----------------------------------------------------------------------===//
625// GFX9
626//===----------------------------------------------------------------------===//
627
628class SMEM_Atomic_Real_vi <bits<8> op, SM_Atomic_Pseudo ps>
629  : SMEM_Real_vi <op, ps>,
630    AtomicNoRet <!subst("_RTN","",NAME), ps.glc> {
631
632  bits<7> sdata;
633
634  let Constraints = ps.Constraints;
635  let DisableEncoding = ps.DisableEncoding;
636
637  let cpol{CPolBit.GLC} = ps.glc;
638  let Inst{12-6} = !if(ps.glc, sdst{6-0}, sdata{6-0});
639}
640
641multiclass SM_Real_Atomics_vi<bits<8> op, string ps> {
642  def _IMM_vi       : SMEM_Atomic_Real_vi <op, !cast<SM_Atomic_Pseudo>(ps#_IMM)>;
643  def _SGPR_vi      : SMEM_Atomic_Real_vi <op, !cast<SM_Atomic_Pseudo>(ps#_SGPR)>;
644  def _IMM_RTN_vi   : SMEM_Atomic_Real_vi <op, !cast<SM_Atomic_Pseudo>(ps#_IMM_RTN)>;
645  def _SGPR_RTN_vi  : SMEM_Atomic_Real_vi <op, !cast<SM_Atomic_Pseudo>(ps#_SGPR_RTN)>;
646}
647
648defm S_BUFFER_ATOMIC_SWAP         : SM_Real_Atomics_vi <0x40, "S_BUFFER_ATOMIC_SWAP">;
649defm S_BUFFER_ATOMIC_CMPSWAP      : SM_Real_Atomics_vi <0x41, "S_BUFFER_ATOMIC_CMPSWAP">;
650defm S_BUFFER_ATOMIC_ADD          : SM_Real_Atomics_vi <0x42, "S_BUFFER_ATOMIC_ADD">;
651defm S_BUFFER_ATOMIC_SUB          : SM_Real_Atomics_vi <0x43, "S_BUFFER_ATOMIC_SUB">;
652defm S_BUFFER_ATOMIC_SMIN         : SM_Real_Atomics_vi <0x44, "S_BUFFER_ATOMIC_SMIN">;
653defm S_BUFFER_ATOMIC_UMIN         : SM_Real_Atomics_vi <0x45, "S_BUFFER_ATOMIC_UMIN">;
654defm S_BUFFER_ATOMIC_SMAX         : SM_Real_Atomics_vi <0x46, "S_BUFFER_ATOMIC_SMAX">;
655defm S_BUFFER_ATOMIC_UMAX         : SM_Real_Atomics_vi <0x47, "S_BUFFER_ATOMIC_UMAX">;
656defm S_BUFFER_ATOMIC_AND          : SM_Real_Atomics_vi <0x48, "S_BUFFER_ATOMIC_AND">;
657defm S_BUFFER_ATOMIC_OR           : SM_Real_Atomics_vi <0x49, "S_BUFFER_ATOMIC_OR">;
658defm S_BUFFER_ATOMIC_XOR          : SM_Real_Atomics_vi <0x4a, "S_BUFFER_ATOMIC_XOR">;
659defm S_BUFFER_ATOMIC_INC          : SM_Real_Atomics_vi <0x4b, "S_BUFFER_ATOMIC_INC">;
660defm S_BUFFER_ATOMIC_DEC          : SM_Real_Atomics_vi <0x4c, "S_BUFFER_ATOMIC_DEC">;
661
662defm S_BUFFER_ATOMIC_SWAP_X2      : SM_Real_Atomics_vi <0x60, "S_BUFFER_ATOMIC_SWAP_X2">;
663defm S_BUFFER_ATOMIC_CMPSWAP_X2   : SM_Real_Atomics_vi <0x61, "S_BUFFER_ATOMIC_CMPSWAP_X2">;
664defm S_BUFFER_ATOMIC_ADD_X2       : SM_Real_Atomics_vi <0x62, "S_BUFFER_ATOMIC_ADD_X2">;
665defm S_BUFFER_ATOMIC_SUB_X2       : SM_Real_Atomics_vi <0x63, "S_BUFFER_ATOMIC_SUB_X2">;
666defm S_BUFFER_ATOMIC_SMIN_X2      : SM_Real_Atomics_vi <0x64, "S_BUFFER_ATOMIC_SMIN_X2">;
667defm S_BUFFER_ATOMIC_UMIN_X2      : SM_Real_Atomics_vi <0x65, "S_BUFFER_ATOMIC_UMIN_X2">;
668defm S_BUFFER_ATOMIC_SMAX_X2      : SM_Real_Atomics_vi <0x66, "S_BUFFER_ATOMIC_SMAX_X2">;
669defm S_BUFFER_ATOMIC_UMAX_X2      : SM_Real_Atomics_vi <0x67, "S_BUFFER_ATOMIC_UMAX_X2">;
670defm S_BUFFER_ATOMIC_AND_X2       : SM_Real_Atomics_vi <0x68, "S_BUFFER_ATOMIC_AND_X2">;
671defm S_BUFFER_ATOMIC_OR_X2        : SM_Real_Atomics_vi <0x69, "S_BUFFER_ATOMIC_OR_X2">;
672defm S_BUFFER_ATOMIC_XOR_X2       : SM_Real_Atomics_vi <0x6a, "S_BUFFER_ATOMIC_XOR_X2">;
673defm S_BUFFER_ATOMIC_INC_X2       : SM_Real_Atomics_vi <0x6b, "S_BUFFER_ATOMIC_INC_X2">;
674defm S_BUFFER_ATOMIC_DEC_X2       : SM_Real_Atomics_vi <0x6c, "S_BUFFER_ATOMIC_DEC_X2">;
675
676defm S_ATOMIC_SWAP                : SM_Real_Atomics_vi <0x80, "S_ATOMIC_SWAP">;
677defm S_ATOMIC_CMPSWAP             : SM_Real_Atomics_vi <0x81, "S_ATOMIC_CMPSWAP">;
678defm S_ATOMIC_ADD                 : SM_Real_Atomics_vi <0x82, "S_ATOMIC_ADD">;
679defm S_ATOMIC_SUB                 : SM_Real_Atomics_vi <0x83, "S_ATOMIC_SUB">;
680defm S_ATOMIC_SMIN                : SM_Real_Atomics_vi <0x84, "S_ATOMIC_SMIN">;
681defm S_ATOMIC_UMIN                : SM_Real_Atomics_vi <0x85, "S_ATOMIC_UMIN">;
682defm S_ATOMIC_SMAX                : SM_Real_Atomics_vi <0x86, "S_ATOMIC_SMAX">;
683defm S_ATOMIC_UMAX                : SM_Real_Atomics_vi <0x87, "S_ATOMIC_UMAX">;
684defm S_ATOMIC_AND                 : SM_Real_Atomics_vi <0x88, "S_ATOMIC_AND">;
685defm S_ATOMIC_OR                  : SM_Real_Atomics_vi <0x89, "S_ATOMIC_OR">;
686defm S_ATOMIC_XOR                 : SM_Real_Atomics_vi <0x8a, "S_ATOMIC_XOR">;
687defm S_ATOMIC_INC                 : SM_Real_Atomics_vi <0x8b, "S_ATOMIC_INC">;
688defm S_ATOMIC_DEC                 : SM_Real_Atomics_vi <0x8c, "S_ATOMIC_DEC">;
689
690defm S_ATOMIC_SWAP_X2             : SM_Real_Atomics_vi <0xa0, "S_ATOMIC_SWAP_X2">;
691defm S_ATOMIC_CMPSWAP_X2          : SM_Real_Atomics_vi <0xa1, "S_ATOMIC_CMPSWAP_X2">;
692defm S_ATOMIC_ADD_X2              : SM_Real_Atomics_vi <0xa2, "S_ATOMIC_ADD_X2">;
693defm S_ATOMIC_SUB_X2              : SM_Real_Atomics_vi <0xa3, "S_ATOMIC_SUB_X2">;
694defm S_ATOMIC_SMIN_X2             : SM_Real_Atomics_vi <0xa4, "S_ATOMIC_SMIN_X2">;
695defm S_ATOMIC_UMIN_X2             : SM_Real_Atomics_vi <0xa5, "S_ATOMIC_UMIN_X2">;
696defm S_ATOMIC_SMAX_X2             : SM_Real_Atomics_vi <0xa6, "S_ATOMIC_SMAX_X2">;
697defm S_ATOMIC_UMAX_X2             : SM_Real_Atomics_vi <0xa7, "S_ATOMIC_UMAX_X2">;
698defm S_ATOMIC_AND_X2              : SM_Real_Atomics_vi <0xa8, "S_ATOMIC_AND_X2">;
699defm S_ATOMIC_OR_X2               : SM_Real_Atomics_vi <0xa9, "S_ATOMIC_OR_X2">;
700defm S_ATOMIC_XOR_X2              : SM_Real_Atomics_vi <0xaa, "S_ATOMIC_XOR_X2">;
701defm S_ATOMIC_INC_X2              : SM_Real_Atomics_vi <0xab, "S_ATOMIC_INC_X2">;
702defm S_ATOMIC_DEC_X2              : SM_Real_Atomics_vi <0xac, "S_ATOMIC_DEC_X2">;
703
704multiclass SM_Real_Discard_vi<bits<8> op, string ps> {
705  def _IMM_vi  : SMEM_Real_vi <op, !cast<SM_Discard_Pseudo>(ps#_IMM)>;
706  def _SGPR_vi : SMEM_Real_vi <op, !cast<SM_Discard_Pseudo>(ps#_SGPR)>;
707}
708
709defm S_DCACHE_DISCARD    : SM_Real_Discard_vi <0x28, "S_DCACHE_DISCARD">;
710defm S_DCACHE_DISCARD_X2 : SM_Real_Discard_vi <0x29, "S_DCACHE_DISCARD_X2">;
711
712//===----------------------------------------------------------------------===//
713// CI
714//===----------------------------------------------------------------------===//
715
716def smrd_literal_offset : NamedOperandU32<"SMRDLiteralOffset",
717                                          NamedMatchClass<"SMRDLiteralOffset">> {
718  let OperandType = "OPERAND_IMMEDIATE";
719}
720
721class SMRD_Real_Load_IMM_ci <bits<5> op, SM_Load_Pseudo ps> :
722  SM_Real<ps>,
723  Enc64 {
724
725  let AssemblerPredicate = isGFX7Only;
726  let DecoderNamespace = "GFX7";
727  let InOperandList = (ins ps.BaseClass:$sbase, smrd_literal_offset:$offset, CPol:$cpol);
728
729  let Inst{7-0}   = 0xff;
730  let Inst{8}     = 0;
731  let Inst{14-9}  = sbase{6-1};
732  let Inst{21-15} = sdst{6-0};
733  let Inst{26-22} = op;
734  let Inst{31-27} = 0x18; //encoding
735  let Inst{63-32} = offset{31-0};
736}
737
738def S_LOAD_DWORD_IMM_ci           : SMRD_Real_Load_IMM_ci <0x00, S_LOAD_DWORD_IMM>;
739def S_LOAD_DWORDX2_IMM_ci         : SMRD_Real_Load_IMM_ci <0x01, S_LOAD_DWORDX2_IMM>;
740def S_LOAD_DWORDX4_IMM_ci         : SMRD_Real_Load_IMM_ci <0x02, S_LOAD_DWORDX4_IMM>;
741def S_LOAD_DWORDX8_IMM_ci         : SMRD_Real_Load_IMM_ci <0x03, S_LOAD_DWORDX8_IMM>;
742def S_LOAD_DWORDX16_IMM_ci        : SMRD_Real_Load_IMM_ci <0x04, S_LOAD_DWORDX16_IMM>;
743def S_BUFFER_LOAD_DWORD_IMM_ci    : SMRD_Real_Load_IMM_ci <0x08, S_BUFFER_LOAD_DWORD_IMM>;
744def S_BUFFER_LOAD_DWORDX2_IMM_ci  : SMRD_Real_Load_IMM_ci <0x09, S_BUFFER_LOAD_DWORDX2_IMM>;
745def S_BUFFER_LOAD_DWORDX4_IMM_ci  : SMRD_Real_Load_IMM_ci <0x0a, S_BUFFER_LOAD_DWORDX4_IMM>;
746def S_BUFFER_LOAD_DWORDX8_IMM_ci  : SMRD_Real_Load_IMM_ci <0x0b, S_BUFFER_LOAD_DWORDX8_IMM>;
747def S_BUFFER_LOAD_DWORDX16_IMM_ci : SMRD_Real_Load_IMM_ci <0x0c, S_BUFFER_LOAD_DWORDX16_IMM>;
748
749class SMRD_Real_ci <bits<5> op, SM_Pseudo ps>
750  : SM_Real<ps>
751  , SIMCInstr<ps.PseudoInstr, SIEncodingFamily.SI>
752  , Enc32 {
753
754  let AssemblerPredicate = isGFX7Only;
755  let DecoderNamespace = "GFX7";
756
757  let Inst{7-0}   = !if(ps.has_offset, offset{7-0}, !if(ps.has_soffset, soffset, ?));
758  let Inst{8}     = ps.has_offset;
759  let Inst{14-9}  = !if(ps.has_sbase, sbase{6-1}, ?);
760  let Inst{21-15} = !if(ps.has_sdst, sdst{6-0}, ?);
761  let Inst{26-22} = op;
762  let Inst{31-27} = 0x18; //encoding
763}
764
765def S_DCACHE_INV_VOL_ci : SMRD_Real_ci <0x1d, S_DCACHE_INV_VOL>;
766
767//===----------------------------------------------------------------------===//
768// Scalar Memory Patterns
769//===----------------------------------------------------------------------===//
770
771def smrd_load : PatFrag <(ops node:$ptr), (load node:$ptr), [{ return isUniformLoad(N);}]> {
772  let GISelPredicateCode = [{
773    if (!MI.hasOneMemOperand())
774      return false;
775    if (!isInstrUniform(MI))
776      return false;
777
778    // FIXME: We should probably be caching this.
779    SmallVector<GEPInfo, 4> AddrInfo;
780    getAddrModeInfo(MI, MRI, AddrInfo);
781
782    if (hasVgprParts(AddrInfo))
783      return false;
784    return true;
785  }];
786}
787
788def SMRDImm         : ComplexPattern<iPTR, 2, "SelectSMRDImm">;
789def SMRDImm32       : ComplexPattern<iPTR, 2, "SelectSMRDImm32">;
790def SMRDSgpr        : ComplexPattern<iPTR, 2, "SelectSMRDSgpr">;
791def SMRDBufferImm   : ComplexPattern<iPTR, 1, "SelectSMRDBufferImm">;
792def SMRDBufferImm32 : ComplexPattern<iPTR, 1, "SelectSMRDBufferImm32">;
793
794multiclass SMRD_Pattern <string Instr, ValueType vt> {
795
796  // 1. IMM offset
797  def : GCNPat <
798    (smrd_load (SMRDImm i64:$sbase, i32:$offset)),
799    (vt (!cast<SM_Pseudo>(Instr#"_IMM") $sbase, $offset, 0))
800  >;
801
802  // 2. 32-bit IMM offset on CI
803  def : GCNPat <
804    (smrd_load (SMRDImm32 i64:$sbase, i32:$offset)),
805    (vt (!cast<InstSI>(Instr#"_IMM_ci") $sbase, $offset, 0))> {
806    let OtherPredicates = [isGFX7Only];
807  }
808
809  // 3. SGPR offset
810  def : GCNPat <
811    (smrd_load (SMRDSgpr i64:$sbase, i32:$offset)),
812    (vt (!cast<SM_Pseudo>(Instr#"_SGPR") $sbase, $offset, 0))
813  >;
814
815  // 4. No offset
816  def : GCNPat <
817    (vt (smrd_load (i64 SReg_64:$sbase))),
818    (vt (!cast<SM_Pseudo>(Instr#"_IMM") i64:$sbase, 0, 0))
819  >;
820}
821
822multiclass SMLoad_Pattern <string Instr, ValueType vt> {
823  // 1. Offset as an immediate
824  def : GCNPat <
825    (SIsbuffer_load v4i32:$sbase, (SMRDBufferImm i32:$offset), timm:$cachepolicy),
826    (vt (!cast<SM_Pseudo>(Instr#"_IMM") SReg_128:$sbase, i32imm:$offset, (extract_cpol $cachepolicy)))> {
827    let AddedComplexity = 2;
828  }
829
830  // 2. 32-bit IMM offset on CI
831  def : GCNPat <
832    (vt (SIsbuffer_load v4i32:$sbase, (SMRDBufferImm32 i32:$offset), timm:$cachepolicy)),
833    (!cast<InstSI>(Instr#"_IMM_ci") SReg_128:$sbase, smrd_literal_offset:$offset,
834                                    (extract_cpol $cachepolicy))> {
835    let OtherPredicates = [isGFX7Only];
836    let AddedComplexity = 1;
837  }
838
839  // 3. Offset loaded in an 32bit SGPR
840  def : GCNPat <
841    (SIsbuffer_load v4i32:$sbase, i32:$offset, timm:$cachepolicy),
842    (vt (!cast<SM_Pseudo>(Instr#"_SGPR") SReg_128:$sbase, SReg_32:$offset, (extract_cpol $cachepolicy)))
843  >;
844}
845
846// Global and constant loads can be selected to either MUBUF or SMRD
847// instructions, but SMRD instructions are faster so we want the instruction
848// selector to prefer those.
849let AddedComplexity = 100 in {
850
851foreach vt = Reg32Types.types in {
852defm : SMRD_Pattern <"S_LOAD_DWORD", vt>;
853}
854
855foreach vt = SReg_64.RegTypes in {
856defm : SMRD_Pattern <"S_LOAD_DWORDX2", vt>;
857}
858
859foreach vt = SReg_128.RegTypes in {
860defm : SMRD_Pattern <"S_LOAD_DWORDX4", vt>;
861}
862
863foreach vt = SReg_256.RegTypes in {
864defm : SMRD_Pattern <"S_LOAD_DWORDX8", vt>;
865}
866
867foreach vt = SReg_512.RegTypes in {
868defm : SMRD_Pattern <"S_LOAD_DWORDX16", vt>;
869}
870
871defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORD",     i32>;
872defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORDX2",   v2i32>;
873defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORDX4",   v4i32>;
874defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORDX8",   v8i32>;
875defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORDX16",  v16i32>;
876
877defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORD",     f32>;
878defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORDX2",   v2f32>;
879defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORDX4",   v4f32>;
880defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORDX8",   v8f32>;
881defm : SMLoad_Pattern <"S_BUFFER_LOAD_DWORDX16",  v16f32>;
882} // End let AddedComplexity = 100
883
884let OtherPredicates = [HasSMemTimeInst] in {
885def : GCNPat <
886  (i64 (readcyclecounter)),
887  (S_MEMTIME)
888>;
889} // let OtherPredicates = [HasSMemTimeInst]
890
891let OtherPredicates = [HasShaderCyclesRegister] in {
892def : GCNPat <
893  (i64 (readcyclecounter)),
894  (REG_SEQUENCE SReg_64,
895    (S_GETREG_B32 getHwRegImm<HWREG.SHADER_CYCLES, 0, -12>.ret), sub0,
896    (S_MOV_B32 (i32 0)), sub1)> {
897  // Prefer this to s_memtime because it has lower and more predictable latency.
898  let AddedComplexity = 1;
899}
900} // let OtherPredicates = [HasShaderCyclesRegister]
901
902//===----------------------------------------------------------------------===//
903// GFX10.
904//===----------------------------------------------------------------------===//
905
906class SMEM_Real_gfx10<bits<8> op, SM_Pseudo ps> :
907    SM_Real<ps>, SIMCInstr<ps.PseudoInstr, SIEncodingFamily.GFX10>, Enc64 {
908  let AssemblerPredicate = isGFX10Plus;
909  let DecoderNamespace = "GFX10";
910
911  let Inst{5-0}   = !if(ps.has_sbase, sbase{6-1}, ?);
912  let Inst{12-6}  = !if(ps.has_sdst, sdst{6-0}, ?);
913  let Inst{14}    = !if(ps.has_dlc, cpol{CPolBit.DLC}, ?);
914  let Inst{16}    = !if(ps.has_glc, cpol{CPolBit.GLC}, ?);
915  let Inst{25-18} = op;
916  let Inst{31-26} = 0x3d;
917
918  // There are SMEM instructions that do not employ any of the offset
919  // fields, in which case we need them to remain undefined.
920  let Inst{52-32} = !if(ps.has_offset, offset{20-0}, !if(ps.has_soffset, 0, ?));
921  let Inst{63-57} = !if(ps.has_soffset, soffset{6-0},
922                        !if(ps.has_offset, !cast<int>(SGPR_NULL_gfxpre11.HWEncoding), ?));
923}
924
925multiclass SM_Real_Loads_gfx10<bits<8> op, string ps,
926                               SM_Load_Pseudo immPs = !cast<SM_Load_Pseudo>(ps#_IMM),
927                               SM_Load_Pseudo sgprPs = !cast<SM_Load_Pseudo>(ps#_SGPR)> {
928  def _IMM_gfx10 : SMEM_Real_gfx10<op, immPs> {
929    let InOperandList = (ins immPs.BaseClass:$sbase, smem_offset:$offset, CPol:$cpol);
930  }
931  def _SGPR_gfx10 : SMEM_Real_gfx10<op, sgprPs> {
932    let InOperandList = (ins sgprPs.BaseClass:$sbase, SReg_32:$soffset, CPol:$cpol);
933  }
934  def _SGPR_IMM_gfx10 : SMEM_Real_gfx10<op, !cast<SM_Load_Pseudo>(ps#_SGPR_IMM)> {
935    let InOperandList = (ins sgprPs.BaseClass:$sbase, SReg_32:$soffset,
936                             smem_offset_mod:$offset, CPol:$cpol);
937  }
938}
939
940class SMEM_Real_Store_gfx10<bits<8> op, SM_Pseudo ps> : SMEM_Real_gfx10<op, ps> {
941  bits<7> sdata;
942
943  let sdst = ?;
944  let Inst{12-6} = !if(ps.has_sdst, sdata{6-0}, ?);
945}
946
947multiclass SM_Real_Stores_gfx10<bits<8> op, string ps,
948                                SM_Store_Pseudo immPs = !cast<SM_Store_Pseudo>(ps#_IMM),
949                                SM_Store_Pseudo sgprPs = !cast<SM_Store_Pseudo>(ps#_SGPR)> {
950  def _IMM_gfx10 : SMEM_Real_Store_gfx10 <op, immPs> {
951    let InOperandList = (ins immPs.SrcClass:$sdata, immPs.BaseClass:$sbase, smem_offset:$offset, CPol:$cpol);
952  }
953
954  def _SGPR_gfx10 : SMEM_Real_Store_gfx10 <op, sgprPs> {
955    let InOperandList = (ins sgprPs.SrcClass:$sdata, sgprPs.BaseClass:$sbase, SReg_32:$soffset, CPol:$cpol);
956  }
957
958  def _SGPR_IMM_gfx10 : SMEM_Real_Store_gfx10 <op, !cast<SM_Store_Pseudo>(ps#_SGPR_IMM)> {
959    let InOperandList = (ins sgprPs.SrcClass:$sdata, sgprPs.BaseClass:$sbase,
960                             SReg_32:$soffset, smem_offset_mod:$offset, CPol:$cpol);
961  }
962}
963
964defm S_LOAD_DWORD            : SM_Real_Loads_gfx10<0x000, "S_LOAD_DWORD">;
965defm S_LOAD_DWORDX2          : SM_Real_Loads_gfx10<0x001, "S_LOAD_DWORDX2">;
966defm S_LOAD_DWORDX4          : SM_Real_Loads_gfx10<0x002, "S_LOAD_DWORDX4">;
967defm S_LOAD_DWORDX8          : SM_Real_Loads_gfx10<0x003, "S_LOAD_DWORDX8">;
968defm S_LOAD_DWORDX16         : SM_Real_Loads_gfx10<0x004, "S_LOAD_DWORDX16">;
969
970let SubtargetPredicate = HasScalarFlatScratchInsts in {
971defm S_SCRATCH_LOAD_DWORD    : SM_Real_Loads_gfx10<0x005, "S_SCRATCH_LOAD_DWORD">;
972defm S_SCRATCH_LOAD_DWORDX2  : SM_Real_Loads_gfx10<0x006, "S_SCRATCH_LOAD_DWORDX2">;
973defm S_SCRATCH_LOAD_DWORDX4  : SM_Real_Loads_gfx10<0x007, "S_SCRATCH_LOAD_DWORDX4">;
974} // End SubtargetPredicate = HasScalarFlatScratchInsts
975
976defm S_BUFFER_LOAD_DWORD     : SM_Real_Loads_gfx10<0x008, "S_BUFFER_LOAD_DWORD">;
977defm S_BUFFER_LOAD_DWORDX2   : SM_Real_Loads_gfx10<0x009, "S_BUFFER_LOAD_DWORDX2">;
978defm S_BUFFER_LOAD_DWORDX4   : SM_Real_Loads_gfx10<0x00a, "S_BUFFER_LOAD_DWORDX4">;
979defm S_BUFFER_LOAD_DWORDX8   : SM_Real_Loads_gfx10<0x00b, "S_BUFFER_LOAD_DWORDX8">;
980defm S_BUFFER_LOAD_DWORDX16  : SM_Real_Loads_gfx10<0x00c, "S_BUFFER_LOAD_DWORDX16">;
981
982let SubtargetPredicate = HasScalarStores in {
983defm S_STORE_DWORD           : SM_Real_Stores_gfx10<0x010, "S_STORE_DWORD">;
984defm S_STORE_DWORDX2         : SM_Real_Stores_gfx10<0x011, "S_STORE_DWORDX2">;
985defm S_STORE_DWORDX4         : SM_Real_Stores_gfx10<0x012, "S_STORE_DWORDX4">;
986let OtherPredicates = [HasScalarFlatScratchInsts] in {
987defm S_SCRATCH_STORE_DWORD   : SM_Real_Stores_gfx10<0x015, "S_SCRATCH_STORE_DWORD">;
988defm S_SCRATCH_STORE_DWORDX2 : SM_Real_Stores_gfx10<0x016, "S_SCRATCH_STORE_DWORDX2">;
989defm S_SCRATCH_STORE_DWORDX4 : SM_Real_Stores_gfx10<0x017, "S_SCRATCH_STORE_DWORDX4">;
990} // End OtherPredicates = [HasScalarFlatScratchInsts]
991defm S_BUFFER_STORE_DWORD    : SM_Real_Stores_gfx10<0x018, "S_BUFFER_STORE_DWORD">;
992defm S_BUFFER_STORE_DWORDX2  : SM_Real_Stores_gfx10<0x019, "S_BUFFER_STORE_DWORDX2">;
993defm S_BUFFER_STORE_DWORDX4  : SM_Real_Stores_gfx10<0x01a, "S_BUFFER_STORE_DWORDX4">;
994} // End SubtargetPredicate = HasScalarStores
995
996def S_MEMREALTIME_gfx10              : SMEM_Real_gfx10<0x025, S_MEMREALTIME>;
997def S_MEMTIME_gfx10                  : SMEM_Real_gfx10<0x024, S_MEMTIME>;
998def S_GL1_INV_gfx10                  : SMEM_Real_gfx10<0x01f, S_GL1_INV>;
999def S_GET_WAVEID_IN_WORKGROUP_gfx10  : SMEM_Real_gfx10<0x02a, S_GET_WAVEID_IN_WORKGROUP>;
1000def S_DCACHE_INV_gfx10               : SMEM_Real_gfx10<0x020, S_DCACHE_INV>;
1001
1002let SubtargetPredicate = HasScalarStores in {
1003def S_DCACHE_WB_gfx10                : SMEM_Real_gfx10<0x021, S_DCACHE_WB>;
1004} // End SubtargetPredicate = HasScalarStores
1005
1006multiclass SM_Real_Probe_gfx10<bits<8> op, string ps> {
1007  def _IMM_gfx10  : SMEM_Real_Store_gfx10 <op, !cast<SM_Pseudo>(ps#_IMM)>;
1008  def _SGPR_gfx10 : SMEM_Real_Store_gfx10 <op, !cast<SM_Pseudo>(ps#_SGPR)>;
1009}
1010
1011defm S_ATC_PROBE        : SM_Real_Probe_gfx10 <0x26, "S_ATC_PROBE">;
1012defm S_ATC_PROBE_BUFFER : SM_Real_Probe_gfx10 <0x27, "S_ATC_PROBE_BUFFER">;
1013
1014class SMEM_Atomic_Real_gfx10 <bits<8> op, SM_Atomic_Pseudo ps>
1015  : SMEM_Real_gfx10 <op, ps>,
1016    AtomicNoRet <!subst("_RTN","",NAME), ps.glc> {
1017
1018  bits<7> sdata;
1019
1020  let Constraints = ps.Constraints;
1021  let DisableEncoding = ps.DisableEncoding;
1022
1023  let cpol{CPolBit.GLC} = ps.glc;
1024
1025  let Inst{14} = !if(ps.has_dlc, cpol{CPolBit.DLC}, 0);
1026  let Inst{12-6} = !if(ps.glc, sdst{6-0}, sdata{6-0});
1027}
1028
1029multiclass SM_Real_Atomics_gfx10<bits<8> op, string ps> {
1030  def _IMM_gfx10       : SMEM_Atomic_Real_gfx10 <op, !cast<SM_Atomic_Pseudo>(ps#_IMM)>;
1031  def _SGPR_gfx10      : SMEM_Atomic_Real_gfx10 <op, !cast<SM_Atomic_Pseudo>(ps#_SGPR)>;
1032  def _IMM_RTN_gfx10   : SMEM_Atomic_Real_gfx10 <op, !cast<SM_Atomic_Pseudo>(ps#_IMM_RTN)>;
1033  def _SGPR_RTN_gfx10  : SMEM_Atomic_Real_gfx10 <op, !cast<SM_Atomic_Pseudo>(ps#_SGPR_RTN)>;
1034}
1035
1036let SubtargetPredicate = HasScalarAtomics in {
1037
1038defm S_BUFFER_ATOMIC_SWAP         : SM_Real_Atomics_gfx10 <0x40, "S_BUFFER_ATOMIC_SWAP">;
1039defm S_BUFFER_ATOMIC_CMPSWAP      : SM_Real_Atomics_gfx10 <0x41, "S_BUFFER_ATOMIC_CMPSWAP">;
1040defm S_BUFFER_ATOMIC_ADD          : SM_Real_Atomics_gfx10 <0x42, "S_BUFFER_ATOMIC_ADD">;
1041defm S_BUFFER_ATOMIC_SUB          : SM_Real_Atomics_gfx10 <0x43, "S_BUFFER_ATOMIC_SUB">;
1042defm S_BUFFER_ATOMIC_SMIN         : SM_Real_Atomics_gfx10 <0x44, "S_BUFFER_ATOMIC_SMIN">;
1043defm S_BUFFER_ATOMIC_UMIN         : SM_Real_Atomics_gfx10 <0x45, "S_BUFFER_ATOMIC_UMIN">;
1044defm S_BUFFER_ATOMIC_SMAX         : SM_Real_Atomics_gfx10 <0x46, "S_BUFFER_ATOMIC_SMAX">;
1045defm S_BUFFER_ATOMIC_UMAX         : SM_Real_Atomics_gfx10 <0x47, "S_BUFFER_ATOMIC_UMAX">;
1046defm S_BUFFER_ATOMIC_AND          : SM_Real_Atomics_gfx10 <0x48, "S_BUFFER_ATOMIC_AND">;
1047defm S_BUFFER_ATOMIC_OR           : SM_Real_Atomics_gfx10 <0x49, "S_BUFFER_ATOMIC_OR">;
1048defm S_BUFFER_ATOMIC_XOR          : SM_Real_Atomics_gfx10 <0x4a, "S_BUFFER_ATOMIC_XOR">;
1049defm S_BUFFER_ATOMIC_INC          : SM_Real_Atomics_gfx10 <0x4b, "S_BUFFER_ATOMIC_INC">;
1050defm S_BUFFER_ATOMIC_DEC          : SM_Real_Atomics_gfx10 <0x4c, "S_BUFFER_ATOMIC_DEC">;
1051
1052defm S_BUFFER_ATOMIC_SWAP_X2      : SM_Real_Atomics_gfx10 <0x60, "S_BUFFER_ATOMIC_SWAP_X2">;
1053defm S_BUFFER_ATOMIC_CMPSWAP_X2   : SM_Real_Atomics_gfx10 <0x61, "S_BUFFER_ATOMIC_CMPSWAP_X2">;
1054defm S_BUFFER_ATOMIC_ADD_X2       : SM_Real_Atomics_gfx10 <0x62, "S_BUFFER_ATOMIC_ADD_X2">;
1055defm S_BUFFER_ATOMIC_SUB_X2       : SM_Real_Atomics_gfx10 <0x63, "S_BUFFER_ATOMIC_SUB_X2">;
1056defm S_BUFFER_ATOMIC_SMIN_X2      : SM_Real_Atomics_gfx10 <0x64, "S_BUFFER_ATOMIC_SMIN_X2">;
1057defm S_BUFFER_ATOMIC_UMIN_X2      : SM_Real_Atomics_gfx10 <0x65, "S_BUFFER_ATOMIC_UMIN_X2">;
1058defm S_BUFFER_ATOMIC_SMAX_X2      : SM_Real_Atomics_gfx10 <0x66, "S_BUFFER_ATOMIC_SMAX_X2">;
1059defm S_BUFFER_ATOMIC_UMAX_X2      : SM_Real_Atomics_gfx10 <0x67, "S_BUFFER_ATOMIC_UMAX_X2">;
1060defm S_BUFFER_ATOMIC_AND_X2       : SM_Real_Atomics_gfx10 <0x68, "S_BUFFER_ATOMIC_AND_X2">;
1061defm S_BUFFER_ATOMIC_OR_X2        : SM_Real_Atomics_gfx10 <0x69, "S_BUFFER_ATOMIC_OR_X2">;
1062defm S_BUFFER_ATOMIC_XOR_X2       : SM_Real_Atomics_gfx10 <0x6a, "S_BUFFER_ATOMIC_XOR_X2">;
1063defm S_BUFFER_ATOMIC_INC_X2       : SM_Real_Atomics_gfx10 <0x6b, "S_BUFFER_ATOMIC_INC_X2">;
1064defm S_BUFFER_ATOMIC_DEC_X2       : SM_Real_Atomics_gfx10 <0x6c, "S_BUFFER_ATOMIC_DEC_X2">;
1065
1066defm S_ATOMIC_SWAP                : SM_Real_Atomics_gfx10 <0x80, "S_ATOMIC_SWAP">;
1067defm S_ATOMIC_CMPSWAP             : SM_Real_Atomics_gfx10 <0x81, "S_ATOMIC_CMPSWAP">;
1068defm S_ATOMIC_ADD                 : SM_Real_Atomics_gfx10 <0x82, "S_ATOMIC_ADD">;
1069defm S_ATOMIC_SUB                 : SM_Real_Atomics_gfx10 <0x83, "S_ATOMIC_SUB">;
1070defm S_ATOMIC_SMIN                : SM_Real_Atomics_gfx10 <0x84, "S_ATOMIC_SMIN">;
1071defm S_ATOMIC_UMIN                : SM_Real_Atomics_gfx10 <0x85, "S_ATOMIC_UMIN">;
1072defm S_ATOMIC_SMAX                : SM_Real_Atomics_gfx10 <0x86, "S_ATOMIC_SMAX">;
1073defm S_ATOMIC_UMAX                : SM_Real_Atomics_gfx10 <0x87, "S_ATOMIC_UMAX">;
1074defm S_ATOMIC_AND                 : SM_Real_Atomics_gfx10 <0x88, "S_ATOMIC_AND">;
1075defm S_ATOMIC_OR                  : SM_Real_Atomics_gfx10 <0x89, "S_ATOMIC_OR">;
1076defm S_ATOMIC_XOR                 : SM_Real_Atomics_gfx10 <0x8a, "S_ATOMIC_XOR">;
1077defm S_ATOMIC_INC                 : SM_Real_Atomics_gfx10 <0x8b, "S_ATOMIC_INC">;
1078defm S_ATOMIC_DEC                 : SM_Real_Atomics_gfx10 <0x8c, "S_ATOMIC_DEC">;
1079
1080defm S_ATOMIC_SWAP_X2             : SM_Real_Atomics_gfx10 <0xa0, "S_ATOMIC_SWAP_X2">;
1081defm S_ATOMIC_CMPSWAP_X2          : SM_Real_Atomics_gfx10 <0xa1, "S_ATOMIC_CMPSWAP_X2">;
1082defm S_ATOMIC_ADD_X2              : SM_Real_Atomics_gfx10 <0xa2, "S_ATOMIC_ADD_X2">;
1083defm S_ATOMIC_SUB_X2              : SM_Real_Atomics_gfx10 <0xa3, "S_ATOMIC_SUB_X2">;
1084defm S_ATOMIC_SMIN_X2             : SM_Real_Atomics_gfx10 <0xa4, "S_ATOMIC_SMIN_X2">;
1085defm S_ATOMIC_UMIN_X2             : SM_Real_Atomics_gfx10 <0xa5, "S_ATOMIC_UMIN_X2">;
1086defm S_ATOMIC_SMAX_X2             : SM_Real_Atomics_gfx10 <0xa6, "S_ATOMIC_SMAX_X2">;
1087defm S_ATOMIC_UMAX_X2             : SM_Real_Atomics_gfx10 <0xa7, "S_ATOMIC_UMAX_X2">;
1088defm S_ATOMIC_AND_X2              : SM_Real_Atomics_gfx10 <0xa8, "S_ATOMIC_AND_X2">;
1089defm S_ATOMIC_OR_X2               : SM_Real_Atomics_gfx10 <0xa9, "S_ATOMIC_OR_X2">;
1090defm S_ATOMIC_XOR_X2              : SM_Real_Atomics_gfx10 <0xaa, "S_ATOMIC_XOR_X2">;
1091defm S_ATOMIC_INC_X2              : SM_Real_Atomics_gfx10 <0xab, "S_ATOMIC_INC_X2">;
1092defm S_ATOMIC_DEC_X2              : SM_Real_Atomics_gfx10 <0xac, "S_ATOMIC_DEC_X2">;
1093
1094multiclass SM_Real_Discard_gfx10<bits<8> op, string ps> {
1095  def _IMM_gfx10  : SMEM_Real_gfx10 <op, !cast<SM_Pseudo>(ps#_IMM)>;
1096  def _SGPR_gfx10 : SMEM_Real_gfx10 <op, !cast<SM_Pseudo>(ps#_SGPR)>;
1097}
1098
1099defm S_DCACHE_DISCARD    : SM_Real_Discard_gfx10 <0x28, "S_DCACHE_DISCARD">;
1100defm S_DCACHE_DISCARD_X2 : SM_Real_Discard_gfx10 <0x29, "S_DCACHE_DISCARD_X2">;
1101
1102} // End SubtargetPredicate = HasScalarAtomics
1103
1104def SMInfoTable : GenericTable {
1105  let FilterClass = "SM_Real";
1106  let CppTypeName = "SMInfo";
1107  let Fields = ["Opcode", "is_buffer"];
1108
1109  let PrimaryKey = ["Opcode"];
1110  let PrimaryKeyName = "getSMEMOpcodeHelper";
1111}
1112