From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 4F9723853D2B; Thu, 17 Aug 2023 20:31:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4F9723853D2B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1692304282; bh=5+XjUiqBrrlA5RB4x8H19Ur6GjEeg1I02u9+++cuids=; h=From:To:Subject:Date:From; b=adqxMcMQeP/HfQjK0OnsBdYr0wGphbMihZAqfz1OJ8+jIMG309oo/g/S6S02DeCl5 tUGT3tbVOzkSkhZAlnFMbPYwdEJbXfqTbb2kJgEwbl5+6xNkeHRbARANQf0qtvNghq 2464nUoDKgPUeurdVh3WPVhLe9nuVq7tI3OFyiSs= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r14-3307] libstdc++: Micro-optimize construction of named std::locale X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/master X-Git-Oldrev: cc3d7baf2741777e99567d4301802c99f5775619 X-Git-Newrev: 74c019b50b7724dd5ed7af640b6c0427383d48df Message-Id: <20230817203122.4F9723853D2B@sourceware.org> Date: Thu, 17 Aug 2023 20:31:22 +0000 (GMT) List-Id: https://gcc.gnu.org/g:74c019b50b7724dd5ed7af640b6c0427383d48df commit r14-3307-g74c019b50b7724dd5ed7af640b6c0427383d48df Author: Jonathan Wakely Date: Wed Jul 19 09:56:58 2023 +0100 libstdc++: Micro-optimize construction of named std::locale This shaves about 100ns off the std::locale constructor for named locales (which is only about 1% of the total time). Using !*s instead of !strcmp(s, "") doesn't make any difference as GCC optimizes that already even at -O1. !strcmp(s, "C") is optimized at -O2 so replacing that with s[0] == 'C' && s[1] == '\0' only matters for the --enable-libstdcxx-debug builds. But !strcmp(s, "POSIX") always makes a call to strcmp at any optimization level. We make that strcmp call, maybe several times, for any locale name except for "C" (which will be matched before we get to the check for "POSIX"). For most targets, locale names begin with a lowercase letter and the only one that begins with 'P' is "POSIX". Replacing !strcmp(s, "POSIX") with s[0] == 'P' && !strcmp(s+1, "OSIX") means that we avoid calling strcmp unless the string really does match "POSIX". Maybe more importantly, I find is_C_locale(s) easier to read than strcmp(s, "C") == 0 || strcmp(s, "POSIX") == 0, and !is_C_locale(s) easier to read than strcmp(s, "C") != 0 && strcmp(s, "POSIX") != 0. libstdc++-v3/ChangeLog: * src/c++98/localename.cc (is_C_locale): New function. (locale::locale(const char*)): Use is_C_locale. Diff: --- libstdc++-v3/src/c++98/localename.cc | 39 +++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/libstdc++-v3/src/c++98/localename.cc b/libstdc++-v3/src/c++98/localename.cc index 25e6d966dca5..68cb81d0709a 100644 --- a/libstdc++-v3/src/c++98/localename.cc +++ b/libstdc++-v3/src/c++98/localename.cc @@ -36,24 +36,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using namespace __gnu_cxx; + static inline bool + is_C_locale(const char* s) + { + switch (s[0]) + { + case 'C': + return s[1] == '\0'; + case 'P': + return !std::strcmp(s+1, "OSIX"); + default: + return false; + } + } + locale::locale(const char* __s) : _M_impl(0) { if (__s) { _S_initialize(); - if (std::strcmp(__s, "C") == 0 || std::strcmp(__s, "POSIX") == 0) + if (is_C_locale(__s)) (_M_impl = _S_classic)->_M_add_reference(); - else if (std::strcmp(__s, "") != 0) + else if (*__s) _M_impl = new _Impl(__s, 1); else { // Get it from the environment. char* __env = std::getenv("LC_ALL"); // If LC_ALL is set we are done. - if (__env && std::strcmp(__env, "") != 0) + if (__env && *__env) { - if (std::strcmp(__env, "C") == 0 - || std::strcmp(__env, "POSIX") == 0) + if (is_C_locale(__env)) (_M_impl = _S_classic)->_M_add_reference(); else _M_impl = new _Impl(__env, 1); @@ -63,9 +76,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // LANG may set a default different from "C". string __lang; __env = std::getenv("LANG"); - if (!__env || std::strcmp(__env, "") == 0 - || std::strcmp(__env, "C") == 0 - || std::strcmp(__env, "POSIX") == 0) + if (!__env || !*__env || is_C_locale(__env)) __lang = "C"; else __lang = __env; @@ -77,17 +88,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION for (; __i < _S_categories_size; ++__i) { __env = std::getenv(_S_categories[__i]); - if (__env && std::strcmp(__env, "") != 0 - && std::strcmp(__env, "C") != 0 - && std::strcmp(__env, "POSIX") != 0) + if (__env && *__env && !is_C_locale(__env)) break; } else for (; __i < _S_categories_size; ++__i) { __env = std::getenv(_S_categories[__i]); - if (__env && std::strcmp(__env, "") != 0 - && __lang != __env) + if (__env && *__env && __lang != __env) break; } @@ -113,14 +121,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __env = std::getenv(_S_categories[__i]); __str += _S_categories[__i]; - if (!__env || std::strcmp(__env, "") == 0) + if (!__env || !*__env) { __str += '='; __str += __lang; __str += ';'; } - else if (std::strcmp(__env, "C") == 0 - || std::strcmp(__env, "POSIX") == 0) + else if (is_C_locale(__env)) __str += "=C;"; else {