blob: f07a566b1c7954636d21f849a7e060b1b8efca9c [file] [log] [blame]
Jan Voung8acded02014-09-22 18:02:25 -07001//===- subzero/src/IceUtils.h - Utility functions ---------------*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// This file declares some utility functions.
12///
Jan Voung8acded02014-09-22 18:02:25 -070013//===----------------------------------------------------------------------===//
14
15#ifndef SUBZERO_SRC_ICEUTILS_H
16#define SUBZERO_SRC_ICEUTILS_H
John Porto67f8de92015-06-25 10:14:17 -070017
Jan Voung8acded02014-09-22 18:02:25 -070018#include <climits>
19
20namespace Ice {
21
Andrew Scull9612d322015-07-06 14:53:25 -070022/// Similar to bit_cast, but allows copying from types of unrelated
23/// sizes. This method was introduced to enable the strict aliasing
24/// optimizations of GCC 4.4. Basically, GCC mindlessly relies on
25/// obscure details in the C++ standard that make reinterpret_cast
26/// virtually useless.
Jan Voung8acded02014-09-22 18:02:25 -070027template <class D, class S> inline D bit_copy(const S &source) {
28 D destination;
29 // This use of memcpy is safe: source and destination cannot overlap.
30 memcpy(&destination, reinterpret_cast<const void *>(&source),
31 sizeof(destination));
32 return destination;
33}
34
35class Utils {
Jim Stichnothc6ead202015-02-24 09:30:30 -080036 Utils() = delete;
37 Utils(const Utils &) = delete;
38 Utils &operator=(const Utils &) = delete;
39
Jan Voung8acded02014-09-22 18:02:25 -070040public:
Andrew Scull9612d322015-07-06 14:53:25 -070041 /// Check whether an N-bit two's-complement representation can hold value.
Jan Voung8acded02014-09-22 18:02:25 -070042 template <typename T> static inline bool IsInt(int N, T value) {
43 assert((0 < N) &&
44 (static_cast<unsigned int>(N) < (CHAR_BIT * sizeof(value))));
45 T limit = static_cast<T>(1) << (N - 1);
46 return (-limit <= value) && (value < limit);
47 }
48
49 template <typename T> static inline bool IsUint(int N, T value) {
50 assert((0 < N) &&
51 (static_cast<unsigned int>(N) < (CHAR_BIT * sizeof(value))));
52 T limit = static_cast<T>(1) << N;
53 return (0 <= value) && (value < limit);
54 }
55
Andrew Scull9612d322015-07-06 14:53:25 -070056 /// Check whether the magnitude of value fits in N bits, i.e., whether an
57 /// (N+1)-bit sign-magnitude representation can hold value.
Jan Voungb2d50842015-05-12 09:53:50 -070058 template <typename T> static inline bool IsAbsoluteUint(int N, T Value) {
59 assert((0 < N) &&
60 (static_cast<unsigned int>(N) < (CHAR_BIT * sizeof(Value))));
61 if (Value < 0)
62 Value = -Value;
63 return IsUint(N, Value);
64 }
65
Andrew Scull9612d322015-07-06 14:53:25 -070066 /// Return true if the addition X + Y will cause integer overflow for
67 /// integers of type T.
Jan Voung8acded02014-09-22 18:02:25 -070068 template <typename T> static inline bool WouldOverflowAdd(T X, T Y) {
69 return ((X > 0 && Y > 0 && (X > std::numeric_limits<T>::max() - Y)) ||
70 (X < 0 && Y < 0 && (X < std::numeric_limits<T>::min() - Y)));
71 }
Jan Voung72984d82015-01-29 14:42:38 -080072
Andrew Scullaa6c1092015-09-03 17:50:30 -070073 /// Adds x to y and stores the result in sum. Returns true if the addition
74 /// overflowed.
75 static inline bool add_overflow(uint32_t x, uint32_t y, uint32_t *sum) {
76 static_assert(std::is_same<uint32_t, unsigned>::value, "Must match type");
77#if __has_builtin(__builtin_uadd_overflow)
78 return __builtin_uadd_overflow(x, y, sum);
79#else
80 *sum = x + y;
81 return WouldOverflowAdd(x, y);
82#endif
83 }
84
Andrew Scull9612d322015-07-06 14:53:25 -070085 /// Return true if X is already aligned by N, where N is a power of 2.
Jan Voungb2d50842015-05-12 09:53:50 -070086 template <typename T> static inline bool IsAligned(T X, intptr_t N) {
87 assert(llvm::isPowerOf2_64(N));
88 return (X & (N - 1)) == 0;
89 }
90
Andrew Scull9612d322015-07-06 14:53:25 -070091 /// Return Value adjusted to the next highest multiple of Alignment.
Jan Voung55500db2015-05-26 14:25:40 -070092 static inline uint32_t applyAlignment(uint32_t Value, uint32_t Alignment) {
93 assert(llvm::isPowerOf2_32(Alignment));
94 return (Value + Alignment - 1) & -Alignment;
95 }
96
Andrew Scull9612d322015-07-06 14:53:25 -070097 /// Return amount which must be added to adjust Pos to the next highest
98 /// multiple of Align.
Jan Voung72984d82015-01-29 14:42:38 -080099 static inline uint64_t OffsetToAlignment(uint64_t Pos, uint64_t Align) {
100 assert(llvm::isPowerOf2_64(Align));
101 uint64_t Mod = Pos & (Align - 1);
102 if (Mod == 0)
103 return 0;
104 return Align - Mod;
105 }
Jan Voungb3401d22015-05-18 09:38:21 -0700106
Andrew Scull9612d322015-07-06 14:53:25 -0700107 /// Rotate the value bit pattern to the left by shift bits.
108 /// Precondition: 0 <= shift < 32
Jan Voungb3401d22015-05-18 09:38:21 -0700109 static inline uint32_t rotateLeft32(uint32_t value, uint32_t shift) {
110 if (shift == 0)
111 return value;
112 return (value << shift) | (value >> (32 - shift));
113 }
114
Andrew Scull9612d322015-07-06 14:53:25 -0700115 /// Rotate the value bit pattern to the right by shift bits.
Jan Voungb3401d22015-05-18 09:38:21 -0700116 static inline uint32_t rotateRight32(uint32_t value, uint32_t shift) {
117 if (shift == 0)
118 return value;
119 return (value >> shift) | (value << (32 - shift));
120 }
Jan Voung8acded02014-09-22 18:02:25 -0700121};
122
Jan Voung8acded02014-09-22 18:02:25 -0700123} // end of namespace Ice
124
125#endif // SUBZERO_SRC_ICEUTILS_H