From a3bca563ac1e484dad10db341c8e8876b3564c36 Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Tue, 21 Oct 2025 16:18:22 -0700 Subject: [PATCH] [flang][runtime] Tweak GetNextNonBlank() performance When skipping blanks during input from an ASCII file, scan the buffered characters directly when possible rather than using the more general path. This adds complexity, but shaves a few percent off the runtime of a code that reads in millions of list-directed integers (best time over multiple runs goes from 17.56 to 16.84 sec). --- .../include/flang-rt/runtime/connection.h | 1 - flang-rt/include/flang-rt/runtime/io-stmt.h | 44 ++++++++++++++----- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/flang-rt/include/flang-rt/runtime/connection.h b/flang-rt/include/flang-rt/runtime/connection.h index 4c1d6a4b1140c..158e156d1b0b3 100644 --- a/flang-rt/include/flang-rt/runtime/connection.h +++ b/flang-rt/include/flang-rt/runtime/connection.h @@ -73,7 +73,6 @@ struct ConnectionState : public ConnectionAttributes { auto least{leftTabLimit.value_or(0)}; auto newPos{positionInRecord + n}; positionInRecord = newPos < least ? least : newPos; - ; } RT_API_ATTRS void BeginRecord() { diff --git a/flang-rt/include/flang-rt/runtime/io-stmt.h b/flang-rt/include/flang-rt/runtime/io-stmt.h index 3de2309954a40..f6a81f7cb8120 100644 --- a/flang-rt/include/flang-rt/runtime/io-stmt.h +++ b/flang-rt/include/flang-rt/runtime/io-stmt.h @@ -184,6 +184,18 @@ class IoStatementState { } connection_.HandleRelativePosition(bytes); } + RT_API_ATTRS bool SkipBlanks() { + if (at_) { + const char *start{at_}; + while (at_ < limit_ && (*at_ == ' ' || *at_ == '\t' || *at_ == '\n')) { + ++at_; + } + connection_.HandleRelativePosition(at_ - start); + return true; + } else { + return false; + } + } // Could there be a list-directed repetition count here? RT_API_ATTRS bool MightBeRepetitionCount() const { @@ -289,24 +301,32 @@ class IoStatementState { // Skips spaces, advances records, and ignores NAMELIST comments RT_API_ATTRS common::optional GetNextNonBlank( std::size_t &byteCount, FastAsciiField *fastField = nullptr) { - auto ch{GetCurrentChar(byteCount, fastField)}; bool inNamelist{mutableModes().inNamelist}; + if (fastField) { + while (fastField->SkipBlanks()) { + if (auto ch{fastField->Next()}) { + if (inNamelist && *ch == '!') { + // skip namelist comment + } else { + byteCount = 1; + return ch; + } + } + if (!AdvanceRecord()) { + break; + } + fastField->NextRecord(*this); + } + } + auto ch{GetCurrentCharSlow(byteCount)}; while (!ch || *ch == ' ' || *ch == '\t' || *ch == '\n' || (inNamelist && *ch == '!')) { if (ch && (*ch == ' ' || *ch == '\t' || *ch == '\n')) { - if (fastField) { - fastField->Advance(0, byteCount); - } else { - HandleRelativePosition(byteCount); - } - } else if (AdvanceRecord()) { - if (fastField) { - fastField->NextRecord(*this); - } - } else { + HandleRelativePosition(byteCount); + } else if (!AdvanceRecord()) { return common::nullopt; } - ch = GetCurrentChar(byteCount, fastField); + ch = GetCurrentCharSlow(byteCount); } return ch; }