From 772b62c91e27d357048a1d2ae1962b5901862e76 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 25 May 2025 21:04:14 -0500 Subject: [PATCH] QChar: micro-optimization: force inlining of qGetProp() Clang was already doing it, but GCC (at least in LTO mode) wasn't and was repeatedly calling qGetProp(). This has the benefit that, in most cases, the input character whose property we seek is UTF-16, so dead code-elimination removes the extra branch - this can happen when QString functions go through the QChar front-end, like QChar::isSpace() or isSymbol(), which route through the char32_t overload. This forced inling allows us to remove the UCS2 overloads of qGetProp() and properties(), because the same const-propagation will apply to all but one of the places where UTF-16 code units were being compared. The 16-bit qGetProp() was only used in qstring.cpp's convertCase_helper(), whose 16-bit overload was only used in foldCase(). The one exception to this is qtextengine.cpp's QBidiAlgorithm::resolveN0(): const QUnicodeTables::Properties *p = QUnicodeTables::properties(char16_t{text[pos].unicode()}); This will now call the full UTF-32 overload. Pick-to: 6.10 Change-Id: Ifa4f2d77475877f26be2fffd9a987ff994dc8ef1 Reviewed-by: Edward Welbourne --- src/corelib/text/qunicodetables.cpp | 13 ++----------- src/corelib/text/qunicodetables_p.h | 2 -- util/unicode/main.cpp | 15 ++------------- 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/src/corelib/text/qunicodetables.cpp b/src/corelib/text/qunicodetables.cpp index f836ea4615f..1af980867ae 100644 --- a/src/corelib/text/qunicodetables.cpp +++ b/src/corelib/text/qunicodetables.cpp @@ -10833,7 +10833,8 @@ static constexpr Properties uc_properties[] = { { 12, 0, 0, 0, 0, -1, 0, 2, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 15, 0, 0, 0 } }; -Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(char32_t ucs4) noexcept +Q_DECL_CONST_FUNCTION static Q_ALWAYS_INLINE +const Properties *qGetProp(char32_t ucs4) noexcept { Q_ASSERT(ucs4 <= QChar::LastValidCodePoint); if (ucs4 < 0x11000) @@ -10843,21 +10844,11 @@ Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(char32_t ucs4) no + uc_property_trie[uc_property_trie[((ucs4 - 0x11000) >> 8) + 0x880] + (ucs4 & 0xff)]; } -Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(char16_t ucs2) noexcept -{ - return uc_properties + uc_property_trie[uc_property_trie[ucs2 >> 5] + (ucs2 & 0x1f)]; -} - const Properties * QT_FASTCALL properties(char32_t ucs4) noexcept { return qGetProp(ucs4); } -const Properties * QT_FASTCALL properties(char16_t ucs2) noexcept -{ - return qGetProp(ucs2); -} - Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(char32_t ucs4) noexcept { return static_cast(qGetProp(ucs4)->graphemeBreakClass); diff --git a/src/corelib/text/qunicodetables_p.h b/src/corelib/text/qunicodetables_p.h index 3275977d356..a9044f68e5d 100644 --- a/src/corelib/text/qunicodetables_p.h +++ b/src/corelib/text/qunicodetables_p.h @@ -67,8 +67,6 @@ struct Properties { Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(char32_t ucs4) noexcept; -Q_DECL_CONST_FUNCTION -Q_CORE_EXPORT const Properties * QT_FASTCALL properties(char16_t ucs2) noexcept; static_assert(sizeof(Properties) == 20); diff --git a/util/unicode/main.cpp b/util/unicode/main.cpp index 6487d887d60..5759b62c0d6 100644 --- a/util/unicode/main.cpp +++ b/util/unicode/main.cpp @@ -2797,7 +2797,8 @@ static QByteArray createPropertyInfo() out.chop(1); out += "\n};\n\n"; - out += "Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(char32_t ucs4) noexcept\n" + out += "Q_DECL_CONST_FUNCTION static Q_ALWAYS_INLINE\n" + "const Properties *qGetProp(char32_t ucs4) noexcept\n" "{\n" " Q_ASSERT(ucs4 <= QChar::LastValidCodePoint);\n" " if (ucs4 < 0x" + QByteArray::number(BMP_END, 16) + ")\n" @@ -2813,21 +2814,9 @@ static QByteArray createPropertyInfo() + QByteArray::number(SMP_BLOCKSIZE - 1, 16) + ")];\n" "}\n" "\n" - "Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(char16_t ucs2) noexcept\n" - "{\n" - " return uc_properties + uc_property_trie[uc_property_trie[ucs2 >> " - + QByteArray::number(BMP_SHIFT) + "] + (ucs2 & 0x" - + QByteArray::number(BMP_BLOCKSIZE - 1, 16) + ")];\n" - "}\n" - "\n" "const Properties * QT_FASTCALL properties(char32_t ucs4) noexcept\n" "{\n" " return qGetProp(ucs4);\n" - "}\n" - "\n" - "const Properties * QT_FASTCALL properties(char16_t ucs2) noexcept\n" - "{\n" - " return qGetProp(ucs2);\n" "}\n\n"; out += "Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(char32_t ucs4) noexcept\n"