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

Reply via email to