474 lines · plain
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file describes the RISC-V instructions from the standard 'A', Atomic10// Instructions extension.11//12//===----------------------------------------------------------------------===//13 14//===----------------------------------------------------------------------===//15// Instruction class templates16//===----------------------------------------------------------------------===//17 18let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in19class 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 _AQRL : LR_r<1, 1, funct3, opcodestr # ".aqrl">;31}32 33let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in34class SC_r<bit aq, bit rl, bits<3> funct3, string opcodestr>35 : RVInstRAtomic<0b00011, aq, rl, funct3, OPC_AMO,36 (outs GPR:$rd), (ins GPR:$rs2, GPRMemZeroOffset:$rs1),37 opcodestr, "$rd, $rs2, $rs1">;38 39multiclass SC_r_aq_rl<bits<3> funct3, string opcodestr> {40 def "" : SC_r<0, 0, funct3, opcodestr>;41 def _AQ : SC_r<1, 0, funct3, opcodestr # ".aq">;42 def _RL : SC_r<0, 1, funct3, opcodestr # ".rl">;43 def _AQRL : SC_r<1, 1, funct3, opcodestr # ".aqrl">;44}45 46let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in47class AMO_rr<bits<5> funct5, bit aq, bit rl, bits<3> funct3, string opcodestr>48 : RVInstRAtomic<funct5, aq, rl, funct3, OPC_AMO,49 (outs GPR:$rd), (ins GPR:$rs2, GPRMemZeroOffset:$rs1),50 opcodestr, "$rd, $rs2, $rs1">;51 52multiclass AMO_rr_aq_rl<bits<5> funct5, bits<3> funct3, string opcodestr> {53 def "" : AMO_rr<funct5, 0, 0, funct3, opcodestr>;54 def _AQ : AMO_rr<funct5, 1, 0, funct3, opcodestr # ".aq">;55 def _RL : AMO_rr<funct5, 0, 1, funct3, opcodestr # ".rl">;56 def _AQRL : AMO_rr<funct5, 1, 1, funct3, opcodestr # ".aqrl">;57}58 59//===----------------------------------------------------------------------===//60// Instructions61//===----------------------------------------------------------------------===//62 63let Predicates = [HasStdExtZalrsc], IsSignExtendingOpW = 1 in {64defm LR_W : LR_r_aq_rl<0b010, "lr.w">, Sched<[WriteAtomicLDW, ReadAtomicLDW]>;65defm SC_W : SC_r_aq_rl<0b010, "sc.w">,66 Sched<[WriteAtomicSTW, ReadAtomicSTW, ReadAtomicSTW]>;67} // Predicates = [HasStdExtZalrsc], IsSignExtendingOpW = 168 69let Predicates = [HasStdExtZaamo], IsSignExtendingOpW = 1 in {70defm AMOSWAP_W : AMO_rr_aq_rl<0b00001, 0b010, "amoswap.w">,71 Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;72defm AMOADD_W : AMO_rr_aq_rl<0b00000, 0b010, "amoadd.w">,73 Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;74defm AMOXOR_W : AMO_rr_aq_rl<0b00100, 0b010, "amoxor.w">,75 Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;76defm AMOAND_W : AMO_rr_aq_rl<0b01100, 0b010, "amoand.w">,77 Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;78defm AMOOR_W : AMO_rr_aq_rl<0b01000, 0b010, "amoor.w">,79 Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;80defm AMOMIN_W : AMO_rr_aq_rl<0b10000, 0b010, "amomin.w">,81 Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;82defm AMOMAX_W : AMO_rr_aq_rl<0b10100, 0b010, "amomax.w">,83 Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;84defm AMOMINU_W : AMO_rr_aq_rl<0b11000, 0b010, "amominu.w">,85 Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;86defm AMOMAXU_W : AMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">,87 Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;88} // Predicates = [HasStdExtZaamo], IsSignExtendingOpW = 189 90let Predicates = [HasStdExtZalrsc, IsRV64] in {91defm LR_D : LR_r_aq_rl<0b011, "lr.d">, Sched<[WriteAtomicLDD, ReadAtomicLDD]>;92defm SC_D : SC_r_aq_rl<0b011, "sc.d">,93 Sched<[WriteAtomicSTD, ReadAtomicSTD, ReadAtomicSTD]>;94} // Predicates = [HasStdExtZalrsc, IsRV64]95 96let Predicates = [HasStdExtZaamo, IsRV64] in {97defm AMOSWAP_D : AMO_rr_aq_rl<0b00001, 0b011, "amoswap.d">,98 Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;99defm AMOADD_D : AMO_rr_aq_rl<0b00000, 0b011, "amoadd.d">,100 Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;101defm AMOXOR_D : AMO_rr_aq_rl<0b00100, 0b011, "amoxor.d">,102 Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;103defm AMOAND_D : AMO_rr_aq_rl<0b01100, 0b011, "amoand.d">,104 Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;105defm AMOOR_D : AMO_rr_aq_rl<0b01000, 0b011, "amoor.d">,106 Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;107defm AMOMIN_D : AMO_rr_aq_rl<0b10000, 0b011, "amomin.d">,108 Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;109defm AMOMAX_D : AMO_rr_aq_rl<0b10100, 0b011, "amomax.d">,110 Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;111defm AMOMINU_D : AMO_rr_aq_rl<0b11000, 0b011, "amominu.d">,112 Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;113defm AMOMAXU_D : AMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">,114 Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;115} // Predicates = [HasStdExtZaamo, IsRV64]116 117//===----------------------------------------------------------------------===//118// Pseudo-instructions and codegen patterns119//===----------------------------------------------------------------------===//120 121let IsAtomic = 1 in {122// An atomic load operation that does not need either acquire or release123// semantics.124class relaxed_load<PatFrags base>125 : PatFrag<(ops node:$ptr), (base node:$ptr)> {126 let IsAtomicOrderingAcquireOrStronger = 0;127}128 129// A atomic load operation that actually needs acquire semantics.130class acquiring_load<PatFrags base>131 : PatFrag<(ops node:$ptr), (base node:$ptr)> {132 let IsAtomicOrderingAcquire = 1;133}134 135// An atomic load operation that needs sequential consistency.136class seq_cst_load<PatFrags base>137 : PatFrag<(ops node:$ptr), (base node:$ptr)> {138 let IsAtomicOrderingSequentiallyConsistent = 1;139}140 141// An atomic store operation that does not need either acquire or release142// semantics.143class relaxed_store<PatFrag base>144 : PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr)> {145 let IsAtomicOrderingReleaseOrStronger = 0;146}147 148// A store operation that actually needs release semantics.149class releasing_store<PatFrag base>150 : PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr)> {151 let IsAtomicOrderingRelease = 1;152}153 154// A store operation that actually needs sequential consistency.155class seq_cst_store<PatFrag base>156 : PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr)> {157 let IsAtomicOrderingSequentiallyConsistent = 1;158}159} // IsAtomic = 1160 161// Atomic load/store are available under +zalrsc (thus also +a) and162// +force-atomics. Fences will be inserted for atomic load/stores according to163// the logic in RISCVTargetLowering::{emitLeadingFence,emitTrailingFence}.164// The normal loads/stores are relaxed (unordered) loads/stores that don't have165// any ordering. This is necessary because AtomicExpandPass has added fences to166// atomic load/stores and changed them to unordered ones.167let Predicates = [HasAtomicLdSt] in {168 // Use unsigned for aext due to no c.lb in Zcb.169 def : LdPat<relaxed_load<atomic_load_sext_8>, LB>;170 def : LdPat<relaxed_load<atomic_load_azext_8>, LBU>;171 def : LdPat<relaxed_load<atomic_load_asext_16>, LH>;172 def : LdPat<relaxed_load<atomic_load_zext_16>, LHU>;173 174 def : StPat<relaxed_store<atomic_store_8>, SB, GPR, XLenVT>;175 def : StPat<relaxed_store<atomic_store_16>, SH, GPR, XLenVT>;176 def : StPat<relaxed_store<atomic_store_32>, SW, GPR, XLenVT>;177}178 179let Predicates = [HasAtomicLdSt, IsRV32] in {180 def : LdPat<relaxed_load<atomic_load_nonext_32>, LW, i32>;181}182 183let Predicates = [HasAtomicLdSt, IsRV64] in {184 def : LdPat<relaxed_load<atomic_load_asext_32>, LW, i64>;185 def : LdPat<relaxed_load<atomic_load_zext_32>, LWU, i64>;186 def : LdPat<relaxed_load<atomic_load_nonext_64>, LD, i64>;187 def : StPat<relaxed_store<atomic_store_64>, SD, GPR, i64>;188}189 190/// AMOs191 192class PatAMO<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT>193 : Pat<(vt (OpNode (XLenVT GPR:$rs1), (vt GPR:$rs2))), (Inst GPR:$rs2, GPR:$rs1)>;194 195multiclass AMOPat<string AtomicOp, string BaseInst, ValueType vt = XLenVT,196 list<Predicate> ExtraPreds = []> {197let Predicates = !listconcat([HasStdExtA, NoStdExtZtso], ExtraPreds) in {198 def : PatAMO<!cast<PatFrag>(AtomicOp#"_monotonic"),199 !cast<RVInst>(BaseInst), vt>;200 def : PatAMO<!cast<PatFrag>(AtomicOp#"_acquire"),201 !cast<RVInst>(BaseInst#"_AQ"), vt>;202 def : PatAMO<!cast<PatFrag>(AtomicOp#"_release"),203 !cast<RVInst>(BaseInst#"_RL"), vt>;204 def : PatAMO<!cast<PatFrag>(AtomicOp#"_acq_rel"),205 !cast<RVInst>(BaseInst#"_AQRL"), vt>;206 def : PatAMO<!cast<PatFrag>(AtomicOp#"_seq_cst"),207 !cast<RVInst>(BaseInst#"_AQRL"), vt>;208}209let Predicates = !listconcat([HasStdExtA, HasStdExtZtso], ExtraPreds) in {210 def : PatAMO<!cast<PatFrag>(AtomicOp#"_monotonic"),211 !cast<RVInst>(BaseInst), vt>;212 def : PatAMO<!cast<PatFrag>(AtomicOp#"_acquire"),213 !cast<RVInst>(BaseInst), vt>;214 def : PatAMO<!cast<PatFrag>(AtomicOp#"_release"),215 !cast<RVInst>(BaseInst), vt>;216 def : PatAMO<!cast<PatFrag>(AtomicOp#"_acq_rel"),217 !cast<RVInst>(BaseInst), vt>;218 def : PatAMO<!cast<PatFrag>(AtomicOp#"_seq_cst"),219 !cast<RVInst>(BaseInst), vt>;220}221}222 223defm : AMOPat<"atomic_swap_i32", "AMOSWAP_W">;224defm : AMOPat<"atomic_load_add_i32", "AMOADD_W">;225defm : AMOPat<"atomic_load_and_i32", "AMOAND_W">;226defm : AMOPat<"atomic_load_or_i32", "AMOOR_W">;227defm : AMOPat<"atomic_load_xor_i32", "AMOXOR_W">;228defm : AMOPat<"atomic_load_max_i32", "AMOMAX_W">;229defm : AMOPat<"atomic_load_min_i32", "AMOMIN_W">;230defm : AMOPat<"atomic_load_umax_i32", "AMOMAXU_W">;231defm : AMOPat<"atomic_load_umin_i32", "AMOMINU_W">;232 233defm : AMOPat<"atomic_swap_i64", "AMOSWAP_D", i64, [IsRV64]>;234defm : AMOPat<"atomic_load_add_i64", "AMOADD_D", i64, [IsRV64]>;235defm : AMOPat<"atomic_load_and_i64", "AMOAND_D", i64, [IsRV64]>;236defm : AMOPat<"atomic_load_or_i64", "AMOOR_D", i64, [IsRV64]>;237defm : AMOPat<"atomic_load_xor_i64", "AMOXOR_D", i64, [IsRV64]>;238defm : AMOPat<"atomic_load_max_i64", "AMOMAX_D", i64, [IsRV64]>;239defm : AMOPat<"atomic_load_min_i64", "AMOMIN_D", i64, [IsRV64]>;240defm : AMOPat<"atomic_load_umax_i64", "AMOMAXU_D", i64, [IsRV64]>;241defm : AMOPat<"atomic_load_umin_i64", "AMOMINU_D", i64, [IsRV64]>;242 243 244/// Pseudo AMOs245 246class PseudoAMO : Pseudo<(outs GPR:$res, GPR:$scratch),247 (ins GPR:$addr, GPR:$incr, ixlenimm:$ordering), []> {248 let Constraints = "@earlyclobber $res,@earlyclobber $scratch";249 let mayLoad = 1;250 let mayStore = 1;251 let hasSideEffects = 0;252}253 254class PseudoMaskedAMO255 : Pseudo<(outs GPR:$res, GPR:$scratch),256 (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$ordering), []> {257 let Constraints = "@earlyclobber $res,@earlyclobber $scratch";258 let mayLoad = 1;259 let mayStore = 1;260 let hasSideEffects = 0;261}262 263class PseudoMaskedAMOMinMax264 : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),265 (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$sextshamt,266 ixlenimm:$ordering), []> {267 let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"268 "@earlyclobber $scratch2";269 let mayLoad = 1;270 let mayStore = 1;271 let hasSideEffects = 0;272}273 274class PseudoMaskedAMOUMinUMax275 : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),276 (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$ordering), []> {277 let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"278 "@earlyclobber $scratch2";279 let mayLoad = 1;280 let mayStore = 1;281 let hasSideEffects = 0;282}283 284// Ordering constants must be kept in sync with the AtomicOrdering enum in285// AtomicOrdering.h.286multiclass PseudoAMOPat<string AtomicOp, Pseudo AMOInst, ValueType vt = XLenVT> {287 def : Pat<(vt (!cast<PatFrag>(AtomicOp#"_monotonic") GPR:$addr, GPR:$incr)),288 (AMOInst GPR:$addr, GPR:$incr, 2)>;289 def : Pat<(vt (!cast<PatFrag>(AtomicOp#"_acquire") GPR:$addr, GPR:$incr)),290 (AMOInst GPR:$addr, GPR:$incr, 4)>;291 def : Pat<(vt (!cast<PatFrag>(AtomicOp#"_release") GPR:$addr, GPR:$incr)),292 (AMOInst GPR:$addr, GPR:$incr, 5)>;293 def : Pat<(vt (!cast<PatFrag>(AtomicOp#"_acq_rel") GPR:$addr, GPR:$incr)),294 (AMOInst GPR:$addr, GPR:$incr, 6)>;295 def : Pat<(vt (!cast<PatFrag>(AtomicOp#"_seq_cst") GPR:$addr, GPR:$incr)),296 (AMOInst GPR:$addr, GPR:$incr, 7)>;297}298 299class PseudoMaskedAMOPat<Intrinsic intrin, Pseudo AMOInst>300 : Pat<(XLenVT (intrin (XLenVT GPR:$addr), (XLenVT GPR:$incr),301 (XLenVT GPR:$mask), (XLenVT timm:$ordering))),302 (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>;303 304class PseudoMaskedAMOMinMaxPat<Intrinsic intrin, Pseudo AMOInst>305 : Pat<(XLenVT (intrin (XLenVT GPR:$addr), (XLenVT GPR:$incr),306 (XLenVT GPR:$mask), (XLenVT GPR:$shiftamt),307 (XLenVT timm:$ordering))),308 (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,309 timm:$ordering)>;310 311let Predicates = [HasStdExtZalrsc, NoStdExtZaamo] in {312 313let Size = 16 in {314def PseudoAtomicSwap32 : PseudoAMO;315def PseudoAtomicLoadAdd32 : PseudoAMO;316def PseudoAtomicLoadSub32 : PseudoAMO;317def PseudoAtomicLoadAnd32 : PseudoAMO;318def PseudoAtomicLoadOr32 : PseudoAMO;319def PseudoAtomicLoadXor32 : PseudoAMO;320} // Size = 16321let Size = 24 in {322def PseudoAtomicLoadMax32 : PseudoAMO;323def PseudoAtomicLoadMin32 : PseudoAMO;324def PseudoAtomicLoadUMax32 : PseudoAMO;325def PseudoAtomicLoadUMin32 : PseudoAMO;326} // Size = 24327 328defm : PseudoAMOPat<"atomic_swap_i32", PseudoAtomicSwap32>;329defm : PseudoAMOPat<"atomic_load_add_i32", PseudoAtomicLoadAdd32>;330defm : PseudoAMOPat<"atomic_load_sub_i32", PseudoAtomicLoadSub32>;331defm : PseudoAMOPat<"atomic_load_and_i32", PseudoAtomicLoadAnd32>;332defm : PseudoAMOPat<"atomic_load_or_i32", PseudoAtomicLoadOr32>;333defm : PseudoAMOPat<"atomic_load_xor_i32", PseudoAtomicLoadXor32>;334defm : PseudoAMOPat<"atomic_load_max_i32", PseudoAtomicLoadMax32>;335defm : PseudoAMOPat<"atomic_load_min_i32", PseudoAtomicLoadMin32>;336defm : PseudoAMOPat<"atomic_load_umax_i32", PseudoAtomicLoadUMax32>;337defm : PseudoAMOPat<"atomic_load_umin_i32", PseudoAtomicLoadUMin32>;338} // Predicates = [HasStdExtZalrsc, NoStdExtZaamo]339 340let Predicates = [HasStdExtZalrsc, NoStdExtZaamo, IsRV64] in {341 342let Size = 16 in {343def PseudoAtomicSwap64 : PseudoAMO;344def PseudoAtomicLoadAdd64 : PseudoAMO;345def PseudoAtomicLoadSub64 : PseudoAMO;346def PseudoAtomicLoadAnd64 : PseudoAMO;347def PseudoAtomicLoadOr64 : PseudoAMO;348def PseudoAtomicLoadXor64 : PseudoAMO;349} // Size = 16350let Size = 24 in {351def PseudoAtomicLoadMax64 : PseudoAMO;352def PseudoAtomicLoadMin64 : PseudoAMO;353def PseudoAtomicLoadUMax64 : PseudoAMO;354def PseudoAtomicLoadUMin64 : PseudoAMO;355} // Size = 24356 357defm : PseudoAMOPat<"atomic_swap_i64", PseudoAtomicSwap64, i64>;358defm : PseudoAMOPat<"atomic_load_add_i64", PseudoAtomicLoadAdd64, i64>;359defm : PseudoAMOPat<"atomic_load_sub_i64", PseudoAtomicLoadSub64, i64>;360defm : PseudoAMOPat<"atomic_load_and_i64", PseudoAtomicLoadAnd64, i64>;361defm : PseudoAMOPat<"atomic_load_or_i64", PseudoAtomicLoadOr64, i64>;362defm : PseudoAMOPat<"atomic_load_xor_i64", PseudoAtomicLoadXor64, i64>;363defm : PseudoAMOPat<"atomic_load_max_i64", PseudoAtomicLoadMax64, i64>;364defm : PseudoAMOPat<"atomic_load_min_i64", PseudoAtomicLoadMin64, i64>;365defm : PseudoAMOPat<"atomic_load_umax_i64", PseudoAtomicLoadUMax64, i64>;366defm : PseudoAMOPat<"atomic_load_umin_i64", PseudoAtomicLoadUMin64, i64>;367} // Predicates = [HasStdExtZalrsc, NoStdExtZaamo, IsRV64]368 369let Predicates = [HasStdExtZalrsc] in {370 371let Size = 20 in372def PseudoAtomicLoadNand32 : PseudoAMO;373defm : PseudoAMOPat<"atomic_load_nand_i32", PseudoAtomicLoadNand32>;374 375let Size = 28 in {376 def PseudoMaskedAtomicSwap32 : PseudoMaskedAMO;377 def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAMO;378 def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAMO;379}380let Size = 32 in {381 def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAMO;382}383let Size = 44 in {384 def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMOMinMax;385 def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMOMinMax;386}387let Size = 36 in {388 def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMOUMinUMax;389 def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMOUMinUMax;390}391 392def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_xchg,393 PseudoMaskedAtomicSwap32>;394def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_add,395 PseudoMaskedAtomicLoadAdd32>;396def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_sub,397 PseudoMaskedAtomicLoadSub32>;398def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_nand,399 PseudoMaskedAtomicLoadNand32>;400def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_max,401 PseudoMaskedAtomicLoadMax32>;402def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_min,403 PseudoMaskedAtomicLoadMin32>;404def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umax,405 PseudoMaskedAtomicLoadUMax32>;406def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umin,407 PseudoMaskedAtomicLoadUMin32>;408} // Predicates = [HasStdExtZalrsc]409 410let Predicates = [HasStdExtZalrsc, IsRV64] in {411 412let Size = 20 in413def PseudoAtomicLoadNand64 : PseudoAMO;414defm : PseudoAMOPat<"atomic_load_nand_i64", PseudoAtomicLoadNand64, i64>;415} // Predicates = [HasStdExtZalrsc, IsRV64]416 417 418/// Compare and exchange419 420class PseudoCmpXchg421 : Pseudo<(outs GPR:$res, GPR:$scratch),422 (ins GPR:$addr, GPR:$cmpval, GPR:$newval, ixlenimm:$ordering), []> {423 let Constraints = "@earlyclobber $res,@earlyclobber $scratch";424 let mayLoad = 1;425 let mayStore = 1;426 let hasSideEffects = 0;427 let Size = 16;428}429 430// Ordering constants must be kept in sync with the AtomicOrdering enum in431// AtomicOrdering.h.432multiclass PseudoCmpXchgPat<string Op, Pseudo CmpXchgInst,433 ValueType vt = XLenVT> {434 def : Pat<(vt (!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$cmp, GPR:$new)),435 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 2)>;436 def : Pat<(vt (!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$cmp, GPR:$new)),437 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 4)>;438 def : Pat<(vt (!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$cmp, GPR:$new)),439 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 5)>;440 def : Pat<(vt (!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$cmp, GPR:$new)),441 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 6)>;442 def : Pat<(vt (!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$cmp, GPR:$new)),443 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 7)>;444}445 446let Predicates = [HasStdExtZalrsc, NoStdExtZacas] in {447def PseudoCmpXchg32 : PseudoCmpXchg;448defm : PseudoCmpXchgPat<"atomic_cmp_swap_i32", PseudoCmpXchg32>;449}450 451let Predicates = [HasStdExtZalrsc, NoStdExtZacas, IsRV64] in {452def PseudoCmpXchg64 : PseudoCmpXchg;453defm : PseudoCmpXchgPat<"atomic_cmp_swap_i64", PseudoCmpXchg64, i64>;454}455 456let Predicates = [HasStdExtZalrsc] in {457def PseudoMaskedCmpXchg32458 : Pseudo<(outs GPR:$res, GPR:$scratch),459 (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask,460 ixlenimm:$ordering), []> {461 let Constraints = "@earlyclobber $res,@earlyclobber $scratch";462 let mayLoad = 1;463 let mayStore = 1;464 let hasSideEffects = 0;465 let Size = 32;466}467 468def : Pat<(XLenVT (int_riscv_masked_cmpxchg469 (XLenVT GPR:$addr), (XLenVT GPR:$cmpval), (XLenVT GPR:$newval),470 (XLenVT GPR:$mask), (XLenVT timm:$ordering))),471 (PseudoMaskedCmpXchg32472 GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;473} // Predicates = [HasStdExtZalrsc]474