Skip to content

Commit

Permalink
[clang][bytecode][NFC] Cache the BuiltinID in Function (#106745)
Browse files Browse the repository at this point in the history
FunctionDecl::getBuiltinID() is surprisingly slow and we tend to call it
quite a bit, especially when interpreting builtin functions. Caching the
BuiltinID here reduces the time I need to compile the
floating_comparison namespace from builtin-functions.cpp from 7.2s to
6.3s locally.
  • Loading branch information
tbaederr authored Aug 30, 2024
1 parent 02eb03d commit 3745a2e
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 28 deletions.
18 changes: 2 additions & 16 deletions clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,6 @@
using namespace clang;
using namespace clang::interp;

/// Unevaluated builtins don't get their arguments put on the stack
/// automatically. They instead operate on the AST of their Call
/// Expression.
/// Similar information is available via ASTContext::BuiltinInfo,
/// but that is not correct for our use cases.
static bool isUnevaluatedBuiltin(unsigned BuiltinID) {
return BuiltinID == Builtin::BI__builtin_classify_type ||
BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size ||
BuiltinID == Builtin::BI__builtin_constant_p;
}

Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {

// Manually created functions that haven't been assigned proper
Expand Down Expand Up @@ -147,14 +136,11 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
// Create a handle over the emitted code.
Function *Func = P.getFunction(FuncDecl);
if (!Func) {
bool IsUnevaluatedBuiltin = false;
if (unsigned BI = FuncDecl->getBuiltinID())
IsUnevaluatedBuiltin = isUnevaluatedBuiltin(BI);

unsigned BuiltinID = FuncDecl->getBuiltinID();
Func =
P.createFunction(FuncDecl, ParamOffset, std::move(ParamTypes),
std::move(ParamDescriptors), std::move(ParamOffsets),
HasThisPointer, HasRVO, IsUnevaluatedBuiltin);
HasThisPointer, HasRVO, BuiltinID);
}

assert(Func);
Expand Down
20 changes: 17 additions & 3 deletions clang/lib/AST/ByteCode/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ Function::Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
llvm::SmallVectorImpl<PrimType> &&ParamTypes,
llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
llvm::SmallVectorImpl<unsigned> &&ParamOffsets,
bool HasThisPointer, bool HasRVO, bool UnevaluatedBuiltin)
bool HasThisPointer, bool HasRVO, unsigned BuiltinID)
: P(P), Source(Source), ArgSize(ArgSize), ParamTypes(std::move(ParamTypes)),
Params(std::move(Params)), ParamOffsets(std::move(ParamOffsets)),
HasThisPointer(HasThisPointer), HasRVO(HasRVO),
IsUnevaluatedBuiltin(UnevaluatedBuiltin) {
HasThisPointer(HasThisPointer), HasRVO(HasRVO), BuiltinID(BuiltinID) {
if (const auto *F = Source.dyn_cast<const FunctionDecl *>())
Variadic = F->isVariadic();
}
Expand Down Expand Up @@ -53,3 +52,18 @@ bool Function::isVirtual() const {
return M->isVirtual();
return false;
}

/// Unevaluated builtins don't get their arguments put on the stack
/// automatically. They instead operate on the AST of their Call
/// Expression.
/// Similar information is available via ASTContext::BuiltinInfo,
/// but that is not correct for our use cases.
static bool isUnevaluatedBuiltin(unsigned BuiltinID) {
return BuiltinID == Builtin::BI__builtin_classify_type ||
BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size ||
BuiltinID == Builtin::BI__builtin_constant_p;
}

bool Function::isUnevaluatedBuiltin() const {
return ::isUnevaluatedBuiltin(BuiltinID);
}
14 changes: 5 additions & 9 deletions clang/lib/AST/ByteCode/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,11 @@ class Function final {

bool isVariadic() const { return Variadic; }

unsigned getBuiltinID() const {
return Source.get<const FunctionDecl *>()->getBuiltinID();
}
unsigned getBuiltinID() const { return BuiltinID; }

bool isBuiltin() const {
return Source.get<const FunctionDecl *>()->getBuiltinID() != 0;
}
bool isBuiltin() const { return getBuiltinID() != 0; }

bool isUnevaluatedBuiltin() const { return IsUnevaluatedBuiltin; }
bool isUnevaluatedBuiltin() const;

unsigned getNumParams() const { return ParamTypes.size(); }

Expand Down Expand Up @@ -232,7 +228,7 @@ class Function final {
llvm::SmallVectorImpl<PrimType> &&ParamTypes,
llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer,
bool HasRVO, bool UnevaluatedBuiltin);
bool HasRVO, unsigned BuiltinID);

/// Sets the code of a function.
void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode,
Expand Down Expand Up @@ -289,7 +285,7 @@ class Function final {
bool HasBody = false;
bool Defined = false;
bool Variadic = false;
bool IsUnevaluatedBuiltin = false;
unsigned BuiltinID = 0;

public:
/// Dumps the disassembled bytecode to \c llvm::errs().
Expand Down

0 comments on commit 3745a2e

Please sign in to comment.