xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoA.td (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
1//===-- RISCVInstrInfoA.td - RISC-V 'A' instructions -------*- 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//
9// This file describes the RISC-V instructions from the standard 'A', Atomic
10// Instructions extension.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15// Instruction class templates
16//===----------------------------------------------------------------------===//
17
18let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
19class LR_r<bit aq, bit rl, bits<3> funct3, string opcodestr>
20    : RVInstRAtomic<0b00010, aq, rl, funct3, OPC_AMO,
21                    (outs GPR:$rd), (ins GPRMemZeroOffset:$rs1),
22                    opcodestr, "$rd, $rs1"> {
23  let rs2 = 0;
24}
25
26multiclass LR_r_aq_rl<bits<3> funct3, string opcodestr> {
27  def ""     : LR_r<0, 0, funct3, opcodestr>;
28  def _AQ    : LR_r<1, 0, funct3, opcodestr # ".aq">;
29  def _RL    : LR_r<0, 1, funct3, opcodestr # ".rl">;
30  def _AQ_RL : LR_r<1, 1, funct3, opcodestr # ".aqrl">;
31}
32
33let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in
34class AMO_rr<bits<5> funct5, bit aq, bit rl, bits<3> funct3, string opcodestr>
35    : RVInstRAtomic<funct5, aq, rl, funct3, OPC_AMO,
36                    (outs GPR:$rd), (ins GPRMemZeroOffset:$rs1, GPR:$rs2),
37                    opcodestr, "$rd, $rs2, $rs1">;
38
39multiclass AMO_rr_aq_rl<bits<5> funct5, bits<3> funct3, string opcodestr> {
40  def ""     : AMO_rr<funct5, 0, 0, funct3, opcodestr>;
41  def _AQ    : AMO_rr<funct5, 1, 0, funct3, opcodestr # ".aq">;
42  def _RL    : AMO_rr<funct5, 0, 1, funct3, opcodestr # ".rl">;
43  def _AQ_RL : AMO_rr<funct5, 1, 1, funct3, opcodestr # ".aqrl">;
44}
45
46//===----------------------------------------------------------------------===//
47// Instructions
48//===----------------------------------------------------------------------===//
49
50let Predicates = [HasStdExtA], IsSignExtendingOpW = 1 in {
51defm LR_W       : LR_r_aq_rl<0b010, "lr.w">, Sched<[WriteAtomicLDW, ReadAtomicLDW]>;
52defm SC_W       : AMO_rr_aq_rl<0b00011, 0b010, "sc.w">,
53                  Sched<[WriteAtomicSTW, ReadAtomicSTW, ReadAtomicSTW]>;
54defm AMOSWAP_W  : AMO_rr_aq_rl<0b00001, 0b010, "amoswap.w">,
55                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
56defm AMOADD_W   : AMO_rr_aq_rl<0b00000, 0b010, "amoadd.w">,
57                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
58defm AMOXOR_W   : AMO_rr_aq_rl<0b00100, 0b010, "amoxor.w">,
59                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
60defm AMOAND_W   : AMO_rr_aq_rl<0b01100, 0b010, "amoand.w">,
61                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
62defm AMOOR_W    : AMO_rr_aq_rl<0b01000, 0b010, "amoor.w">,
63                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
64defm AMOMIN_W   : AMO_rr_aq_rl<0b10000, 0b010, "amomin.w">,
65                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
66defm AMOMAX_W   : AMO_rr_aq_rl<0b10100, 0b010, "amomax.w">,
67                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
68defm AMOMINU_W  : AMO_rr_aq_rl<0b11000, 0b010, "amominu.w">,
69                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
70defm AMOMAXU_W  : AMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">,
71                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
72} // Predicates = [HasStdExtA]
73
74let Predicates = [HasStdExtA, IsRV64] in {
75defm LR_D       : LR_r_aq_rl<0b011, "lr.d">, Sched<[WriteAtomicLDD, ReadAtomicLDD]>;
76defm SC_D       : AMO_rr_aq_rl<0b00011, 0b011, "sc.d">,
77                  Sched<[WriteAtomicSTD, ReadAtomicSTD, ReadAtomicSTD]>;
78defm AMOSWAP_D  : AMO_rr_aq_rl<0b00001, 0b011, "amoswap.d">,
79                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
80defm AMOADD_D   : AMO_rr_aq_rl<0b00000, 0b011, "amoadd.d">,
81                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
82defm AMOXOR_D   : AMO_rr_aq_rl<0b00100, 0b011, "amoxor.d">,
83                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
84defm AMOAND_D   : AMO_rr_aq_rl<0b01100, 0b011, "amoand.d">,
85                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
86defm AMOOR_D    : AMO_rr_aq_rl<0b01000, 0b011, "amoor.d">,
87                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
88defm AMOMIN_D   : AMO_rr_aq_rl<0b10000, 0b011, "amomin.d">,
89                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
90defm AMOMAX_D   : AMO_rr_aq_rl<0b10100, 0b011, "amomax.d">,
91                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
92defm AMOMINU_D  : AMO_rr_aq_rl<0b11000, 0b011, "amominu.d">,
93                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
94defm AMOMAXU_D  : AMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">,
95                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
96} // Predicates = [HasStdExtA, IsRV64]
97
98//===----------------------------------------------------------------------===//
99// Pseudo-instructions and codegen patterns
100//===----------------------------------------------------------------------===//
101
102// Atomic load/store are available under both +a and +force-atomics.
103// Fences will be inserted for atomic load/stores according to the logic in
104// RISCVTargetLowering::{emitLeadingFence,emitTrailingFence}.
105let Predicates = [HasAtomicLdSt] in {
106  def : LdPat<atomic_load_8,  LB>;
107  def : LdPat<atomic_load_16, LH>;
108  def : LdPat<atomic_load_32, LW>;
109
110  def : StPat<atomic_store_8,  SB, GPR, XLenVT>;
111  def : StPat<atomic_store_16, SH, GPR, XLenVT>;
112  def : StPat<atomic_store_32, SW, GPR, XLenVT>;
113}
114
115let Predicates = [HasAtomicLdSt, IsRV64] in {
116  def : LdPat<atomic_load_64, LD, i64>;
117  def : StPat<atomic_store_64, SD, GPR, i64>;
118}
119
120/// AMOs
121
122multiclass AMOPat<string AtomicOp, string BaseInst, ValueType vt = XLenVT,
123                  list<Predicate> ExtraPreds = []> {
124let Predicates = !listconcat([HasStdExtA, NotHasStdExtZtso], ExtraPreds) in {
125  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_monotonic"),
126                  !cast<RVInst>(BaseInst), vt>;
127  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acquire"),
128                  !cast<RVInst>(BaseInst#"_AQ"), vt>;
129  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_release"),
130                  !cast<RVInst>(BaseInst#"_RL"), vt>;
131  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acq_rel"),
132                  !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
133  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_seq_cst"),
134                  !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
135}
136let Predicates = !listconcat([HasStdExtA, HasStdExtZtso], ExtraPreds) in {
137  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_monotonic"),
138                  !cast<RVInst>(BaseInst), vt>;
139  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acquire"),
140                  !cast<RVInst>(BaseInst), vt>;
141  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_release"),
142                  !cast<RVInst>(BaseInst), vt>;
143  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acq_rel"),
144                  !cast<RVInst>(BaseInst), vt>;
145  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_seq_cst"),
146                  !cast<RVInst>(BaseInst), vt>;
147}
148}
149
150defm : AMOPat<"atomic_swap_32", "AMOSWAP_W">;
151defm : AMOPat<"atomic_load_add_32", "AMOADD_W">;
152defm : AMOPat<"atomic_load_and_32", "AMOAND_W">;
153defm : AMOPat<"atomic_load_or_32", "AMOOR_W">;
154defm : AMOPat<"atomic_load_xor_32", "AMOXOR_W">;
155defm : AMOPat<"atomic_load_max_32", "AMOMAX_W">;
156defm : AMOPat<"atomic_load_min_32", "AMOMIN_W">;
157defm : AMOPat<"atomic_load_umax_32", "AMOMAXU_W">;
158defm : AMOPat<"atomic_load_umin_32", "AMOMINU_W">;
159
160let Predicates = [HasStdExtA] in {
161
162/// Pseudo AMOs
163
164class PseudoAMO : Pseudo<(outs GPR:$res, GPR:$scratch),
165                         (ins GPR:$addr, GPR:$incr, ixlenimm:$ordering), []> {
166  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
167  let mayLoad = 1;
168  let mayStore = 1;
169  let hasSideEffects = 0;
170}
171
172let Size = 20 in
173def PseudoAtomicLoadNand32 : PseudoAMO;
174// Ordering constants must be kept in sync with the AtomicOrdering enum in
175// AtomicOrdering.h.
176def : Pat<(XLenVT (atomic_load_nand_32_monotonic GPR:$addr, GPR:$incr)),
177          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 2)>;
178def : Pat<(XLenVT (atomic_load_nand_32_acquire GPR:$addr, GPR:$incr)),
179          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 4)>;
180def : Pat<(XLenVT (atomic_load_nand_32_release GPR:$addr, GPR:$incr)),
181          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 5)>;
182def : Pat<(XLenVT (atomic_load_nand_32_acq_rel GPR:$addr, GPR:$incr)),
183          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 6)>;
184def : Pat<(XLenVT (atomic_load_nand_32_seq_cst GPR:$addr, GPR:$incr)),
185          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 7)>;
186
187class PseudoMaskedAMO
188    : Pseudo<(outs GPR:$res, GPR:$scratch),
189             (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$ordering), []> {
190  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
191  let mayLoad = 1;
192  let mayStore = 1;
193  let hasSideEffects = 0;
194}
195
196class PseudoMaskedAMOMinMax
197    : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
198             (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$sextshamt,
199              ixlenimm:$ordering), []> {
200  let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
201                    "@earlyclobber $scratch2";
202  let mayLoad = 1;
203  let mayStore = 1;
204  let hasSideEffects = 0;
205}
206
207class PseudoMaskedAMOUMinUMax
208    : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
209             (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$ordering), []> {
210  let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
211                    "@earlyclobber $scratch2";
212  let mayLoad = 1;
213  let mayStore = 1;
214  let hasSideEffects = 0;
215}
216
217class PseudoMaskedAMOPat<Intrinsic intrin, Pseudo AMOInst>
218    : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering),
219          (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>;
220
221class PseudoMaskedAMOMinMaxPat<Intrinsic intrin, Pseudo AMOInst>
222    : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
223           timm:$ordering),
224          (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
225           timm:$ordering)>;
226
227let Size = 28 in
228def PseudoMaskedAtomicSwap32 : PseudoMaskedAMO;
229def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_xchg_i32,
230                         PseudoMaskedAtomicSwap32>;
231let Size = 28 in
232def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAMO;
233def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_add_i32,
234                         PseudoMaskedAtomicLoadAdd32>;
235let Size = 28 in
236def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAMO;
237def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_sub_i32,
238                         PseudoMaskedAtomicLoadSub32>;
239let Size = 32 in
240def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAMO;
241def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_nand_i32,
242                         PseudoMaskedAtomicLoadNand32>;
243let Size = 44 in
244def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMOMinMax;
245def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_max_i32,
246                               PseudoMaskedAtomicLoadMax32>;
247let Size = 44 in
248def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMOMinMax;
249def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_min_i32,
250                               PseudoMaskedAtomicLoadMin32>;
251let Size = 36 in
252def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMOUMinUMax;
253def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umax_i32,
254                         PseudoMaskedAtomicLoadUMax32>;
255let Size = 36 in
256def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMOUMinUMax;
257def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umin_i32,
258                         PseudoMaskedAtomicLoadUMin32>;
259
260/// Compare and exchange
261
262class PseudoCmpXchg
263    : Pseudo<(outs GPR:$res, GPR:$scratch),
264             (ins GPR:$addr, GPR:$cmpval, GPR:$newval, ixlenimm:$ordering), []> {
265  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
266  let mayLoad = 1;
267  let mayStore = 1;
268  let hasSideEffects = 0;
269  let Size = 16;
270}
271
272// Ordering constants must be kept in sync with the AtomicOrdering enum in
273// AtomicOrdering.h.
274multiclass PseudoCmpXchgPat<string Op, Pseudo CmpXchgInst,
275                            ValueType vt = XLenVT> {
276  def : Pat<(vt (!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$cmp, GPR:$new)),
277            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 2)>;
278  def : Pat<(vt (!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$cmp, GPR:$new)),
279            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 4)>;
280  def : Pat<(vt (!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$cmp, GPR:$new)),
281            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 5)>;
282  def : Pat<(vt (!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$cmp, GPR:$new)),
283            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 6)>;
284  def : Pat<(vt (!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$cmp, GPR:$new)),
285            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 7)>;
286}
287
288def PseudoCmpXchg32 : PseudoCmpXchg;
289defm : PseudoCmpXchgPat<"atomic_cmp_swap_32", PseudoCmpXchg32>;
290
291def PseudoMaskedCmpXchg32
292    : Pseudo<(outs GPR:$res, GPR:$scratch),
293             (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask,
294              ixlenimm:$ordering), []> {
295  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
296  let mayLoad = 1;
297  let mayStore = 1;
298  let hasSideEffects = 0;
299  let Size = 32;
300}
301
302def : Pat<(int_riscv_masked_cmpxchg_i32
303            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
304          (PseudoMaskedCmpXchg32
305            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
306
307} // Predicates = [HasStdExtA]
308
309defm : AMOPat<"atomic_swap_64", "AMOSWAP_D", i64, [IsRV64]>;
310defm : AMOPat<"atomic_load_add_64", "AMOADD_D", i64, [IsRV64]>;
311defm : AMOPat<"atomic_load_and_64", "AMOAND_D", i64, [IsRV64]>;
312defm : AMOPat<"atomic_load_or_64", "AMOOR_D", i64, [IsRV64]>;
313defm : AMOPat<"atomic_load_xor_64", "AMOXOR_D", i64, [IsRV64]>;
314defm : AMOPat<"atomic_load_max_64", "AMOMAX_D", i64, [IsRV64]>;
315defm : AMOPat<"atomic_load_min_64", "AMOMIN_D", i64, [IsRV64]>;
316defm : AMOPat<"atomic_load_umax_64", "AMOMAXU_D", i64, [IsRV64]>;
317defm : AMOPat<"atomic_load_umin_64", "AMOMINU_D", i64, [IsRV64]>;
318
319let Predicates = [HasStdExtA, IsRV64] in {
320
321/// 64-bit pseudo AMOs
322
323let Size = 20 in
324def PseudoAtomicLoadNand64 : PseudoAMO;
325// Ordering constants must be kept in sync with the AtomicOrdering enum in
326// AtomicOrdering.h.
327def : Pat<(i64 (atomic_load_nand_64_monotonic GPR:$addr, GPR:$incr)),
328          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 2)>;
329def : Pat<(i64 (atomic_load_nand_64_acquire GPR:$addr, GPR:$incr)),
330          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 4)>;
331def : Pat<(i64 (atomic_load_nand_64_release GPR:$addr, GPR:$incr)),
332          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 5)>;
333def : Pat<(i64 (atomic_load_nand_64_acq_rel GPR:$addr, GPR:$incr)),
334          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 6)>;
335def : Pat<(i64 (atomic_load_nand_64_seq_cst GPR:$addr, GPR:$incr)),
336          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 7)>;
337
338def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_xchg_i64,
339                         PseudoMaskedAtomicSwap32>;
340def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_add_i64,
341                         PseudoMaskedAtomicLoadAdd32>;
342def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_sub_i64,
343                         PseudoMaskedAtomicLoadSub32>;
344def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_nand_i64,
345                         PseudoMaskedAtomicLoadNand32>;
346def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_max_i64,
347                               PseudoMaskedAtomicLoadMax32>;
348def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_min_i64,
349                               PseudoMaskedAtomicLoadMin32>;
350def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umax_i64,
351                         PseudoMaskedAtomicLoadUMax32>;
352def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umin_i64,
353                         PseudoMaskedAtomicLoadUMin32>;
354
355/// 64-bit compare and exchange
356
357def PseudoCmpXchg64 : PseudoCmpXchg;
358defm : PseudoCmpXchgPat<"atomic_cmp_swap_64", PseudoCmpXchg64, i64>;
359
360def : Pat<(int_riscv_masked_cmpxchg_i64
361            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
362          (PseudoMaskedCmpXchg32
363            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
364} // Predicates = [HasStdExtA, IsRV64]
365
366//===----------------------------------------------------------------------===//
367// Experimental RV64 i32 legalization patterns.
368//===----------------------------------------------------------------------===//
369
370class PatGprGprA<SDPatternOperator OpNode, RVInst Inst, ValueType vt>
371    : Pat<(vt (OpNode (XLenVT GPR:$rs1), (vt GPR:$rs2))), (Inst GPR:$rs1, GPR:$rs2)>;
372
373multiclass AMOPat2<string AtomicOp, string BaseInst, ValueType vt = XLenVT,
374                   list<Predicate> ExtraPreds = []> {
375let Predicates = !listconcat([HasStdExtA, NotHasStdExtZtso], ExtraPreds) in {
376  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_monotonic"),
377                   !cast<RVInst>(BaseInst), vt>;
378  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acquire"),
379                   !cast<RVInst>(BaseInst#"_AQ"), vt>;
380  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_release"),
381                   !cast<RVInst>(BaseInst#"_RL"), vt>;
382  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acq_rel"),
383                   !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
384  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_seq_cst"),
385                   !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
386}
387let Predicates = !listconcat([HasStdExtA, HasStdExtZtso], ExtraPreds) in {
388  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_monotonic"),
389                   !cast<RVInst>(BaseInst), vt>;
390  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acquire"),
391                   !cast<RVInst>(BaseInst), vt>;
392  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_release"),
393                   !cast<RVInst>(BaseInst), vt>;
394  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acq_rel"),
395                   !cast<RVInst>(BaseInst), vt>;
396  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_seq_cst"),
397                   !cast<RVInst>(BaseInst), vt>;
398}
399}
400
401defm : AMOPat2<"atomic_swap_32", "AMOSWAP_W", i32>;
402defm : AMOPat2<"atomic_load_add_32", "AMOADD_W", i32>;
403defm : AMOPat2<"atomic_load_and_32", "AMOAND_W", i32>;
404defm : AMOPat2<"atomic_load_or_32", "AMOOR_W", i32>;
405defm : AMOPat2<"atomic_load_xor_32", "AMOXOR_W", i32>;
406defm : AMOPat2<"atomic_load_max_32", "AMOMAX_W", i32>;
407defm : AMOPat2<"atomic_load_min_32", "AMOMIN_W", i32>;
408defm : AMOPat2<"atomic_load_umax_32", "AMOMAXU_W", i32>;
409defm : AMOPat2<"atomic_load_umin_32", "AMOMINU_W", i32>;
410
411defm : PseudoCmpXchgPat<"atomic_cmp_swap_32", PseudoCmpXchg32, i32>;
412
413let Predicates = [HasAtomicLdSt] in {
414  def : LdPat<atomic_load_8,  LB, i32>;
415  def : LdPat<atomic_load_16, LH, i32>;
416  def : LdPat<atomic_load_32, LW, i32>;
417
418  def : StPat<atomic_store_8,  SB, GPR, i32>;
419  def : StPat<atomic_store_16, SH, GPR, i32>;
420  def : StPat<atomic_store_32, SW, GPR, i32>;
421}
422
423