AArch64InstrAtomics.td 25 KB

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