From 597b4d4afbb4177bacbe1ac9a061b9858452b703 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sat, 11 Jun 2022 14:20:28 -0700 Subject: [PATCH] ircd::spirit: Add optimized interpositions for qi char_range / string_parse. --- include/ircd/spirit/qi_char.h | 70 ++++++++++++++++++++++++++++++--- include/ircd/spirit/qi_string.h | 46 ++++++++++++++++++++++ 2 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 include/ircd/spirit/qi_string.h diff --git a/include/ircd/spirit/qi_char.h b/include/ircd/spirit/qi_char.h index ebb2c2cba..5f5a662e7 100644 --- a/include/ircd/spirit/qi_char.h +++ b/include/ircd/spirit/qi_char.h @@ -82,13 +82,13 @@ boost::spirit::qi::literal_char [[gnu::hot]] - bool test(CharParam ch, Context &) const + bool test(const CharParam ch, Context &) const { static_assert(std::is_same::value); @@ -96,7 +96,7 @@ boost::spirit::qi::literal_char::call(ch)); #endif - return this->ch == char_type(ch); + return this->ch == ch; } template @@ -108,9 +108,67 @@ boost::spirit::qi::literal_char - literal_char(Char ch) - :ch(static_cast(ch)) + constexpr + literal_char(const char ch) + :ch(ch) {} }; #endif + +#if defined(__clang__) +template<> +struct [[clang::internal_linkage, gnu::visibility("internal")]] +boost::spirit::qi::char_range +:char_parser +< + char_range, + typename char_encoding::standard::char_type +> +{ + using CharEncoding = boost::spirit::char_encoding::standard; + using char_type = typename CharEncoding::char_type; + using char_encoding = CharEncoding; + + private: + const char_type from alignas(16); + const char_type to alignas(16); + + public: + template + [[gnu::hot]] + bool test(const CharParam ch_, Context &) const + { + using ischar = typename traits::ischar; + using ircd::boolmask; + + #ifndef NDEBUG + ircd::always_assert(ischar::call(ch_)); + #endif + + const char_type ch(ch_); + const char_type res[2] + { + boolmask(ch >= from), + boolmask(ch <= to), + }; + + return res[0] & res[1]; + } + + template + info what(Context &) const + { + return info {"char-range"}; + } + + constexpr + char_range(const char_type from, + const char_type to) + :from{from} + ,to{to} + { + assert(from <= to); + } +}; +#endif diff --git a/include/ircd/spirit/qi_string.h b/include/ircd/spirit/qi_string.h new file mode 100644 index 000000000..3b934ab66 --- /dev/null +++ b/include/ircd/spirit/qi_string.h @@ -0,0 +1,46 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2022 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_SPIRIT_STRING_H + +#if defined(__clang__) +namespace boost::spirit::qi::detail +{ + template + [[gnu::always_inline]] + inline bool + string_parse(const char *str, + iterator &first, + const iterator &last, + attribute &attr) + { + char ch; + iterator it(first); + #pragma clang loop unroll(disable) vectorize(enable) + for(ch = *str; likely(ch != 0); ch = *str) + { + if(likely(it == last)) + return false; + + if(unlikely(ch != *it)) + return false; + + ++it; + ++str; + } + + spirit::traits::assign_to(first, it, attr); + first = it; + return true; + } +} +#endif