Skip to content

Commit

Permalink
[ValueLattice] Use union to shave off ptr size bytes from elements.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
fhahn committed Jan 20, 2018
1 parent 10fbe29 commit 2d05f76
Showing 1 changed file with 77 additions and 14 deletions.
91 changes: 77 additions & 14 deletions include/llvm/Analysis/ValueLattice.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,73 @@ class ValueLatticeElement {
overdefined
};

/// Val: This stores the current lattice value along with the Constant* for
/// the constant if this is a 'constant' or 'notconstant' value.
ValueLatticeElementTy Tag;
Constant *Val;
ConstantRange Range;

/// The union either stores a pointer to a constant or a constant range,
/// associated to the lattice element. We have to ensure that Range is
/// initialized or destroyed when changing state to or from constantrange.
union {
Constant *ConstVal;
ConstantRange Range;
};

public:
ValueLatticeElement() : Tag(undefined), Val(nullptr), Range(1, true) {}
// Const and Range are initialized on-demand.
ValueLatticeElement() : Tag(undefined) {}

/// Custom destructor to ensure Range is properly destroyed, when the object
/// is deallocated.
~ValueLatticeElement() {
switch (Tag) {
case overdefined:
case undefined:
case constant:
case notconstant:
break;
case constantrange:
Range.~ConstantRange();
break;
};
}

/// Custom copy constructor, to ensure Range gets initialized when
/// copying a constant range lattice element.
ValueLatticeElement(const ValueLatticeElement &Other) : Tag(undefined) {
*this = Other;
}

/// Custom assignment operator, to ensure Range gets initialized when
/// assigning a constant range lattice element.
ValueLatticeElement &operator=(const ValueLatticeElement &Other) {
// If we change the state of this from constant range to non constant range,
// destroy Range.
if (isConstantRange() && !Other.isConstantRange())
Range.~ConstantRange();

// If we change the state of this from a valid ConstVal to another a state
// without a valid ConstVal, zero the pointer.
if ((isConstant() || isNotConstant()) && !Other.isConstant() &&
!Other.isNotConstant())
ConstVal = nullptr;

switch (Other.Tag) {
case constantrange:
if (!isConstantRange())
new (&Range) ConstantRange(Other.Range);
else
Range = Other.Range;
break;
case constant:
case notconstant:
ConstVal = Other.ConstVal;
break;
case overdefined:
case undefined:
break;
}
Tag = Other.Tag;
return *this;
}

static ValueLatticeElement get(Constant *C) {
ValueLatticeElement Res;
Expand Down Expand Up @@ -89,12 +148,12 @@ class ValueLatticeElement {

Constant *getConstant() const {
assert(isConstant() && "Cannot get the constant of a non-constant!");
return Val;
return ConstVal;
}

Constant *getNotConstant() const {
assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
return Val;
return ConstVal;
}

const ConstantRange &getConstantRange() const {
Expand All @@ -104,10 +163,10 @@ class ValueLatticeElement {
}

Optional<APInt> asConstantInteger() const {
if (isConstant() && isa<ConstantInt>(Val)) {
return cast<ConstantInt>(Val)->getValue();
} else if (isConstantRange() && Range.isSingleElement()) {
return *Range.getSingleElement();
if (isConstant() && isa<ConstantInt>(getConstant())) {
return cast<ConstantInt>(getConstant())->getValue();
} else if (isConstantRange() && getConstantRange().isSingleElement()) {
return *getConstantRange().getSingleElement();
}
return None;
}
Expand All @@ -116,6 +175,10 @@ class ValueLatticeElement {
void markOverdefined() {
if (isOverdefined())
return;
if (isConstant() || isNotConstant())
ConstVal = nullptr;
if (isConstantRange())
Range.~ConstantRange();
Tag = overdefined;
}

Expand All @@ -132,7 +195,7 @@ class ValueLatticeElement {
"Marking constant with different value");
assert(isUndefined());
Tag = constant;
Val = V;
ConstVal = V;
}

void markNotConstant(Constant *V) {
Expand All @@ -150,7 +213,7 @@ class ValueLatticeElement {
"Marking !constant with different value");
assert(isUndefined() || isConstant());
Tag = notconstant;
Val = V;
ConstVal = V;
}

void markConstantRange(ConstantRange NewR) {
Expand All @@ -168,7 +231,7 @@ class ValueLatticeElement {
markOverdefined();
else {
Tag = constantrange;
Range = std::move(NewR);
new (&Range) ConstantRange(std::move(NewR));
}
}

Expand Down

0 comments on commit 2d05f76

Please sign in to comment.