[flang-rt] Simplify INDEX with len-1 SUBSTRING. (#137889)
The len-1 case is noticeably slower than gfortran's straightforward
implementation
075611b646/libgfortran/intrinsics/string_intrinsics_inc.c (L253)
This change speeds up a simple microkernel by 37% on icelake.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include "flang/Common/uint128.h"
|
||||
#include "flang/Runtime/character.h"
|
||||
#include "flang/Runtime/cpp-type.h"
|
||||
#include "flang/Runtime/freestanding-tools.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
@@ -293,6 +294,24 @@ inline RT_API_ATTRS std::size_t Index(const CHAR *x, std::size_t xLen,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (wantLen == 1) {
|
||||
// Trivial case for single character lookup.
|
||||
// We can use simple forward search.
|
||||
CHAR ch{want[0]};
|
||||
if constexpr (std::is_same_v<CHAR, char>) {
|
||||
if (auto pos{reinterpret_cast<const CHAR *>(
|
||||
Fortran::runtime::memchr(x, ch, xLen))}) {
|
||||
return pos - x + 1;
|
||||
}
|
||||
} else {
|
||||
for (std::size_t at{0}; at < xLen; ++at) {
|
||||
if (x[at] == ch) {
|
||||
return at + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// Non-trivial forward substring search: use a simplified form of
|
||||
// Boyer-Moore substring searching.
|
||||
for (std::size_t at{1}; at + wantLen - 1 <= xLen;) {
|
||||
|
||||
@@ -354,6 +354,7 @@ TYPED_TEST(SearchTests, IndexTests) {
|
||||
{"", "a", true, 0},
|
||||
{"aa", "a", false, 1},
|
||||
{"aa", "a", true, 2},
|
||||
{"aAA", "A", false, 2},
|
||||
{"Fortran that I ran", "that I ran", false, 9},
|
||||
{"Fortran that I ran", "that I ran", true, 9},
|
||||
{"Fortran that you ran", "that I ran", false, 0},
|
||||
|
||||
Reference in New Issue
Block a user