-
Notifications
You must be signed in to change notification settings - Fork 989
Introduce variadic template implementation of stringf
that supports std::string
parameters
#5221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0ca673c
to
258dc0b
Compare
A followup commit to extend this to For the sake of keeping this PR simple I've done the bare minimum to get things working and support |
👀 |
c8887f6
to
6a04722
Compare
The build is failing in |
Also the Visual Studio C++ build is failing. I'll see if I can guess the problems and fix them... |
You'll probably need to deprecate the |
What compatibility expectations/guarantees are you offering? Are they documented anywhere? Are you promising that Yosys maintains ABI compatibility, so that existing binary builds of Yosys-using code continue to work with future versions of Yosys? If you require that people upgrading Yosys recompile their Yosys-using code, then this change should probably be OK. As you can see, only a very small number of the existing uses of |
6a04722
to
a854287
Compare
The Windows build failure was because the Win32 header files helpfully #define |
I don't think we provide any explicit guarantees, certainly not ABI compatibility. I know I do tend towards more verbosity than many of the other maintainers, but I think we generally deprecate public methods for a release version so that downstream developers get a deprecation warning that informs them of any changes necessary. Though in this case I'm not sure exactly how that applies since there is still a stringf method just not exactly the same. Unfortunately our resident Verific maintainer is on leave for the next few weeks so there might be some delay in checking the verific builds to try fix the failures there. |
Yeah, the intent here is to be 100% compatible with
I guess there's some prebuilt library that links to Yosys symbols that needs to be rebuilt every time Yosys changes ABI? |
Ah, this will be a little tricky to merge - there's some proprietary code (for our rewriters that manipulate the verific AST) that's pre-compiled and manually uploaded to our private CI runner each month along with the verific binaries, and this code is also making use of |
@nakengelhardt I have some other changes that reuse this code for |
I like making split PRs, with the disclaimer that until a dependency PR is merged, the diff will look messy, as some of the commits aren't part of the discussed change. That could be a good move here as well but requested changes then need awkward rebasing FYI we have public development meetings on mondays 15:00 Central European (Summer) Time which are a good opportunity to discuss hairier contributions like this. I will unfortunately miss the next one as I'm away next week though |
I will try to join. |
a854287
to
b7aee70
Compare
b7aee70
to
6ea8281
Compare
Unfortunately this has a 3.4% performance regression when synthesizing the OpenROAD flow scripts jpeg example design that I use as a perf smoke test. The performance impact is spread out over commands that print things. As an isolated example, reading and dumping any RTLIL file should do
Sorry I only got to seriously playing with it now but I suppose it means we'll push this and the improvements that build on top of it into the next release cycle |
6ea8281
to
53e1552
Compare
OK. Thanks for looking at it anyway. I dug into performance and it was reasonably easy to make improvements. Probably the most important one was to add a special case for
C++17 before: Time (mean ± σ): 101.3 ms ± 0.8 ms [User: 85.6 ms, System: 15.6 ms] |
One thing I should point out, which is now mentioned in the commit message, is that this makes format string processing more lenient. E.g. passing a Applying strict bitwidth truncation could be done but it would require more code. One other thing about performance: this PR really does open up more possibilities for improvements. For example everywhere that currently calls |
… format string checking. Checking only happens at compile time if -std=c++20 (or greater) is enabled. Otherwise the checking happens at run time. This requires the format string to be a compile-time constant (when compiling with C++20), so fix a few places where that isn't true. The format string behavior is a bit more lenient than C printf. For %d/%u you can pass any integer type and it will be converted and output without truncating bits, i.e. any length specifier is ignored and the conversion is always treated as 'll'. Any truncation needs to be done by casting the argument itself. For %f/%g you can pass anything that converts to double, including integers. Performance results with clang 19 -O3 on Linux: ``` hyperfine './yosys -dp "read_rtlil /usr/local/google/home/rocallahan/Downloads/jpeg.synth.il; dump"' ``` C++17 before: Time (mean ± σ): 101.3 ms ± 0.8 ms [User: 85.6 ms, System: 15.6 ms] C++17 after: Time (mean ± σ): 98.4 ms ± 1.2 ms [User: 82.1 ms, System: 16.1 ms] C++20 before: Time (mean ± σ): 100.9 ms ± 1.1 ms [User: 87.0 ms, System: 13.8 ms] C++20 after: Time (mean ± σ): 97.8 ms ± 1.4 ms [User: 83.1 ms, System: 14.7 ms] The generated code is reasonably efficient. E.g. with clang 19, `stringf()` with a format with no %% escapes and no other parameters (a weirdly common case) often compiles to a fully inlined `std::string` construction. In general the format string parsing is often (not always) compiled away.
53e1552
to
6ee3cd8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, it's a (tiny) performance improvement now in that synth
smoke test. I'm okay with removing accidental truncations in our string formatting
Thanks for merging this! There's PR #5243 as well. |
Format string checking happens at compile time if
-std=c++20
(or greater) is enabled. Otherwise the checking happens at run time --- invalid format strings will result in a call toabort()
.Compile-time format string checking requires the format string to be a compile-time constant, so fix a few places where that isn't true.
What are the reasons/motivation for this change?
See #5210. By replacing
stringf()
and thenlog()
and related varargs functions with variadic template implementations, and adding direct support for C++ types such asstd::string
, we will be able to clean up some pretty ugly code and avoid some space leaks.