[flang-commits] [flang] [flang][Parser] Don't build a discarded list while scanning identifiers (PR #219330)
via flang-commits
flang-commits at lists.llvm.org
Thu Aug 27 16:55:23 PDT 2026
https://github.com/khaki3 created https://github.com/llvm/llvm-project/pull/219330
```c++
constexpr auto rawName{nonDigitIdChar >> many(nonDigitIdChar || digit)};
TYPE_PARSER(space >> sourced(rawName >> construct<Name>()))
```
In this code `many()` has resultType `std::list<const char *>`, so
scanning an identifier heap-allocates one node per character. The `>>`
operator discards its left operand's value, so that list is destroyed
unread -- `sourced()` recovers the text from the cursor span instead.
Backtracking rescans identifiers, so CloverLeaf_Serial (401KB) does 3.9M
unnecessary allocations.
Fix: use `skipMany`, documented as "equivalent to many(x) but with no
result", with the same `BacktrackingParser` wrapper. -0.88%
instructions:u; emitted code byte-identical with CloverLeaf_Serial.
>From 63ccfd175166a91eceaaad2869687234a7be7ebb Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Thu, 27 Aug 2026 16:26:52 -0700
Subject: [PATCH] [flang][Parser] Don't build a discarded list while scanning
identifiers
rawName used many(), whose resultType is std::list<const char *>, so
scanning an identifier heap-allocated one list node per character after
the first. Both uses of rawName are `rawName >> construct<Name>()`, and
SequenceParser evaluates its first parser only for success and returns
the second one's result, so the list was destroyed without ever being
read. Backtracking rescans the same identifiers repeatedly, which
multiplies the cost: compiling the 401KB CloverLeaf_Serial sources
performs 3.9M of these allocation/free pairs.
skipMany wraps its argument in the same BacktrackingParser as many, so
failure handling and message restoration are unchanged, and its loop
terminates on the same no-forward-progress condition.
-0.88% of instructions:u compiling CloverLeaf_Serial (44 files, -O2).
Emitted .text/.data/.rodata are byte-identical on all 44.
---
flang/lib/Parser/Fortran-parsers.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp
index 72de71bf0ac63..a20983e095d18 100644
--- a/flang/lib/Parser/Fortran-parsers.cpp
+++ b/flang/lib/Parser/Fortran-parsers.cpp
@@ -44,7 +44,7 @@ namespace Fortran::parser {
// R601 alphanumeric-character -> letter | digit | underscore
// R603 name -> letter [alphanumeric-character]...
constexpr auto nonDigitIdChar{letter || otherIdChar};
-constexpr auto rawName{nonDigitIdChar >> many(nonDigitIdChar || digit)};
+constexpr auto rawName{nonDigitIdChar >> skipMany(nonDigitIdChar || digit)};
TYPE_PARSER(space >> sourced(rawName >> construct<Name>()))
// R608 intrinsic-operator ->
More information about the flang-commits
mailing list