Skip to content

Commit 346aa9b

Browse files
cor3ntinsvkeerthy
authored andcommitted
[Clang] Optimize some getBeginLoc implementations (#141058)
The bulk of the changes are in `CallExpr` We cache Begin/End source locs in the trailing objects, in the space left by making the offset to the trailing objects static. We also set a flag to indicate that we are calling an explicit object member function, further reducing the cost of getBeginLoc. Fixes #140876
1 parent 160d9d5 commit 346aa9b

File tree

10 files changed

+201
-134
lines changed

10 files changed

+201
-134
lines changed

clang/include/clang/AST/Expr.h

Lines changed: 86 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,7 +1344,13 @@ class DeclRefExpr final
13441344

13451345
SourceLocation getLocation() const { return DeclRefExprBits.Loc; }
13461346
void setLocation(SourceLocation L) { DeclRefExprBits.Loc = L; }
1347-
SourceLocation getBeginLoc() const LLVM_READONLY;
1347+
1348+
SourceLocation getBeginLoc() const {
1349+
if (hasQualifier())
1350+
return getQualifierLoc().getBeginLoc();
1351+
return DeclRefExprBits.Loc;
1352+
}
1353+
13481354
SourceLocation getEndLoc() const LLVM_READONLY;
13491355

13501356
/// Determine whether this declaration reference was preceded by a
@@ -2901,34 +2907,43 @@ class CallExpr : public Expr {
29012907
//
29022908
// * An optional of type FPOptionsOverride.
29032909
//
2904-
// Note that we store the offset in bytes from the this pointer to the start
2905-
// of the trailing objects. It would be perfectly possible to compute it
2906-
// based on the dynamic kind of the CallExpr. However 1.) we have plenty of
2907-
// space in the bit-fields of Stmt. 2.) It was benchmarked to be faster to
2908-
// compute this once and then load the offset from the bit-fields of Stmt,
2909-
// instead of re-computing the offset each time the trailing objects are
2910-
// accessed.
2910+
// CallExpr subclasses are asssumed to be 32 bytes or less, and CallExpr
2911+
// itself is 24 bytes. To avoid having to recompute or store the offset of the
2912+
// trailing objects, we put it at 32 bytes (such that it is suitable for all
2913+
// subclasses) We use the 8 bytes gap left for instances of CallExpr to store
2914+
// the begin source location, which has a significant impact on perf as
2915+
// getBeginLoc is assumed to be cheap.
2916+
// The layourt is as follow:
2917+
// CallExpr | Begin | 4 bytes left | Trailing Objects
2918+
// CXXMemberCallExpr | Trailing Objects
2919+
// A bit in CallExprBitfields indicates if source locations are present.
29112920

2921+
protected:
2922+
static constexpr unsigned OffsetToTrailingObjects = 32;
2923+
template <typename T>
2924+
static constexpr unsigned
2925+
sizeToAllocateForCallExprSubclass(unsigned SizeOfTrailingObjects) {
2926+
static_assert(sizeof(T) <= CallExpr::OffsetToTrailingObjects);
2927+
return SizeOfTrailingObjects + CallExpr::OffsetToTrailingObjects;
2928+
}
2929+
2930+
private:
29122931
/// Return a pointer to the start of the trailing array of "Stmt *".
29132932
Stmt **getTrailingStmts() {
29142933
return reinterpret_cast<Stmt **>(reinterpret_cast<char *>(this) +
2915-
CallExprBits.OffsetToTrailingObjects);
2934+
OffsetToTrailingObjects);
29162935
}
29172936
Stmt *const *getTrailingStmts() const {
29182937
return const_cast<CallExpr *>(this)->getTrailingStmts();
29192938
}
29202939

2921-
/// Map a statement class to the appropriate offset in bytes from the
2922-
/// this pointer to the trailing objects.
2923-
static unsigned offsetToTrailingObjects(StmtClass SC);
2924-
29252940
unsigned getSizeOfTrailingStmts() const {
29262941
return (1 + getNumPreArgs() + getNumArgs()) * sizeof(Stmt *);
29272942
}
29282943

29292944
size_t getOffsetOfTrailingFPFeatures() const {
29302945
assert(hasStoredFPFeatures());
2931-
return CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts();
2946+
return OffsetToTrailingObjects + getSizeOfTrailingStmts();
29322947
}
29332948

29342949
public:
@@ -2975,14 +2990,14 @@ class CallExpr : public Expr {
29752990
FPOptionsOverride *getTrailingFPFeatures() {
29762991
assert(hasStoredFPFeatures());
29772992
return reinterpret_cast<FPOptionsOverride *>(
2978-
reinterpret_cast<char *>(this) + CallExprBits.OffsetToTrailingObjects +
2993+
reinterpret_cast<char *>(this) + OffsetToTrailingObjects +
29792994
getSizeOfTrailingStmts());
29802995
}
29812996
const FPOptionsOverride *getTrailingFPFeatures() const {
29822997
assert(hasStoredFPFeatures());
29832998
return reinterpret_cast<const FPOptionsOverride *>(
2984-
reinterpret_cast<const char *>(this) +
2985-
CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts());
2999+
reinterpret_cast<const char *>(this) + OffsetToTrailingObjects +
3000+
getSizeOfTrailingStmts());
29863001
}
29873002

29883003
public:
@@ -3028,6 +3043,19 @@ class CallExpr : public Expr {
30283043

30293044
bool hasStoredFPFeatures() const { return CallExprBits.HasFPFeatures; }
30303045

3046+
bool usesMemberSyntax() const {
3047+
return CallExprBits.ExplicitObjectMemFunUsingMemberSyntax;
3048+
}
3049+
void setUsesMemberSyntax(bool V = true) {
3050+
CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = V;
3051+
// Because the source location may be different for explicit
3052+
// member, we reset the cached values.
3053+
if (CallExprBits.HasTrailingSourceLoc) {
3054+
CallExprBits.HasTrailingSourceLoc = false;
3055+
updateTrailingSourceLoc();
3056+
}
3057+
}
3058+
30313059
bool isCoroElideSafe() const { return CallExprBits.IsCoroElideSafe; }
30323060
void setCoroElideSafe(bool V = true) { CallExprBits.IsCoroElideSafe = V; }
30333061

@@ -3187,9 +3215,48 @@ class CallExpr : public Expr {
31873215
SourceLocation getRParenLoc() const { return RParenLoc; }
31883216
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
31893217

3190-
SourceLocation getBeginLoc() const LLVM_READONLY;
3191-
SourceLocation getEndLoc() const LLVM_READONLY;
3218+
SourceLocation getBeginLoc() const {
3219+
if (CallExprBits.HasTrailingSourceLoc) {
3220+
static_assert(sizeof(CallExpr) <=
3221+
OffsetToTrailingObjects + sizeof(SourceLocation));
3222+
return *reinterpret_cast<const SourceLocation *>(
3223+
reinterpret_cast<const char *>(this + 1));
3224+
}
3225+
3226+
if (usesMemberSyntax())
3227+
if (auto FirstArgLoc = getArg(0)->getBeginLoc(); FirstArgLoc.isValid())
3228+
return FirstArgLoc;
3229+
3230+
// FIXME: Some builtins have no callee begin location
3231+
SourceLocation begin = getCallee()->getBeginLoc();
3232+
if (begin.isInvalid() && getNumArgs() > 0 && getArg(0))
3233+
begin = getArg(0)->getBeginLoc();
3234+
return begin;
3235+
}
3236+
3237+
SourceLocation getEndLoc() const { return getRParenLoc(); }
31923238

3239+
private:
3240+
friend class ASTStmtReader;
3241+
bool hasTrailingSourceLoc() const {
3242+
return CallExprBits.HasTrailingSourceLoc;
3243+
}
3244+
3245+
void updateTrailingSourceLoc() {
3246+
assert(!CallExprBits.HasTrailingSourceLoc &&
3247+
"Trailing source loc already set?");
3248+
assert(getStmtClass() == CallExprClass &&
3249+
"Calling setTrailingSourceLocs on a subclass of CallExpr");
3250+
static_assert(sizeof(CallExpr) <=
3251+
OffsetToTrailingObjects + sizeof(SourceLocation));
3252+
3253+
SourceLocation *Locs =
3254+
reinterpret_cast<SourceLocation *>(reinterpret_cast<char *>(this + 1));
3255+
new (Locs) SourceLocation(getBeginLoc());
3256+
CallExprBits.HasTrailingSourceLoc = true;
3257+
}
3258+
3259+
public:
31933260
/// Return true if this is a call to __assume() or __builtin_assume() with
31943261
/// a non-value-dependent constant parameter evaluating as false.
31953262
bool isBuiltinAssumeFalse(const ASTContext &Ctx) const;

clang/include/clang/AST/NestedNameSpecifier.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,9 @@ class NestedNameSpecifierLoc {
283283
/// For example, if this instance refers to a nested-name-specifier
284284
/// \c \::std::vector<int>::, the returned source range would cover
285285
/// from the initial '::' to the last '::'.
286-
SourceRange getSourceRange() const LLVM_READONLY;
286+
SourceRange getSourceRange() const LLVM_READONLY {
287+
return SourceRange(getBeginLoc(), getEndLoc());
288+
}
287289

288290
/// Retrieve the source range covering just the last part of
289291
/// this nested-name-specifier, not including the prefix.
@@ -296,14 +298,18 @@ class NestedNameSpecifierLoc {
296298
/// Retrieve the location of the beginning of this
297299
/// nested-name-specifier.
298300
SourceLocation getBeginLoc() const {
299-
return getSourceRange().getBegin();
301+
if (!Qualifier)
302+
return SourceLocation();
303+
304+
NestedNameSpecifierLoc First = *this;
305+
while (NestedNameSpecifierLoc Prefix = First.getPrefix())
306+
First = Prefix;
307+
return First.getLocalSourceRange().getBegin();
300308
}
301309

302310
/// Retrieve the location of the end of this
303311
/// nested-name-specifier.
304-
SourceLocation getEndLoc() const {
305-
return getSourceRange().getEnd();
306-
}
312+
SourceLocation getEndLoc() const { return getLocalSourceRange().getEnd(); }
307313

308314
/// Retrieve the location of the beginning of this
309315
/// component of the nested-name-specifier.

clang/include/clang/AST/Stmt.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -563,17 +563,21 @@ class alignas(void *) Stmt {
563563
unsigned HasFPFeatures : 1;
564564

565565
/// True if the call expression is a must-elide call to a coroutine.
566+
LLVM_PREFERRED_TYPE(bool)
566567
unsigned IsCoroElideSafe : 1;
567568

568-
/// Padding used to align OffsetToTrailingObjects to a byte multiple.
569-
unsigned : 24 - 4 - NumExprBits;
569+
/// Tracks when CallExpr is used to represent an explicit object
570+
/// member function, in order to adjust the begin location.
571+
LLVM_PREFERRED_TYPE(bool)
572+
unsigned ExplicitObjectMemFunUsingMemberSyntax : 1;
570573

571-
/// The offset in bytes from the this pointer to the start of the
572-
/// trailing objects belonging to CallExpr. Intentionally byte sized
573-
/// for faster access.
574-
unsigned OffsetToTrailingObjects : 8;
574+
/// Indicates that SourceLocations are cached as
575+
/// Trailing objects. See the definition of CallExpr.
576+
LLVM_PREFERRED_TYPE(bool)
577+
unsigned HasTrailingSourceLoc : 1;
575578
};
576-
enum { NumCallExprBits = 32 };
579+
580+
enum { NumCallExprBits = 25 };
577581

578582
class MemberExprBitfields {
579583
friend class ASTStmtReader;

0 commit comments

Comments
 (0)