xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoA.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric//===-- RISCVInstrInfoA.td - RISC-V 'A' instructions -------*- tablegen -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file describes the RISC-V instructions from the standard 'A', Atomic
101db9f3b2SDimitry Andric// Instructions extension.
110b57cec5SDimitry Andric//
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric// Instruction class templates
160b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric
180b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
190b57cec5SDimitry Andricclass LR_r<bit aq, bit rl, bits<3> funct3, string opcodestr>
200b57cec5SDimitry Andric    : RVInstRAtomic<0b00010, aq, rl, funct3, OPC_AMO,
2181ad6265SDimitry Andric                    (outs GPR:$rd), (ins GPRMemZeroOffset:$rs1),
220b57cec5SDimitry Andric                    opcodestr, "$rd, $rs1"> {
230b57cec5SDimitry Andric  let rs2 = 0;
240b57cec5SDimitry Andric}
250b57cec5SDimitry Andric
260b57cec5SDimitry Andricmulticlass LR_r_aq_rl<bits<3> funct3, string opcodestr> {
270b57cec5SDimitry Andric  def ""     : LR_r<0, 0, funct3, opcodestr>;
280b57cec5SDimitry Andric  def _AQ    : LR_r<1, 0, funct3, opcodestr # ".aq">;
290b57cec5SDimitry Andric  def _RL    : LR_r<0, 1, funct3, opcodestr # ".rl">;
300b57cec5SDimitry Andric  def _AQ_RL : LR_r<1, 1, funct3, opcodestr # ".aqrl">;
310b57cec5SDimitry Andric}
320b57cec5SDimitry Andric
33*0fca6ea1SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
34*0fca6ea1SDimitry Andricclass SC_r<bit aq, bit rl, bits<3> funct3, string opcodestr>
35*0fca6ea1SDimitry Andric    : RVInstRAtomic<0b00011, aq, rl, funct3, OPC_AMO,
36*0fca6ea1SDimitry Andric                    (outs GPR:$rd), (ins GPRMemZeroOffset:$rs1, GPR:$rs2),
37*0fca6ea1SDimitry Andric                    opcodestr, "$rd, $rs2, $rs1">;
38*0fca6ea1SDimitry Andric
39*0fca6ea1SDimitry Andricmulticlass SC_r_aq_rl<bits<3> funct3, string opcodestr> {
40*0fca6ea1SDimitry Andric  def ""     : SC_r<0, 0, funct3, opcodestr>;
41*0fca6ea1SDimitry Andric  def _AQ    : SC_r<1, 0, funct3, opcodestr # ".aq">;
42*0fca6ea1SDimitry Andric  def _RL    : SC_r<0, 1, funct3, opcodestr # ".rl">;
43*0fca6ea1SDimitry Andric  def _AQ_RL : SC_r<1, 1, funct3, opcodestr # ".aqrl">;
44*0fca6ea1SDimitry Andric}
45*0fca6ea1SDimitry Andric
460b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 1 in
470b57cec5SDimitry Andricclass AMO_rr<bits<5> funct5, bit aq, bit rl, bits<3> funct3, string opcodestr>
480b57cec5SDimitry Andric    : RVInstRAtomic<funct5, aq, rl, funct3, OPC_AMO,
4981ad6265SDimitry Andric                    (outs GPR:$rd), (ins GPRMemZeroOffset:$rs1, GPR:$rs2),
500b57cec5SDimitry Andric                    opcodestr, "$rd, $rs2, $rs1">;
510b57cec5SDimitry Andric
520b57cec5SDimitry Andricmulticlass AMO_rr_aq_rl<bits<5> funct5, bits<3> funct3, string opcodestr> {
530b57cec5SDimitry Andric  def ""     : AMO_rr<funct5, 0, 0, funct3, opcodestr>;
540b57cec5SDimitry Andric  def _AQ    : AMO_rr<funct5, 1, 0, funct3, opcodestr # ".aq">;
550b57cec5SDimitry Andric  def _RL    : AMO_rr<funct5, 0, 1, funct3, opcodestr # ".rl">;
560b57cec5SDimitry Andric  def _AQ_RL : AMO_rr<funct5, 1, 1, funct3, opcodestr # ".aqrl">;
570b57cec5SDimitry Andric}
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
600b57cec5SDimitry Andric// Instructions
610b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
620b57cec5SDimitry Andric
63*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtAOrZalrsc], IsSignExtendingOpW = 1 in {
6413138422SDimitry Andricdefm LR_W       : LR_r_aq_rl<0b010, "lr.w">, Sched<[WriteAtomicLDW, ReadAtomicLDW]>;
65*0fca6ea1SDimitry Andricdefm SC_W       : SC_r_aq_rl<0b010, "sc.w">,
6613138422SDimitry Andric                  Sched<[WriteAtomicSTW, ReadAtomicSTW, ReadAtomicSTW]>;
67*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtAOrZalrsc], IsSignExtendingOpW = 1
68*0fca6ea1SDimitry Andric
69*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtAOrZaamo], IsSignExtendingOpW = 1 in {
7013138422SDimitry Andricdefm AMOSWAP_W  : AMO_rr_aq_rl<0b00001, 0b010, "amoswap.w">,
7113138422SDimitry Andric                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
7213138422SDimitry Andricdefm AMOADD_W   : AMO_rr_aq_rl<0b00000, 0b010, "amoadd.w">,
7313138422SDimitry Andric                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
7413138422SDimitry Andricdefm AMOXOR_W   : AMO_rr_aq_rl<0b00100, 0b010, "amoxor.w">,
7513138422SDimitry Andric                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
7613138422SDimitry Andricdefm AMOAND_W   : AMO_rr_aq_rl<0b01100, 0b010, "amoand.w">,
7713138422SDimitry Andric                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
7813138422SDimitry Andricdefm AMOOR_W    : AMO_rr_aq_rl<0b01000, 0b010, "amoor.w">,
7913138422SDimitry Andric                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
8013138422SDimitry Andricdefm AMOMIN_W   : AMO_rr_aq_rl<0b10000, 0b010, "amomin.w">,
8113138422SDimitry Andric                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
8213138422SDimitry Andricdefm AMOMAX_W   : AMO_rr_aq_rl<0b10100, 0b010, "amomax.w">,
8313138422SDimitry Andric                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
8413138422SDimitry Andricdefm AMOMINU_W  : AMO_rr_aq_rl<0b11000, 0b010, "amominu.w">,
8513138422SDimitry Andric                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
8613138422SDimitry Andricdefm AMOMAXU_W  : AMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">,
8713138422SDimitry Andric                  Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
88*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtAOrZaamo], IsSignExtendingOpW = 1
890b57cec5SDimitry Andric
90*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtAOrZalrsc, IsRV64] in {
9113138422SDimitry Andricdefm LR_D       : LR_r_aq_rl<0b011, "lr.d">, Sched<[WriteAtomicLDD, ReadAtomicLDD]>;
92*0fca6ea1SDimitry Andricdefm SC_D       : SC_r_aq_rl<0b011, "sc.d">,
9313138422SDimitry Andric                  Sched<[WriteAtomicSTD, ReadAtomicSTD, ReadAtomicSTD]>;
94*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtAOrZalrsc, IsRV64]
95*0fca6ea1SDimitry Andric
96*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtAOrZaamo, IsRV64] in {
9713138422SDimitry Andricdefm AMOSWAP_D  : AMO_rr_aq_rl<0b00001, 0b011, "amoswap.d">,
9813138422SDimitry Andric                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
9913138422SDimitry Andricdefm AMOADD_D   : AMO_rr_aq_rl<0b00000, 0b011, "amoadd.d">,
10013138422SDimitry Andric                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
10113138422SDimitry Andricdefm AMOXOR_D   : AMO_rr_aq_rl<0b00100, 0b011, "amoxor.d">,
10213138422SDimitry Andric                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
10313138422SDimitry Andricdefm AMOAND_D   : AMO_rr_aq_rl<0b01100, 0b011, "amoand.d">,
10413138422SDimitry Andric                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
10513138422SDimitry Andricdefm AMOOR_D    : AMO_rr_aq_rl<0b01000, 0b011, "amoor.d">,
10613138422SDimitry Andric                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
10713138422SDimitry Andricdefm AMOMIN_D   : AMO_rr_aq_rl<0b10000, 0b011, "amomin.d">,
10813138422SDimitry Andric                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
10913138422SDimitry Andricdefm AMOMAX_D   : AMO_rr_aq_rl<0b10100, 0b011, "amomax.d">,
11013138422SDimitry Andric                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
11113138422SDimitry Andricdefm AMOMINU_D  : AMO_rr_aq_rl<0b11000, 0b011, "amominu.d">,
11213138422SDimitry Andric                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
11313138422SDimitry Andricdefm AMOMAXU_D  : AMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">,
11413138422SDimitry Andric                  Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
115*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtAOrZaamo, IsRV64]
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1180b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns
1190b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1200b57cec5SDimitry Andric
121bdd1243dSDimitry Andric// Atomic load/store are available under both +a and +force-atomics.
1220b57cec5SDimitry Andric// Fences will be inserted for atomic load/stores according to the logic in
1230b57cec5SDimitry Andric// RISCVTargetLowering::{emitLeadingFence,emitTrailingFence}.
124bdd1243dSDimitry Andriclet Predicates = [HasAtomicLdSt] in {
12506c3fb27SDimitry Andric  def : LdPat<atomic_load_8,  LB>;
12606c3fb27SDimitry Andric  def : LdPat<atomic_load_16, LH>;
12706c3fb27SDimitry Andric  def : LdPat<atomic_load_32, LW>;
1280b57cec5SDimitry Andric
1295f757f3fSDimitry Andric  def : StPat<atomic_store_8,  SB, GPR, XLenVT>;
1305f757f3fSDimitry Andric  def : StPat<atomic_store_16, SH, GPR, XLenVT>;
1315f757f3fSDimitry Andric  def : StPat<atomic_store_32, SW, GPR, XLenVT>;
132bdd1243dSDimitry Andric}
133bdd1243dSDimitry Andric
134bdd1243dSDimitry Andriclet Predicates = [HasAtomicLdSt, IsRV64] in {
13506c3fb27SDimitry Andric  def : LdPat<atomic_load_64, LD, i64>;
1365f757f3fSDimitry Andric  def : StPat<atomic_store_64, SD, GPR, i64>;
137bdd1243dSDimitry Andric}
138bdd1243dSDimitry Andric
1390b57cec5SDimitry Andric/// AMOs
1400b57cec5SDimitry Andric
1415f757f3fSDimitry Andricmulticlass AMOPat<string AtomicOp, string BaseInst, ValueType vt = XLenVT,
1425f757f3fSDimitry Andric                  list<Predicate> ExtraPreds = []> {
1435f757f3fSDimitry Andriclet Predicates = !listconcat([HasStdExtA, NotHasStdExtZtso], ExtraPreds) in {
1440b57cec5SDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_monotonic"),
14506c3fb27SDimitry Andric                  !cast<RVInst>(BaseInst), vt>;
1460b57cec5SDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acquire"),
14706c3fb27SDimitry Andric                  !cast<RVInst>(BaseInst#"_AQ"), vt>;
1480b57cec5SDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_release"),
14906c3fb27SDimitry Andric                  !cast<RVInst>(BaseInst#"_RL"), vt>;
1500b57cec5SDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acq_rel"),
15106c3fb27SDimitry Andric                  !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
1520b57cec5SDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_seq_cst"),
15306c3fb27SDimitry Andric                  !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
1540b57cec5SDimitry Andric}
1555f757f3fSDimitry Andriclet Predicates = !listconcat([HasStdExtA, HasStdExtZtso], ExtraPreds) in {
1565f757f3fSDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_monotonic"),
1575f757f3fSDimitry Andric                  !cast<RVInst>(BaseInst), vt>;
1585f757f3fSDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acquire"),
1595f757f3fSDimitry Andric                  !cast<RVInst>(BaseInst), vt>;
1605f757f3fSDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_release"),
1615f757f3fSDimitry Andric                  !cast<RVInst>(BaseInst), vt>;
1625f757f3fSDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acq_rel"),
1635f757f3fSDimitry Andric                  !cast<RVInst>(BaseInst), vt>;
1645f757f3fSDimitry Andric  def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_seq_cst"),
1655f757f3fSDimitry Andric                  !cast<RVInst>(BaseInst), vt>;
1665f757f3fSDimitry Andric}
1675f757f3fSDimitry Andric}
1680b57cec5SDimitry Andric
169*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_swap_i32", "AMOSWAP_W">;
170*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_add_i32", "AMOADD_W">;
171*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_and_i32", "AMOAND_W">;
172*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_or_i32", "AMOOR_W">;
173*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_xor_i32", "AMOXOR_W">;
174*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_max_i32", "AMOMAX_W">;
175*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_min_i32", "AMOMIN_W">;
176*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_umax_i32", "AMOMAXU_W">;
177*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_umin_i32", "AMOMINU_W">;
1780b57cec5SDimitry Andric
179*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_swap_i64", "AMOSWAP_D", i64, [IsRV64]>;
180*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_add_i64", "AMOADD_D", i64, [IsRV64]>;
181*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_and_i64", "AMOAND_D", i64, [IsRV64]>;
182*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_or_i64", "AMOOR_D", i64, [IsRV64]>;
183*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_xor_i64", "AMOXOR_D", i64, [IsRV64]>;
184*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_max_i64", "AMOMAX_D", i64, [IsRV64]>;
185*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_min_i64", "AMOMIN_D", i64, [IsRV64]>;
186*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_umax_i64", "AMOMAXU_D", i64, [IsRV64]>;
187*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_umin_i64", "AMOMINU_D", i64, [IsRV64]>;
188297eecfbSDimitry Andric
1890b57cec5SDimitry Andric
1900b57cec5SDimitry Andric/// Pseudo AMOs
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andricclass PseudoAMO : Pseudo<(outs GPR:$res, GPR:$scratch),
1930b57cec5SDimitry Andric                         (ins GPR:$addr, GPR:$incr, ixlenimm:$ordering), []> {
1940b57cec5SDimitry Andric  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
1950b57cec5SDimitry Andric  let mayLoad = 1;
1960b57cec5SDimitry Andric  let mayStore = 1;
1970b57cec5SDimitry Andric  let hasSideEffects = 0;
1980b57cec5SDimitry Andric}
1990b57cec5SDimitry Andric
2000b57cec5SDimitry Andricclass PseudoMaskedAMO
2010b57cec5SDimitry Andric    : Pseudo<(outs GPR:$res, GPR:$scratch),
2020b57cec5SDimitry Andric             (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$ordering), []> {
2030b57cec5SDimitry Andric  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
2040b57cec5SDimitry Andric  let mayLoad = 1;
2050b57cec5SDimitry Andric  let mayStore = 1;
2060b57cec5SDimitry Andric  let hasSideEffects = 0;
2070b57cec5SDimitry Andric}
2080b57cec5SDimitry Andric
2090b57cec5SDimitry Andricclass PseudoMaskedAMOMinMax
2100b57cec5SDimitry Andric    : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
2110b57cec5SDimitry Andric             (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$sextshamt,
2120b57cec5SDimitry Andric              ixlenimm:$ordering), []> {
2130b57cec5SDimitry Andric  let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
2140b57cec5SDimitry Andric                    "@earlyclobber $scratch2";
2150b57cec5SDimitry Andric  let mayLoad = 1;
2160b57cec5SDimitry Andric  let mayStore = 1;
2170b57cec5SDimitry Andric  let hasSideEffects = 0;
2180b57cec5SDimitry Andric}
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andricclass PseudoMaskedAMOUMinUMax
2210b57cec5SDimitry Andric    : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
2220b57cec5SDimitry Andric             (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$ordering), []> {
2230b57cec5SDimitry Andric  let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
2240b57cec5SDimitry Andric                    "@earlyclobber $scratch2";
2250b57cec5SDimitry Andric  let mayLoad = 1;
2260b57cec5SDimitry Andric  let mayStore = 1;
2270b57cec5SDimitry Andric  let hasSideEffects = 0;
2280b57cec5SDimitry Andric}
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andricclass PseudoMaskedAMOPat<Intrinsic intrin, Pseudo AMOInst>
2318bcb0991SDimitry Andric    : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering),
2325ffd83dbSDimitry Andric          (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>;
2330b57cec5SDimitry Andric
2340b57cec5SDimitry Andricclass PseudoMaskedAMOMinMaxPat<Intrinsic intrin, Pseudo AMOInst>
2350b57cec5SDimitry Andric    : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
2368bcb0991SDimitry Andric           timm:$ordering),
2370b57cec5SDimitry Andric          (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
2385ffd83dbSDimitry Andric           timm:$ordering)>;
2390b57cec5SDimitry Andric
240297eecfbSDimitry Andriclet Predicates = [HasStdExtA] in {
241297eecfbSDimitry Andric
242297eecfbSDimitry Andriclet Size = 20 in
243297eecfbSDimitry Andricdef PseudoAtomicLoadNand32 : PseudoAMO;
244297eecfbSDimitry Andric// Ordering constants must be kept in sync with the AtomicOrdering enum in
245297eecfbSDimitry Andric// AtomicOrdering.h.
246*0fca6ea1SDimitry Andricdef : Pat<(XLenVT (atomic_load_nand_i32_monotonic GPR:$addr, GPR:$incr)),
247297eecfbSDimitry Andric          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 2)>;
248*0fca6ea1SDimitry Andricdef : Pat<(XLenVT (atomic_load_nand_i32_acquire GPR:$addr, GPR:$incr)),
249297eecfbSDimitry Andric          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 4)>;
250*0fca6ea1SDimitry Andricdef : Pat<(XLenVT (atomic_load_nand_i32_release GPR:$addr, GPR:$incr)),
251297eecfbSDimitry Andric          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 5)>;
252*0fca6ea1SDimitry Andricdef : Pat<(XLenVT (atomic_load_nand_i32_acq_rel GPR:$addr, GPR:$incr)),
253297eecfbSDimitry Andric          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 6)>;
254*0fca6ea1SDimitry Andricdef : Pat<(XLenVT (atomic_load_nand_i32_seq_cst GPR:$addr, GPR:$incr)),
255297eecfbSDimitry Andric          (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 7)>;
256297eecfbSDimitry Andric
2571fd87a68SDimitry Andriclet Size = 28 in
2580b57cec5SDimitry Andricdef PseudoMaskedAtomicSwap32 : PseudoMaskedAMO;
2590b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_xchg_i32,
2600b57cec5SDimitry Andric                         PseudoMaskedAtomicSwap32>;
2611fd87a68SDimitry Andriclet Size = 28 in
2620b57cec5SDimitry Andricdef PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAMO;
2630b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_add_i32,
2640b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadAdd32>;
2651fd87a68SDimitry Andriclet Size = 28 in
2660b57cec5SDimitry Andricdef PseudoMaskedAtomicLoadSub32 : PseudoMaskedAMO;
2670b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_sub_i32,
2680b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadSub32>;
2691fd87a68SDimitry Andriclet Size = 32 in
2700b57cec5SDimitry Andricdef PseudoMaskedAtomicLoadNand32 : PseudoMaskedAMO;
2710b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_nand_i32,
2720b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadNand32>;
2731fd87a68SDimitry Andriclet Size = 44 in
2740b57cec5SDimitry Andricdef PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMOMinMax;
2750b57cec5SDimitry Andricdef : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_max_i32,
2760b57cec5SDimitry Andric                               PseudoMaskedAtomicLoadMax32>;
2771fd87a68SDimitry Andriclet Size = 44 in
2780b57cec5SDimitry Andricdef PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMOMinMax;
2790b57cec5SDimitry Andricdef : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_min_i32,
2800b57cec5SDimitry Andric                               PseudoMaskedAtomicLoadMin32>;
2811fd87a68SDimitry Andriclet Size = 36 in
2820b57cec5SDimitry Andricdef PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMOUMinUMax;
2830b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umax_i32,
2840b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadUMax32>;
2851fd87a68SDimitry Andriclet Size = 36 in
2860b57cec5SDimitry Andricdef PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMOUMinUMax;
2870b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umin_i32,
2880b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadUMin32>;
2890b57cec5SDimitry Andric} // Predicates = [HasStdExtA]
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andriclet Predicates = [HasStdExtA, IsRV64] in {
2920b57cec5SDimitry Andric
2931fd87a68SDimitry Andriclet Size = 20 in
2940b57cec5SDimitry Andricdef PseudoAtomicLoadNand64 : PseudoAMO;
2950b57cec5SDimitry Andric// Ordering constants must be kept in sync with the AtomicOrdering enum in
2960b57cec5SDimitry Andric// AtomicOrdering.h.
297*0fca6ea1SDimitry Andricdef : Pat<(i64 (atomic_load_nand_i64_monotonic GPR:$addr, GPR:$incr)),
2980b57cec5SDimitry Andric          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 2)>;
299*0fca6ea1SDimitry Andricdef : Pat<(i64 (atomic_load_nand_i64_acquire GPR:$addr, GPR:$incr)),
3000b57cec5SDimitry Andric          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 4)>;
301*0fca6ea1SDimitry Andricdef : Pat<(i64 (atomic_load_nand_i64_release GPR:$addr, GPR:$incr)),
3020b57cec5SDimitry Andric          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 5)>;
303*0fca6ea1SDimitry Andricdef : Pat<(i64 (atomic_load_nand_i64_acq_rel GPR:$addr, GPR:$incr)),
3040b57cec5SDimitry Andric          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 6)>;
305*0fca6ea1SDimitry Andricdef : Pat<(i64 (atomic_load_nand_i64_seq_cst GPR:$addr, GPR:$incr)),
3060b57cec5SDimitry Andric          (PseudoAtomicLoadNand64 GPR:$addr, GPR:$incr, 7)>;
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_xchg_i64,
3090b57cec5SDimitry Andric                         PseudoMaskedAtomicSwap32>;
3100b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_add_i64,
3110b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadAdd32>;
3120b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_sub_i64,
3130b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadSub32>;
3140b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_nand_i64,
3150b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadNand32>;
3160b57cec5SDimitry Andricdef : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_max_i64,
3170b57cec5SDimitry Andric                               PseudoMaskedAtomicLoadMax32>;
3180b57cec5SDimitry Andricdef : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_min_i64,
3190b57cec5SDimitry Andric                               PseudoMaskedAtomicLoadMin32>;
3200b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umax_i64,
3210b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadUMax32>;
3220b57cec5SDimitry Andricdef : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umin_i64,
3230b57cec5SDimitry Andric                         PseudoMaskedAtomicLoadUMin32>;
324297eecfbSDimitry Andric} // Predicates = [HasStdExtA, IsRV64]
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andric
327297eecfbSDimitry Andric/// Compare and exchange
328297eecfbSDimitry Andric
329297eecfbSDimitry Andricclass PseudoCmpXchg
330297eecfbSDimitry Andric    : Pseudo<(outs GPR:$res, GPR:$scratch),
331297eecfbSDimitry Andric             (ins GPR:$addr, GPR:$cmpval, GPR:$newval, ixlenimm:$ordering), []> {
332297eecfbSDimitry Andric  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
333297eecfbSDimitry Andric  let mayLoad = 1;
334297eecfbSDimitry Andric  let mayStore = 1;
335297eecfbSDimitry Andric  let hasSideEffects = 0;
336297eecfbSDimitry Andric  let Size = 16;
337297eecfbSDimitry Andric}
338297eecfbSDimitry Andric
339297eecfbSDimitry Andric// Ordering constants must be kept in sync with the AtomicOrdering enum in
340297eecfbSDimitry Andric// AtomicOrdering.h.
341297eecfbSDimitry Andricmulticlass PseudoCmpXchgPat<string Op, Pseudo CmpXchgInst,
342297eecfbSDimitry Andric                            ValueType vt = XLenVT> {
343297eecfbSDimitry Andric  def : Pat<(vt (!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$cmp, GPR:$new)),
344297eecfbSDimitry Andric            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 2)>;
345297eecfbSDimitry Andric  def : Pat<(vt (!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$cmp, GPR:$new)),
346297eecfbSDimitry Andric            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 4)>;
347297eecfbSDimitry Andric  def : Pat<(vt (!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$cmp, GPR:$new)),
348297eecfbSDimitry Andric            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 5)>;
349297eecfbSDimitry Andric  def : Pat<(vt (!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$cmp, GPR:$new)),
350297eecfbSDimitry Andric            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 6)>;
351297eecfbSDimitry Andric  def : Pat<(vt (!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$cmp, GPR:$new)),
352297eecfbSDimitry Andric            (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 7)>;
353297eecfbSDimitry Andric}
354297eecfbSDimitry Andric
355297eecfbSDimitry Andriclet Predicates = [HasStdExtA, NoStdExtZacas] in {
356297eecfbSDimitry Andricdef PseudoCmpXchg32 : PseudoCmpXchg;
357*0fca6ea1SDimitry Andricdefm : PseudoCmpXchgPat<"atomic_cmp_swap_i32", PseudoCmpXchg32>;
358297eecfbSDimitry Andric}
359297eecfbSDimitry Andric
360297eecfbSDimitry Andriclet Predicates = [HasStdExtA, NoStdExtZacas, IsRV64] in {
3610b57cec5SDimitry Andricdef PseudoCmpXchg64 : PseudoCmpXchg;
362*0fca6ea1SDimitry Andricdefm : PseudoCmpXchgPat<"atomic_cmp_swap_i64", PseudoCmpXchg64, i64>;
363297eecfbSDimitry Andric}
3640b57cec5SDimitry Andric
365297eecfbSDimitry Andriclet Predicates = [HasStdExtA] in {
366297eecfbSDimitry Andricdef PseudoMaskedCmpXchg32
367297eecfbSDimitry Andric    : Pseudo<(outs GPR:$res, GPR:$scratch),
368297eecfbSDimitry Andric             (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask,
369297eecfbSDimitry Andric              ixlenimm:$ordering), []> {
370297eecfbSDimitry Andric  let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
371297eecfbSDimitry Andric  let mayLoad = 1;
372297eecfbSDimitry Andric  let mayStore = 1;
373297eecfbSDimitry Andric  let hasSideEffects = 0;
374297eecfbSDimitry Andric  let Size = 32;
375297eecfbSDimitry Andric}
376297eecfbSDimitry Andric
377297eecfbSDimitry Andricdef : Pat<(int_riscv_masked_cmpxchg_i32
378297eecfbSDimitry Andric            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
379297eecfbSDimitry Andric          (PseudoMaskedCmpXchg32
380297eecfbSDimitry Andric            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
381297eecfbSDimitry Andric} // Predicates = [HasStdExtA]
382297eecfbSDimitry Andric
383297eecfbSDimitry Andriclet Predicates = [HasStdExtA, IsRV64] in {
3840b57cec5SDimitry Andricdef : Pat<(int_riscv_masked_cmpxchg_i64
3858bcb0991SDimitry Andric            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
3860b57cec5SDimitry Andric          (PseudoMaskedCmpXchg32
3875ffd83dbSDimitry Andric            GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
3880b57cec5SDimitry Andric} // Predicates = [HasStdExtA, IsRV64]
3895f757f3fSDimitry Andric
3905f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
3915f757f3fSDimitry Andric// Experimental RV64 i32 legalization patterns.
3925f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
3935f757f3fSDimitry Andric
3945f757f3fSDimitry Andricclass PatGprGprA<SDPatternOperator OpNode, RVInst Inst, ValueType vt>
3955f757f3fSDimitry Andric    : Pat<(vt (OpNode (XLenVT GPR:$rs1), (vt GPR:$rs2))), (Inst GPR:$rs1, GPR:$rs2)>;
3965f757f3fSDimitry Andric
3975f757f3fSDimitry Andricmulticlass AMOPat2<string AtomicOp, string BaseInst, ValueType vt = XLenVT,
3985f757f3fSDimitry Andric                   list<Predicate> ExtraPreds = []> {
3995f757f3fSDimitry Andriclet Predicates = !listconcat([HasStdExtA, NotHasStdExtZtso], ExtraPreds) in {
4005f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_monotonic"),
4015f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst), vt>;
4025f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acquire"),
4035f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst#"_AQ"), vt>;
4045f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_release"),
4055f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst#"_RL"), vt>;
4065f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acq_rel"),
4075f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
4085f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_seq_cst"),
4095f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
4105f757f3fSDimitry Andric}
4115f757f3fSDimitry Andriclet Predicates = !listconcat([HasStdExtA, HasStdExtZtso], ExtraPreds) in {
4125f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_monotonic"),
4135f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst), vt>;
4145f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acquire"),
4155f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst), vt>;
4165f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_release"),
4175f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst), vt>;
4185f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acq_rel"),
4195f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst), vt>;
4205f757f3fSDimitry Andric  def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_seq_cst"),
4215f757f3fSDimitry Andric                   !cast<RVInst>(BaseInst), vt>;
4225f757f3fSDimitry Andric}
4235f757f3fSDimitry Andric}
4245f757f3fSDimitry Andric
425*0fca6ea1SDimitry Andricdefm : AMOPat2<"atomic_swap_i32", "AMOSWAP_W", i32>;
426*0fca6ea1SDimitry Andricdefm : AMOPat2<"atomic_load_add_i32", "AMOADD_W", i32>;
427*0fca6ea1SDimitry Andricdefm : AMOPat2<"atomic_load_and_i32", "AMOAND_W", i32>;
428*0fca6ea1SDimitry Andricdefm : AMOPat2<"atomic_load_or_i32", "AMOOR_W", i32>;
429*0fca6ea1SDimitry Andricdefm : AMOPat2<"atomic_load_xor_i32", "AMOXOR_W", i32>;
430*0fca6ea1SDimitry Andricdefm : AMOPat2<"atomic_load_max_i32", "AMOMAX_W", i32>;
431*0fca6ea1SDimitry Andricdefm : AMOPat2<"atomic_load_min_i32", "AMOMIN_W", i32>;
432*0fca6ea1SDimitry Andricdefm : AMOPat2<"atomic_load_umax_i32", "AMOMAXU_W", i32>;
433*0fca6ea1SDimitry Andricdefm : AMOPat2<"atomic_load_umin_i32", "AMOMINU_W", i32>;
4345f757f3fSDimitry Andric
435297eecfbSDimitry Andriclet Predicates = [HasStdExtA, IsRV64] in
436*0fca6ea1SDimitry Andricdefm : PseudoCmpXchgPat<"atomic_cmp_swap_i32", PseudoCmpXchg32, i32>;
4375f757f3fSDimitry Andric
4385f757f3fSDimitry Andriclet Predicates = [HasAtomicLdSt] in {
4395f757f3fSDimitry Andric  def : LdPat<atomic_load_8,  LB, i32>;
4405f757f3fSDimitry Andric  def : LdPat<atomic_load_16, LH, i32>;
4415f757f3fSDimitry Andric  def : LdPat<atomic_load_32, LW, i32>;
4425f757f3fSDimitry Andric
4435f757f3fSDimitry Andric  def : StPat<atomic_store_8,  SB, GPR, i32>;
4445f757f3fSDimitry Andric  def : StPat<atomic_store_16, SH, GPR, i32>;
4455f757f3fSDimitry Andric  def : StPat<atomic_store_32, SW, GPR, i32>;
4465f757f3fSDimitry Andric}
4475f757f3fSDimitry Andric
448