Skip to content

Commit 2d05f76

Browse files
committed
[ValueLattice] Use union to shave off ptr size bytes from elements.
By using a union for Constant* and ConstantRange we can shave off ptr size bytes off lattice elements. On 64 bit systems, it brings down the size to 40 bytes from 48 bytes. Initialization of Range happens on-demand using placement new, if the state changes to constantrange from non-constantrange. Similarly, the Range object is destroyed if the state changes from constantrange to non-constantrange. Reviewers: reames, anna, davide Reviewed By: reames, davide Differential Revision: https://reviews.llvm.org/D41903 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@323049 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 10fbe29 commit 2d05f76

File tree

1 file changed

+77
-14
lines changed

1 file changed

+77
-14
lines changed

include/llvm/Analysis/ValueLattice.h

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,73 @@ class ValueLatticeElement {
4949
overdefined
5050
};
5151

52-
/// Val: This stores the current lattice value along with the Constant* for
53-
/// the constant if this is a 'constant' or 'notconstant' value.
5452
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+
};
5761

5862
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+
}
60119

61120
static ValueLatticeElement get(Constant *C) {
62121
ValueLatticeElement Res;
@@ -89,12 +148,12 @@ class ValueLatticeElement {
89148

90149
Constant *getConstant() const {
91150
assert(isConstant() && "Cannot get the constant of a non-constant!");
92-
return Val;
151+
return ConstVal;
93152
}
94153

95154
Constant *getNotConstant() const {
96155
assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
97-
return Val;
156+
return ConstVal;
98157
}
99158

100159
const ConstantRange &getConstantRange() const {
@@ -104,10 +163,10 @@ class ValueLatticeElement {
104163
}
105164

106165
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();
111170
}
112171
return None;
113172
}
@@ -116,6 +175,10 @@ class ValueLatticeElement {
116175
void markOverdefined() {
117176
if (isOverdefined())
118177
return;
178+
if (isConstant() || isNotConstant())
179+
ConstVal = nullptr;
180+
if (isConstantRange())
181+
Range.~ConstantRange();
119182
Tag = overdefined;
120183
}
121184

@@ -132,7 +195,7 @@ class ValueLatticeElement {
132195
"Marking constant with different value");
133196
assert(isUndefined());
134197
Tag = constant;
135-
Val = V;
198+
ConstVal = V;
136199
}
137200

138201
void markNotConstant(Constant *V) {
@@ -150,7 +213,7 @@ class ValueLatticeElement {
150213
"Marking !constant with different value");
151214
assert(isUndefined() || isConstant());
152215
Tag = notconstant;
153-
Val = V;
216+
ConstVal = V;
154217
}
155218

156219
void markConstantRange(ConstantRange NewR) {
@@ -168,7 +231,7 @@ class ValueLatticeElement {
168231
markOverdefined();
169232
else {
170233
Tag = constantrange;
171-
Range = std::move(NewR);
234+
new (&Range) ConstantRange(std::move(NewR));
172235
}
173236
}
174237

0 commit comments

Comments
 (0)