AArch64InstrAtomics.td 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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. // Atomic fences
  14. //===----------------------------------
  15. let AddedComplexity = 15, Size = 0 in
  16. def CompilerBarrier : Pseudo<(outs), (ins i32imm:$ordering),
  17. [(atomic_fence timm:$ordering, 0)]>, Sched<[]>;
  18. def : Pat<(atomic_fence (i64 4), (timm)), (DMB (i32 0x9))>;
  19. def : Pat<(atomic_fence (timm), (timm)), (DMB (i32 0xb))>;
  20. //===----------------------------------
  21. // Atomic loads
  22. //===----------------------------------
  23. // When they're actually atomic, only one addressing mode (GPR64sp) is
  24. // supported, but when they're relaxed and anything can be used, all the
  25. // standard modes would be valid and may give efficiency gains.
  26. // A atomic load operation that actually needs acquire semantics.
  27. class acquiring_load<PatFrag base>
  28. : PatFrag<(ops node:$ptr), (base node:$ptr)> {
  29. let IsAtomic = 1;
  30. let IsAtomicOrderingAcquireOrStronger = 1;
  31. }
  32. // An atomic load operation that does not need either acquire or release
  33. // semantics.
  34. class relaxed_load<PatFrag base>
  35. : PatFrag<(ops node:$ptr), (base node:$ptr)> {
  36. let IsAtomic = 1;
  37. let IsAtomicOrderingAcquireOrStronger = 0;
  38. }
  39. // 8-bit loads
  40. def : Pat<(acquiring_load<atomic_load_8> GPR64sp:$ptr), (LDARB GPR64sp:$ptr)>;
  41. def : Pat<(relaxed_load<atomic_load_8> (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
  42. ro_Wextend8:$offset)),
  43. (LDRBBroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$offset)>;
  44. def : Pat<(relaxed_load<atomic_load_8> (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
  45. ro_Xextend8:$offset)),
  46. (LDRBBroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$offset)>;
  47. def : Pat<(relaxed_load<atomic_load_8> (am_indexed8 GPR64sp:$Rn,
  48. uimm12s1:$offset)),
  49. (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>;
  50. def : Pat<(relaxed_load<atomic_load_8>
  51. (am_unscaled8 GPR64sp:$Rn, simm9:$offset)),
  52. (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
  53. // 16-bit loads
  54. def : Pat<(acquiring_load<atomic_load_16> GPR64sp:$ptr), (LDARH GPR64sp:$ptr)>;
  55. def : Pat<(relaxed_load<atomic_load_16> (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
  56. ro_Wextend16:$extend)),
  57. (LDRHHroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend)>;
  58. def : Pat<(relaxed_load<atomic_load_16> (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
  59. ro_Xextend16:$extend)),
  60. (LDRHHroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend)>;
  61. def : Pat<(relaxed_load<atomic_load_16> (am_indexed16 GPR64sp:$Rn,
  62. uimm12s2:$offset)),
  63. (LDRHHui GPR64sp:$Rn, uimm12s2:$offset)>;
  64. def : Pat<(relaxed_load<atomic_load_16>
  65. (am_unscaled16 GPR64sp:$Rn, simm9:$offset)),
  66. (LDURHHi GPR64sp:$Rn, simm9:$offset)>;
  67. // 32-bit loads
  68. def : Pat<(acquiring_load<atomic_load_32> GPR64sp:$ptr), (LDARW GPR64sp:$ptr)>;
  69. def : Pat<(relaxed_load<atomic_load_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
  70. ro_Wextend32:$extend)),
  71. (LDRWroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>;
  72. def : Pat<(relaxed_load<atomic_load_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
  73. ro_Xextend32:$extend)),
  74. (LDRWroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>;
  75. def : Pat<(relaxed_load<atomic_load_32> (am_indexed32 GPR64sp:$Rn,
  76. uimm12s4:$offset)),
  77. (LDRWui GPR64sp:$Rn, uimm12s4:$offset)>;
  78. def : Pat<(relaxed_load<atomic_load_32>
  79. (am_unscaled32 GPR64sp:$Rn, simm9:$offset)),
  80. (LDURWi GPR64sp:$Rn, simm9:$offset)>;
  81. // 64-bit loads
  82. def : Pat<(acquiring_load<atomic_load_64> GPR64sp:$ptr), (LDARX GPR64sp:$ptr)>;
  83. def : Pat<(relaxed_load<atomic_load_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
  84. ro_Wextend64:$extend)),
  85. (LDRXroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>;
  86. def : Pat<(relaxed_load<atomic_load_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
  87. ro_Xextend64:$extend)),
  88. (LDRXroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>;
  89. def : Pat<(relaxed_load<atomic_load_64> (am_indexed64 GPR64sp:$Rn,
  90. uimm12s8:$offset)),
  91. (LDRXui GPR64sp:$Rn, uimm12s8:$offset)>;
  92. def : Pat<(relaxed_load<atomic_load_64>
  93. (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
  94. (LDURXi GPR64sp:$Rn, simm9:$offset)>;
  95. // FP 32-bit loads
  96. def : Pat<(f32 (bitconvert (i32 (relaxed_load<atomic_load_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
  97. ro_Wextend32:$extend))))),
  98. (LDRSroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>;
  99. def : Pat<(f32 (bitconvert (i32 (relaxed_load<atomic_load_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
  100. ro_Xextend32:$extend))))),
  101. (LDRSroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>;
  102. def : Pat<(f32 (bitconvert (i32 (relaxed_load<atomic_load_32> (am_indexed32 GPR64sp:$Rn,
  103. uimm12s8:$offset))))),
  104. (LDRSui GPR64sp:$Rn, uimm12s8:$offset)>;
  105. def : Pat<(f32 (bitconvert (i32 (relaxed_load<atomic_load_32>
  106. (am_unscaled32 GPR64sp:$Rn, simm9:$offset))))),
  107. (LDURSi GPR64sp:$Rn, simm9:$offset)>;
  108. // FP 64-bit loads
  109. def : Pat<(f64 (bitconvert (i64 (relaxed_load<atomic_load_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
  110. ro_Wextend64:$extend))))),
  111. (LDRDroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>;
  112. def : Pat<(f64 (bitconvert (i64 (relaxed_load<atomic_load_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
  113. ro_Xextend64:$extend))))),
  114. (LDRDroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>;
  115. def : Pat<(f64 (bitconvert (i64 (relaxed_load<atomic_load_64> (am_indexed64 GPR64sp:$Rn,
  116. uimm12s8:$offset))))),
  117. (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>;
  118. def : Pat<(f64 (bitconvert (i64 (relaxed_load<atomic_load_64>
  119. (am_unscaled64 GPR64sp:$Rn, simm9:$offset))))),
  120. (LDURDi GPR64sp:$Rn, simm9:$offset)>;
  121. //===----------------------------------
  122. // Atomic stores
  123. //===----------------------------------
  124. // When they're actually atomic, only one addressing mode (GPR64sp) is
  125. // supported, but when they're relaxed and anything can be used, all the
  126. // standard modes would be valid and may give efficiency gains.
  127. // A store operation that actually needs release semantics.
  128. class releasing_store<PatFrag base>
  129. : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val)> {
  130. let IsAtomic = 1;
  131. let IsAtomicOrderingReleaseOrStronger = 1;
  132. }
  133. // An atomic store operation that doesn't actually need to be atomic on AArch64.
  134. class relaxed_store<PatFrag base>
  135. : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val)> {
  136. let IsAtomic = 1;
  137. let IsAtomicOrderingReleaseOrStronger = 0;
  138. }
  139. // 8-bit stores
  140. def : Pat<(releasing_store<atomic_store_8> GPR64sp:$ptr, GPR32:$val),
  141. (STLRB GPR32:$val, GPR64sp:$ptr)>;
  142. def : Pat<(relaxed_store<atomic_store_8>
  143. (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
  144. GPR32:$val),
  145. (STRBBroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend)>;
  146. def : Pat<(relaxed_store<atomic_store_8>
  147. (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
  148. GPR32:$val),
  149. (STRBBroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend)>;
  150. def : Pat<(relaxed_store<atomic_store_8>
  151. (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset), GPR32:$val),
  152. (STRBBui GPR32:$val, GPR64sp:$Rn, uimm12s1:$offset)>;
  153. def : Pat<(relaxed_store<atomic_store_8>
  154. (am_unscaled8 GPR64sp:$Rn, simm9:$offset), GPR32:$val),
  155. (STURBBi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>;
  156. // 16-bit stores
  157. def : Pat<(releasing_store<atomic_store_16> GPR64sp:$ptr, GPR32:$val),
  158. (STLRH GPR32:$val, GPR64sp:$ptr)>;
  159. def : Pat<(relaxed_store<atomic_store_16> (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
  160. ro_Wextend16:$extend),
  161. GPR32:$val),
  162. (STRHHroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend)>;
  163. def : Pat<(relaxed_store<atomic_store_16> (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
  164. ro_Xextend16:$extend),
  165. GPR32:$val),
  166. (STRHHroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend)>;
  167. def : Pat<(relaxed_store<atomic_store_16>
  168. (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset), GPR32:$val),
  169. (STRHHui GPR32:$val, GPR64sp:$Rn, uimm12s2:$offset)>;
  170. def : Pat<(relaxed_store<atomic_store_16>
  171. (am_unscaled16 GPR64sp:$Rn, simm9:$offset), GPR32:$val),
  172. (STURHHi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>;
  173. // 32-bit stores
  174. def : Pat<(releasing_store<atomic_store_32> GPR64sp:$ptr, GPR32:$val),
  175. (STLRW GPR32:$val, GPR64sp:$ptr)>;
  176. def : Pat<(relaxed_store<atomic_store_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
  177. ro_Wextend32:$extend),
  178. GPR32:$val),
  179. (STRWroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>;
  180. def : Pat<(relaxed_store<atomic_store_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
  181. ro_Xextend32:$extend),
  182. GPR32:$val),
  183. (STRWroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>;
  184. def : Pat<(relaxed_store<atomic_store_32>
  185. (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset), GPR32:$val),
  186. (STRWui GPR32:$val, GPR64sp:$Rn, uimm12s4:$offset)>;
  187. def : Pat<(relaxed_store<atomic_store_32>
  188. (am_unscaled32 GPR64sp:$Rn, simm9:$offset), GPR32:$val),
  189. (STURWi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>;
  190. // 64-bit stores
  191. def : Pat<(releasing_store<atomic_store_64> GPR64sp:$ptr, GPR64:$val),
  192. (STLRX GPR64:$val, GPR64sp:$ptr)>;
  193. def : Pat<(relaxed_store<atomic_store_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
  194. ro_Wextend16:$extend),
  195. GPR64:$val),
  196. (STRXroW GPR64:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>;
  197. def : Pat<(relaxed_store<atomic_store_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
  198. ro_Xextend16:$extend),
  199. GPR64:$val),
  200. (STRXroX GPR64:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>;
  201. def : Pat<(relaxed_store<atomic_store_64>
  202. (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset), GPR64:$val),
  203. (STRXui GPR64:$val, GPR64sp:$Rn, uimm12s8:$offset)>;
  204. def : Pat<(relaxed_store<atomic_store_64>
  205. (am_unscaled64 GPR64sp:$Rn, simm9:$offset), GPR64:$val),
  206. (STURXi GPR64:$val, GPR64sp:$Rn, simm9:$offset)>;
  207. // FP 32-bit stores
  208. def : Pat<(relaxed_store<atomic_store_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
  209. ro_Wextend32:$extend),
  210. (i32 (bitconvert (f32 FPR32Op:$val)))),
  211. (STRSroW FPR32Op:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>;
  212. def : Pat<(relaxed_store<atomic_store_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
  213. ro_Xextend32:$extend),
  214. (i32 (bitconvert (f32 FPR32Op:$val)))),
  215. (STRSroX FPR32Op:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>;
  216. def : Pat<(relaxed_store<atomic_store_32>
  217. (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset), (i32 (bitconvert (f32 FPR32Op:$val)))),
  218. (STRSui FPR32Op:$val, GPR64sp:$Rn, uimm12s4:$offset)>;
  219. def : Pat<(relaxed_store<atomic_store_32>
  220. (am_unscaled32 GPR64sp:$Rn, simm9:$offset), (i32 (bitconvert (f32 FPR32Op:$val)))),
  221. (STURSi FPR32Op:$val, GPR64sp:$Rn, simm9:$offset)>;
  222. // FP 64-bit stores
  223. def : Pat<(relaxed_store<atomic_store_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
  224. ro_Wextend64:$extend),
  225. (i64 (bitconvert (f64 FPR64Op:$val)))),
  226. (STRDroW FPR64Op:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>;
  227. def : Pat<(relaxed_store<atomic_store_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
  228. ro_Xextend64:$extend),
  229. (i64 (bitconvert (f64 FPR64Op:$val)))),
  230. (STRDroX FPR64Op:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>;
  231. def : Pat<(relaxed_store<atomic_store_64>
  232. (am_indexed64 GPR64sp:$Rn, uimm12s4:$offset), (i64 (bitconvert (f64 FPR64Op:$val)))),
  233. (STRDui FPR64Op:$val, GPR64sp:$Rn, uimm12s4:$offset)>;
  234. def : Pat<(relaxed_store<atomic_store_64>
  235. (am_unscaled64 GPR64sp:$Rn, simm9:$offset), (i64 (bitconvert (f64 FPR64Op:$val)))),
  236. (STURDi FPR64Op:$val, GPR64sp:$Rn, simm9:$offset)>;
  237. //===----------------------------------
  238. // Low-level exclusive operations
  239. //===----------------------------------
  240. // Load-exclusives.
  241. def ldxr_1 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{
  242. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
  243. }]> {
  244. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 1); }];
  245. }
  246. def ldxr_2 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{
  247. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
  248. }]> {
  249. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 2); }];
  250. }
  251. def ldxr_4 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{
  252. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
  253. }]> {
  254. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 4); }];
  255. }
  256. def ldxr_8 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{
  257. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
  258. }]> {
  259. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 8); }];
  260. }
  261. def : Pat<(ldxr_1 GPR64sp:$addr),
  262. (SUBREG_TO_REG (i64 0), (LDXRB GPR64sp:$addr), sub_32)>;
  263. def : Pat<(ldxr_2 GPR64sp:$addr),
  264. (SUBREG_TO_REG (i64 0), (LDXRH GPR64sp:$addr), sub_32)>;
  265. def : Pat<(ldxr_4 GPR64sp:$addr),
  266. (SUBREG_TO_REG (i64 0), (LDXRW GPR64sp:$addr), sub_32)>;
  267. def : Pat<(ldxr_8 GPR64sp:$addr), (LDXRX GPR64sp:$addr)>;
  268. def : Pat<(and (ldxr_1 GPR64sp:$addr), 0xff),
  269. (SUBREG_TO_REG (i64 0), (LDXRB GPR64sp:$addr), sub_32)>;
  270. def : Pat<(and (ldxr_2 GPR64sp:$addr), 0xffff),
  271. (SUBREG_TO_REG (i64 0), (LDXRH GPR64sp:$addr), sub_32)>;
  272. def : Pat<(and (ldxr_4 GPR64sp:$addr), 0xffffffff),
  273. (SUBREG_TO_REG (i64 0), (LDXRW GPR64sp:$addr), sub_32)>;
  274. // Load-exclusives.
  275. def ldaxr_1 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{
  276. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
  277. }]> {
  278. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 1); }];
  279. }
  280. def ldaxr_2 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{
  281. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
  282. }]> {
  283. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 2); }];
  284. }
  285. def ldaxr_4 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{
  286. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
  287. }]> {
  288. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 4); }];
  289. }
  290. def ldaxr_8 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{
  291. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
  292. }]> {
  293. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 8); }];
  294. }
  295. def : Pat<(ldaxr_1 GPR64sp:$addr),
  296. (SUBREG_TO_REG (i64 0), (LDAXRB GPR64sp:$addr), sub_32)>;
  297. def : Pat<(ldaxr_2 GPR64sp:$addr),
  298. (SUBREG_TO_REG (i64 0), (LDAXRH GPR64sp:$addr), sub_32)>;
  299. def : Pat<(ldaxr_4 GPR64sp:$addr),
  300. (SUBREG_TO_REG (i64 0), (LDAXRW GPR64sp:$addr), sub_32)>;
  301. def : Pat<(ldaxr_8 GPR64sp:$addr), (LDAXRX GPR64sp:$addr)>;
  302. def : Pat<(and (ldaxr_1 GPR64sp:$addr), 0xff),
  303. (SUBREG_TO_REG (i64 0), (LDAXRB GPR64sp:$addr), sub_32)>;
  304. def : Pat<(and (ldaxr_2 GPR64sp:$addr), 0xffff),
  305. (SUBREG_TO_REG (i64 0), (LDAXRH GPR64sp:$addr), sub_32)>;
  306. def : Pat<(and (ldaxr_4 GPR64sp:$addr), 0xffffffff),
  307. (SUBREG_TO_REG (i64 0), (LDAXRW GPR64sp:$addr), sub_32)>;
  308. // Store-exclusives.
  309. def stxr_1 : PatFrag<(ops node:$val, node:$ptr),
  310. (int_aarch64_stxr node:$val, node:$ptr), [{
  311. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
  312. }]> {
  313. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 1); }];
  314. }
  315. def stxr_2 : PatFrag<(ops node:$val, node:$ptr),
  316. (int_aarch64_stxr node:$val, node:$ptr), [{
  317. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
  318. }]> {
  319. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 2); }];
  320. }
  321. def stxr_4 : PatFrag<(ops node:$val, node:$ptr),
  322. (int_aarch64_stxr node:$val, node:$ptr), [{
  323. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
  324. }]> {
  325. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 4); }];
  326. }
  327. def stxr_8 : PatFrag<(ops node:$val, node:$ptr),
  328. (int_aarch64_stxr node:$val, node:$ptr), [{
  329. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
  330. }]> {
  331. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 8); }];
  332. }
  333. def : Pat<(stxr_1 GPR64:$val, GPR64sp:$addr),
  334. (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  335. def : Pat<(stxr_2 GPR64:$val, GPR64sp:$addr),
  336. (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  337. def : Pat<(stxr_4 GPR64:$val, GPR64sp:$addr),
  338. (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  339. def : Pat<(stxr_8 GPR64:$val, GPR64sp:$addr),
  340. (STXRX GPR64:$val, GPR64sp:$addr)>;
  341. def : Pat<(stxr_1 (zext (and GPR32:$val, 0xff)), GPR64sp:$addr),
  342. (STXRB GPR32:$val, GPR64sp:$addr)>;
  343. def : Pat<(stxr_2 (zext (and GPR32:$val, 0xffff)), GPR64sp:$addr),
  344. (STXRH GPR32:$val, GPR64sp:$addr)>;
  345. def : Pat<(stxr_4 (zext GPR32:$val), GPR64sp:$addr),
  346. (STXRW GPR32:$val, GPR64sp:$addr)>;
  347. def : Pat<(stxr_1 (and GPR64:$val, 0xff), GPR64sp:$addr),
  348. (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  349. def : Pat<(stxr_2 (and GPR64:$val, 0xffff), GPR64sp:$addr),
  350. (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  351. def : Pat<(stxr_4 (and GPR64:$val, 0xffffffff), GPR64sp:$addr),
  352. (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  353. // Store-release-exclusives.
  354. def stlxr_1 : PatFrag<(ops node:$val, node:$ptr),
  355. (int_aarch64_stlxr node:$val, node:$ptr), [{
  356. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
  357. }]> {
  358. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 1); }];
  359. }
  360. def stlxr_2 : PatFrag<(ops node:$val, node:$ptr),
  361. (int_aarch64_stlxr node:$val, node:$ptr), [{
  362. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
  363. }]> {
  364. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 2); }];
  365. }
  366. def stlxr_4 : PatFrag<(ops node:$val, node:$ptr),
  367. (int_aarch64_stlxr node:$val, node:$ptr), [{
  368. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
  369. }]> {
  370. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 4); }];
  371. }
  372. def stlxr_8 : PatFrag<(ops node:$val, node:$ptr),
  373. (int_aarch64_stlxr node:$val, node:$ptr), [{
  374. return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
  375. }]> {
  376. let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 8); }];
  377. }
  378. def : Pat<(stlxr_1 GPR64:$val, GPR64sp:$addr),
  379. (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  380. def : Pat<(stlxr_2 GPR64:$val, GPR64sp:$addr),
  381. (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  382. def : Pat<(stlxr_4 GPR64:$val, GPR64sp:$addr),
  383. (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  384. def : Pat<(stlxr_8 GPR64:$val, GPR64sp:$addr),
  385. (STLXRX GPR64:$val, GPR64sp:$addr)>;
  386. def : Pat<(stlxr_1 (zext (and GPR32:$val, 0xff)), GPR64sp:$addr),
  387. (STLXRB GPR32:$val, GPR64sp:$addr)>;
  388. def : Pat<(stlxr_2 (zext (and GPR32:$val, 0xffff)), GPR64sp:$addr),
  389. (STLXRH GPR32:$val, GPR64sp:$addr)>;
  390. def : Pat<(stlxr_4 (zext GPR32:$val), GPR64sp:$addr),
  391. (STLXRW GPR32:$val, GPR64sp:$addr)>;
  392. def : Pat<(stlxr_1 (and GPR64:$val, 0xff), GPR64sp:$addr),
  393. (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  394. def : Pat<(stlxr_2 (and GPR64:$val, 0xffff), GPR64sp:$addr),
  395. (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  396. def : Pat<(stlxr_4 (and GPR64:$val, 0xffffffff), GPR64sp:$addr),
  397. (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
  398. // And clear exclusive.
  399. def : Pat<(int_aarch64_clrex), (CLREX 0xf)>;
  400. //===----------------------------------
  401. // Atomic cmpxchg for -O0
  402. //===----------------------------------
  403. // The fast register allocator used during -O0 inserts spills to cover any VRegs
  404. // live across basic block boundaries. When this happens between an LDXR and an
  405. // STXR it can clear the exclusive monitor, causing all cmpxchg attempts to
  406. // fail.
  407. // Unfortunately, this means we have to have an alternative (expanded
  408. // post-regalloc) path for -O0 compilations. Fortunately this path can be
  409. // significantly more naive than the standard expansion: we conservatively
  410. // assume seq_cst, strong cmpxchg and omit clrex on failure.
  411. let Constraints = "@earlyclobber $Rd,@earlyclobber $scratch",
  412. mayLoad = 1, mayStore = 1 in {
  413. def CMP_SWAP_8 : Pseudo<(outs GPR32:$Rd, GPR32:$scratch),
  414. (ins GPR64:$addr, GPR32:$desired, GPR32:$new), []>,
  415. Sched<[WriteAtomic]>;
  416. def CMP_SWAP_16 : Pseudo<(outs GPR32:$Rd, GPR32:$scratch),
  417. (ins GPR64:$addr, GPR32:$desired, GPR32:$new), []>,
  418. Sched<[WriteAtomic]>;
  419. def CMP_SWAP_32 : Pseudo<(outs GPR32:$Rd, GPR32:$scratch),
  420. (ins GPR64:$addr, GPR32:$desired, GPR32:$new), []>,
  421. Sched<[WriteAtomic]>;
  422. def CMP_SWAP_64 : Pseudo<(outs GPR64:$Rd, GPR32:$scratch),
  423. (ins GPR64:$addr, GPR64:$desired, GPR64:$new), []>,
  424. Sched<[WriteAtomic]>;
  425. }
  426. let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi,@earlyclobber $scratch",
  427. mayLoad = 1, mayStore = 1 in {
  428. class cmp_swap_128 : Pseudo<(outs GPR64:$RdLo, GPR64:$RdHi, GPR32common:$scratch),
  429. (ins GPR64:$addr, GPR64:$desiredLo, GPR64:$desiredHi,
  430. GPR64:$newLo, GPR64:$newHi), []>,
  431. Sched<[WriteAtomic]>;
  432. def CMP_SWAP_128 : cmp_swap_128;
  433. def CMP_SWAP_128_RELEASE : cmp_swap_128;
  434. def CMP_SWAP_128_ACQUIRE : cmp_swap_128;
  435. def CMP_SWAP_128_MONOTONIC : cmp_swap_128;
  436. }
  437. // v8.1 Atomic instructions:
  438. let Predicates = [HasLSE] in {
  439. defm : LDOPregister_patterns<"LDADD", "atomic_load_add">;
  440. defm : LDOPregister_patterns<"LDSET", "atomic_load_or">;
  441. defm : LDOPregister_patterns<"LDEOR", "atomic_load_xor">;
  442. defm : LDOPregister_patterns<"LDCLR", "atomic_load_clr">;
  443. defm : LDOPregister_patterns<"LDSMAX", "atomic_load_max">;
  444. defm : LDOPregister_patterns<"LDSMIN", "atomic_load_min">;
  445. defm : LDOPregister_patterns<"LDUMAX", "atomic_load_umax">;
  446. defm : LDOPregister_patterns<"LDUMIN", "atomic_load_umin">;
  447. defm : LDOPregister_patterns<"SWP", "atomic_swap">;
  448. defm : CASregister_patterns<"CAS", "atomic_cmp_swap">;
  449. // These two patterns are only needed for global isel, selection dag isel
  450. // converts atomic load-sub into a sub and atomic load-add, and likewise for
  451. // and -> clr.
  452. defm : LDOPregister_patterns_mod<"LDADD", "atomic_load_sub", "SUB">;
  453. defm : LDOPregister_patterns_mod<"LDCLR", "atomic_load_and", "ORN">;
  454. }