18bcb0991SDimitry Andric //===-- llvm/Support/Alignment.h - Useful alignment functions ---*- C++ -*-===//
28bcb0991SDimitry Andric //
38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68bcb0991SDimitry Andric //
78bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
88bcb0991SDimitry Andric //
98bcb0991SDimitry Andric // This file contains types to represent alignments.
108bcb0991SDimitry Andric // They are instrumented to guarantee some invariants are preserved and prevent
118bcb0991SDimitry Andric // invalid manipulations.
128bcb0991SDimitry Andric //
138bcb0991SDimitry Andric // - Align represents an alignment in bytes, it is always set and always a valid
148bcb0991SDimitry Andric // power of two, its minimum value is 1 which means no alignment requirements.
158bcb0991SDimitry Andric //
168bcb0991SDimitry Andric // - MaybeAlign is an optional type, it may be undefined or set. When it's set
178bcb0991SDimitry Andric // you can get the underlying Align type by using the getValue() method.
188bcb0991SDimitry Andric //
198bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
208bcb0991SDimitry Andric 
218bcb0991SDimitry Andric #ifndef LLVM_SUPPORT_ALIGNMENT_H_
228bcb0991SDimitry Andric #define LLVM_SUPPORT_ALIGNMENT_H_
238bcb0991SDimitry Andric 
248bcb0991SDimitry Andric #include "llvm/Support/MathExtras.h"
258bcb0991SDimitry Andric #include <cassert>
26bdd1243dSDimitry Andric #include <optional>
275ffd83dbSDimitry Andric #ifndef NDEBUG
285ffd83dbSDimitry Andric #include <string>
295ffd83dbSDimitry Andric #endif // NDEBUG
308bcb0991SDimitry Andric 
318bcb0991SDimitry Andric namespace llvm {
328bcb0991SDimitry Andric 
338bcb0991SDimitry Andric #define ALIGN_CHECK_ISPOSITIVE(decl)                                           \
348bcb0991SDimitry Andric   assert(decl > 0 && (#decl " should be defined"))
358bcb0991SDimitry Andric 
368bcb0991SDimitry Andric /// This struct is a compact representation of a valid (non-zero power of two)
378bcb0991SDimitry Andric /// alignment.
388bcb0991SDimitry Andric /// It is suitable for use as static global constants.
398bcb0991SDimitry Andric struct Align {
408bcb0991SDimitry Andric private:
418bcb0991SDimitry Andric   uint8_t ShiftValue = 0; /// The log2 of the required alignment.
428bcb0991SDimitry Andric                           /// ShiftValue is less than 64 by construction.
438bcb0991SDimitry Andric 
448bcb0991SDimitry Andric   friend struct MaybeAlign;
458bcb0991SDimitry Andric   friend unsigned Log2(Align);
468bcb0991SDimitry Andric   friend bool operator==(Align Lhs, Align Rhs);
478bcb0991SDimitry Andric   friend bool operator!=(Align Lhs, Align Rhs);
488bcb0991SDimitry Andric   friend bool operator<=(Align Lhs, Align Rhs);
498bcb0991SDimitry Andric   friend bool operator>=(Align Lhs, Align Rhs);
508bcb0991SDimitry Andric   friend bool operator<(Align Lhs, Align Rhs);
518bcb0991SDimitry Andric   friend bool operator>(Align Lhs, Align Rhs);
528bcb0991SDimitry Andric   friend unsigned encode(struct MaybeAlign A);
538bcb0991SDimitry Andric   friend struct MaybeAlign decodeMaybeAlign(unsigned Value);
548bcb0991SDimitry Andric 
558bcb0991SDimitry Andric   /// A trivial type to allow construction of constexpr Align.
568bcb0991SDimitry Andric   /// This is currently needed to workaround a bug in GCC 5.3 which prevents
578bcb0991SDimitry Andric   /// definition of constexpr assign operators.
588bcb0991SDimitry Andric   /// https://stackoverflow.com/questions/46756288/explicitly-defaulted-function-cannot-be-declared-as-constexpr-because-the-implic
598bcb0991SDimitry Andric   /// FIXME: Remove this, make all assign operators constexpr and introduce user
608bcb0991SDimitry Andric   /// defined literals when we don't have to support GCC 5.3 anymore.
618bcb0991SDimitry Andric   /// https://llvm.org/docs/GettingStarted.html#getting-a-modern-host-c-toolchain
628bcb0991SDimitry Andric   struct LogValue {
638bcb0991SDimitry Andric     uint8_t Log;
648bcb0991SDimitry Andric   };
658bcb0991SDimitry Andric 
668bcb0991SDimitry Andric public:
678bcb0991SDimitry Andric   /// Default is byte-aligned.
688bcb0991SDimitry Andric   constexpr Align() = default;
698bcb0991SDimitry Andric   /// Do not perform checks in case of copy/move construct/assign, because the
708bcb0991SDimitry Andric   /// checks have been performed when building `Other`.
718bcb0991SDimitry Andric   constexpr Align(const Align &Other) = default;
728bcb0991SDimitry Andric   constexpr Align(Align &&Other) = default;
738bcb0991SDimitry Andric   Align &operator=(const Align &Other) = default;
748bcb0991SDimitry Andric   Align &operator=(Align &&Other) = default;
758bcb0991SDimitry Andric 
AlignAlign768bcb0991SDimitry Andric   explicit Align(uint64_t Value) {
778bcb0991SDimitry Andric     assert(Value > 0 && "Value must not be 0");
788bcb0991SDimitry Andric     assert(llvm::isPowerOf2_64(Value) && "Alignment is not a power of 2");
798bcb0991SDimitry Andric     ShiftValue = Log2_64(Value);
808bcb0991SDimitry Andric     assert(ShiftValue < 64 && "Broken invariant");
818bcb0991SDimitry Andric   }
828bcb0991SDimitry Andric 
838bcb0991SDimitry Andric   /// This is a hole in the type system and should not be abused.
848bcb0991SDimitry Andric   /// Needed to interact with C for instance.
valueAlign858bcb0991SDimitry Andric   uint64_t value() const { return uint64_t(1) << ShiftValue; }
868bcb0991SDimitry Andric 
8781ad6265SDimitry Andric   // Returns the previous alignment.
previousAlign8881ad6265SDimitry Andric   Align previous() const {
8981ad6265SDimitry Andric     assert(ShiftValue != 0 && "Undefined operation");
9081ad6265SDimitry Andric     Align Out;
9181ad6265SDimitry Andric     Out.ShiftValue = ShiftValue - 1;
9281ad6265SDimitry Andric     return Out;
9381ad6265SDimitry Andric   }
9481ad6265SDimitry Andric 
958bcb0991SDimitry Andric   /// Allow constructions of constexpr Align.
ConstantAlign96bdd1243dSDimitry Andric   template <size_t kValue> constexpr static Align Constant() {
978bcb0991SDimitry Andric     return LogValue{static_cast<uint8_t>(CTLog2<kValue>())};
988bcb0991SDimitry Andric   }
998bcb0991SDimitry Andric 
1008bcb0991SDimitry Andric   /// Allow constructions of constexpr Align from types.
1018bcb0991SDimitry Andric   /// Compile time equivalent to Align(alignof(T)).
OfAlign102bdd1243dSDimitry Andric   template <typename T> constexpr static Align Of() {
103*06c3fb27SDimitry Andric     return Constant<std::alignment_of_v<T>>();
1048bcb0991SDimitry Andric   }
1058bcb0991SDimitry Andric 
1068bcb0991SDimitry Andric   /// Constexpr constructor from LogValue type.
AlignAlign1078bcb0991SDimitry Andric   constexpr Align(LogValue CA) : ShiftValue(CA.Log) {}
1088bcb0991SDimitry Andric };
1098bcb0991SDimitry Andric 
1108bcb0991SDimitry Andric /// Treats the value 0 as a 1, so Align is always at least 1.
assumeAligned(uint64_t Value)1118bcb0991SDimitry Andric inline Align assumeAligned(uint64_t Value) {
1128bcb0991SDimitry Andric   return Value ? Align(Value) : Align();
1138bcb0991SDimitry Andric }
1148bcb0991SDimitry Andric 
1158bcb0991SDimitry Andric /// This struct is a compact representation of a valid (power of two) or
1168bcb0991SDimitry Andric /// undefined (0) alignment.
117bdd1243dSDimitry Andric struct MaybeAlign : public std::optional<Align> {
1188bcb0991SDimitry Andric private:
119bdd1243dSDimitry Andric   using UP = std::optional<Align>;
1208bcb0991SDimitry Andric 
1218bcb0991SDimitry Andric public:
1228bcb0991SDimitry Andric   /// Default is undefined.
1238bcb0991SDimitry Andric   MaybeAlign() = default;
1248bcb0991SDimitry Andric   /// Do not perform checks in case of copy/move construct/assign, because the
1258bcb0991SDimitry Andric   /// checks have been performed when building `Other`.
1268bcb0991SDimitry Andric   MaybeAlign(const MaybeAlign &Other) = default;
1278bcb0991SDimitry Andric   MaybeAlign &operator=(const MaybeAlign &Other) = default;
1288bcb0991SDimitry Andric   MaybeAlign(MaybeAlign &&Other) = default;
1298bcb0991SDimitry Andric   MaybeAlign &operator=(MaybeAlign &&Other) = default;
1308bcb0991SDimitry Andric 
MaybeAlignMaybeAlign131bdd1243dSDimitry Andric   constexpr MaybeAlign(std::nullopt_t None) : UP(None) {}
MaybeAlignMaybeAlign132bdd1243dSDimitry Andric   constexpr MaybeAlign(Align Value) : UP(Value) {}
MaybeAlignMaybeAlign1338bcb0991SDimitry Andric   explicit MaybeAlign(uint64_t Value) {
1348bcb0991SDimitry Andric     assert((Value == 0 || llvm::isPowerOf2_64(Value)) &&
1358bcb0991SDimitry Andric            "Alignment is neither 0 nor a power of 2");
1368bcb0991SDimitry Andric     if (Value)
1378bcb0991SDimitry Andric       emplace(Value);
1388bcb0991SDimitry Andric   }
1398bcb0991SDimitry Andric 
1408bcb0991SDimitry Andric   /// For convenience, returns a valid alignment or 1 if undefined.
valueOrOneMaybeAlign14181ad6265SDimitry Andric   Align valueOrOne() const { return value_or(Align()); }
1428bcb0991SDimitry Andric };
1438bcb0991SDimitry Andric 
1448bcb0991SDimitry Andric /// Checks that SizeInBytes is a multiple of the alignment.
isAligned(Align Lhs,uint64_t SizeInBytes)1458bcb0991SDimitry Andric inline bool isAligned(Align Lhs, uint64_t SizeInBytes) {
1468bcb0991SDimitry Andric   return SizeInBytes % Lhs.value() == 0;
1478bcb0991SDimitry Andric }
1488bcb0991SDimitry Andric 
1498bcb0991SDimitry Andric /// Checks that Addr is a multiple of the alignment.
isAddrAligned(Align Lhs,const void * Addr)1508bcb0991SDimitry Andric inline bool isAddrAligned(Align Lhs, const void *Addr) {
1518bcb0991SDimitry Andric   return isAligned(Lhs, reinterpret_cast<uintptr_t>(Addr));
1528bcb0991SDimitry Andric }
1538bcb0991SDimitry Andric 
1548bcb0991SDimitry Andric /// Returns a multiple of A needed to store `Size` bytes.
alignTo(uint64_t Size,Align A)1558bcb0991SDimitry Andric inline uint64_t alignTo(uint64_t Size, Align A) {
1565ffd83dbSDimitry Andric   const uint64_t Value = A.value();
1575ffd83dbSDimitry Andric   // The following line is equivalent to `(Size + Value - 1) / Value * Value`.
1588bcb0991SDimitry Andric 
1598bcb0991SDimitry Andric   // The division followed by a multiplication can be thought of as a right
1608bcb0991SDimitry Andric   // shift followed by a left shift which zeros out the extra bits produced in
1615ffd83dbSDimitry Andric   // the bump; `~(Value - 1)` is a mask where all those bits being zeroed out
1628bcb0991SDimitry Andric   // are just zero.
1638bcb0991SDimitry Andric 
1648bcb0991SDimitry Andric   // Most compilers can generate this code but the pattern may be missed when
1658bcb0991SDimitry Andric   // multiple functions gets inlined.
1665ffd83dbSDimitry Andric   return (Size + Value - 1) & ~(Value - 1U);
1675ffd83dbSDimitry Andric }
1685ffd83dbSDimitry Andric 
1695ffd83dbSDimitry Andric /// If non-zero \p Skew is specified, the return value will be a minimal integer
1705ffd83dbSDimitry Andric /// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
1715ffd83dbSDimitry Andric /// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
1725ffd83dbSDimitry Andric /// Skew mod \p A'.
1735ffd83dbSDimitry Andric ///
1745ffd83dbSDimitry Andric /// Examples:
1755ffd83dbSDimitry Andric /// \code
1765ffd83dbSDimitry Andric ///   alignTo(5, Align(8), 7) = 7
1775ffd83dbSDimitry Andric ///   alignTo(17, Align(8), 1) = 17
1785ffd83dbSDimitry Andric ///   alignTo(~0LL, Align(8), 3) = 3
1795ffd83dbSDimitry Andric /// \endcode
alignTo(uint64_t Size,Align A,uint64_t Skew)1805ffd83dbSDimitry Andric inline uint64_t alignTo(uint64_t Size, Align A, uint64_t Skew) {
1815ffd83dbSDimitry Andric   const uint64_t Value = A.value();
1825ffd83dbSDimitry Andric   Skew %= Value;
18381ad6265SDimitry Andric   return alignTo(Size - Skew, A) + Skew;
1848bcb0991SDimitry Andric }
1858bcb0991SDimitry Andric 
1868bcb0991SDimitry Andric /// Aligns `Addr` to `Alignment` bytes, rounding up.
alignAddr(const void * Addr,Align Alignment)1878bcb0991SDimitry Andric inline uintptr_t alignAddr(const void *Addr, Align Alignment) {
1888bcb0991SDimitry Andric   uintptr_t ArithAddr = reinterpret_cast<uintptr_t>(Addr);
1898bcb0991SDimitry Andric   assert(static_cast<uintptr_t>(ArithAddr + Alignment.value() - 1) >=
1905ffd83dbSDimitry Andric              ArithAddr &&
1915ffd83dbSDimitry Andric          "Overflow");
1928bcb0991SDimitry Andric   return alignTo(ArithAddr, Alignment);
1938bcb0991SDimitry Andric }
1948bcb0991SDimitry Andric 
1958bcb0991SDimitry Andric /// Returns the offset to the next integer (mod 2**64) that is greater than
1968bcb0991SDimitry Andric /// or equal to \p Value and is a multiple of \p Align.
offsetToAlignment(uint64_t Value,Align Alignment)1978bcb0991SDimitry Andric inline uint64_t offsetToAlignment(uint64_t Value, Align Alignment) {
1988bcb0991SDimitry Andric   return alignTo(Value, Alignment) - Value;
1998bcb0991SDimitry Andric }
2008bcb0991SDimitry Andric 
2018bcb0991SDimitry Andric /// Returns the necessary adjustment for aligning `Addr` to `Alignment`
2028bcb0991SDimitry Andric /// bytes, rounding up.
offsetToAlignedAddr(const void * Addr,Align Alignment)2038bcb0991SDimitry Andric inline uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment) {
2048bcb0991SDimitry Andric   return offsetToAlignment(reinterpret_cast<uintptr_t>(Addr), Alignment);
2058bcb0991SDimitry Andric }
2068bcb0991SDimitry Andric 
2078bcb0991SDimitry Andric /// Returns the log2 of the alignment.
Log2(Align A)2088bcb0991SDimitry Andric inline unsigned Log2(Align A) { return A.ShiftValue; }
2098bcb0991SDimitry Andric 
2108bcb0991SDimitry Andric /// Returns the alignment that satisfies both alignments.
2118bcb0991SDimitry Andric /// Same semantic as MinAlign.
commonAlignment(Align A,uint64_t Offset)2128bcb0991SDimitry Andric inline Align commonAlignment(Align A, uint64_t Offset) {
2138bcb0991SDimitry Andric   return Align(MinAlign(A.value(), Offset));
2148bcb0991SDimitry Andric }
2158bcb0991SDimitry Andric 
2168bcb0991SDimitry Andric /// Returns a representation of the alignment that encodes undefined as 0.
encode(MaybeAlign A)2178bcb0991SDimitry Andric inline unsigned encode(MaybeAlign A) { return A ? A->ShiftValue + 1 : 0; }
2188bcb0991SDimitry Andric 
2198bcb0991SDimitry Andric /// Dual operation of the encode function above.
decodeMaybeAlign(unsigned Value)2208bcb0991SDimitry Andric inline MaybeAlign decodeMaybeAlign(unsigned Value) {
2218bcb0991SDimitry Andric   if (Value == 0)
2228bcb0991SDimitry Andric     return MaybeAlign();
2238bcb0991SDimitry Andric   Align Out;
2248bcb0991SDimitry Andric   Out.ShiftValue = Value - 1;
2258bcb0991SDimitry Andric   return Out;
2268bcb0991SDimitry Andric }
2278bcb0991SDimitry Andric 
2288bcb0991SDimitry Andric /// Returns a representation of the alignment, the encoded value is positive by
2298bcb0991SDimitry Andric /// definition.
encode(Align A)2308bcb0991SDimitry Andric inline unsigned encode(Align A) { return encode(MaybeAlign(A)); }
2318bcb0991SDimitry Andric 
2328bcb0991SDimitry Andric /// Comparisons between Align and scalars. Rhs must be positive.
2338bcb0991SDimitry Andric inline bool operator==(Align Lhs, uint64_t Rhs) {
2348bcb0991SDimitry Andric   ALIGN_CHECK_ISPOSITIVE(Rhs);
2358bcb0991SDimitry Andric   return Lhs.value() == Rhs;
2368bcb0991SDimitry Andric }
2378bcb0991SDimitry Andric inline bool operator!=(Align Lhs, uint64_t Rhs) {
2388bcb0991SDimitry Andric   ALIGN_CHECK_ISPOSITIVE(Rhs);
2398bcb0991SDimitry Andric   return Lhs.value() != Rhs;
2408bcb0991SDimitry Andric }
2418bcb0991SDimitry Andric inline bool operator<=(Align Lhs, uint64_t Rhs) {
2428bcb0991SDimitry Andric   ALIGN_CHECK_ISPOSITIVE(Rhs);
2438bcb0991SDimitry Andric   return Lhs.value() <= Rhs;
2448bcb0991SDimitry Andric }
2458bcb0991SDimitry Andric inline bool operator>=(Align Lhs, uint64_t Rhs) {
2468bcb0991SDimitry Andric   ALIGN_CHECK_ISPOSITIVE(Rhs);
2478bcb0991SDimitry Andric   return Lhs.value() >= Rhs;
2488bcb0991SDimitry Andric }
2498bcb0991SDimitry Andric inline bool operator<(Align Lhs, uint64_t Rhs) {
2508bcb0991SDimitry Andric   ALIGN_CHECK_ISPOSITIVE(Rhs);
2518bcb0991SDimitry Andric   return Lhs.value() < Rhs;
2528bcb0991SDimitry Andric }
2538bcb0991SDimitry Andric inline bool operator>(Align Lhs, uint64_t Rhs) {
2548bcb0991SDimitry Andric   ALIGN_CHECK_ISPOSITIVE(Rhs);
2558bcb0991SDimitry Andric   return Lhs.value() > Rhs;
2568bcb0991SDimitry Andric }
2578bcb0991SDimitry Andric 
2588bcb0991SDimitry Andric /// Comparisons operators between Align.
2598bcb0991SDimitry Andric inline bool operator==(Align Lhs, Align Rhs) {
2608bcb0991SDimitry Andric   return Lhs.ShiftValue == Rhs.ShiftValue;
2618bcb0991SDimitry Andric }
2628bcb0991SDimitry Andric inline bool operator!=(Align Lhs, Align Rhs) {
2638bcb0991SDimitry Andric   return Lhs.ShiftValue != Rhs.ShiftValue;
2648bcb0991SDimitry Andric }
2658bcb0991SDimitry Andric inline bool operator<=(Align Lhs, Align Rhs) {
2668bcb0991SDimitry Andric   return Lhs.ShiftValue <= Rhs.ShiftValue;
2678bcb0991SDimitry Andric }
2688bcb0991SDimitry Andric inline bool operator>=(Align Lhs, Align Rhs) {
2698bcb0991SDimitry Andric   return Lhs.ShiftValue >= Rhs.ShiftValue;
2708bcb0991SDimitry Andric }
2718bcb0991SDimitry Andric inline bool operator<(Align Lhs, Align Rhs) {
2728bcb0991SDimitry Andric   return Lhs.ShiftValue < Rhs.ShiftValue;
2738bcb0991SDimitry Andric }
2748bcb0991SDimitry Andric inline bool operator>(Align Lhs, Align Rhs) {
2758bcb0991SDimitry Andric   return Lhs.ShiftValue > Rhs.ShiftValue;
2768bcb0991SDimitry Andric }
2778bcb0991SDimitry Andric 
2785ffd83dbSDimitry Andric // Don't allow relational comparisons with MaybeAlign.
2795ffd83dbSDimitry Andric bool operator<=(Align Lhs, MaybeAlign Rhs) = delete;
2805ffd83dbSDimitry Andric bool operator>=(Align Lhs, MaybeAlign Rhs) = delete;
2815ffd83dbSDimitry Andric bool operator<(Align Lhs, MaybeAlign Rhs) = delete;
2825ffd83dbSDimitry Andric bool operator>(Align Lhs, MaybeAlign Rhs) = delete;
2835ffd83dbSDimitry Andric 
2845ffd83dbSDimitry Andric bool operator<=(MaybeAlign Lhs, Align Rhs) = delete;
2855ffd83dbSDimitry Andric bool operator>=(MaybeAlign Lhs, Align Rhs) = delete;
2865ffd83dbSDimitry Andric bool operator<(MaybeAlign Lhs, Align Rhs) = delete;
2875ffd83dbSDimitry Andric bool operator>(MaybeAlign Lhs, Align Rhs) = delete;
2885ffd83dbSDimitry Andric 
2895ffd83dbSDimitry Andric bool operator<=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
2905ffd83dbSDimitry Andric bool operator>=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
2915ffd83dbSDimitry Andric bool operator<(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
2925ffd83dbSDimitry Andric bool operator>(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
2935ffd83dbSDimitry Andric 
294bdd1243dSDimitry Andric // Allow equality comparisons between Align and MaybeAlign.
295bdd1243dSDimitry Andric inline bool operator==(MaybeAlign Lhs, Align Rhs) { return Lhs && *Lhs == Rhs; }
296bdd1243dSDimitry Andric inline bool operator!=(MaybeAlign Lhs, Align Rhs) { return !(Lhs == Rhs); }
297bdd1243dSDimitry Andric inline bool operator==(Align Lhs, MaybeAlign Rhs) { return Rhs == Lhs; }
298bdd1243dSDimitry Andric inline bool operator!=(Align Lhs, MaybeAlign Rhs) { return !(Rhs == Lhs); }
299bdd1243dSDimitry Andric // Allow equality comparisons with MaybeAlign.
300bdd1243dSDimitry Andric inline bool operator==(MaybeAlign Lhs, MaybeAlign Rhs) {
301bdd1243dSDimitry Andric   return (Lhs && Rhs && (*Lhs == *Rhs)) || (!Lhs && !Rhs);
302bdd1243dSDimitry Andric }
303bdd1243dSDimitry Andric inline bool operator!=(MaybeAlign Lhs, MaybeAlign Rhs) { return !(Lhs == Rhs); }
304bdd1243dSDimitry Andric // Allow equality comparisons with std::nullopt.
305bdd1243dSDimitry Andric inline bool operator==(MaybeAlign Lhs, std::nullopt_t) { return !bool(Lhs); }
306bdd1243dSDimitry Andric inline bool operator!=(MaybeAlign Lhs, std::nullopt_t) { return bool(Lhs); }
307bdd1243dSDimitry Andric inline bool operator==(std::nullopt_t, MaybeAlign Rhs) { return !bool(Rhs); }
308bdd1243dSDimitry Andric inline bool operator!=(std::nullopt_t, MaybeAlign Rhs) { return bool(Rhs); }
309bdd1243dSDimitry Andric 
3105ffd83dbSDimitry Andric #ifndef NDEBUG
3115ffd83dbSDimitry Andric // For usage in LLVM_DEBUG macros.
DebugStr(const Align & A)3125ffd83dbSDimitry Andric inline std::string DebugStr(const Align &A) {
3135ffd83dbSDimitry Andric   return std::to_string(A.value());
3145ffd83dbSDimitry Andric }
3155ffd83dbSDimitry Andric // For usage in LLVM_DEBUG macros.
DebugStr(const MaybeAlign & MA)3165ffd83dbSDimitry Andric inline std::string DebugStr(const MaybeAlign &MA) {
3175ffd83dbSDimitry Andric   if (MA)
3185ffd83dbSDimitry Andric     return std::to_string(MA->value());
3195ffd83dbSDimitry Andric   return "None";
3205ffd83dbSDimitry Andric }
3215ffd83dbSDimitry Andric #endif // NDEBUG
3225ffd83dbSDimitry Andric 
3238bcb0991SDimitry Andric #undef ALIGN_CHECK_ISPOSITIVE
3248bcb0991SDimitry Andric 
3258bcb0991SDimitry Andric } // namespace llvm
3268bcb0991SDimitry Andric 
3278bcb0991SDimitry Andric #endif // LLVM_SUPPORT_ALIGNMENT_H_
328