[clang] df2a1f2 - Add profiling support for APValues.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 27 20:06:09 PDT 2020
Author: Richard Smith
Date: 2020-09-27T20:05:39-07:00
New Revision: df2a1f2aabf6692daa83e849f0fdc37f9e402fca
URL: https://github.com/llvm/llvm-project/commit/df2a1f2aabf6692daa83e849f0fdc37f9e402fca
DIFF: https://github.com/llvm/llvm-project/commit/df2a1f2aabf6692daa83e849f0fdc37f9e402fca.diff
LOG: Add profiling support for APValues.
For C++20 P0732R2; unused so far. Will be used and tested by a follow-on
commit.
Added:
Modified:
clang/include/clang/AST/APValue.h
clang/lib/AST/APValue.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h
index 6307f8a92e5a..ac8ed0818af0 100644
--- a/clang/include/clang/AST/APValue.h
+++ b/clang/include/clang/AST/APValue.h
@@ -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 @@ class APValue {
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 @@ class APValue {
}
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 @@ class APValue {
/// Swaps the contents of this and the given APValue.
void swap(APValue &RHS);
+ /// Profile this value. There is no guarantee that values of
diff erent
+ /// 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; }
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index 32d3ff7ce1d0..7efd0caf3f1d 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -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;
More information about the cfe-commits
mailing list