@@ -49,14 +49,73 @@ class ValueLatticeElement {
49
49
overdefined
50
50
};
51
51
52
- // / Val: This stores the current lattice value along with the Constant* for
53
- // / the constant if this is a 'constant' or 'notconstant' value.
54
52
ValueLatticeElementTy Tag;
55
- Constant *Val;
56
- ConstantRange Range;
53
+
54
+ // / The union either stores a pointer to a constant or a constant range,
55
+ // / associated to the lattice element. We have to ensure that Range is
56
+ // / initialized or destroyed when changing state to or from constantrange.
57
+ union {
58
+ Constant *ConstVal;
59
+ ConstantRange Range;
60
+ };
57
61
58
62
public:
59
- ValueLatticeElement () : Tag(undefined), Val(nullptr ), Range(1 , true ) {}
63
+ // Const and Range are initialized on-demand.
64
+ ValueLatticeElement () : Tag(undefined) {}
65
+
66
+ // / Custom destructor to ensure Range is properly destroyed, when the object
67
+ // / is deallocated.
68
+ ~ValueLatticeElement () {
69
+ switch (Tag) {
70
+ case overdefined:
71
+ case undefined:
72
+ case constant:
73
+ case notconstant:
74
+ break ;
75
+ case constantrange:
76
+ Range.~ConstantRange ();
77
+ break ;
78
+ };
79
+ }
80
+
81
+ // / Custom copy constructor, to ensure Range gets initialized when
82
+ // / copying a constant range lattice element.
83
+ ValueLatticeElement (const ValueLatticeElement &Other) : Tag(undefined) {
84
+ *this = Other;
85
+ }
86
+
87
+ // / Custom assignment operator, to ensure Range gets initialized when
88
+ // / assigning a constant range lattice element.
89
+ ValueLatticeElement &operator =(const ValueLatticeElement &Other) {
90
+ // If we change the state of this from constant range to non constant range,
91
+ // destroy Range.
92
+ if (isConstantRange () && !Other.isConstantRange ())
93
+ Range.~ConstantRange ();
94
+
95
+ // If we change the state of this from a valid ConstVal to another a state
96
+ // without a valid ConstVal, zero the pointer.
97
+ if ((isConstant () || isNotConstant ()) && !Other.isConstant () &&
98
+ !Other.isNotConstant ())
99
+ ConstVal = nullptr ;
100
+
101
+ switch (Other.Tag ) {
102
+ case constantrange:
103
+ if (!isConstantRange ())
104
+ new (&Range) ConstantRange (Other.Range );
105
+ else
106
+ Range = Other.Range ;
107
+ break ;
108
+ case constant:
109
+ case notconstant:
110
+ ConstVal = Other.ConstVal ;
111
+ break ;
112
+ case overdefined:
113
+ case undefined:
114
+ break ;
115
+ }
116
+ Tag = Other.Tag ;
117
+ return *this ;
118
+ }
60
119
61
120
static ValueLatticeElement get (Constant *C) {
62
121
ValueLatticeElement Res;
@@ -89,12 +148,12 @@ class ValueLatticeElement {
89
148
90
149
Constant *getConstant () const {
91
150
assert (isConstant () && " Cannot get the constant of a non-constant!" );
92
- return Val ;
151
+ return ConstVal ;
93
152
}
94
153
95
154
Constant *getNotConstant () const {
96
155
assert (isNotConstant () && " Cannot get the constant of a non-notconstant!" );
97
- return Val ;
156
+ return ConstVal ;
98
157
}
99
158
100
159
const ConstantRange &getConstantRange () const {
@@ -104,10 +163,10 @@ class ValueLatticeElement {
104
163
}
105
164
106
165
Optional<APInt> asConstantInteger () const {
107
- if (isConstant () && isa<ConstantInt>(Val )) {
108
- return cast<ConstantInt>(Val )->getValue ();
109
- } else if (isConstantRange () && Range .isSingleElement ()) {
110
- return *Range .getSingleElement ();
166
+ if (isConstant () && isa<ConstantInt>(getConstant () )) {
167
+ return cast<ConstantInt>(getConstant () )->getValue ();
168
+ } else if (isConstantRange () && getConstantRange () .isSingleElement ()) {
169
+ return *getConstantRange () .getSingleElement ();
111
170
}
112
171
return None;
113
172
}
@@ -116,6 +175,10 @@ class ValueLatticeElement {
116
175
void markOverdefined () {
117
176
if (isOverdefined ())
118
177
return ;
178
+ if (isConstant () || isNotConstant ())
179
+ ConstVal = nullptr ;
180
+ if (isConstantRange ())
181
+ Range.~ConstantRange ();
119
182
Tag = overdefined;
120
183
}
121
184
@@ -132,7 +195,7 @@ class ValueLatticeElement {
132
195
" Marking constant with different value" );
133
196
assert (isUndefined ());
134
197
Tag = constant;
135
- Val = V;
198
+ ConstVal = V;
136
199
}
137
200
138
201
void markNotConstant (Constant *V) {
@@ -150,7 +213,7 @@ class ValueLatticeElement {
150
213
" Marking !constant with different value" );
151
214
assert (isUndefined () || isConstant ());
152
215
Tag = notconstant;
153
- Val = V;
216
+ ConstVal = V;
154
217
}
155
218
156
219
void markConstantRange (ConstantRange NewR) {
@@ -168,7 +231,7 @@ class ValueLatticeElement {
168
231
markOverdefined ();
169
232
else {
170
233
Tag = constantrange;
171
- Range = std::move (NewR);
234
+ new (& Range) ConstantRange ( std::move (NewR) );
172
235
}
173
236
}
174
237
0 commit comments