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