AtomicOrdering.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// Atomic ordering constants.
  16. ///
  17. /// These values are used by LLVM to represent atomic ordering for C++11's
  18. /// memory model and more, as detailed in docs/Atomics.rst.
  19. ///
  20. //===----------------------------------------------------------------------===//
  21. #ifndef LLVM_SUPPORT_ATOMICORDERING_H
  22. #define LLVM_SUPPORT_ATOMICORDERING_H
  23. #include <cstddef>
  24. namespace llvm {
  25. /// Atomic ordering for C11 / C++11's memory models.
  26. ///
  27. /// These values cannot change because they are shared with standard library
  28. /// implementations as well as with other compilers.
  29. enum class AtomicOrderingCABI {
  30. relaxed = 0,
  31. consume = 1,
  32. acquire = 2,
  33. release = 3,
  34. acq_rel = 4,
  35. seq_cst = 5,
  36. };
  37. bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
  38. bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
  39. bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
  40. bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
  41. // Validate an integral value which isn't known to fit within the enum's range
  42. // is a valid AtomicOrderingCABI.
  43. template <typename Int> inline bool isValidAtomicOrderingCABI(Int I) {
  44. return (Int)AtomicOrderingCABI::relaxed <= I &&
  45. I <= (Int)AtomicOrderingCABI::seq_cst;
  46. }
  47. /// Atomic ordering for LLVM's memory model.
  48. ///
  49. /// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and
  50. /// Unordered, which are both below the C++ orders.
  51. ///
  52. /// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
  53. /// \-->consume-->acquire--/
  54. enum class AtomicOrdering : unsigned {
  55. NotAtomic = 0,
  56. Unordered = 1,
  57. Monotonic = 2, // Equivalent to C++'s relaxed.
  58. // Consume = 3, // Not specified yet.
  59. Acquire = 4,
  60. Release = 5,
  61. AcquireRelease = 6,
  62. SequentiallyConsistent = 7,
  63. LAST = SequentiallyConsistent
  64. };
  65. bool operator<(AtomicOrdering, AtomicOrdering) = delete;
  66. bool operator>(AtomicOrdering, AtomicOrdering) = delete;
  67. bool operator<=(AtomicOrdering, AtomicOrdering) = delete;
  68. bool operator>=(AtomicOrdering, AtomicOrdering) = delete;
  69. // Validate an integral value which isn't known to fit within the enum's range
  70. // is a valid AtomicOrdering.
  71. template <typename Int> inline bool isValidAtomicOrdering(Int I) {
  72. return static_cast<Int>(AtomicOrdering::NotAtomic) <= I &&
  73. I <= static_cast<Int>(AtomicOrdering::SequentiallyConsistent);
  74. }
  75. /// String used by LLVM IR to represent atomic ordering.
  76. inline const char *toIRString(AtomicOrdering ao) {
  77. static const char *names[8] = {"not_atomic", "unordered", "monotonic",
  78. "consume", "acquire", "release",
  79. "acq_rel", "seq_cst"};
  80. return names[static_cast<size_t>(ao)];
  81. }
  82. /// Returns true if ao is stronger than other as defined by the AtomicOrdering
  83. /// lattice, which is based on C++'s definition.
  84. inline bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other) {
  85. static const bool lookup[8][8] = {
  86. // NA UN RX CO AC RE AR SC
  87. /* NotAtomic */ {false, false, false, false, false, false, false, false},
  88. /* Unordered */ { true, false, false, false, false, false, false, false},
  89. /* relaxed */ { true, true, false, false, false, false, false, false},
  90. /* consume */ { true, true, true, false, false, false, false, false},
  91. /* acquire */ { true, true, true, true, false, false, false, false},
  92. /* release */ { true, true, true, false, false, false, false, false},
  93. /* acq_rel */ { true, true, true, true, true, true, false, false},
  94. /* seq_cst */ { true, true, true, true, true, true, true, false},
  95. };
  96. return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)];
  97. }
  98. inline bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other) {
  99. static const bool lookup[8][8] = {
  100. // NA UN RX CO AC RE AR SC
  101. /* NotAtomic */ { true, false, false, false, false, false, false, false},
  102. /* Unordered */ { true, true, false, false, false, false, false, false},
  103. /* relaxed */ { true, true, true, false, false, false, false, false},
  104. /* consume */ { true, true, true, true, false, false, false, false},
  105. /* acquire */ { true, true, true, true, true, false, false, false},
  106. /* release */ { true, true, true, false, false, true, false, false},
  107. /* acq_rel */ { true, true, true, true, true, true, true, false},
  108. /* seq_cst */ { true, true, true, true, true, true, true, true},
  109. };
  110. return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)];
  111. }
  112. inline bool isStrongerThanUnordered(AtomicOrdering AO) {
  113. return isStrongerThan(AO, AtomicOrdering::Unordered);
  114. }
  115. inline bool isStrongerThanMonotonic(AtomicOrdering AO) {
  116. return isStrongerThan(AO, AtomicOrdering::Monotonic);
  117. }
  118. inline bool isAcquireOrStronger(AtomicOrdering AO) {
  119. return isAtLeastOrStrongerThan(AO, AtomicOrdering::Acquire);
  120. }
  121. inline bool isReleaseOrStronger(AtomicOrdering AO) {
  122. return isAtLeastOrStrongerThan(AO, AtomicOrdering::Release);
  123. }
  124. /// Return a single atomic ordering that is at least as strong as both the \p AO
  125. /// and \p Other orderings for an atomic operation.
  126. inline AtomicOrdering getMergedAtomicOrdering(AtomicOrdering AO,
  127. AtomicOrdering Other) {
  128. if ((AO == AtomicOrdering::Acquire && Other == AtomicOrdering::Release) ||
  129. (AO == AtomicOrdering::Release && Other == AtomicOrdering::Acquire))
  130. return AtomicOrdering::AcquireRelease;
  131. return isStrongerThan(AO, Other) ? AO : Other;
  132. }
  133. inline AtomicOrderingCABI toCABI(AtomicOrdering AO) {
  134. static const AtomicOrderingCABI lookup[8] = {
  135. /* NotAtomic */ AtomicOrderingCABI::relaxed,
  136. /* Unordered */ AtomicOrderingCABI::relaxed,
  137. /* relaxed */ AtomicOrderingCABI::relaxed,
  138. /* consume */ AtomicOrderingCABI::consume,
  139. /* acquire */ AtomicOrderingCABI::acquire,
  140. /* release */ AtomicOrderingCABI::release,
  141. /* acq_rel */ AtomicOrderingCABI::acq_rel,
  142. /* seq_cst */ AtomicOrderingCABI::seq_cst,
  143. };
  144. return lookup[static_cast<size_t>(AO)];
  145. }
  146. } // end namespace llvm
  147. #endif // LLVM_SUPPORT_ATOMICORDERING_H
  148. #ifdef __GNUC__
  149. #pragma GCC diagnostic pop
  150. #endif