Skip to content

Commit ea5262f

Browse files
authored
[flang][runtime] Use dumber but faster check for list-directed repeti… (#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.
1 parent 286f451 commit ea5262f

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

flang-rt/include/flang-rt/runtime/io-stmt.h

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,7 @@ class IoStatementState {
149149
: connection_{connection} {}
150150
RT_API_ATTRS FastAsciiField(
151151
ConnectionState &connection, const char *start, std::size_t bytes)
152-
: connection_{connection}, at_{start}, limit_{start + bytes} {
153-
CheckForAsterisk();
154-
}
152+
: connection_{connection}, at_{start}, limit_{start + bytes} {}
155153
RT_API_ATTRS ConnectionState &connection() { return connection_; }
156154
RT_API_ATTRS std::size_t got() const { return got_; }
157155

@@ -168,7 +166,6 @@ class IoStatementState {
168166
if (at_) {
169167
if (std::size_t bytes{io.GetNextInputBytes(at_)}) {
170168
limit_ = at_ + bytes;
171-
CheckForAsterisk();
172169
} else {
173170
at_ = limit_ = nullptr;
174171
}
@@ -181,19 +178,28 @@ class IoStatementState {
181178
}
182179
connection_.HandleRelativePosition(bytes);
183180
}
184-
RT_API_ATTRS bool MightHaveAsterisk() const { return !at_ || hasAsterisk_; }
185181

186-
private:
187-
RT_API_ATTRS void CheckForAsterisk() {
188-
hasAsterisk_ = at_ && at_ < limit_ &&
189-
runtime::memchr(at_, '*', limit_ - at_) != nullptr;
182+
// Could there be a list-directed repetition count here?
183+
RT_API_ATTRS bool MightBeRepetitionCount() const {
184+
if (!at_) {
185+
return true; // must use slow path for internal KIND/=1 input
186+
} else {
187+
if (const char *p{at_}; *p >= '0' && *p <= '9') {
188+
while (++p < limit_) {
189+
if (*p < '0' || *p > '9') {
190+
return *p == '*';
191+
}
192+
}
193+
}
194+
return false;
195+
}
190196
}
191197

198+
private:
192199
ConnectionState &connection_;
193200
const char *at_{nullptr};
194201
const char *limit_{nullptr};
195202
std::size_t got_{0}; // for READ(..., SIZE=)
196-
bool hasAsterisk_{false};
197203
};
198204

199205
RT_API_ATTRS FastAsciiField GetUpcomingFastAsciiField();

flang-rt/lib/runtime/io-stmt.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -905,8 +905,8 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
905905
if (imaginaryPart_) { // can't repeat components
906906
return edit;
907907
}
908-
if (*ch >= '0' && *ch <= '9' && fastField.MightHaveAsterisk()) {
909-
// look for "r*" repetition count
908+
if (*ch >= '0' && *ch <= '9' && fastField.MightBeRepetitionCount()) {
909+
// There's decimal digits followed by '*'.
910910
auto start{fastField.connection().positionInRecord};
911911
int r{0};
912912
do {

0 commit comments

Comments
 (0)