From 2d05f76ffa9d24a4ac13f46d8cf35db8b795cbef Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 20 Jan 2018 19:52:16 +0000 Subject: [PATCH] [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 --- include/llvm/Analysis/ValueLattice.h | 91 ++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/include/llvm/Analysis/ValueLattice.h b/include/llvm/Analysis/ValueLattice.h index fb1f6c66297..6fb8f79aad8 100644 --- a/include/llvm/Analysis/ValueLattice.h +++ b/include/llvm/Analysis/ValueLattice.h @@ -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; @@ -89,12 +148,12 @@ public: 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 { @@ -104,10 +163,10 @@ public: } Optional asConstantInteger() const { - if (isConstant() && isa(Val)) { - return cast(Val)->getValue(); - } else if (isConstantRange() && Range.isSingleElement()) { - return *Range.getSingleElement(); + if (isConstant() && isa(getConstant())) { + return cast(getConstant())->getValue(); + } else if (isConstantRange() && getConstantRange().isSingleElement()) { + return *getConstantRange().getSingleElement(); } return None; } @@ -116,6 +175,10 @@ private: void markOverdefined() { if (isOverdefined()) return; + if (isConstant() || isNotConstant()) + ConstVal = nullptr; + if (isConstantRange()) + Range.~ConstantRange(); Tag = overdefined; } @@ -132,7 +195,7 @@ private: "Marking constant with different value"); assert(isUndefined()); Tag = constant; - Val = V; + ConstVal = V; } void markNotConstant(Constant *V) { @@ -150,7 +213,7 @@ private: "Marking !constant with different value"); assert(isUndefined() || isConstant()); Tag = notconstant; - Val = V; + ConstVal = V; } void markConstantRange(ConstantRange NewR) { @@ -168,7 +231,7 @@ private: markOverdefined(); else { Tag = constantrange; - Range = std::move(NewR); + new (&Range) ConstantRange(std::move(NewR)); } } -- 2.11.0