forked from OSchip/llvm-project
Add profiling support for APValues.
For C++20 P0732R2; unused so far. Will be used and tested by a follow-on commit.
This commit is contained in:
parent
9dcd96f728
commit
df2a1f2aab
|
@ -19,6 +19,7 @@
|
|||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
|
||||
namespace clang {
|
||||
class AddrLabelExpr;
|
||||
|
@ -149,6 +150,8 @@ public:
|
|||
static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
|
||||
static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
|
||||
|
||||
void profile(llvm::FoldingSetNodeID &ID) const;
|
||||
|
||||
template <class T>
|
||||
bool is() const { return Ptr.is<T>(); }
|
||||
|
||||
|
@ -215,6 +218,8 @@ public:
|
|||
}
|
||||
uint64_t getAsArrayIndex() const { return Value; }
|
||||
|
||||
void profile(llvm::FoldingSetNodeID &ID) const;
|
||||
|
||||
friend bool operator==(LValuePathEntry A, LValuePathEntry B) {
|
||||
return A.Value == B.Value;
|
||||
}
|
||||
|
@ -357,6 +362,11 @@ public:
|
|||
/// Swaps the contents of this and the given APValue.
|
||||
void swap(APValue &RHS);
|
||||
|
||||
/// Profile this value. There is no guarantee that values of different
|
||||
/// types will not produce the same profiled value, so the type should
|
||||
/// typically also be profiled if it's not implied by the context.
|
||||
void profile(llvm::FoldingSetNodeID &ID) const;
|
||||
|
||||
ValueKind getKind() const { return Kind; }
|
||||
|
||||
bool isAbsent() const { return Kind == None; }
|
||||
|
|
|
@ -77,6 +77,14 @@ QualType APValue::LValueBase::getDynamicAllocType() const {
|
|||
return QualType::getFromOpaquePtr(DynamicAllocType);
|
||||
}
|
||||
|
||||
void APValue::LValueBase::profile(llvm::FoldingSetNodeID &ID) const {
|
||||
ID.AddPointer(Ptr.getOpaqueValue());
|
||||
if (is<TypeInfoLValue>() || is<DynamicAllocLValue>())
|
||||
return;
|
||||
ID.AddInteger(Local.CallIndex);
|
||||
ID.AddInteger(Local.Version);
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
bool operator==(const APValue::LValueBase &LHS,
|
||||
const APValue::LValueBase &RHS) {
|
||||
|
@ -95,6 +103,10 @@ APValue::LValuePathEntry::LValuePathEntry(BaseOrMemberType BaseOrMember) {
|
|||
Value = reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue());
|
||||
}
|
||||
|
||||
void APValue::LValuePathEntry::profile(llvm::FoldingSetNodeID &ID) const {
|
||||
ID.AddInteger(Value);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct LVBase {
|
||||
APValue::LValueBase Base;
|
||||
|
@ -402,6 +414,147 @@ void APValue::swap(APValue &RHS) {
|
|||
std::swap(Data, RHS.Data);
|
||||
}
|
||||
|
||||
void APValue::profile(llvm::FoldingSetNodeID &ID) const {
|
||||
ID.AddInteger(Kind);
|
||||
|
||||
switch (Kind) {
|
||||
case None:
|
||||
case Indeterminate:
|
||||
return;
|
||||
|
||||
case AddrLabelDiff:
|
||||
ID.AddPointer(getAddrLabelDiffLHS()->getLabel()->getCanonicalDecl());
|
||||
ID.AddPointer(getAddrLabelDiffRHS()->getLabel()->getCanonicalDecl());
|
||||
return;
|
||||
|
||||
case Struct:
|
||||
ID.AddInteger(getStructNumBases());
|
||||
for (unsigned I = 0, N = getStructNumBases(); I != N; ++I)
|
||||
getStructBase(I).profile(ID);
|
||||
ID.AddInteger(getStructNumFields());
|
||||
for (unsigned I = 0, N = getStructNumFields(); I != N; ++I)
|
||||
getStructField(I).profile(ID);
|
||||
return;
|
||||
|
||||
case Union:
|
||||
if (!getUnionField()) {
|
||||
ID.AddPointer(nullptr);
|
||||
return;
|
||||
}
|
||||
ID.AddPointer(getUnionField()->getCanonicalDecl());
|
||||
getUnionValue().profile(ID);
|
||||
return;
|
||||
|
||||
case Array: {
|
||||
ID.AddInteger(getArraySize());
|
||||
if (getArraySize() == 0)
|
||||
return;
|
||||
|
||||
// The profile should not depend on whether the array is expanded or
|
||||
// not, but we don't want to profile the array filler many times for
|
||||
// a large array. So treat all equal trailing elements as the filler.
|
||||
// Elements are profiled in reverse order to support this, and the
|
||||
// first profiled element is followed by a count. For example:
|
||||
//
|
||||
// ['a', 'c', 'x', 'x', 'x'] is profiled as
|
||||
// [5, 'x', 3, 'c', 'a']
|
||||
llvm::FoldingSetNodeID FillerID;
|
||||
(hasArrayFiller() ? getArrayFiller() :
|
||||
getArrayInitializedElt(getArrayInitializedElts() -
|
||||
1)).profile(FillerID);
|
||||
ID.AddNodeID(FillerID);
|
||||
unsigned NumFillers = getArraySize() - getArrayInitializedElts();
|
||||
unsigned N = getArrayInitializedElts();
|
||||
|
||||
// Count the number of elements equal to the last one. This loop ends
|
||||
// by adding an integer indicating the number of such elements, with
|
||||
// N set to the number of elements left to profile.
|
||||
while (true) {
|
||||
if (N == 0) {
|
||||
// All elements are fillers.
|
||||
assert(NumFillers == getArraySize());
|
||||
ID.AddInteger(NumFillers);
|
||||
break;
|
||||
}
|
||||
|
||||
// No need to check if the last element is equal to the last
|
||||
// element.
|
||||
if (N != getArraySize()) {
|
||||
llvm::FoldingSetNodeID ElemID;
|
||||
getArrayInitializedElt(N - 1).profile(ElemID);
|
||||
if (ElemID != FillerID) {
|
||||
ID.AddInteger(NumFillers);
|
||||
ID.AddNodeID(ElemID);
|
||||
--N;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a filler.
|
||||
++NumFillers;
|
||||
--N;
|
||||
}
|
||||
|
||||
// Emit the remaining elements.
|
||||
for (; N != 0; --N)
|
||||
getArrayInitializedElt(N - 1).profile(ID);
|
||||
return;
|
||||
}
|
||||
|
||||
case Vector:
|
||||
ID.AddInteger(getVectorLength());
|
||||
for (unsigned I = 0, N = getVectorLength(); I != N; ++I)
|
||||
getVectorElt(I).profile(ID);
|
||||
return;
|
||||
|
||||
case Int:
|
||||
// We don't need to include the sign bit; it's implied by the type.
|
||||
getInt().APInt::Profile(ID);
|
||||
return;
|
||||
|
||||
case Float:
|
||||
getFloat().Profile(ID);
|
||||
return;
|
||||
|
||||
case FixedPoint:
|
||||
// We don't need to include the fixed-point semantics; they're
|
||||
// implied by the type.
|
||||
getFixedPoint().getValue().APInt::Profile(ID);
|
||||
return;
|
||||
|
||||
case ComplexFloat:
|
||||
getComplexFloatReal().Profile(ID);
|
||||
getComplexFloatImag().Profile(ID);
|
||||
return;
|
||||
|
||||
case ComplexInt:
|
||||
getComplexIntReal().APInt::Profile(ID);
|
||||
getComplexIntImag().APInt::Profile(ID);
|
||||
return;
|
||||
|
||||
case LValue:
|
||||
getLValueBase().profile(ID);
|
||||
ID.AddInteger(getLValueOffset().getQuantity());
|
||||
ID.AddInteger(isNullPointer());
|
||||
ID.AddInteger(isLValueOnePastTheEnd());
|
||||
// For uniqueness, we only need to profile the entries corresponding
|
||||
// to union members, but we don't have the type here so we don't know
|
||||
// how to interpret the entries.
|
||||
for (LValuePathEntry E : getLValuePath())
|
||||
E.profile(ID);
|
||||
return;
|
||||
|
||||
case MemberPointer:
|
||||
ID.AddPointer(getMemberPointerDecl());
|
||||
ID.AddInteger(isMemberPointerToDerivedMember());
|
||||
for (const CXXRecordDecl *D : getMemberPointerPath())
|
||||
ID.AddPointer(D);
|
||||
return;
|
||||
}
|
||||
|
||||
llvm_unreachable("Unknown APValue kind!");
|
||||
}
|
||||
|
||||
static double GetApproxValue(const llvm::APFloat &F) {
|
||||
llvm::APFloat V = F;
|
||||
bool ignored;
|
||||
|
|
Loading…
Reference in New Issue