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