[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;
   }