[llvm] [flang][runtime] Use dumber but faster check for list-directed repeti… (PR #159867)

Peter Klausler via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 19 15:58:46 PDT 2025


https://github.com/klausler created https://github.com/llvm/llvm-project/pull/159867

…tion

When scanning list-directed input for nulls and repetition counts, the current library depends on having each record be prescanned for the presence of asterisk characters.  It turns out that the overhead of calling memchr(...,'*',...) on each record doesn't pay off, especially on systems without SIMD-vectorized memchr implementations -- even on those, it's faster (about 10%) to just scan ahead for asterisks when decimal digits are encountered.  Only when an asterisk is present, which is not common, should we then bother to convert the digits to their integer value.

>From fd0b7f298da3824c194671962da154f7f284d57b Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Fri, 19 Sep 2025 15:51:13 -0700
Subject: [PATCH] [flang][runtime] Use dumber but faster check for
 list-directed repetition

When scanning list-directed input for nulls and repetition counts,
the current library depends on having each record be prescanned for
the presence of asterisk characters.  It turns out that the overhead
of calling memchr(...,'*',...) on each record doesn't pay off, especially
on systems without SIMD-vectorized memchr implementations -- even on those,
it's faster (about 10%) to just scan ahead for asterisks when decimal
digits are encountered.  Only when an asterisk is present, which is
not common, should we then bother to convert the digits to their integer
value.
---
 flang-rt/include/flang-rt/runtime/io-stmt.h | 20 ++++++++++----------
 flang-rt/lib/runtime/io-stmt.cpp            |  4 ++--
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/flang-rt/include/flang-rt/runtime/io-stmt.h b/flang-rt/include/flang-rt/runtime/io-stmt.h
index 03b6efd65ddfc..5db5a4ec3a443 100644
--- a/flang-rt/include/flang-rt/runtime/io-stmt.h
+++ b/flang-rt/include/flang-rt/runtime/io-stmt.h
@@ -149,9 +149,7 @@ class IoStatementState {
         : connection_{connection} {}
     RT_API_ATTRS FastAsciiField(
         ConnectionState &connection, const char *start, std::size_t bytes)
-        : connection_{connection}, at_{start}, limit_{start + bytes} {
-      CheckForAsterisk();
-    }
+        : connection_{connection}, at_{start}, limit_{start + bytes} {}
     RT_API_ATTRS ConnectionState &connection() { return connection_; }
     RT_API_ATTRS std::size_t got() const { return got_; }
 
@@ -168,7 +166,6 @@ class IoStatementState {
       if (at_) {
         if (std::size_t bytes{io.GetNextInputBytes(at_)}) {
           limit_ = at_ + bytes;
-          CheckForAsterisk();
         } else {
           at_ = limit_ = nullptr;
         }
@@ -181,19 +178,22 @@ class IoStatementState {
       }
       connection_.HandleRelativePosition(bytes);
     }
-    RT_API_ATTRS bool MightHaveAsterisk() const { return !at_ || hasAsterisk_; }
 
-  private:
-    RT_API_ATTRS void CheckForAsterisk() {
-      hasAsterisk_ = at_ && at_ < limit_ &&
-          runtime::memchr(at_, '*', limit_ - at_) != nullptr;
+    // Is there decimal integer followed by an asterisk?
+    RT_API_ATTRS bool MightBeRepetitionCount() const {
+      for (const char *p{at_}; p < limit_; ++p) {
+        if (*p < '0' || *p > '9') {
+          return p > at_ && *p == '*';
+        }
+      }
+      return false;
     }
 
+  private:
     ConnectionState &connection_;
     const char *at_{nullptr};
     const char *limit_{nullptr};
     std::size_t got_{0}; // for READ(..., SIZE=)
-    bool hasAsterisk_{false};
   };
 
   RT_API_ATTRS FastAsciiField GetUpcomingFastAsciiField();
diff --git a/flang-rt/lib/runtime/io-stmt.cpp b/flang-rt/lib/runtime/io-stmt.cpp
index e260c0ca7511d..6cb08df85a90b 100644
--- a/flang-rt/lib/runtime/io-stmt.cpp
+++ b/flang-rt/lib/runtime/io-stmt.cpp
@@ -905,8 +905,8 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
   if (imaginaryPart_) { // can't repeat components
     return edit;
   }
-  if (*ch >= '0' && *ch <= '9' && fastField.MightHaveAsterisk()) {
-    // look for "r*" repetition count
+  if (fastField.MightBeRepetitionCount()) {
+    // There's decimal digits followed by '*'.
     auto start{fastField.connection().positionInRecord};
     int r{0};
     do {



More information about the llvm-commits mailing list