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 <edward.welbourne@qt.io>
This commit is contained in:
Thiago Macieira 2025-05-25 21:04:14 -05:00
parent 71e2eecb4a
commit 772b62c91e
3 changed files with 4 additions and 26 deletions

View File

@ -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<GraphemeBreakClass>(qGetProp(ucs4)->graphemeBreakClass);

View File

@ -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);

View File

@ -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"