Commit Graph
196 Commits
Author SHA1 Message Date
David BlaikieandRichard Smith dfed743de2 Add vtable pointers to class layout (#4407)
A small step to virtual functions - adding vtable pointers to the
layout, but not initializing or otherwise using them at this stage.

A few open design questions I'd love feedback on:

* Is this the right/good enough SemIR representation for now? This patch
adds a `is_dynamic` attribute to `SemIR::Class` and populates/flags it
based on the flag of the base class, or if any virtual function is
declared in the class (or, at least that's my intent). Some other
options include:
* Each `Class` could store a `ClassId` (or `TypeId`?) of the (possibly
indirect, possibly self) base class that is the first one that is
dynamic/has a vtable pointer
* Could make the property narrower, like `has vtable pointer` and have
it `true` only on the type that introduces the vtable - then derived
classes would have to walk their base classes to check if they're the
one that needs to define the vtable pointer or not
* Should the vtable be the first element in the type? If there's a
non-dynamic base type, we could have a layout that's `{<non-dynamic base
type>, vtable ptr, <derived members>}`? Derived types would still be
able to uniquely identify where their vtable pointer is just fine... -
and the vtable pointer is, in a sense, a member of that intermediate
type, so it does seem a bit strange to force it to the front - but I
guess it's probably more efficient in some ways?

Open to any other suggestions/advice/thoughts on the direction, etc.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-10-16 21:26:17 +00:00
Jon Ross-Perkins 77facdd775 Remove unused benchmark_main.h (#4409)
This was refactored to Testing::GetExePath, but apparently the header
was missed.
2024-10-15 20:43:26 +00:00
Jon Ross-Perkins e2256516e8 Fix InitLLVM argv (#4405)
`args_.push_back(nullptr);` can resize `args_`, invalidating `argv`. The
order needs to be switched.
2024-10-13 17:47:57 +00:00
Jon Ross-Perkins 9b0519d236 Convert CommandLine member references to pointers (#4301)
This follows up on a [style
question](https://discord.com/channels/655572317891461132/821113559755784242/1283516297686286377)
about whether to prefer reference members or pointers. This PR converts
to pointers as a demonstration of that style choice.

Note, I'm trying to update constructors to match use of `*` based on
whether they keep a reference. I'm removing a few `const&` uses where no
reference was kept (i.e., it was just copied, and didn't seem worth a
move).

I'm changing `AddArgImpl` to return an `Arg*` because it just gets
passed to a constructor, seems simpler this way.
2024-09-20 20:30:04 +00:00
Chandler Carruth 1d904556ef Remove [[clang::preserve_most]] (#4319)
These appear to be causing some subtle misinteractions with MSan that we
don't understand, and may be a compiler bug. =/ Fortunately, they
weren't essential to the performance gains so just remove them for now.
When benchmarked on an x86 server, where I would expect this to be more
important due to relatively few named registers, the performance change
appears to be either an improvement or in the noise.

Huge credit to Jon for tracking down that this is related to the MSan
issues.
2024-09-16 22:55:55 +00:00
4845f40dff Switch CARBON_CHECK to a format string API (#4285)
This switches `DCHECK` and `FATAL` as well.

The goal is to reduce the code size impact of these assertions so that
we can keep more of them enabled. Currently, the largest cost I see from
`CHECK` is not the actual check or the cold code itself, but actually
the failure to inline trivial functions due to the presence of the cold
code. This means that our goal isn't to reduce apparent code size in the
final binary but the LLVM IR cost assessed for these routines in the
inliner, which closely correlates with code size but is a bit different.

As discussed in #4283, experimentation shows that a single function call
with a minimal number of arguments is the lowest cost model for these.
This is easily achieved with a format-string API that internally uses
`llvm::formatv`. This PR is essentially the `CHECK` version of #4283.

However, the check macros are substantially harder to make work with
both format strings and streaming because they also take a condition.
Also, unexpectedly, I was very successful at devising a regular
expression based automated rewrite from the streaming to the format
string form with only low 10s of manual fixes. This includes compacting
strings broken up across lines, etc. Given how well that went, I've
prepared this PR which just directly switches to the format string API
and migrate everything to use it.

One nice side-effect is that the format string approach ends up greatly
simplifying the implementation here as well.

This is ... *shockingly* effective. Parsing speeds up by more than 3%
with just this change. And checking speeds up by **8%** with this change
alone:
```
BM_CompileAPIFileDenseDecls<Phase::Parse>/256      86.3µs ± 1%  82.9µs ± 1%  -3.94%  (p=0.000 n=17+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/1024      431µs ± 1%   415µs ± 1%  -3.76%  (p=0.000 n=18+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/4096     1.77ms ± 1%  1.71ms ± 1%  -3.18%  (p=0.000 n=18+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/16384    7.44ms ± 1%  7.17ms ± 2%  -3.56%  (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/65536    30.7ms ± 1%  29.7ms ± 1%  -3.15%  (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/262144    131ms ± 1%   127ms ± 1%  -2.81%  (p=0.000 n=18+18)
BM_CompileAPIFileDenseDecls<Phase::Check>/256       878µs ± 2%   800µs ± 1%  -8.91%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/1024     1.88ms ± 2%  1.72ms ± 1%  -8.56%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/4096     5.78ms ± 2%  5.28ms ± 1%  -8.70%  (p=0.000 n=20+18)
BM_CompileAPIFileDenseDecls<Phase::Check>/16384    21.9ms ± 1%  20.1ms ± 1%  -8.02%  (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/65536    90.4ms ± 2%  83.1ms ± 1%  -8.04%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/262144    381ms ± 2%   352ms ± 1%  -7.79%  (p=0.000 n=19+19)
```

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2024-09-12 16:42:08 +00:00
Jon Ross-Perkins de57c9988c Break out driver environment info into its own type. (#4299)
I want to split commands out so that we don't keep piling onto driver
(particularly as I'm eyeing clang-related commands). This extracts out
the DriverEnv so that it can be easily shared, with the CompilationUnit
as an example.

CARBON_VLOG_TO is to remove the vlog_stream_ requirement of CARBON_VLOG.
2024-09-12 00:06:31 +00:00
Chandler Carruth 0c8ab663c9 Migrate all CARBON_VLOG to the format string variant. (#4284)
This mostly uses a hilarious set of regular expressions to mechanically
switch all but two uses, and then manually fixed the last two. There
weren't too many.

Also simplifies the `vlog` implementation now that it's all going
through a format string.

This alone has a nice impact on parse and check of about 2% and 1%
respectively. The impact on lex in my timings looks like noise (no
change in instruction count, unlike the other phases).
```
name                                               old cpu/op   new cpu/op   delta
BM_CompileAPIFileDenseDecls<Phase::Lex>/256        39.1µs ± 3%  38.1µs ± 2%  -2.42%  (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Lex>/1024        187µs ± 3%   183µs ± 1%  -2.30%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Lex>/4096        776µs ± 4%   756µs ± 1%  -2.62%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Lex>/16384      3.36ms ± 1%  3.33ms ± 1%  -0.90%  (p=0.000 n=18+18)
BM_CompileAPIFileDenseDecls<Phase::Lex>/65536      14.4ms ± 2%  14.2ms ± 1%  -1.41%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Lex>/262144     65.7ms ± 1%  65.2ms ± 2%  -0.86%  (p=0.002 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/256      87.5µs ± 1%  86.3µs ± 1%  -1.43%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/1024      438µs ± 2%   431µs ± 1%  -1.54%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/4096     1.81ms ± 2%  1.77ms ± 1%  -2.12%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/16384    7.54ms ± 1%  7.43ms ± 1%  -1.44%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/65536    31.2ms ± 1%  30.6ms ± 1%  -2.03%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/262144    133ms ± 1%   130ms ± 1%  -1.85%  (p=0.000 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/256       882µs ± 1%   878µs ± 1%  -0.52%  (p=0.001 n=17+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/1024     1.90ms ± 2%  1.88ms ± 1%  -1.17%  (p=0.000 n=19+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/4096     5.85ms ± 2%  5.76ms ± 1%  -1.43%  (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/16384    22.2ms ± 2%  21.9ms ± 2%  -1.20%  (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/65536    91.2ms ± 2%  90.3ms ± 1%  -1.00%  (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/262144    382ms ± 1%   380ms ± 1%  -0.51%  (p=0.003 n=18+19)
```
2024-09-11 12:11:23 +00:00
e48101b608 Switch CARBON_VLOG to support a format string API. (#4283)
The goal is to replace our stream operator APIs with format string APIs
that can be made to have much less impact on inlining and other
optimizations of the performance critical path through the code.

Several experiments show that the most compact representation we can
arrange for is one that calls an uninlined function and passes a minimal
number of arguments to it. It doesn't help to do any work to minimize
the arguments such as building a lambda -- the cost of extra code to
merge the arguments is likely to outweigh the benefit.

Initial experiments showed that switching a hot but uninlined function
to this new API enabled inlining and the subsequent performance
improvement.

This also adds a 'TemplateString` utility that allows using a string
literal as a template parameter. This is useful to remove the format
string itself from the arguments passed to the function by passing it as
a template argument instead.

Currently, support is left in place for both APIs because with
`CARBON_VLOG` we can detect whether or not any message was provided
expecting a format string. This should allow incrementally migrating
code to this API. I've added some test coverage in this PR, but I'll
separate out any switching of parts of the codebase over.

The goal is to eventually replace all the usages and remove the
streaming support entirely.

This PR doesn't update `CARBON_CHECK` in the same way because it is
substantially more complex to switch. I have a few experimental PRs
looking at that and will discuss how best to approach this with the
specific challenges check presents separately. But the goal is for all
of the macro-based output APIs to move to format strings rather than
streams.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-09-11 10:38:59 +00:00
Jon Ross-Perkins 43c6259fb2 Update LLVM and fix formatv issues. (#4282)
https://github.com/llvm/llvm-project/pull/105745 increased validation of
formatv requirements, this fixes a couple issues.

Note the CommandLine case was untested, and caught separately.
2024-09-09 23:54:35 +00:00
Richard SmithandJon Ross-Perkins 187a3608df Use As and ImplicitAs interfaces for conversions. (#4209)
Add these interfaces to the core library. For now, they're two separate
interfaces because we don't yet support one interface extending another.

This collapses a lot of the layering in check: for example, the call
building logic depends on implicit conversions, conversions now depend
on the overloaded operator machinery, and that machinery depends on
building calls.

In passing, improve the diagnostics for failing to find a name required
from the prelude. Also convert all the transitively-called code from
`NodeId` to `LocId` given the latter is what the conversion machinery
has available.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-09-05 23:39:58 +00:00
Chandler Carruth 5d0ec91c20 Collection of minor tweaks to get approx. 10-15% compile time (#4245)
Most of these are about enabling inlining, in a couple of cases moving
code to a header and throughout switching to `CARBON_DCHECK`. The code
size of `CARBON_CHECK` seems to make inliing quite unreliable. I'm going
to think about whether there are ways to improve this, but a reasonably
small number of these seem worth switching for now to get some compile
time savings.

Also moves VLOG out of the hot path which helps a bit as well.

All combined, this net a bit over 10%, although it varies a bit exactly
how much. We're now pretty consistently over 800k lines/second for check
in the compilation benchmark for files >=4k lines, which makes me happy.
That's remarkably close to our original target.

Not really planning to keep optimizing here, just was glancing at the
profile and many of these stood out to me and were easy to fix.
2024-08-23 14:43:54 +00:00
David Blaikie 5a11048c34 Remove some explicit (Mutable)ArrayRef constructions (#4238)
Rely on implicit conversion in call sites and initialization.

Removing the explicit conversions is only code simplication.
Moving from `auto x = Y(z)` to `Y x = z;` helps ensure that only
implicit constructors/conversions are happening (whereas the prior
syntax allows explicit conversions) which can help with readability
since implicit conversions are generally "less
complex"/risky/attention-requiring.
2024-08-22 19:40:54 +00:00
Chandler Carruth 72cb9d0d06 Refactor testing exe path and benchmark main handling. (#4216)
Consolidates both main libraries into `//testing/base`, and factors out
the exe path handling for benchmarks and unit tests into a common
library to remove duplication. Refactors how that logic is managed to be
cleaner and avoid a confusing bool that came up in code review.

Updates all the tests and benchmarks that use these. I still need to
update other benchmarks to use the same main, but I wanted to keep this
PR somewhat minimal.

This also fixes a bug noticed in passing that the compilation benchmark
didn't have the required dependency on the benchmark library itself,
just the benchmark main library.
2024-08-14 17:50:08 +00:00
a9c815c9f4 Introduce a source generator and end-to-end compile benchmarks (#4124)
The big addition here is a very, very rough and very early skeleton of a
source code generator framework. This builds upon the lexers identifier
synthesis logic, improving on its framework and wiring it up with the
most rudimentary of source file generation. This is just enough to
roughly replicate my "big API file" source code benchmarks.

The source generation works *very* hard to both vary the structure and
content of the source as much as possible while ensuring the same
*total* amount of each construct is in use, from bytes in identifiers to
line breaks, parameters, etc. This lets us generate randomly structure
inputs that should consistently take the exact same amount of total work
to compile.

The complex identifier synthesis logic from the lexer's benchmark is
moved over here and the lexer uses APIs in the source generator for
identifiers. The other source synthesis in the lexer's benchmark isn't
yet moved over, but should likely be slowly absorbed here as it can be
refactored into a more principled and re-usable form. Some bits may stay
of course if they're just too lexer-specific.

Next, this adds a simple end-to-end compile benchmark for the driver
that directly and much more clearly reproduces all the measurements I've
done manually up until now. It should also be easy to extend to more
patterns over time as we add support to the source generator to produce
those patterns.

Last but not least, I've added a tiny CLI to the source generator so
that you can generate source code manually. This is especially nice for
generating demo source code to actually run through the driver or look
at in an editor. The CLI can also generate C++ source code which lets us
do some minimal comparative benchmarking between Carbon and C++/Clang.

There are huge number of TODOs in the source generation framework. This
is going to be a large ongoing effort I suspect.

There are also a bunch of rough edges I've left to try and get this out
for review sooner. I've left TODOs for refactorings that really need to
be done here, but hoping these can maybe be follow-ups. If not, please
flag and I'll try to layer them on here.

Sample compile benchmark output, nicely showing where we are w.r.t. our
goal speeds (2x behind on lex and check, 5x on parse) at least on a
recent AMD server CPU:
```
------------------------------------------------------------------------------------------------------
Benchmark                                                 Time             CPU   Iterations      Lines
------------------------------------------------------------------------------------------------------
BM_CompileAPIFileDenseDecls<Phase::Lex>/256           29420 ns        29419 ns        22860 6.62847M/s
BM_CompileAPIFileDenseDecls<Phase::Lex>/1024         146130 ns       146128 ns         4840 6.69959M/s
BM_CompileAPIFileDenseDecls<Phase::Lex>/4096         601584 ns       601577 ns         1020 6.69573M/s
BM_CompileAPIFileDenseDecls<Phase::Lex>/16384       2547578 ns      2547313 ns          280   6.404M/s
BM_CompileAPIFileDenseDecls<Phase::Lex>/65536      10816591 ns     10816389 ns           80 6.05193M/s
BM_CompileAPIFileDenseDecls<Phase::Lex>/262144     52191320 ns     52189828 ns           20 5.02261M/s
BM_CompileAPIFileDenseDecls<Phase::Parse>/256        101706 ns       101698 ns         6900 1.91745M/s
BM_CompileAPIFileDenseDecls<Phase::Parse>/1024       512161 ns       512162 ns         1380  1.9115M/s
BM_CompileAPIFileDenseDecls<Phase::Parse>/4096      2078426 ns      2078430 ns          340   1.938M/s
BM_CompileAPIFileDenseDecls<Phase::Parse>/16384     8795786 ns      8795583 ns          100 1.85468M/s
BM_CompileAPIFileDenseDecls<Phase::Parse>/65536    35073596 ns     35072973 ns           20 1.86639M/s
BM_CompileAPIFileDenseDecls<Phase::Parse>/262144  151100688 ns    151097370 ns           20 1.73483M/s
BM_CompileAPIFileDenseDecls<Phase::Check>/256        957059 ns       957049 ns          740 203.751k/s
BM_CompileAPIFileDenseDecls<Phase::Check>/1024      1956134 ns      1955985 ns          360 500.515k/s
BM_CompileAPIFileDenseDecls<Phase::Check>/4096      5797864 ns      5797417 ns          120 694.792k/s
BM_CompileAPIFileDenseDecls<Phase::Check>/16384    21219608 ns     21217584 ns           40 768.843k/s
BM_CompileAPIFileDenseDecls<Phase::Check>/65536    96311116 ns     96302334 ns           20 679.734k/s
BM_CompileAPIFileDenseDecls<Phase::Check>/262144  371637963 ns    371609964 ns           20 705.387k/s
```

Lest someone think this is *bad*, the fact that we're already within 2x
of our rather audacious goals makes me quite happy. =D

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-08-13 19:37:55 +00:00
Jon Ross-Perkins efa158d496 Refactor InstBlockStack to use ArrayStack. (#4104)
The use of ArrayStack here is intended to simplify the logic, and also
make better use of the inst heap allocations. Prior changes #4101 and
#4103 removed the less related logic from InstBlockStack, although #4103
is the actual part that blocked using ArrayStack.

BTW, note the PrintForStackDump implementation was incorrect because it
didn't apply size_. This simplification fixes the issue.
2024-07-03 19:19:57 +00:00
Jon Ross-PerkinsandChandler Carruth d437e4bffe Create an array stack type for a shared use-case (#4100)
Based on discussion around the region handling in generic_region_stack,
create a generic structure for the stack-of-vectors support. I also want
to add this to InstBlockStack, but that's a little more complex due to
GlobalInit, so cutting a PR here to check with review.

My work here is how I noticed #4099; I want to be sure that I'm correct
about the issue, but it's the difference between being able to use
PeekArray or not.

Note in scope_stack.h, I believe we could remove next_compile_time_index
and make it just based on elements_size(). However, I want to verify
with you before I make further changes there.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2024-07-03 16:58:47 +00:00
Chandler Carruth a8748f3e2d Key context improvements (#4095)
This injects a customization point for hashtable-specific equality
testing that the key context uses by default. While this is rarely
needed, there are LLVM types where it is necessary and it seems a good
general tool to have to avoid unnecessary complexity from custom key
contexts when a simple customization of equality is all that is
required.

This also adds a CRTP mixin for implementing a common pattern of key
contexts where the context provides translation of some key types into
another type, potentially using state. Rather than having to implement
the entire key context API, code can derive from this template and
simply provide a set of overloads for the types it wants to translate.
Any key types used which can be passed to one of those overloads will
get translated before following the same logic as the default key
context. While this updates the only usage so far of this pattern, a
subsequent PR will add several more users making the pattern worth
abstracting here.
2024-07-02 21:20:14 +00:00
bf736e6b03 A collection of hashing improvements from using hashtables. (#4094)
LLVM's `APInt` and `APFloat` need specialized handling to be used
effectively in hashtables. We can't inject overrides into LLVM so we
need to handle them in our hashing routine.

There were also problematic limits on hashing pairs and tuples. First,
the unique-object-representation hashing of pairs was more restricted
than tuples which was a problematic asymmetry and isn't needed. But the
larger issue is that we didn't support recursively hashing when
necessary. That requires a careful predicate to avoid infinite recursion
but lets us handle important use cases for hashtables with a tuple as a
key.

Also added support for hashing arrays that recurse in addition to arrays
where we can hash the raw storage, and added overloads to redirect to
common array handling from various array-like types.

Last but not least, re-worked the constraint model for hashing as raw
data to not override custom hashing functions.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2024-07-02 20:53:48 +00:00
Chandler Carruth 6310293330 Fix some subtle UB found by MSan. (#4093)
Technically, any small size buffer's lifetime has ended by the time we
get to the base's destructor. This means its no longer valid to access
table contents if stored there from the base destructor. We need to
handle destruction in the table class instead.

This ends up being a trivial change because the logic is already
factored out, we just need to call it from a different point.
2024-06-29 07:44:34 +00:00
Chandler CarruthandRichard Smith 9d95c6836d Add a key-returning callback insert to Set. (#4072)
This turns out to be super useful now that we have the `key_context`
mechanism and can do much more meaningful heterogeneous lookups, where
the stored key can be *very* different from the lookup key.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-06-22 00:57:41 +00:00
Chandler CarruthandRichard Smith af6312a3aa Add assignment support to the hashtables. (#4066)
This lets copy and move assignment work. While it's a bit suboptimal to
do assignment with these tables, it still seems like an unreasonable
burden to not allow the basics to work. Even the toolchain ended up
doing this in a few places.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-06-21 21:49:56 +00:00
Chandler CarruthandJon Ross-Perkins b51dc7f8e2 Introduce version and build info stamping. (#4054)
This adds a defined Carbon version to the Bazel build and codebase that
can be used both to implement features like version checks and to report
a meaningful version on the command line. This replaces a hard-coded
string and a TODO in the driver.

As part of this, it adds support for defining the version in Bazel, and
special build flags for overriding relevant parts such as the
pre-release marker used. The exact structure and meaning of our version
string, including the pre-release parts, is implemented here in line
with the draft proposal:

https://docs.google.com/document/d/11S5VAPe5Pm_BZPlajWrqDDVr9qc7-7tS2VshqO0wWkk/edit?resourcekey=0-2YFC9Uvl4puuDnWlr2MmYw

This also introduces a workspace status command to the repository to
extract the git commit SHA and other information when building, and the
logic to stamp that into binaries as part of the version string when
useful. The technique used leverages weak symbols with whole archive
linking to allow a link-time override of unstamped data with stamped
data in the leaf executable. This makes building with `--stamp` a
reasonable default, especially for development builds. The CI system is
explicitly opted out of this as there it has no benefit.

Last but not least, all of these are wired into the install rules so
that we build installable packages with the version number in a
conventional place in the directory and filename.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-06-18 00:33:05 +00:00
Chandler Carruthandjosh11b 07fadc6474 Add growth API to the new hashtables. (#4044)
This adds two different growth APIs. This is instead of the more
conventional STL `reserve` method. One allows users that aren't trying
to grow in anticipation of an *exact* count of insertions, but generally
trying to size the table to the correct ballpark with a power-of-two
estimate.

The other API allows pre-growing to allow a specific number of
insertions to be performed without further growth. This API takes the
maximum load factor and other implementation details into account.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2024-06-12 19:38:35 +00:00
Chandler Carruth b773ff3695 Reduce the new hashtable test times. (#4047)
While it was convenient once to have an immediate check while inserting,
it is indeed far too quadratic. The test was taking 30-60 seconds for
me. =[ So most of the fix here is just to stop doing the check on every
insertion for all previous elements.

There were a few other somewhat slow steps, and I tried to pull those
back as well. I don't think we lose any utility here. Now everything
runs nice and quickly. =]
2024-06-11 03:43:18 +00:00
Chandler Carruth 26ead9addc Add a build of boost_unordered for benchmarking. (#4045)
This uses a header-only extraction of the Boost unordered hashtable
project to allow a trivial Bazel build and for us to benchmark against
it effectively.
2024-06-10 22:10:10 +00:00
Chandler CarruthandRichard Smith 3be57b71e0 Collect more detailed metrics on hashtables. (#4046)
Previously we just looked at the raw count of probed keys. Now, we
compute the average and max of both the probe _distance_ measured in the
number of _groups_ probed, and the number of probe _compares_ measured
in the compares required _before_ finding the matching entry.

This lets us understand the relative impact of probe-distance vs. tag
collisions on a given set of benchmark keys. Some of this is motivated
by considering additional optimization techniques similar to those used
in Boost's table and the F14 table from Facebook/Meta.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-06-10 21:43:13 +00:00
Chandler Carruthandjosh11b 21a81bc59e Introduce custom hash table data structures. (#3940)
The hash table design is heavily based on Abseil's ["Swiss
Tables"][swiss-tables] design. It uses an array of bytes storing
metadata about each entry and an array of entries where each is a pair
of key and value. The metadata byte consists of 7-bits of hash of the
key (distinct from the bits used to index the table), and one bit
indicating the presence of a special entry -- either empty or deleted.

[swiss-tables]: https://abseil.io/about/design/swisstables

There are a large range of optimizations and other nuanced aspects of
this hash table design and implementation, a good point to understand
that context is `raw_hashtable.h` which has an overview of the design
and references to various other files for relevant details.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2024-06-08 01:50:02 +00:00
Chandler Carruth 8c64f0bfdd Add -Wmissing-prototypes and fix issues it finds. (#4019)
Most of these are places where we failed to include a header file and
simply never got an error about this. The fix is to include the header
file.

Most other cases are functions that should have been marked `static` but
were not. Finding all of these was a main motivation for me enabling the
warning despite how much work it is.

One complicating factor was that we weren't including the `handle.h` for
all the state-based handler functions. While this isn't a tiny amount of
code, it is just declarations and doesn't add any extra dependencies. It
also lets us have the checking for which functions need to be `static`
and which don't. For the `parse` library I had to add the `handle.h`
header as well, I tried to match the design of it in `check`.

I have also had to work around a bug in the warning, but given the value
it seems to be providing, that seems reasonable. I've filed the bug
upstream: https://github.com/llvm/llvm-project/issues/94138

I also had to use some hacks to work around limitations of Bazel rules
that wrap `cc_library` rules and don't expose `copts`. I filed a bug for
`cc_proto_library` specifically:
~https://github.com/bazelbuild/bazel/issues/22610~ 
https://github.com/bazelbuild/bazel/issues/4446
2024-06-04 20:04:45 +00:00
Chandler Carruth dd0890619a Enable a couple of boring warnings. (#4018)
Just spotted these while looking at warnings that seem to fire on our
code are probably are things we'd fix if we saw them. None of these seem
important FWIW.

Also removes a redundant flag that is part of `-Wall`.

I have a follow-up for the high-value warning I spotted that motivated
me to look at all of this. But it's noisy so kept it as a separate PR.
2024-06-03 05:02:26 +00:00
Richard SmithandJon Ross-Perkins 3c01ee69ed Move information on the token associated with a parse node from the .def file into the typed node. (#4001)
Instead of tracking the token associated with a parse node in the `.def`
file macro, track it on the typed node instead. List the token as a
field inside the node structure to show the order of the token relative
to the other components of the grammar production, and to allow the
token index to be accessed when the node is extracted.

Remove the corresponding information from the `.def` file, leaving
behind just a list of parse node kinds in the majority of cases.

This also removes the checking of the token kind associated with a parse
node in the case where the parse node has errors. Previously we had a
flag on the node kind to indicate whether we should check this, but per
[discord
discussion](https://discord.com/channels/655572317891461132/655578254970716160/1246214418979881052),
we have decided to remove this.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-05-31 23:11:51 +00:00
Jon Ross-Perkins 16942e4d07 Move errs tie to LLVM to include test infrastructure. (#4006)
The lack of flushing can sometimes be observed when streaming test
output, particularly with --dump_output. My thought is moving it into
our LLVM init is probably reasonable, given the driver's already doing
this for similar reasons; this means it's used in tests through our
gtest_main.cpp in addition to the driver.
2024-05-30 21:08:44 +00:00
Jon Ross-Perkins cda5f66d22 Refactor NodeCategory to provide a class API (#4004)
Mirroring #4003 for NodeCategory.

Note we template a lot more on NodeCategory's enum, so this is a
slightly more awkward delta.

Also, switch from Enum in KeywordModifierSet to RawEnumType for
consistency with EnumBase. The templating on NodeCategory had me
thinking about that more.
2024-05-29 22:47:50 +00:00
Chandler Carruth 582b2c04dd Allow GoogleTest tests to locate their executable path. (#3992)
This also factors out the code for doing this location from the driver
to a tiny helper library.

The motivation for this is letting tests locate data files like the
prelude or other files needed by the toolchain more easily. A subsequent
PR will use this heavily in the Clang runner and related logic for
example.
2024-05-28 23:50:57 +00:00
Richard Smith 5c8fa6ad5c Replace FoldingSet with DenseMap for instruction canonicalization. (#3979)
Switch from recursing into non-canonical instruction fields to
separately canonicalizing those fields. This means we now form canonical
`InstBlockId`s, `TypeBlockId`s, `IntId`s, `FloatId`s, and `BindNameId`s
at least in the cases when they're referenced by a constant instruction.

This reduces the overall runtime for @chandlerc's 10MLoC example by
27.5% on my machine.
2024-05-23 00:48:49 +00:00
Chandler Carruth b473eac5bc Fix clang-tidy issues in //common. (#3962)
These likely predate the CI integration for `clang-tidy` runs.

Most of these seem good generally, even though I disabled some with
nolint comments. The multilevel pointer one seems almost like a bug in
the check to detect the specific case of `memcpy`, but otherwise seems
like a solid lint.
2024-05-20 23:29:07 +00:00
Jon Ross-Perkins b19a87642b Update LLVM (#3956)
Fix use of newly deprecated API
2024-05-17 19:36:21 +00:00
f5c01ee487 Add a custom main library for benchmarks. (#3872)
This largely reproduces the upstream one, but has a few advantages:

1) It initializes LLVM which can be important if we use the backends.
2) It parses commandline flags with Abseil allowing the use of Abseil
   flags in benchmarks.
3) It flips the default for tabular display of results which we use
   pretty heavily.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2024-04-09 20:36:41 +00:00
Jon Ross-Perkins e66406ec93 Disable bugprone-macro-parentheses and let clang-format insert braces. (#3825)
-
[bugprone-macro-parentheses](https://clang.llvm.org/extra/clang-tidy/checks/bugprone/macro-parentheses.html)
-- this is just a false positive issue, I don't think it's helping us
catch bugs.
-
[InsertBraces](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#insertbraces)
-- although there's a warning about this creating issues due to
incomplete semantic information, it seems to be happy with our code, and
allows clang-format to fix something that clang-tidy would otherwise
warn about.
2024-04-02 11:18:25 +00:00
Richard SmithandJon Ross-Perkins f9ce0b194d Defer parsing of method bodies until the end of a suitable enclosing scope. (#3832)
In parse, form a list of methods that are defined inline, tracking where
they start, where they end, and which other inline methods are nested
within them.

In check, when we reach an inline method body, skip it and add it to a
worklist to be processed later. We also track when we reach the start
and end of a context in which inline method bodies are deferred, so that
we know when to replay the bodies.

When suspending a function definition to be processed later, the
`DeclNameStack` entry is moved to separate storage, including popping
the corresponding scopes from the scope stack and removing the
corresponding lexical names from lexical lookup. Later, when we return
to the function and parse its definition, the `DeclNameStack` entry is
restored. The same is done when we reach the end of a nested context
that can have inline methods, so that we can reenter the nested scope
before processing its members.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-04-01 18:25:27 +00:00
Richard Smith f0e940ddfd Initial support for builtin functions. (#3803)
For now, a builtin function is defined by specifying a string literal
initializer in a function declaration:

```carbon
fn MyBuiltin(a: i32) -> i32 = "builtin.name";
```

End-to-end support is included for a sample `"int.add"` builtin
performing integer addition, covering constant evaluation and code
generation.

The implementation here needs substantial refactoring before we'll be
ready to start adding more builtins. That refactoring work will be
coming next. This change is aiming to checkpoint some incremental
progress.
2024-03-21 20:46:34 +00:00
Jon Ross-Perkins a3b1c433be Remove legacy repo_name settings (#3772)
I'd kept these in to separate the bazel module update from the BUILD
file changes, then forgot about it. I think all of these can be cleanly
removed now. I think it's something we should clean up for consistency
with the bazel central repository names; I think it's best to reduce
that divergence.

llvm_zlib and llvm_zstd remain because of how llvm depends on the
particular names.
2024-03-13 22:58:56 +00:00
cui fliter fea2651e7c chore: fix typos (#3738)
Signed-off-by: cui fliter <imcusg@gmail.com>
2024-03-04 16:27:31 +00:00
Jon Ross-Perkins 1974e44fd9 Rename factory functions from 'Create' to 'Make' (#3706)
Similar to #3705, we actually have a mix of `Make` and `Create` in
factory functions too, so this PR is normalizing on `Make`. It's
intended to be consistent with the naming choice for Carbon factory
functions.

Note, MakeSyntheticBlock is the only one I feel a little weird about
because llvm's own APIs use Create, and this is essentially wrapping
LLVM calls. But the flipside is it also feels like a vague line to draw,
when we also differ from LLVM coding style in other ways.
2024-02-14 18:26:56 +00:00
Calvin 9305d9888b Add help information printing for a specific subcommand (#3699)
The `command_library` provides functionality for end users to query
documentation and help information about commands through the command
line interface itself. At present, this is implemented as:

* A flag, `--help`, on every command
* A meta subcommand, `help`, on every command that has other subcommands

To match with common functionality in other command line interfaces,
this PR amends the `help` meta subcommand to accept an optional
positional string argument. This argument specifies which subcommand to
print help information for. When not specified, the present behavior is
maintained, printing the help information for its parent command.

A potentially unexpected consequence of this implementation is that you
can query for help on meta subcommands as well: `help help` is a valid
input which prints the help information about the `help` meta subcommand
(e.g., same for `version`). I don't see any harm in this behavior so I
chose not to explicitly prevent it, but I'm open to preventing it if
deemed unwanted. (I'm also happy to workshop the strings in this PR.)

Closes #3694.

#### Before

```
$ carbon help compile
```
```
ERROR: Found unexpected positional argument or subcommand: 'compile'
```

#### After

```
$ carbon help compile
```
```
Compile Carbon source code.

This subcommand runs the Carbon compiler over input source code, checking it for errors and producing the requested output.

Error messages are written to the standard error stream.

Different phases of the compiler can be selected to run, and intermediate state can be written to standard output as these phases progress.

Subcommand 'compile' usage:
  carbon [-v] compile [OPTIONS] <FILE>...

...
```
2024-02-11 09:30:11 +00:00
Chandler Carruth 2e236759ca Switch //common to use C++20 concepts. (#3665)
This removes the use of `enable_if` and tries to adopt concepts instead
of type traits when available.

The `ostream.h` change is a bit subtle as it adds a restriction not
previously in place -- that the stream is *contvertible* to
`std::ostream` as well as having it as a base class. This seems to match
the intent of the code.

The `hashing.h` code adds an implementation detail concept, and so I've
also clarified that the dispatch namespace is an internal one that isn't
part of the public API.
2024-01-30 18:14:07 +00:00
Chandler Carruth bf02d1f4b0 Remove headers marked as unused by ClangD. (#3661)
This required adding a few headers that were found transitively before,
but not too many. This is sadly a fairly manual process of opening every
file in my IDE, but I think I got everything in `//common` and
`//toolchain`.

There are a few cases where technically we don't need `foo.h` to be
included into `foo.cpp`, but I've forced those to stay with a pragma.

I've tried to catch the places where we can cut deps in Bazel as well,
but not sure I got all of those.

I had been noticing these in other PRs and it seemed better to isolate
the change.
2024-01-29 16:15:35 +00:00
Chandler Carruth ebbdc11877 Switch to a "better" multiplicative hash constant. (#3629)
Testing this hash function with representative hash table
implementations showed significant differences in quality between
different multiplicative hashing constants. The constants used and
documented were OK but had clear limitations when merely using a single
64-bit multiplication. However, a search uncovered (partly by luck)
a constant that has empirically been shown to be both significantly
better than other constants and generally not have problematic
weaknesses. There are still plenty of collisions for string keys and
heavily loaded hash tables of course, but no examples of severe outlier
collision rates as observed with all other constants we have tried.

There is a slightly longer comment explaining some of this context and
the other constants we have tried in the PR as well.

To this day, we still don't fully understand why the constant used here
behaves so much better than other constants we have tried, including all
of those we've found in other hashing algorithms.
2024-01-20 22:14:19 +00:00
Chandler Carruth 5f62cf752d Fix an oversight that dropped the buffer. (#3628)
This lost any seed or prior hashing done, which isn't good. I've added
some basic testing that would have caught this immediately.
2024-01-20 21:09:17 +00:00
Chandler Carruth 7e9760d9e4 Simplify the index & tag extraction API for hash codes. (#3627)
The fancier API ended up not being helpful and making it harder to
optimize a hash table implemented on top of this.
2024-01-20 20:55:15 +00:00