https://github.com/cyndyishida created https://github.com/llvm/llvm-project/pull/205162
`initializeBuiltins()` previously registered every builtin through an allocated std::string every time a `CompilerInstance` initialized. This was hot for module-heavy builds, where each built module re-registered the full set. Add `getBuiltinNameInto()`, which writes the name into a caller-provided buffer and returns a `StringRef`, with no allocation when the shard has no prefix (the common case). `Info::getName` now delegates to it so the two cannot diverge. This change is output behavior-preserving. Resolves: rdar://178672190 >From 77b3c94fb4e05aa4fdd1199df113ec06f258488f Mon Sep 17 00:00:00 2001 From: Cyndy Ishida <[email protected]> Date: Mon, 22 Jun 2026 08:54:20 -0700 Subject: [PATCH] [clang] Avoid per-builtin std::string allocation in initializeBuiltins `initializeBuiltins()` previously registered every builtin through a heap-allocated std::string every time a `CompilerInstance` initialized. This was hot for module-heavy builds, where each implicitly built module re-registered the full set. Add `getBuiltinNameInto()`, which writes the name into a caller-provided buffer and returns a `StringRef`, with no allocation when the shard has no prefix (the common case). `Info::getName` now delegates to it so the two cannot diverge. This change is behavior preserving. Resolves: rdar://178672190 --- clang/lib/Basic/Builtins.cpp | 23 ++++++++++++++++++---- clang/test/AST/builtin-name-registration.c | 12 +++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 clang/test/AST/builtin-name-registration.c diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp index 49517fc748112..06fba04eb2df3 100644 --- a/clang/lib/Basic/Builtins.cpp +++ b/clang/lib/Basic/Builtins.cpp @@ -15,6 +15,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" using namespace clang; @@ -71,8 +72,21 @@ Builtin::Context::getShardAndInfo(unsigned ID) const { llvm_unreachable("Invalid target builtin shard structure!"); } +/// Return a non-owning StringRef of the builtin's name, reconstructed into Buf. +static StringRef getBuiltinNameInto(const Builtin::InfosShard &Shard, + const Builtin::Info &BuiltinInfo, + SmallVectorImpl<char> &Buf) { + StringRef Name = (*Shard.Strings)[BuiltinInfo.Offsets.Name]; + if (Shard.NamePrefix.empty()) + return Name; + Buf.assign(Shard.NamePrefix.begin(), Shard.NamePrefix.end()); + Buf.append(Name.begin(), Name.end()); + return StringRef(Buf.data(), Buf.size()); +} + std::string Builtin::Info::getName(const Builtin::InfosShard &Shard) const { - return (Twine(Shard.NamePrefix) + (*Shard.Strings)[Offsets.Name]).str(); + SmallString<256> Buf; + return getBuiltinNameInto(Shard, *this, Buf).str(); } /// Return the identifier name for the specified builtin, @@ -297,12 +311,13 @@ void Builtin::Context::initializeBuiltins(IdentifierTable &Table, const LangOptions &LangOpts) { { unsigned ID = 0; + llvm::SmallString<256> NameBuf; // Step #1: mark all target-independent builtins with their ID's. for (const auto &Shard : BuiltinShards) for (const auto &I : Shard.Infos) { // If this is a real builtin (ID != 0) and is supported, add it. if (ID != 0 && builtinIsSupported(*Shard.Strings, I, LangOpts)) - Table.get(I.getName(Shard)).setBuiltinID(ID); + Table.get(getBuiltinNameInto(Shard, I, NameBuf)).setBuiltinID(ID); ++ID; } assert(ID == FirstTSBuiltin && "Should have added all non-target IDs!"); @@ -311,14 +326,14 @@ void Builtin::Context::initializeBuiltins(IdentifierTable &Table, for (const auto &Shard : TargetShards) for (const auto &I : Shard.Infos) { if (builtinIsSupported(*Shard.Strings, I, LangOpts)) - Table.get(I.getName(Shard)).setBuiltinID(ID); + Table.get(getBuiltinNameInto(Shard, I, NameBuf)).setBuiltinID(ID); ++ID; } // Step #3: Register target-specific builtins for AuxTarget. for (const auto &Shard : AuxTargetShards) for (const auto &I : Shard.Infos) { - Table.get(I.getName(Shard)).setBuiltinID(ID); + Table.get(getBuiltinNameInto(Shard, I, NameBuf)).setBuiltinID(ID); ++ID; } } diff --git a/clang/test/AST/builtin-name-registration.c b/clang/test/AST/builtin-name-registration.c new file mode 100644 index 0000000000000..c5e81c665a280 --- /dev/null +++ b/clang/test/AST/builtin-name-registration.c @@ -0,0 +1,12 @@ +// Verify builtins register under their full name when formed with a prefix. +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -ast-dump %s | FileCheck %s + +void use(void) { + (void)__builtin_abs(-1); + __builtin_ia32_pause(); +} + +// CHECK: FunctionDecl {{.*}} implicit used __builtin_abs 'int (int)' +// CHECK: BuiltinAttr +// CHECK: FunctionDecl {{.*}} implicit used __builtin_ia32_pause 'void (void)' +// CHECK: BuiltinAttr _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
