Do some tactical inlining across lexer and parser. (#4307)

These are based on looking at our compilation benchmark and looking at
function bodies that seem surprising to not get inlined.

Note that this will have a bit more impact on x86 where function call
overhead (especially due to pushing and popping registers) is a bit
higher than Arm.

For a recent AMD server, this makes parsing around 15% faster, and full
"check" phase 5% faster.

Benchmark results:
```
name                                               old cpu/op   new cpu/op   delta
BM_CompileAPIFileDenseDecls<Phase::Lex>/256        40.2µs ± 2%  37.8µs ± 1%   -5.89%  (p=0.000 n=19+17)
BM_CompileAPIFileDenseDecls<Phase::Lex>/1024        190µs ± 2%   181µs ± 2%   -4.93%  (p=0.000 n=19+18)
BM_CompileAPIFileDenseDecls<Phase::Lex>/4096        779µs ± 1%   745µs ± 2%   -4.29%  (p=0.000 n=19+19)
BM_CompileAPIFileDenseDecls<Phase::Lex>/16384      3.44ms ± 1%  3.32ms ± 3%   -3.32%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Lex>/65536      14.6ms ± 2%  14.3ms ± 3%   -2.46%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Lex>/262144     66.7ms ± 2%  65.0ms ± 4%   -2.52%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/256      85.7µs ± 2%  71.3µs ± 2%  -16.77%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/1024      421µs ± 2%   352µs ± 2%  -16.38%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/4096     1.71ms ± 2%  1.44ms ± 2%  -15.89%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/16384    7.19ms ± 2%  6.10ms ± 2%  -15.24%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/65536    29.8ms ± 2%  25.3ms ± 2%  -14.91%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/262144    127ms ± 2%   109ms ± 2%  -14.28%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/256       785µs ± 1%   752µs ± 1%   -4.13%  (p=0.000 n=20+18)
BM_CompileAPIFileDenseDecls<Phase::Check>/1024     1.71ms ± 1%  1.62ms ± 1%   -5.17%  (p=0.000 n=20+18)
BM_CompileAPIFileDenseDecls<Phase::Check>/4096     5.28ms ± 1%  4.97ms ± 1%   -6.04%  (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/16384    20.2ms ± 1%  19.0ms ± 2%   -5.98%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/65536    83.8ms ± 1%  78.9ms ± 2%   -5.84%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/262144    354ms ± 1%   335ms ± 1%   -5.41%  (p=0.000 n=19+20)
```
This commit is contained in:
Chandler Carruth
2024-09-15 23:48:19 +00:00
committed by GitHub
parent 580e84513c
commit 06344aeb7c
4 changed files with 44 additions and 48 deletions
-28
View File
@@ -20,10 +20,6 @@
namespace Carbon::Lex {
auto TokenizedBuffer::GetKind(TokenIndex token) const -> TokenKind {
return GetTokenInfo(token).kind();
}
auto TokenizedBuffer::GetLine(TokenIndex token) const -> LineIndex {
return FindLineIndex(GetTokenInfo(token).byte_offset());
}
@@ -159,16 +155,6 @@ auto TokenizedBuffer::GetMatchedOpeningToken(TokenIndex closing_token) const
return closing_token_info.opening_token_index();
}
auto TokenizedBuffer::HasLeadingWhitespace(TokenIndex token) const -> bool {
return GetTokenInfo(token).has_leading_space();
}
auto TokenizedBuffer::HasTrailingWhitespace(TokenIndex token) const -> bool {
TokenIterator it(token);
++it;
return it != tokens().end() && GetTokenInfo(*it).has_leading_space();
}
auto TokenizedBuffer::IsRecoveryToken(TokenIndex token) const -> bool {
if (recovery_tokens_.empty()) {
return false;
@@ -359,20 +345,6 @@ auto TokenizedBuffer::AddLine(LineInfo info) -> LineIndex {
return LineIndex(static_cast<int>(line_infos_.size()) - 1);
}
auto TokenizedBuffer::GetTokenInfo(TokenIndex token) -> TokenInfo& {
return token_infos_[token.index];
}
auto TokenizedBuffer::GetTokenInfo(TokenIndex token) const -> const TokenInfo& {
return token_infos_[token.index];
}
auto TokenizedBuffer::AddToken(TokenInfo info) -> TokenIndex {
token_infos_.push_back(info);
expected_max_parse_tree_size_ += info.kind().expected_max_parse_tree_size();
return TokenIndex(static_cast<int>(token_infos_.size()) - 1);
}
auto TokenizedBuffer::CollectMemUsage(MemUsage& mem_usage,
llvm::StringRef label) const -> void {
mem_usage.Add(MemUsage::ConcatLabel(label, "allocator_"), allocator_);
+32
View File
@@ -477,6 +477,38 @@ using LexerDiagnosticEmitter = DiagnosticEmitter<const char*>;
// A diagnostic emitter that uses tokens as its source of location information.
using TokenDiagnosticEmitter = DiagnosticEmitter<TokenIndex>;
inline auto TokenizedBuffer::GetKind(TokenIndex token) const -> TokenKind {
return GetTokenInfo(token).kind();
}
inline auto TokenizedBuffer::HasLeadingWhitespace(TokenIndex token) const
-> bool {
return GetTokenInfo(token).has_leading_space();
}
inline auto TokenizedBuffer::HasTrailingWhitespace(TokenIndex token) const
-> bool {
TokenIterator it(token);
++it;
return it != tokens().end() && GetTokenInfo(*it).has_leading_space();
}
inline auto TokenizedBuffer::GetTokenInfo(TokenIndex token) -> TokenInfo& {
return token_infos_[token.index];
}
inline auto TokenizedBuffer::GetTokenInfo(TokenIndex token) const
-> const TokenInfo& {
return token_infos_[token.index];
}
inline auto TokenizedBuffer::AddToken(TokenInfo info) -> TokenIndex {
TokenIndex index(token_infos_.size());
token_infos_.push_back(info);
expected_max_parse_tree_size_ += info.kind().expected_max_parse_tree_size();
return index;
}
} // namespace Carbon::Lex
#endif // CARBON_TOOLCHAIN_LEX_TOKENIZED_BUFFER_H_
-17
View File
@@ -66,16 +66,6 @@ Context::Context(Tree& tree, Lex::TokenizedBuffer& tokens,
tokens_->GetKind(*end_));
}
auto Context::AddLeafNode(NodeKind kind, Lex::TokenIndex token, bool has_error)
-> void {
tree_->node_impls_.push_back(Tree::NodeImpl(kind, has_error, token));
}
auto Context::AddNode(NodeKind kind, Lex::TokenIndex token, bool has_error)
-> void {
tree_->node_impls_.push_back(Tree::NodeImpl(kind, has_error, token));
}
auto Context::ReplacePlaceholderNode(int32_t position, NodeKind kind,
Lex::TokenIndex token, bool has_error)
-> void {
@@ -143,13 +133,6 @@ auto Context::ConsumeChecked(Lex::TokenKind kind) -> Lex::TokenIndex {
return Consume();
}
auto Context::ConsumeIf(Lex::TokenKind kind) -> std::optional<Lex::TokenIndex> {
if (!PositionIs(kind)) {
return std::nullopt;
}
return Consume();
}
auto Context::FindNextOf(std::initializer_list<Lex::TokenKind> desired_kinds)
-> std::optional<Lex::TokenIndex> {
auto new_position = position_;
+12 -3
View File
@@ -97,10 +97,14 @@ class Context {
// Adds a node to the parse tree that has no children (a leaf).
auto AddLeafNode(NodeKind kind, Lex::TokenIndex token, bool has_error = false)
-> void;
-> void {
tree_->node_impls_.push_back(Tree::NodeImpl(kind, has_error, token));
}
// Adds a node to the parse tree that has children.
auto AddNode(NodeKind kind, Lex::TokenIndex token, bool has_error) -> void;
auto AddNode(NodeKind kind, Lex::TokenIndex token, bool has_error) -> void {
tree_->node_impls_.push_back(Tree::NodeImpl(kind, has_error, token));
}
// Replaces the placeholder node at the indicated position with a leaf node.
//
@@ -154,7 +158,12 @@ class Context {
// If the current position's token matches this `Kind`, returns it and
// advances to the next position. Otherwise returns an empty optional.
auto ConsumeIf(Lex::TokenKind kind) -> std::optional<Lex::TokenIndex>;
auto ConsumeIf(Lex::TokenKind kind) -> std::optional<Lex::TokenIndex> {
if (!PositionIs(kind)) {
return std::nullopt;
}
return Consume();
}
// Find the next token of any of the given kinds at the current bracketing
// level.