1//=- AArch64InstrAtomics.td - AArch64 Atomic codegen support -*- tablegen -*-=// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// AArch64 Atomic operand code-gen constructs. 10// 11//===----------------------------------------------------------------------===// 12 13//===---------------------------------- 14// Atomic fences 15//===---------------------------------- 16let AddedComplexity = 15 in 17def : Pat<(atomic_fence (timm), 0), (MEMBARRIER)>; 18def : Pat<(atomic_fence (i64 4), (timm)), (DMB (i32 0x9))>; 19def : Pat<(atomic_fence (timm), (timm)), (DMB (i32 0xb))>; 20 21//===---------------------------------- 22// Atomic loads 23//===---------------------------------- 24 25// When they're actually atomic, only one addressing mode (GPR64sp) is 26// supported, but when they're relaxed and anything can be used, all the 27// standard modes would be valid and may give efficiency gains. 28 29// An atomic load operation that does not need either acquire or release 30// semantics. 31class relaxed_load<PatFrags base> 32 : PatFrag<(ops node:$ptr), (base node:$ptr)> { 33 let IsAtomic = 1; 34 let IsAtomicOrderingAcquireOrStronger = 0; 35} 36 37// A atomic load operation that actually needs acquire semantics. 38class acquiring_load<PatFrags base> 39 : PatFrag<(ops node:$ptr), (base node:$ptr)> { 40 let IsAtomic = 1; 41 let IsAtomicOrderingAcquire = 1; 42} 43 44// An atomic load operation that needs sequential consistency. 45class seq_cst_load<PatFrags base> 46 : PatFrag<(ops node:$ptr), (base node:$ptr)> { 47 let IsAtomic = 1; 48 let IsAtomicOrderingSequentiallyConsistent = 1; 49} 50 51let Predicates = [HasRCPC] in { 52 // v8.3 Release Consistent Processor Consistent support, optional in v8.2. 53 // 8-bit loads 54 def : Pat<(acquiring_load<atomic_load_8> GPR64sp:$ptr), (LDAPRB GPR64sp:$ptr)>; 55 // 16-bit loads 56 def : Pat<(acquiring_load<atomic_load_16> GPR64sp:$ptr), (LDAPRH GPR64sp:$ptr)>; 57 // 32-bit loads 58 def : Pat<(acquiring_load<atomic_load_32> GPR64sp:$ptr), (LDAPRW GPR64sp:$ptr)>; 59 // 64-bit loads 60 def : Pat<(acquiring_load<atomic_load_64> GPR64sp:$ptr), (LDAPRX GPR64sp:$ptr)>; 61} 62 63// 8-bit loads 64def : Pat<(seq_cst_load<atomic_load_az_8> GPR64sp:$ptr), (LDARB GPR64sp:$ptr)>; 65def : Pat<(acquiring_load<atomic_load_az_8> GPR64sp:$ptr), (LDARB GPR64sp:$ptr)>; 66def : Pat<(relaxed_load<atomic_load_az_8> (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm, 67 ro_Wextend8:$offset)), 68 (LDRBBroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$offset)>; 69def : Pat<(relaxed_load<atomic_load_az_8> (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm, 70 ro_Xextend8:$offset)), 71 (LDRBBroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$offset)>; 72def : Pat<(relaxed_load<atomic_load_az_8> (am_indexed8 GPR64sp:$Rn, 73 uimm12s1:$offset)), 74 (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>; 75def : Pat<(relaxed_load<atomic_load_az_8> 76 (am_unscaled8 GPR64sp:$Rn, simm9:$offset)), 77 (LDURBBi GPR64sp:$Rn, simm9:$offset)>; 78 79// 16-bit loads 80def : Pat<(seq_cst_load<atomic_load_az_16> GPR64sp:$ptr), (LDARH GPR64sp:$ptr)>; 81def : Pat<(acquiring_load<atomic_load_az_16> GPR64sp:$ptr), (LDARH GPR64sp:$ptr)>; 82def : Pat<(relaxed_load<atomic_load_az_16> (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm, 83 ro_Wextend16:$extend)), 84 (LDRHHroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend)>; 85def : Pat<(relaxed_load<atomic_load_az_16> (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm, 86 ro_Xextend16:$extend)), 87 (LDRHHroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend)>; 88def : Pat<(relaxed_load<atomic_load_az_16> (am_indexed16 GPR64sp:$Rn, 89 uimm12s2:$offset)), 90 (LDRHHui GPR64sp:$Rn, uimm12s2:$offset)>; 91def : Pat<(relaxed_load<atomic_load_az_16> 92 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)), 93 (LDURHHi GPR64sp:$Rn, simm9:$offset)>; 94 95// 32-bit loads 96def : Pat<(seq_cst_load<atomic_load_32> GPR64sp:$ptr), (LDARW GPR64sp:$ptr)>; 97def : Pat<(acquiring_load<atomic_load_32> GPR64sp:$ptr), (LDARW GPR64sp:$ptr)>; 98def : Pat<(relaxed_load<atomic_load_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm, 99 ro_Wextend32:$extend)), 100 (LDRWroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>; 101def : Pat<(relaxed_load<atomic_load_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm, 102 ro_Xextend32:$extend)), 103 (LDRWroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>; 104def : Pat<(relaxed_load<atomic_load_32> (am_indexed32 GPR64sp:$Rn, 105 uimm12s4:$offset)), 106 (LDRWui GPR64sp:$Rn, uimm12s4:$offset)>; 107def : Pat<(relaxed_load<atomic_load_32> 108 (am_unscaled32 GPR64sp:$Rn, simm9:$offset)), 109 (LDURWi GPR64sp:$Rn, simm9:$offset)>; 110 111// 64-bit loads 112def : Pat<(seq_cst_load<atomic_load_64> GPR64sp:$ptr), (LDARX GPR64sp:$ptr)>; 113def : Pat<(acquiring_load<atomic_load_64> GPR64sp:$ptr), (LDARX GPR64sp:$ptr)>; 114def : Pat<(relaxed_load<atomic_load_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, 115 ro_Wextend64:$extend)), 116 (LDRXroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>; 117def : Pat<(relaxed_load<atomic_load_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, 118 ro_Xextend64:$extend)), 119 (LDRXroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>; 120def : Pat<(relaxed_load<atomic_load_64> (am_indexed64 GPR64sp:$Rn, 121 uimm12s8:$offset)), 122 (LDRXui GPR64sp:$Rn, uimm12s8:$offset)>; 123def : Pat<(relaxed_load<atomic_load_64> 124 (am_unscaled64 GPR64sp:$Rn, simm9:$offset)), 125 (LDURXi GPR64sp:$Rn, simm9:$offset)>; 126 127// FP 32-bit loads 128def : Pat<(f32 (bitconvert (i32 (relaxed_load<atomic_load_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm, 129 ro_Wextend32:$extend))))), 130 (LDRSroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>; 131def : Pat<(f32 (bitconvert (i32 (relaxed_load<atomic_load_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm, 132 ro_Xextend32:$extend))))), 133 (LDRSroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>; 134def : Pat<(f32 (bitconvert (i32 (relaxed_load<atomic_load_32> (am_indexed32 GPR64sp:$Rn, 135 uimm12s8:$offset))))), 136 (LDRSui GPR64sp:$Rn, uimm12s8:$offset)>; 137def : Pat<(f32 (bitconvert (i32 (relaxed_load<atomic_load_32> 138 (am_unscaled32 GPR64sp:$Rn, simm9:$offset))))), 139 (LDURSi GPR64sp:$Rn, simm9:$offset)>; 140 141// FP 64-bit loads 142def : Pat<(f64 (bitconvert (i64 (relaxed_load<atomic_load_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, 143 ro_Wextend64:$extend))))), 144 (LDRDroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>; 145def : Pat<(f64 (bitconvert (i64 (relaxed_load<atomic_load_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, 146 ro_Xextend64:$extend))))), 147 (LDRDroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>; 148def : Pat<(f64 (bitconvert (i64 (relaxed_load<atomic_load_64> (am_indexed64 GPR64sp:$Rn, 149 uimm12s8:$offset))))), 150 (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>; 151def : Pat<(f64 (bitconvert (i64 (relaxed_load<atomic_load_64> 152 (am_unscaled64 GPR64sp:$Rn, simm9:$offset))))), 153 (LDURDi GPR64sp:$Rn, simm9:$offset)>; 154 155//===---------------------------------- 156// Atomic stores 157//===---------------------------------- 158 159// When they're actually atomic, only one addressing mode (GPR64sp) is 160// supported, but when they're relaxed and anything can be used, all the 161// standard modes would be valid and may give efficiency gains. 162 163// A store operation that actually needs release semantics. 164class releasing_store<PatFrag base> 165 : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val)> { 166 let IsAtomic = 1; 167 let IsAtomicOrderingReleaseOrStronger = 1; 168} 169 170// An atomic store operation that doesn't actually need to be atomic on AArch64. 171class relaxed_store<PatFrag base> 172 : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val)> { 173 let IsAtomic = 1; 174 let IsAtomicOrderingReleaseOrStronger = 0; 175} 176 177// 8-bit stores 178def : Pat<(releasing_store<atomic_store_8> GPR64sp:$ptr, GPR32:$val), 179 (STLRB GPR32:$val, GPR64sp:$ptr)>; 180def : Pat<(relaxed_store<atomic_store_8> 181 (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend), 182 GPR32:$val), 183 (STRBBroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend)>; 184def : Pat<(relaxed_store<atomic_store_8> 185 (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend), 186 GPR32:$val), 187 (STRBBroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend)>; 188def : Pat<(relaxed_store<atomic_store_8> 189 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset), GPR32:$val), 190 (STRBBui GPR32:$val, GPR64sp:$Rn, uimm12s1:$offset)>; 191def : Pat<(relaxed_store<atomic_store_8> 192 (am_unscaled8 GPR64sp:$Rn, simm9:$offset), GPR32:$val), 193 (STURBBi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>; 194 195// 16-bit stores 196def : Pat<(releasing_store<atomic_store_16> GPR64sp:$ptr, GPR32:$val), 197 (STLRH GPR32:$val, GPR64sp:$ptr)>; 198def : Pat<(relaxed_store<atomic_store_16> (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm, 199 ro_Wextend16:$extend), 200 GPR32:$val), 201 (STRHHroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend)>; 202def : Pat<(relaxed_store<atomic_store_16> (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm, 203 ro_Xextend16:$extend), 204 GPR32:$val), 205 (STRHHroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend)>; 206def : Pat<(relaxed_store<atomic_store_16> 207 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset), GPR32:$val), 208 (STRHHui GPR32:$val, GPR64sp:$Rn, uimm12s2:$offset)>; 209def : Pat<(relaxed_store<atomic_store_16> 210 (am_unscaled16 GPR64sp:$Rn, simm9:$offset), GPR32:$val), 211 (STURHHi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>; 212 213// 32-bit stores 214def : Pat<(releasing_store<atomic_store_32> GPR64sp:$ptr, GPR32:$val), 215 (STLRW GPR32:$val, GPR64sp:$ptr)>; 216def : Pat<(relaxed_store<atomic_store_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm, 217 ro_Wextend32:$extend), 218 GPR32:$val), 219 (STRWroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>; 220def : Pat<(relaxed_store<atomic_store_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm, 221 ro_Xextend32:$extend), 222 GPR32:$val), 223 (STRWroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>; 224def : Pat<(relaxed_store<atomic_store_32> 225 (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset), GPR32:$val), 226 (STRWui GPR32:$val, GPR64sp:$Rn, uimm12s4:$offset)>; 227def : Pat<(relaxed_store<atomic_store_32> 228 (am_unscaled32 GPR64sp:$Rn, simm9:$offset), GPR32:$val), 229 (STURWi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>; 230 231// 64-bit stores 232def : Pat<(releasing_store<atomic_store_64> GPR64sp:$ptr, GPR64:$val), 233 (STLRX GPR64:$val, GPR64sp:$ptr)>; 234def : Pat<(relaxed_store<atomic_store_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, 235 ro_Wextend16:$extend), 236 GPR64:$val), 237 (STRXroW GPR64:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>; 238def : Pat<(relaxed_store<atomic_store_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, 239 ro_Xextend16:$extend), 240 GPR64:$val), 241 (STRXroX GPR64:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>; 242def : Pat<(relaxed_store<atomic_store_64> 243 (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset), GPR64:$val), 244 (STRXui GPR64:$val, GPR64sp:$Rn, uimm12s8:$offset)>; 245def : Pat<(relaxed_store<atomic_store_64> 246 (am_unscaled64 GPR64sp:$Rn, simm9:$offset), GPR64:$val), 247 (STURXi GPR64:$val, GPR64sp:$Rn, simm9:$offset)>; 248 249// FP 32-bit stores 250def : Pat<(relaxed_store<atomic_store_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm, 251 ro_Wextend32:$extend), 252 (i32 (bitconvert (f32 FPR32Op:$val)))), 253 (STRSroW FPR32Op:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>; 254def : Pat<(relaxed_store<atomic_store_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm, 255 ro_Xextend32:$extend), 256 (i32 (bitconvert (f32 FPR32Op:$val)))), 257 (STRSroX FPR32Op:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>; 258def : Pat<(relaxed_store<atomic_store_32> 259 (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset), (i32 (bitconvert (f32 FPR32Op:$val)))), 260 (STRSui FPR32Op:$val, GPR64sp:$Rn, uimm12s4:$offset)>; 261def : Pat<(relaxed_store<atomic_store_32> 262 (am_unscaled32 GPR64sp:$Rn, simm9:$offset), (i32 (bitconvert (f32 FPR32Op:$val)))), 263 (STURSi FPR32Op:$val, GPR64sp:$Rn, simm9:$offset)>; 264 265// FP 64-bit stores 266def : Pat<(relaxed_store<atomic_store_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, 267 ro_Wextend64:$extend), 268 (i64 (bitconvert (f64 FPR64Op:$val)))), 269 (STRDroW FPR64Op:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>; 270def : Pat<(relaxed_store<atomic_store_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, 271 ro_Xextend64:$extend), 272 (i64 (bitconvert (f64 FPR64Op:$val)))), 273 (STRDroX FPR64Op:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>; 274def : Pat<(relaxed_store<atomic_store_64> 275 (am_indexed64 GPR64sp:$Rn, uimm12s4:$offset), (i64 (bitconvert (f64 FPR64Op:$val)))), 276 (STRDui FPR64Op:$val, GPR64sp:$Rn, uimm12s4:$offset)>; 277def : Pat<(relaxed_store<atomic_store_64> 278 (am_unscaled64 GPR64sp:$Rn, simm9:$offset), (i64 (bitconvert (f64 FPR64Op:$val)))), 279 (STURDi FPR64Op:$val, GPR64sp:$Rn, simm9:$offset)>; 280 281//===---------------------------------- 282// Low-level exclusive operations 283//===---------------------------------- 284 285// Load-exclusives. 286 287def ldxr_1 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{ 288 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8; 289}]> { 290 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 1); }]; 291} 292 293def ldxr_2 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{ 294 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16; 295}]> { 296 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 2); }]; 297} 298 299def ldxr_4 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{ 300 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32; 301}]> { 302 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 4); }]; 303} 304 305def ldxr_8 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{ 306 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64; 307}]> { 308 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 8); }]; 309} 310 311def : Pat<(ldxr_1 GPR64sp:$addr), 312 (SUBREG_TO_REG (i64 0), (LDXRB GPR64sp:$addr), sub_32)>; 313def : Pat<(ldxr_2 GPR64sp:$addr), 314 (SUBREG_TO_REG (i64 0), (LDXRH GPR64sp:$addr), sub_32)>; 315def : Pat<(ldxr_4 GPR64sp:$addr), 316 (SUBREG_TO_REG (i64 0), (LDXRW GPR64sp:$addr), sub_32)>; 317def : Pat<(ldxr_8 GPR64sp:$addr), (LDXRX GPR64sp:$addr)>; 318 319def : Pat<(and (ldxr_1 GPR64sp:$addr), 0xff), 320 (SUBREG_TO_REG (i64 0), (LDXRB GPR64sp:$addr), sub_32)>; 321def : Pat<(and (ldxr_2 GPR64sp:$addr), 0xffff), 322 (SUBREG_TO_REG (i64 0), (LDXRH GPR64sp:$addr), sub_32)>; 323def : Pat<(and (ldxr_4 GPR64sp:$addr), 0xffffffff), 324 (SUBREG_TO_REG (i64 0), (LDXRW GPR64sp:$addr), sub_32)>; 325 326// Load-exclusives. 327 328def ldaxr_1 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{ 329 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8; 330}]> { 331 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 1); }]; 332} 333 334def ldaxr_2 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{ 335 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16; 336}]> { 337 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 2); }]; 338} 339 340def ldaxr_4 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{ 341 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32; 342}]> { 343 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 4); }]; 344} 345 346def ldaxr_8 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{ 347 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64; 348}]> { 349 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 8); }]; 350} 351 352def : Pat<(ldaxr_1 GPR64sp:$addr), 353 (SUBREG_TO_REG (i64 0), (LDAXRB GPR64sp:$addr), sub_32)>; 354def : Pat<(ldaxr_2 GPR64sp:$addr), 355 (SUBREG_TO_REG (i64 0), (LDAXRH GPR64sp:$addr), sub_32)>; 356def : Pat<(ldaxr_4 GPR64sp:$addr), 357 (SUBREG_TO_REG (i64 0), (LDAXRW GPR64sp:$addr), sub_32)>; 358def : Pat<(ldaxr_8 GPR64sp:$addr), (LDAXRX GPR64sp:$addr)>; 359 360def : Pat<(and (ldaxr_1 GPR64sp:$addr), 0xff), 361 (SUBREG_TO_REG (i64 0), (LDAXRB GPR64sp:$addr), sub_32)>; 362def : Pat<(and (ldaxr_2 GPR64sp:$addr), 0xffff), 363 (SUBREG_TO_REG (i64 0), (LDAXRH GPR64sp:$addr), sub_32)>; 364def : Pat<(and (ldaxr_4 GPR64sp:$addr), 0xffffffff), 365 (SUBREG_TO_REG (i64 0), (LDAXRW GPR64sp:$addr), sub_32)>; 366 367// Store-exclusives. 368 369def stxr_1 : PatFrag<(ops node:$val, node:$ptr), 370 (int_aarch64_stxr node:$val, node:$ptr), [{ 371 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8; 372}]> { 373 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 1); }]; 374} 375 376def stxr_2 : PatFrag<(ops node:$val, node:$ptr), 377 (int_aarch64_stxr node:$val, node:$ptr), [{ 378 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16; 379}]> { 380 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 2); }]; 381} 382 383def stxr_4 : PatFrag<(ops node:$val, node:$ptr), 384 (int_aarch64_stxr node:$val, node:$ptr), [{ 385 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32; 386}]> { 387 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 4); }]; 388} 389 390def stxr_8 : PatFrag<(ops node:$val, node:$ptr), 391 (int_aarch64_stxr node:$val, node:$ptr), [{ 392 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64; 393}]> { 394 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 8); }]; 395} 396 397 398def : Pat<(stxr_1 GPR64:$val, GPR64sp:$addr), 399 (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 400def : Pat<(stxr_2 GPR64:$val, GPR64sp:$addr), 401 (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 402def : Pat<(stxr_4 GPR64:$val, GPR64sp:$addr), 403 (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 404def : Pat<(stxr_8 GPR64:$val, GPR64sp:$addr), 405 (STXRX GPR64:$val, GPR64sp:$addr)>; 406 407def : Pat<(stxr_1 (zext (and GPR32:$val, 0xff)), GPR64sp:$addr), 408 (STXRB GPR32:$val, GPR64sp:$addr)>; 409def : Pat<(stxr_2 (zext (and GPR32:$val, 0xffff)), GPR64sp:$addr), 410 (STXRH GPR32:$val, GPR64sp:$addr)>; 411def : Pat<(stxr_4 (zext GPR32:$val), GPR64sp:$addr), 412 (STXRW GPR32:$val, GPR64sp:$addr)>; 413 414def : Pat<(stxr_1 (and GPR64:$val, 0xff), GPR64sp:$addr), 415 (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 416def : Pat<(stxr_2 (and GPR64:$val, 0xffff), GPR64sp:$addr), 417 (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 418def : Pat<(stxr_4 (and GPR64:$val, 0xffffffff), GPR64sp:$addr), 419 (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 420 421// Store-release-exclusives. 422 423def stlxr_1 : PatFrag<(ops node:$val, node:$ptr), 424 (int_aarch64_stlxr node:$val, node:$ptr), [{ 425 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8; 426}]> { 427 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 1); }]; 428} 429 430def stlxr_2 : PatFrag<(ops node:$val, node:$ptr), 431 (int_aarch64_stlxr node:$val, node:$ptr), [{ 432 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16; 433}]> { 434 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 2); }]; 435} 436 437def stlxr_4 : PatFrag<(ops node:$val, node:$ptr), 438 (int_aarch64_stlxr node:$val, node:$ptr), [{ 439 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32; 440}]> { 441 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 4); }]; 442} 443 444def stlxr_8 : PatFrag<(ops node:$val, node:$ptr), 445 (int_aarch64_stlxr node:$val, node:$ptr), [{ 446 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64; 447}]> { 448 let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 8); }]; 449} 450 451 452def : Pat<(stlxr_1 GPR64:$val, GPR64sp:$addr), 453 (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 454def : Pat<(stlxr_2 GPR64:$val, GPR64sp:$addr), 455 (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 456def : Pat<(stlxr_4 GPR64:$val, GPR64sp:$addr), 457 (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 458def : Pat<(stlxr_8 GPR64:$val, GPR64sp:$addr), 459 (STLXRX GPR64:$val, GPR64sp:$addr)>; 460 461def : Pat<(stlxr_1 (zext (and GPR32:$val, 0xff)), GPR64sp:$addr), 462 (STLXRB GPR32:$val, GPR64sp:$addr)>; 463def : Pat<(stlxr_2 (zext (and GPR32:$val, 0xffff)), GPR64sp:$addr), 464 (STLXRH GPR32:$val, GPR64sp:$addr)>; 465def : Pat<(stlxr_4 (zext GPR32:$val), GPR64sp:$addr), 466 (STLXRW GPR32:$val, GPR64sp:$addr)>; 467 468def : Pat<(stlxr_1 (and GPR64:$val, 0xff), GPR64sp:$addr), 469 (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 470def : Pat<(stlxr_2 (and GPR64:$val, 0xffff), GPR64sp:$addr), 471 (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 472def : Pat<(stlxr_4 (and GPR64:$val, 0xffffffff), GPR64sp:$addr), 473 (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; 474 475 476// And clear exclusive. 477 478def : Pat<(int_aarch64_clrex), (CLREX 0xf)>; 479 480//===---------------------------------- 481// Atomic cmpxchg for -O0 482//===---------------------------------- 483 484// The fast register allocator used during -O0 inserts spills to cover any VRegs 485// live across basic block boundaries. When this happens between an LDXR and an 486// STXR it can clear the exclusive monitor, causing all cmpxchg attempts to 487// fail. 488 489// Unfortunately, this means we have to have an alternative (expanded 490// post-regalloc) path for -O0 compilations. Fortunately this path can be 491// significantly more naive than the standard expansion: we conservatively 492// assume seq_cst, strong cmpxchg and omit clrex on failure. 493 494let Constraints = "@earlyclobber $Rd,@earlyclobber $scratch", 495 mayLoad = 1, mayStore = 1 in { 496def CMP_SWAP_8 : Pseudo<(outs GPR32:$Rd, GPR32:$scratch), 497 (ins GPR64:$addr, GPR32:$desired, GPR32:$new), []>, 498 Sched<[WriteAtomic]>; 499 500def CMP_SWAP_16 : Pseudo<(outs GPR32:$Rd, GPR32:$scratch), 501 (ins GPR64:$addr, GPR32:$desired, GPR32:$new), []>, 502 Sched<[WriteAtomic]>; 503 504def CMP_SWAP_32 : Pseudo<(outs GPR32:$Rd, GPR32:$scratch), 505 (ins GPR64:$addr, GPR32:$desired, GPR32:$new), []>, 506 Sched<[WriteAtomic]>; 507 508def CMP_SWAP_64 : Pseudo<(outs GPR64:$Rd, GPR32:$scratch), 509 (ins GPR64:$addr, GPR64:$desired, GPR64:$new), []>, 510 Sched<[WriteAtomic]>; 511} 512 513let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi,@earlyclobber $scratch", 514 mayLoad = 1, mayStore = 1 in { 515class cmp_swap_128 : Pseudo<(outs GPR64common:$RdLo, GPR64common:$RdHi, 516 GPR32common:$scratch), 517 (ins GPR64:$addr, GPR64:$desiredLo, GPR64:$desiredHi, 518 GPR64:$newLo, GPR64:$newHi), []>, 519 Sched<[WriteAtomic]>; 520def CMP_SWAP_128 : cmp_swap_128; 521def CMP_SWAP_128_RELEASE : cmp_swap_128; 522def CMP_SWAP_128_ACQUIRE : cmp_swap_128; 523def CMP_SWAP_128_MONOTONIC : cmp_swap_128; 524} 525 526// v8.1 Atomic instructions: 527let Predicates = [HasLSE] in { 528 defm : LDOPregister_patterns<"LDADD", "atomic_load_add">; 529 defm : LDOPregister_patterns<"LDSET", "atomic_load_or">; 530 defm : LDOPregister_patterns<"LDEOR", "atomic_load_xor">; 531 defm : LDOPregister_patterns<"LDCLR", "atomic_load_clr">; 532 defm : LDOPregister_patterns<"LDSMAX", "atomic_load_max">; 533 defm : LDOPregister_patterns<"LDSMIN", "atomic_load_min">; 534 defm : LDOPregister_patterns<"LDUMAX", "atomic_load_umax">; 535 defm : LDOPregister_patterns<"LDUMIN", "atomic_load_umin">; 536 defm : LDOPregister_patterns<"SWP", "atomic_swap">; 537 defm : CASregister_patterns<"CAS", "atomic_cmp_swap">; 538 539 // These two patterns are only needed for global isel, selection dag isel 540 // converts atomic load-sub into a sub and atomic load-add, and likewise for 541 // and -> clr. 542 defm : LDOPregister_patterns_mod<"LDADD", "atomic_load_sub", "SUB">; 543 defm : LDOPregister_patterns_mod<"LDCLR", "atomic_load_and", "ORN">; 544} 545 546// v8.9a/v9.4a FEAT_LRCPC patterns 547let Predicates = [HasRCPC3, HasNEON] in { 548 // LDAP1 loads 549 def : Pat<(vector_insert (v2i64 VecListOne128:$Rd), 550 (i64 (acquiring_load<atomic_load_64> GPR64sp:$Rn)), VectorIndexD:$idx), 551 (LDAP1 VecListOne128:$Rd, VectorIndexD:$idx, GPR64sp:$Rn)>; 552 def : Pat<(vector_insert (v2f64 VecListOne128:$Rd), 553 (f64 (bitconvert (i64 (acquiring_load<atomic_load_64> GPR64sp:$Rn)))), VectorIndexD:$idx), 554 (LDAP1 VecListOne128:$Rd, VectorIndexD:$idx, GPR64sp:$Rn)>; 555 def : Pat<(v1i64 (scalar_to_vector 556 (i64 (acquiring_load<atomic_load_64> GPR64sp:$Rn)))), 557 (EXTRACT_SUBREG (LDAP1 (v2i64 (IMPLICIT_DEF)), (i64 0), GPR64sp:$Rn), dsub)>; 558 def : Pat<(v1f64 (scalar_to_vector 559 (f64 (bitconvert (i64 (acquiring_load<atomic_load_64> GPR64sp:$Rn)))))), 560 (EXTRACT_SUBREG (LDAP1 (v2f64 (IMPLICIT_DEF)), (i64 0), GPR64sp:$Rn), dsub)>; 561 562 // STL1 stores 563 def : Pat<(releasing_store<atomic_store_64> GPR64sp:$Rn, 564 (i64 (vector_extract (v2i64 VecListOne128:$Vt), VectorIndexD:$idx))), 565 (STL1 VecListOne128:$Vt, VectorIndexD:$idx, GPR64sp:$Rn)>; 566 def : Pat<(releasing_store<atomic_store_64> GPR64sp:$Rn, 567 (i64 (bitconvert (f64 (vector_extract (v2f64 VecListOne128:$Vt), VectorIndexD:$idx))))), 568 (STL1 VecListOne128:$Vt, VectorIndexD:$idx, GPR64sp:$Rn)>; 569 // The v1i64 version of the vldap1_lane_* intrinsic is represented as a 570 // vector_insert -> vector_extract -> atomic store sequence, which is captured 571 // by the patterns above. We only need to cover the v1f64 case manually. 572 def : Pat<(releasing_store<atomic_store_64> GPR64sp:$Rn, 573 (i64 (bitconvert (v1f64 VecListOne64:$Vt)))), 574 (STL1 (SUBREG_TO_REG (i64 0), VecListOne64:$Vt, dsub), (i64 0), GPR64sp:$Rn)>; 575} 576