@@ -35,21 +35,23 @@ namespace llvm {
35
35
// / We always_inline all operations; removing these results in a 1.5x
36
36
// / performance slowdown.
37
37
// /
38
- // / When HoldsLarge is true, a SlowMPInt is held in the union. If it is false,
39
- // / the int64_t is held. Using std::variant instead would lead to significantly
40
- // / worse performance.
38
+ // / When isLarge returns true, a SlowMPInt is held in the union. If isSmall
39
+ // / returns true, the int64_t is held. We don't have a separate field for
40
+ // / indicating this, and instead "steal" memory from ValLarge when it is not in
41
+ // / use because we know that the memory layout of APInt is such that BitWidth
42
+ // / doesn't overlap with ValSmall (see static_assert_layout). Using std::variant
43
+ // / instead would lead to significantly worse performance.
41
44
class DynamicAPInt {
42
45
union {
43
46
int64_t ValSmall;
44
47
detail::SlowDynamicAPInt ValLarge;
45
48
};
46
- unsigned HoldsLarge;
47
49
48
50
LLVM_ATTRIBUTE_ALWAYS_INLINE void initSmall (int64_t O) {
49
51
if (LLVM_UNLIKELY (isLarge ()))
50
52
ValLarge.detail ::SlowDynamicAPInt::~SlowDynamicAPInt ();
51
53
ValSmall = O;
52
- HoldsLarge = false ;
54
+ ValLarge. Val . BitWidth = 0 ;
53
55
}
54
56
LLVM_ATTRIBUTE_ALWAYS_INLINE void
55
57
initLarge (const detail::SlowDynamicAPInt &O) {
@@ -66,14 +68,17 @@ class DynamicAPInt {
66
68
// and leak it.
67
69
ValLarge = O;
68
70
}
69
- HoldsLarge = true ;
70
71
}
71
72
72
73
LLVM_ATTRIBUTE_ALWAYS_INLINE explicit DynamicAPInt (
73
74
const detail::SlowDynamicAPInt &Val)
74
- : ValLarge(Val), HoldsLarge(true ) {}
75
- LLVM_ATTRIBUTE_ALWAYS_INLINE bool isSmall () const { return !HoldsLarge; }
76
- LLVM_ATTRIBUTE_ALWAYS_INLINE bool isLarge () const { return HoldsLarge; }
75
+ : ValLarge(Val) {}
76
+ LLVM_ATTRIBUTE_ALWAYS_INLINE constexpr bool isSmall () const {
77
+ return ValLarge.Val .BitWidth == 0 ;
78
+ }
79
+ LLVM_ATTRIBUTE_ALWAYS_INLINE constexpr bool isLarge () const {
80
+ return !isSmall ();
81
+ }
77
82
// / Get the stored value. For getSmall/Large,
78
83
// / the stored value should be small/large.
79
84
LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t getSmall () const {
@@ -105,14 +110,17 @@ class DynamicAPInt {
105
110
106
111
public:
107
112
LLVM_ATTRIBUTE_ALWAYS_INLINE explicit DynamicAPInt (int64_t Val)
108
- : ValSmall(Val), HoldsLarge(false ) {}
113
+ : ValSmall(Val) {
114
+ ValLarge.Val .BitWidth = 0 ;
115
+ }
109
116
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt () : DynamicAPInt(0 ) {}
110
117
LLVM_ATTRIBUTE_ALWAYS_INLINE ~DynamicAPInt () {
111
118
if (LLVM_UNLIKELY (isLarge ()))
112
119
ValLarge.detail ::SlowDynamicAPInt::~SlowDynamicAPInt ();
113
120
}
114
121
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt (const DynamicAPInt &O)
115
- : ValSmall(O.ValSmall), HoldsLarge(false ) {
122
+ : ValSmall(O.ValSmall) {
123
+ ValLarge.Val .BitWidth = 0 ;
116
124
if (LLVM_UNLIKELY (O.isLarge ()))
117
125
initLarge (O.ValLarge );
118
126
}
@@ -203,6 +211,8 @@ class DynamicAPInt {
203
211
204
212
friend hash_code hash_value (const DynamicAPInt &x); // NOLINT
205
213
214
+ void static_assert_layout (); // NOLINT
215
+
206
216
raw_ostream &print (raw_ostream &OS) const ;
207
217
LLVM_DUMP_METHOD void dump () const ;
208
218
};
0 commit comments