A format string like "{}" is quite common. In this case avoid parsing
the format-spec when it's not present. Before the parsing was always
called, therefore some refactoring is done to make sure the formatters
work properly when their parse member isn't called.
From the wording it's not entirely clear whether this optimization is
allowed
[tab:formatter]
```
and the range [pc.begin(), pc.end()) from the last call to f.parse(pc).
```
Implies there's always a call to `f.parse` even when the format-spec
isn't present. Therefore this optimization isn't done for handle
classes; it's unclear whether that would break user defined formatters.
The improvements give a small reduciton is code size:
719408 12472 488 732368 b2cd0 before
718824 12472 488 731784 b2a88 after
The performance benefits when not using a format-spec are:
```
Comparing ./formatter_int.libcxx.out-baseline to ./formatter_int.libcxx.out
Benchmark Time CPU Time Old Time New CPU Old CPU New
----------------------------------------------------------------------------------------------------------------------------------------------------
BM_Basic<uint32_t> -0.0688 -0.0687 67 62 67 62
BM_Basic<int32_t> -0.1105 -0.1107 73 65 73 65
BM_Basic<uint64_t> -0.1053 -0.1049 95 85 95 85
BM_Basic<int64_t> -0.0889 -0.0888 93 85 93 85
BM_BasicLow<__uint128_t> -0.0655 -0.0655 96 90 96 90
BM_BasicLow<__int128_t> -0.0693 -0.0694 97 90 97 90
BM_Basic<__uint128_t> -0.0359 -0.0359 256 247 256 247
BM_Basic<__int128_t> -0.0414 -0.0414 239 229 239 229
```
For the cases where a format-spec is used the results remain similar,
some are faster some are slower, differing per run.
Reviewed By: ldionne, #libc
Differential Revision: https://reviews.llvm.org/D129426
79 lines
2.6 KiB
C++
79 lines
2.6 KiB
C++
// -*- C++ -*-
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP___FORMAT_FORMATTER_BOOL_H
|
|
#define _LIBCPP___FORMAT_FORMATTER_BOOL_H
|
|
|
|
#include <__algorithm/copy.h>
|
|
#include <__availability>
|
|
#include <__config>
|
|
#include <__debug>
|
|
#include <__format/format_error.h>
|
|
#include <__format/format_fwd.h>
|
|
#include <__format/format_parse_context.h>
|
|
#include <__format/formatter.h>
|
|
#include <__format/formatter_integral.h>
|
|
#include <__format/parser_std_format_spec.h>
|
|
#include <__utility/unreachable.h>
|
|
#include <string_view>
|
|
|
|
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
|
# include <locale>
|
|
#endif
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
# pragma GCC system_header
|
|
#endif
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
#if _LIBCPP_STD_VER > 17
|
|
|
|
template <__formatter::__char_type _CharT>
|
|
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<bool, _CharT> {
|
|
public:
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto
|
|
parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) {
|
|
auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral);
|
|
__format_spec::__process_parsed_bool(__parser_);
|
|
return __result;
|
|
}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI auto format(bool __value, auto& __ctx) const -> decltype(__ctx.out()) {
|
|
switch (__parser_.__type_) {
|
|
case __format_spec::__type::__default:
|
|
case __format_spec::__type::__string:
|
|
return __formatter::__format_bool(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx));
|
|
|
|
case __format_spec::__type::__binary_lower_case:
|
|
case __format_spec::__type::__binary_upper_case:
|
|
case __format_spec::__type::__octal:
|
|
case __format_spec::__type::__decimal:
|
|
case __format_spec::__type::__hexadecimal_lower_case:
|
|
case __format_spec::__type::__hexadecimal_upper_case:
|
|
// Promotes bool to an integral type. This reduces the number of
|
|
// instantiations of __format_integer reducing code size.
|
|
return __formatter::__format_integer(
|
|
static_cast<unsigned>(__value), __ctx, __parser_.__get_parsed_std_specifications(__ctx));
|
|
|
|
default:
|
|
_LIBCPP_ASSERT(false, "The parse function should have validated the type");
|
|
__libcpp_unreachable();
|
|
}
|
|
}
|
|
|
|
__format_spec::__parser<_CharT> __parser_;
|
|
};
|
|
|
|
#endif //_LIBCPP_STD_VER > 17
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
#endif // _LIBCPP___FORMAT_FORMATTER_BOOL_H
|