Alex Bradbury | 8c345c5 | 2017-11-09 15:00:03 +0000 | [diff] [blame] | 1 | //===-- RISCVInstrInfoA.td - RISC-V 'A' instructions -------*- tablegen -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file describes the RISC-V instructions from the standard 'A', Atomic |
| 11 | // Instructions extension. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | // Instruction class templates |
| 17 | //===----------------------------------------------------------------------===// |
| 18 | |
| 19 | let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in |
| 20 | class LR_r<bit aq, bit rl, bits<3> funct3, string opcodestr> |
| 21 | : RVInstRAtomic<0b00010, aq, rl, funct3, OPC_AMO, |
| 22 | (outs GPR:$rd), (ins GPR:$rs1), |
| 23 | opcodestr, "$rd, (${rs1})"> { |
| 24 | let rs2 = 0; |
| 25 | } |
| 26 | |
| 27 | multiclass 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 | |
| 34 | let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in |
| 35 | class 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 GPR:$rs1, GPR:$rs2), |
| 38 | opcodestr, "$rd, $rs2, (${rs1})">; |
| 39 | |
| 40 | multiclass 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 | |
Roger Ferrer Ibanez | fe28217 | 2018-08-27 07:08:18 +0000 | [diff] [blame] | 47 | multiclass AtomicStPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy> { |
| 48 | def : Pat<(StoreOp GPR:$rs1, StTy:$rs2), (Inst StTy:$rs2, GPR:$rs1, 0)>; |
| 49 | def : Pat<(StoreOp AddrFI:$rs1, StTy:$rs2), (Inst StTy:$rs2, AddrFI:$rs1, 0)>; |
| 50 | def : Pat<(StoreOp (add GPR:$rs1, simm12:$imm12), StTy:$rs2), |
| 51 | (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>; |
| 52 | def : Pat<(StoreOp (add AddrFI:$rs1, simm12:$imm12), StTy:$rs2), |
| 53 | (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; |
| 54 | def : Pat<(StoreOp (IsOrAdd AddrFI:$rs1, simm12:$imm12), StTy:$rs2), |
| 55 | (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; |
| 56 | } |
| 57 | |
Alex Bradbury | 8c345c5 | 2017-11-09 15:00:03 +0000 | [diff] [blame] | 58 | //===----------------------------------------------------------------------===// |
| 59 | // Instructions |
| 60 | //===----------------------------------------------------------------------===// |
| 61 | |
| 62 | let Predicates = [HasStdExtA] in { |
| 63 | defm LR_W : LR_r_aq_rl<0b010, "lr.w">; |
| 64 | defm SC_W : AMO_rr_aq_rl<0b00011, 0b010, "sc.w">; |
| 65 | defm AMOSWAP_W : AMO_rr_aq_rl<0b00001, 0b010, "amoswap.w">; |
| 66 | defm AMOADD_W : AMO_rr_aq_rl<0b00000, 0b010, "amoadd.w">; |
| 67 | defm AMOXOR_W : AMO_rr_aq_rl<0b00100, 0b010, "amoxor.w">; |
| 68 | defm AMOAND_W : AMO_rr_aq_rl<0b01100, 0b010, "amoand.w">; |
| 69 | defm AMOOR_W : AMO_rr_aq_rl<0b01000, 0b010, "amoor.w">; |
| 70 | defm AMOMIN_W : AMO_rr_aq_rl<0b10000, 0b010, "amomin.w">; |
| 71 | defm AMOMAX_W : AMO_rr_aq_rl<0b10100, 0b010, "amomax.w">; |
| 72 | defm AMOMINU_W : AMO_rr_aq_rl<0b11000, 0b010, "amominu.w">; |
| 73 | defm AMOMAXU_W : AMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">; |
| 74 | } // Predicates = [HasStdExtA] |
Alex Bradbury | 48f95a6 | 2017-12-07 10:59:12 +0000 | [diff] [blame] | 75 | |
| 76 | let Predicates = [HasStdExtA, IsRV64] in { |
| 77 | defm LR_D : LR_r_aq_rl<0b011, "lr.d">; |
| 78 | defm SC_D : AMO_rr_aq_rl<0b00011, 0b011, "sc.d">; |
| 79 | defm AMOSWAP_D : AMO_rr_aq_rl<0b00001, 0b011, "amoswap.d">; |
| 80 | defm AMOADD_D : AMO_rr_aq_rl<0b00000, 0b011, "amoadd.d">; |
| 81 | defm AMOXOR_D : AMO_rr_aq_rl<0b00100, 0b011, "amoxor.d">; |
| 82 | defm AMOAND_D : AMO_rr_aq_rl<0b01100, 0b011, "amoand.d">; |
| 83 | defm AMOOR_D : AMO_rr_aq_rl<0b01000, 0b011, "amoor.d">; |
| 84 | defm AMOMIN_D : AMO_rr_aq_rl<0b10000, 0b011, "amomin.d">; |
| 85 | defm AMOMAX_D : AMO_rr_aq_rl<0b10100, 0b011, "amomax.d">; |
| 86 | defm AMOMINU_D : AMO_rr_aq_rl<0b11000, 0b011, "amominu.d">; |
| 87 | defm AMOMAXU_D : AMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">; |
| 88 | } // Predicates = [HasStedExtA, IsRV64] |
Alex Bradbury | 96f492d | 2018-06-13 12:04:51 +0000 | [diff] [blame] | 89 | |
| 90 | //===----------------------------------------------------------------------===// |
| 91 | // Pseudo-instructions and codegen patterns |
| 92 | //===----------------------------------------------------------------------===// |
| 93 | |
| 94 | let Predicates = [HasStdExtA] in { |
| 95 | |
| 96 | /// Atomic loads and stores |
| 97 | |
| 98 | // Fences will be inserted for atomic load/stores according to the logic in |
| 99 | // RISCVTargetLowering::{emitLeadingFence,emitTrailingFence}. |
| 100 | |
| 101 | defm : LdPat<atomic_load_8, LB>; |
| 102 | defm : LdPat<atomic_load_16, LH>; |
| 103 | defm : LdPat<atomic_load_32, LW>; |
| 104 | |
Roger Ferrer Ibanez | fe28217 | 2018-08-27 07:08:18 +0000 | [diff] [blame] | 105 | defm : AtomicStPat<atomic_store_8, SB, GPR>; |
| 106 | defm : AtomicStPat<atomic_store_16, SH, GPR>; |
| 107 | defm : AtomicStPat<atomic_store_32, SW, GPR>; |
Alex Bradbury | 21aea51 | 2018-09-19 10:54:22 +0000 | [diff] [blame] | 108 | |
| 109 | /// AMOs |
| 110 | |
| 111 | multiclass AMOPat<string AtomicOp, string BaseInst> { |
| 112 | def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_monotonic"), |
| 113 | !cast<RVInst>(BaseInst)>; |
| 114 | def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acquire"), |
| 115 | !cast<RVInst>(BaseInst#"_AQ")>; |
| 116 | def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_release"), |
| 117 | !cast<RVInst>(BaseInst#"_RL")>; |
| 118 | def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acq_rel"), |
| 119 | !cast<RVInst>(BaseInst#"_AQ_RL")>; |
| 120 | def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_seq_cst"), |
| 121 | !cast<RVInst>(BaseInst#"_AQ_RL")>; |
| 122 | } |
| 123 | |
| 124 | defm : AMOPat<"atomic_swap_32", "AMOSWAP_W">; |
| 125 | defm : AMOPat<"atomic_load_add_32", "AMOADD_W">; |
| 126 | defm : AMOPat<"atomic_load_and_32", "AMOAND_W">; |
| 127 | defm : AMOPat<"atomic_load_or_32", "AMOOR_W">; |
| 128 | defm : AMOPat<"atomic_load_xor_32", "AMOXOR_W">; |
| 129 | defm : AMOPat<"atomic_load_max_32", "AMOMAX_W">; |
| 130 | defm : AMOPat<"atomic_load_min_32", "AMOMIN_W">; |
| 131 | defm : AMOPat<"atomic_load_umax_32", "AMOMAXU_W">; |
| 132 | defm : AMOPat<"atomic_load_umin_32", "AMOMINU_W">; |
| 133 | |
| 134 | def : Pat<(atomic_load_sub_32_monotonic GPR:$addr, GPR:$incr), |
| 135 | (AMOADD_W GPR:$addr, (SUB X0, GPR:$incr))>; |
| 136 | def : Pat<(atomic_load_sub_32_acquire GPR:$addr, GPR:$incr), |
| 137 | (AMOADD_W_AQ GPR:$addr, (SUB X0, GPR:$incr))>; |
| 138 | def : Pat<(atomic_load_sub_32_release GPR:$addr, GPR:$incr), |
| 139 | (AMOADD_W_RL GPR:$addr, (SUB X0, GPR:$incr))>; |
| 140 | def : Pat<(atomic_load_sub_32_acq_rel GPR:$addr, GPR:$incr), |
| 141 | (AMOADD_W_AQ_RL GPR:$addr, (SUB X0, GPR:$incr))>; |
| 142 | def : Pat<(atomic_load_sub_32_seq_cst GPR:$addr, GPR:$incr), |
| 143 | (AMOADD_W_AQ_RL GPR:$addr, (SUB X0, GPR:$incr))>; |
| 144 | |
| 145 | /// Pseudo AMOs |
| 146 | |
| 147 | class PseudoAMO : Pseudo<(outs GPR:$res, GPR:$scratch), |
Alex Bradbury | d464ed8 | 2018-10-03 11:14:26 +0000 | [diff] [blame] | 148 | (ins GPR:$addr, GPR:$incr, ixlenimm:$ordering), []> { |
Alex Bradbury | 21aea51 | 2018-09-19 10:54:22 +0000 | [diff] [blame] | 149 | let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; |
| 150 | let mayLoad = 1; |
| 151 | let mayStore = 1; |
| 152 | let hasSideEffects = 0; |
| 153 | } |
| 154 | |
| 155 | def PseudoAtomicLoadNand32 : PseudoAMO; |
Alex Bradbury | 66d9a75 | 2018-11-29 20:43:42 +0000 | [diff] [blame] | 156 | // Ordering constants must be kept in sync with the AtomicOrdering enum in |
Alex Bradbury | 21aea51 | 2018-09-19 10:54:22 +0000 | [diff] [blame] | 157 | // AtomicOrdering.h. |
| 158 | def : Pat<(atomic_load_nand_32_monotonic GPR:$addr, GPR:$incr), |
| 159 | (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 2)>; |
| 160 | def : Pat<(atomic_load_nand_32_acquire GPR:$addr, GPR:$incr), |
| 161 | (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 4)>; |
| 162 | def : Pat<(atomic_load_nand_32_release GPR:$addr, GPR:$incr), |
| 163 | (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 5)>; |
| 164 | def : Pat<(atomic_load_nand_32_acq_rel GPR:$addr, GPR:$incr), |
| 165 | (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 6)>; |
| 166 | def : Pat<(atomic_load_nand_32_seq_cst GPR:$addr, GPR:$incr), |
| 167 | (PseudoAtomicLoadNand32 GPR:$addr, GPR:$incr, 7)>; |
| 168 | |
| 169 | class PseudoMaskedAMO |
| 170 | : Pseudo<(outs GPR:$res, GPR:$scratch), |
Alex Bradbury | d464ed8 | 2018-10-03 11:14:26 +0000 | [diff] [blame] | 171 | (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$ordering), []> { |
Alex Bradbury | 21aea51 | 2018-09-19 10:54:22 +0000 | [diff] [blame] | 172 | let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; |
| 173 | let mayLoad = 1; |
| 174 | let mayStore = 1; |
| 175 | let hasSideEffects = 0; |
| 176 | } |
| 177 | |
| 178 | class PseudoMaskedAMOMinMax |
| 179 | : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2), |
Alex Bradbury | d464ed8 | 2018-10-03 11:14:26 +0000 | [diff] [blame] | 180 | (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$sextshamt, |
| 181 | ixlenimm:$ordering), []> { |
Alex Bradbury | 21aea51 | 2018-09-19 10:54:22 +0000 | [diff] [blame] | 182 | let Constraints = "@earlyclobber $res,@earlyclobber $scratch1," |
| 183 | "@earlyclobber $scratch2"; |
| 184 | let mayLoad = 1; |
| 185 | let mayStore = 1; |
| 186 | let hasSideEffects = 0; |
| 187 | } |
| 188 | |
| 189 | class PseudoMaskedAMOUMinUMax |
| 190 | : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2), |
Alex Bradbury | d464ed8 | 2018-10-03 11:14:26 +0000 | [diff] [blame] | 191 | (ins GPR:$addr, GPR:$incr, GPR:$mask, ixlenimm:$ordering), []> { |
Alex Bradbury | 21aea51 | 2018-09-19 10:54:22 +0000 | [diff] [blame] | 192 | let Constraints = "@earlyclobber $res,@earlyclobber $scratch1," |
| 193 | "@earlyclobber $scratch2"; |
| 194 | let mayLoad = 1; |
| 195 | let mayStore = 1; |
| 196 | let hasSideEffects = 0; |
| 197 | } |
| 198 | |
| 199 | class PseudoMaskedAMOPat<Intrinsic intrin, Pseudo AMOInst> |
| 200 | : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, imm:$ordering), |
| 201 | (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, imm:$ordering)>; |
| 202 | |
| 203 | class PseudoMaskedAMOMinMaxPat<Intrinsic intrin, Pseudo AMOInst> |
| 204 | : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, |
| 205 | imm:$ordering), |
| 206 | (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, |
| 207 | imm:$ordering)>; |
| 208 | |
| 209 | def PseudoMaskedAtomicSwap32 : PseudoMaskedAMO; |
| 210 | def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_xchg_i32, |
| 211 | PseudoMaskedAtomicSwap32>; |
| 212 | def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAMO; |
| 213 | def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_add_i32, |
| 214 | PseudoMaskedAtomicLoadAdd32>; |
| 215 | def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAMO; |
| 216 | def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_sub_i32, |
| 217 | PseudoMaskedAtomicLoadSub32>; |
| 218 | def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAMO; |
| 219 | def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_nand_i32, |
| 220 | PseudoMaskedAtomicLoadNand32>; |
| 221 | def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMOMinMax; |
| 222 | def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_max_i32, |
| 223 | PseudoMaskedAtomicLoadMax32>; |
| 224 | def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMOMinMax; |
| 225 | def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_min_i32, |
| 226 | PseudoMaskedAtomicLoadMin32>; |
| 227 | def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMOUMinUMax; |
| 228 | def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umax_i32, |
| 229 | PseudoMaskedAtomicLoadUMax32>; |
| 230 | def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMOUMinUMax; |
| 231 | def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umin_i32, |
| 232 | PseudoMaskedAtomicLoadUMin32>; |
Alex Bradbury | 66d9a75 | 2018-11-29 20:43:42 +0000 | [diff] [blame] | 233 | |
| 234 | /// Compare and exchange |
| 235 | |
| 236 | class PseudoCmpXchg |
| 237 | : Pseudo<(outs GPR:$res, GPR:$scratch), |
| 238 | (ins GPR:$addr, GPR:$cmpval, GPR:$newval, i32imm:$ordering), []> { |
| 239 | let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; |
| 240 | let mayLoad = 1; |
| 241 | let mayStore = 1; |
| 242 | let hasSideEffects = 0; |
| 243 | } |
| 244 | |
| 245 | // Ordering constants must be kept in sync with the AtomicOrdering enum in |
| 246 | // AtomicOrdering.h. |
| 247 | multiclass PseudoCmpXchgPat<string Op, Pseudo CmpXchgInst> { |
| 248 | def : Pat<(!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$cmp, GPR:$new), |
| 249 | (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 2)>; |
| 250 | def : Pat<(!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$cmp, GPR:$new), |
| 251 | (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 4)>; |
| 252 | def : Pat<(!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$cmp, GPR:$new), |
| 253 | (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 5)>; |
| 254 | def : Pat<(!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$cmp, GPR:$new), |
| 255 | (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 6)>; |
| 256 | def : Pat<(!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$cmp, GPR:$new), |
| 257 | (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 7)>; |
| 258 | } |
| 259 | |
| 260 | def PseudoCmpXchg32 : PseudoCmpXchg; |
| 261 | defm : PseudoCmpXchgPat<"atomic_cmp_swap_32", PseudoCmpXchg32>; |
| 262 | |
| 263 | def PseudoMaskedCmpXchg32 |
| 264 | : Pseudo<(outs GPR:$res, GPR:$scratch), |
| 265 | (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, |
| 266 | i32imm:$ordering), []> { |
| 267 | let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; |
| 268 | let mayLoad = 1; |
| 269 | let mayStore = 1; |
| 270 | let hasSideEffects = 0; |
| 271 | } |
| 272 | |
| 273 | def : Pat<(int_riscv_masked_cmpxchg_i32 |
| 274 | GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, imm:$ordering), |
| 275 | (PseudoMaskedCmpXchg32 |
| 276 | GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, imm:$ordering)>; |
| 277 | |
Roger Ferrer Ibanez | fe28217 | 2018-08-27 07:08:18 +0000 | [diff] [blame] | 278 | } // Predicates = [HasStdExtA] |