[clang] [clang] Avoid per-builtin std::string allocation in initializeBuiltins (PR #205162)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 22 11:47:44 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Cyndy Ishida (cyndyishida)
<details>
<summary>Changes</summary>
`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
---
Full diff: https://github.com/llvm/llvm-project/pull/205162.diff
2 Files Affected:
- (modified) clang/lib/Basic/Builtins.cpp (+19-4)
- (added) clang/test/AST/builtin-name-registration.c (+12)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/205162
More information about the cfe-commits
mailing list