Skip to content

[lld][bolt][flang][mlir] Avoid premature Twine .str() materialization - #204838

Closed
tgymnich wants to merge 1 commit into
llvm:mainfrom
tgymnich:twine-str-lld-bolt-flang-mlir
Closed

[lld][bolt][flang][mlir] Avoid premature Twine .str() materialization#204838
tgymnich wants to merge 1 commit into
llvm:mainfrom
tgymnich:twine-str-lld-bolt-flang-mlir

Conversation

@tgymnich

Copy link
Copy Markdown
Member

Call sites in lld (MachO/ELF), BOLT, Flang (FIR) and MLIR pass expr.str() to parameters of type const llvm::Twine &, forcing a throwaway heap std::string that is immediately rewrapped into a Twine. Drop the .str() and let Twine accept the StringRef/concatenation directly.

Assisted-by: Claude Opus 4.8

@llvmorg-github-actions

llvmorg-github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown

@llvm/pr-subscribers-bolt
@llvm/pr-subscribers-mlir-core
@llvm/pr-subscribers-lld-elf
@llvm/pr-subscribers-flang-fir-hlfir

@llvm/pr-subscribers-lld-macho

Author: Tim Gymnich (tgymnich)

Changes

Call sites in lld (MachO/ELF), BOLT, Flang (FIR) and MLIR pass expr.str() to parameters of type const llvm::Twine &, forcing a throwaway heap std::string that is immediately rewrapped into a Twine. Drop the .str() and let Twine accept the StringRef/concatenation directly.

Assisted-by: Claude Opus 4.8


Full diff: https://github.com/llvm/llvm-project/pull/204838.diff

8 Files Affected:

  • (modified) bolt/lib/Core/BinaryContext.cpp (+1-1)
  • (modified) flang/lib/Optimizer/Dialect/FIROps.cpp (+1-1)
  • (modified) flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp (+1-1)
  • (modified) lld/ELF/Driver.cpp (+1-1)
  • (modified) lld/ELF/LTO.cpp (+1-1)
  • (modified) lld/MachO/DriverUtils.cpp (+1-1)
  • (modified) lld/MachO/ObjC.cpp (+1-1)
  • (modified) mlir/lib/Transforms/ViewOpGraph.cpp (+1-1)
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index 43ce56ef083b5..a67e3092c3953 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -1582,7 +1582,7 @@ void BinaryContext::foldFunction(BinaryFunction &ChildBF,
   // this effectively renames the function.
   WriteCtxLock.lock();
   ChildBF.getSymbols().push_back(
-      Ctx->getOrCreateSymbol("__ICF_" + ChildName.str()));
+      Ctx->getOrCreateSymbol("__ICF_" + ChildName));
   WriteCtxLock.unlock();
 
   ChildBF.setFolded(&ParentBF);
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 1d61989eba6cf..d57dec7063ab7 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -6553,7 +6553,7 @@ static mlir::ParseResult parseSpecifierList(
 
   if (regionArgs.size() != regionArgTypes.size())
     return parser.emitError(parser.getNameLoc(), "mismatch in number of " +
-                                                     specifierKeyword.str() +
+                                                     specifierKeyword +
                                                      " arg and types");
 
   if (failed(parser.parseRParen()))
diff --git a/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp b/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp
index cf4c38453c8ee..56a0b2dce1080 100644
--- a/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp
+++ b/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp
@@ -37,7 +37,7 @@ FIROpenACCSupportAnalysis::emitNYI(Location loc, const Twine &message) {
   TODO(loc, message);
   // Should be unreachable, but we return an actual diagnostic
   // to satisfy the interface.
-  return mlir::emitError(loc, "not yet implemented: " + message.str());
+  return mlir::emitError(loc, "not yet implemented: " + message);
 }
 
 bool FIROpenACCSupportAnalysis::isValidSymbolUse(Operation *user,
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7ec7dfcae6bca..d3084da9f6273 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2622,7 +2622,7 @@ static void writeDependencyFile(Ctx &ctx) {
   // * $ is escapes as $$.
   auto printFilename = [](raw_fd_ostream &os, StringRef filename) {
     llvm::SmallString<256> nativePath;
-    llvm::sys::path::native(filename.str(), nativePath);
+    llvm::sys::path::native(filename, nativePath);
     llvm::sys::path::remove_dots(nativePath, /*remove_dot_dot=*/true);
     for (unsigned i = 0, e = nativePath.size(); i != e; ++i) {
       if (nativePath[i] == '#') {
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index e40575bffec62..5300e8eeff1e6 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -82,7 +82,7 @@ static lto::Config createConfig(Ctx &ctx) {
       c.Options.BBSections = BasicBlockSection::None;
     } else {
       ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
-          MemoryBuffer::getFile(ctx.arg.ltoBasicBlockSections.str());
+          MemoryBuffer::getFile(ctx.arg.ltoBasicBlockSections);
       if (!MBOrErr) {
         ErrAlways(ctx) << "cannot open " << ctx.arg.ltoBasicBlockSections << ":"
                        << MBOrErr.getError().message();
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index 3ff9d96ed53ce..fb4ab2ddb4848 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -339,7 +339,7 @@ macho::findPathCombination(const Twine &name,
       bool exists = fs::exists(location);
       searchedDylib(location, exists);
       if (exists)
-        return saver().save(location.str());
+        return saver().save(location);
     }
   }
   return {};
diff --git a/lld/MachO/ObjC.cpp b/lld/MachO/ObjC.cpp
index 4522c574c137f..cd9f65a29d7a9 100644
--- a/lld/MachO/ObjC.cpp
+++ b/lld/MachO/ObjC.cpp
@@ -1345,7 +1345,7 @@ void ObjcCategoryMerger::doMerge() {
     }
     if (!merged)
       warn("ObjC category merging skipped for class symbol' " +
-           baseClass->getName().str() + "'\n");
+           baseClass->getName() + "'\n");
   }
 
   // Erase all categories that were merged
diff --git a/mlir/lib/Transforms/ViewOpGraph.cpp b/mlir/lib/Transforms/ViewOpGraph.cpp
index 2d7e40d18efca..9f90d010b7ae6 100644
--- a/mlir/lib/Transforms/ViewOpGraph.cpp
+++ b/mlir/lib/Transforms/ViewOpGraph.cpp
@@ -470,7 +470,7 @@ std::unique_ptr<Pass> mlir::createViewOpGraphPass(raw_ostream &os) {
 /// Generate a CFG for a region and show it in a window.
 static void llvmViewGraph(Region &region, const Twine &name) {
   int fd;
-  std::string filename = llvm::createGraphFilename(name.str(), fd);
+  std::string filename = llvm::createGraphFilename(name, fd);
   {
     llvm::raw_fd_ostream os(fd, /*shouldClose=*/true);
     if (fd == -1) {

@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-lld

Author: Tim Gymnich (tgymnich)

Changes

Call sites in lld (MachO/ELF), BOLT, Flang (FIR) and MLIR pass expr.str() to parameters of type const llvm::Twine &amp;, forcing a throwaway heap std::string that is immediately rewrapped into a Twine. Drop the .str() and let Twine accept the StringRef/concatenation directly.

Assisted-by: Claude Opus 4.8


Full diff: https://github.com/llvm/llvm-project/pull/204838.diff

8 Files Affected:

  • (modified) bolt/lib/Core/BinaryContext.cpp (+1-1)
  • (modified) flang/lib/Optimizer/Dialect/FIROps.cpp (+1-1)
  • (modified) flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp (+1-1)
  • (modified) lld/ELF/Driver.cpp (+1-1)
  • (modified) lld/ELF/LTO.cpp (+1-1)
  • (modified) lld/MachO/DriverUtils.cpp (+1-1)
  • (modified) lld/MachO/ObjC.cpp (+1-1)
  • (modified) mlir/lib/Transforms/ViewOpGraph.cpp (+1-1)
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index 43ce56ef083b5..a67e3092c3953 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -1582,7 +1582,7 @@ void BinaryContext::foldFunction(BinaryFunction &ChildBF,
   // this effectively renames the function.
   WriteCtxLock.lock();
   ChildBF.getSymbols().push_back(
-      Ctx->getOrCreateSymbol("__ICF_" + ChildName.str()));
+      Ctx->getOrCreateSymbol("__ICF_" + ChildName));
   WriteCtxLock.unlock();
 
   ChildBF.setFolded(&ParentBF);
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 1d61989eba6cf..d57dec7063ab7 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -6553,7 +6553,7 @@ static mlir::ParseResult parseSpecifierList(
 
   if (regionArgs.size() != regionArgTypes.size())
     return parser.emitError(parser.getNameLoc(), "mismatch in number of " +
-                                                     specifierKeyword.str() +
+                                                     specifierKeyword +
                                                      " arg and types");
 
   if (failed(parser.parseRParen()))
diff --git a/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp b/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp
index cf4c38453c8ee..56a0b2dce1080 100644
--- a/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp
+++ b/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp
@@ -37,7 +37,7 @@ FIROpenACCSupportAnalysis::emitNYI(Location loc, const Twine &message) {
   TODO(loc, message);
   // Should be unreachable, but we return an actual diagnostic
   // to satisfy the interface.
-  return mlir::emitError(loc, "not yet implemented: " + message.str());
+  return mlir::emitError(loc, "not yet implemented: " + message);
 }
 
 bool FIROpenACCSupportAnalysis::isValidSymbolUse(Operation *user,
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7ec7dfcae6bca..d3084da9f6273 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2622,7 +2622,7 @@ static void writeDependencyFile(Ctx &ctx) {
   // * $ is escapes as $$.
   auto printFilename = [](raw_fd_ostream &os, StringRef filename) {
     llvm::SmallString<256> nativePath;
-    llvm::sys::path::native(filename.str(), nativePath);
+    llvm::sys::path::native(filename, nativePath);
     llvm::sys::path::remove_dots(nativePath, /*remove_dot_dot=*/true);
     for (unsigned i = 0, e = nativePath.size(); i != e; ++i) {
       if (nativePath[i] == '#') {
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index e40575bffec62..5300e8eeff1e6 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -82,7 +82,7 @@ static lto::Config createConfig(Ctx &ctx) {
       c.Options.BBSections = BasicBlockSection::None;
     } else {
       ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
-          MemoryBuffer::getFile(ctx.arg.ltoBasicBlockSections.str());
+          MemoryBuffer::getFile(ctx.arg.ltoBasicBlockSections);
       if (!MBOrErr) {
         ErrAlways(ctx) << "cannot open " << ctx.arg.ltoBasicBlockSections << ":"
                        << MBOrErr.getError().message();
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index 3ff9d96ed53ce..fb4ab2ddb4848 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -339,7 +339,7 @@ macho::findPathCombination(const Twine &name,
       bool exists = fs::exists(location);
       searchedDylib(location, exists);
       if (exists)
-        return saver().save(location.str());
+        return saver().save(location);
     }
   }
   return {};
diff --git a/lld/MachO/ObjC.cpp b/lld/MachO/ObjC.cpp
index 4522c574c137f..cd9f65a29d7a9 100644
--- a/lld/MachO/ObjC.cpp
+++ b/lld/MachO/ObjC.cpp
@@ -1345,7 +1345,7 @@ void ObjcCategoryMerger::doMerge() {
     }
     if (!merged)
       warn("ObjC category merging skipped for class symbol' " +
-           baseClass->getName().str() + "'\n");
+           baseClass->getName() + "'\n");
   }
 
   // Erase all categories that were merged
diff --git a/mlir/lib/Transforms/ViewOpGraph.cpp b/mlir/lib/Transforms/ViewOpGraph.cpp
index 2d7e40d18efca..9f90d010b7ae6 100644
--- a/mlir/lib/Transforms/ViewOpGraph.cpp
+++ b/mlir/lib/Transforms/ViewOpGraph.cpp
@@ -470,7 +470,7 @@ std::unique_ptr<Pass> mlir::createViewOpGraphPass(raw_ostream &os) {
 /// Generate a CFG for a region and show it in a window.
 static void llvmViewGraph(Region &region, const Twine &name) {
   int fd;
-  std::string filename = llvm::createGraphFilename(name.str(), fd);
+  std::string filename = llvm::createGraphFilename(name, fd);
   {
     llvm::raw_fd_ostream os(fd, /*shouldClose=*/true);
     if (fd == -1) {

@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-mlir

Author: Tim Gymnich (tgymnich)

Changes

Call sites in lld (MachO/ELF), BOLT, Flang (FIR) and MLIR pass expr.str() to parameters of type const llvm::Twine &amp;, forcing a throwaway heap std::string that is immediately rewrapped into a Twine. Drop the .str() and let Twine accept the StringRef/concatenation directly.

Assisted-by: Claude Opus 4.8


Full diff: https://github.com/llvm/llvm-project/pull/204838.diff

8 Files Affected:

  • (modified) bolt/lib/Core/BinaryContext.cpp (+1-1)
  • (modified) flang/lib/Optimizer/Dialect/FIROps.cpp (+1-1)
  • (modified) flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp (+1-1)
  • (modified) lld/ELF/Driver.cpp (+1-1)
  • (modified) lld/ELF/LTO.cpp (+1-1)
  • (modified) lld/MachO/DriverUtils.cpp (+1-1)
  • (modified) lld/MachO/ObjC.cpp (+1-1)
  • (modified) mlir/lib/Transforms/ViewOpGraph.cpp (+1-1)
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index 43ce56ef083b5..a67e3092c3953 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -1582,7 +1582,7 @@ void BinaryContext::foldFunction(BinaryFunction &ChildBF,
   // this effectively renames the function.
   WriteCtxLock.lock();
   ChildBF.getSymbols().push_back(
-      Ctx->getOrCreateSymbol("__ICF_" + ChildName.str()));
+      Ctx->getOrCreateSymbol("__ICF_" + ChildName));
   WriteCtxLock.unlock();
 
   ChildBF.setFolded(&ParentBF);
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 1d61989eba6cf..d57dec7063ab7 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -6553,7 +6553,7 @@ static mlir::ParseResult parseSpecifierList(
 
   if (regionArgs.size() != regionArgTypes.size())
     return parser.emitError(parser.getNameLoc(), "mismatch in number of " +
-                                                     specifierKeyword.str() +
+                                                     specifierKeyword +
                                                      " arg and types");
 
   if (failed(parser.parseRParen()))
diff --git a/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp b/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp
index cf4c38453c8ee..56a0b2dce1080 100644
--- a/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp
+++ b/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp
@@ -37,7 +37,7 @@ FIROpenACCSupportAnalysis::emitNYI(Location loc, const Twine &message) {
   TODO(loc, message);
   // Should be unreachable, but we return an actual diagnostic
   // to satisfy the interface.
-  return mlir::emitError(loc, "not yet implemented: " + message.str());
+  return mlir::emitError(loc, "not yet implemented: " + message);
 }
 
 bool FIROpenACCSupportAnalysis::isValidSymbolUse(Operation *user,
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7ec7dfcae6bca..d3084da9f6273 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2622,7 +2622,7 @@ static void writeDependencyFile(Ctx &ctx) {
   // * $ is escapes as $$.
   auto printFilename = [](raw_fd_ostream &os, StringRef filename) {
     llvm::SmallString<256> nativePath;
-    llvm::sys::path::native(filename.str(), nativePath);
+    llvm::sys::path::native(filename, nativePath);
     llvm::sys::path::remove_dots(nativePath, /*remove_dot_dot=*/true);
     for (unsigned i = 0, e = nativePath.size(); i != e; ++i) {
       if (nativePath[i] == '#') {
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index e40575bffec62..5300e8eeff1e6 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -82,7 +82,7 @@ static lto::Config createConfig(Ctx &ctx) {
       c.Options.BBSections = BasicBlockSection::None;
     } else {
       ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
-          MemoryBuffer::getFile(ctx.arg.ltoBasicBlockSections.str());
+          MemoryBuffer::getFile(ctx.arg.ltoBasicBlockSections);
       if (!MBOrErr) {
         ErrAlways(ctx) << "cannot open " << ctx.arg.ltoBasicBlockSections << ":"
                        << MBOrErr.getError().message();
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index 3ff9d96ed53ce..fb4ab2ddb4848 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -339,7 +339,7 @@ macho::findPathCombination(const Twine &name,
       bool exists = fs::exists(location);
       searchedDylib(location, exists);
       if (exists)
-        return saver().save(location.str());
+        return saver().save(location);
     }
   }
   return {};
diff --git a/lld/MachO/ObjC.cpp b/lld/MachO/ObjC.cpp
index 4522c574c137f..cd9f65a29d7a9 100644
--- a/lld/MachO/ObjC.cpp
+++ b/lld/MachO/ObjC.cpp
@@ -1345,7 +1345,7 @@ void ObjcCategoryMerger::doMerge() {
     }
     if (!merged)
       warn("ObjC category merging skipped for class symbol' " +
-           baseClass->getName().str() + "'\n");
+           baseClass->getName() + "'\n");
   }
 
   // Erase all categories that were merged
diff --git a/mlir/lib/Transforms/ViewOpGraph.cpp b/mlir/lib/Transforms/ViewOpGraph.cpp
index 2d7e40d18efca..9f90d010b7ae6 100644
--- a/mlir/lib/Transforms/ViewOpGraph.cpp
+++ b/mlir/lib/Transforms/ViewOpGraph.cpp
@@ -470,7 +470,7 @@ std::unique_ptr<Pass> mlir::createViewOpGraphPass(raw_ostream &os) {
 /// Generate a CFG for a region and show it in a window.
 static void llvmViewGraph(Region &region, const Twine &name) {
   int fd;
-  std::string filename = llvm::createGraphFilename(name.str(), fd);
+  std::string filename = llvm::createGraphFilename(name, fd);
   {
     llvm::raw_fd_ostream os(fd, /*shouldClose=*/true);
     if (fd == -1) {

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown

✅ With the latest revision this PR passed the C/C++ code formatter.

@tgymnich
tgymnich force-pushed the twine-str-lld-bolt-flang-mlir branch from bc39cbe to 7922107 Compare June 19, 2026 14:24
Call sites in lld (MachO/ELF), BOLT, Flang (FIR) and MLIR pass
`expr.str()` to parameters of type `const llvm::Twine &`, forcing a
throwaway heap std::string that is immediately rewrapped into a Twine.
Drop the `.str()` and let Twine accept the StringRef/concatenation
directly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tgymnich
tgymnich force-pushed the twine-str-lld-bolt-flang-mlir branch from 7922107 to 9d586fe Compare June 19, 2026 14:25
@tgymnich tgymnich closed this Aug 14, 2026
@tgymnich
tgymnich deleted the twine-str-lld-bolt-flang-mlir branch August 14, 2026 08:51
@smeenai

smeenai commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Sorry, I missed this. It's generally better to break things up per-project, so that a project's usual reviewers feel comfortable approving the whole thing. (This one seems straightforward enough, it probably just got missed by everyone.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BOLT flang:fir-hlfir flang Flang issues not falling into any other category lld:ELF lld:MachO lld mlir:core MLIR Core Infrastructure mlir openacc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants