[flang][runtime] Tweak GetNextNonBlank() performance (#164521)
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).
diff --git a/flang-rt/include/flang-rt/runtime/connection.h b/flang-rt/include/flang-rt/runtime/connection.h
index 4c1d6a4..158e156 100644
--- a/flang-rt/include/flang-rt/runtime/connection.h
+++ b/flang-rt/include/flang-rt/runtime/connection.h
@@ -73,7 +73,6 @@
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 3de2309..f6a81f7 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 @@
}
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 @@
// Skips spaces, advances records, and ignores NAMELIST comments
RT_API_ATTRS common::optional<char32_t> 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;
}