-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Zir: implement explicit block_comptime
instruction
#14819
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
fc9d9ae
to
2326ef2
Compare
I think this is actually ready (didn't expect it to pass CI first time!), but I intend to do some basic profiling before marking it ready for review just to make sure I'm not regressing any performance. The CI runtimes look completely normal though, so that's a good sign. |
2326ef2
to
16145c2
Compare
16145c2
to
efee876
Compare
I tried compiling the self-hosted compiler (in debug mode, with a ReleaseFast compiler) before and after my change, and observed no noteworthy difference in performance (avg ~125s pre, ~124s post). I also tried running the native behaviour tests in ReleaseFast, and again saw no noticeable difference (avg ~15.9s pre, ~16.0s post). Given this and the relatively low change in ZIR size observed, I'm happy to say this doesn't regress perf and mark it ready for review. (The push after this comment has no changes, it's just changing the commit message, so CI should still pass) |
efee876
to
5a7328d
Compare
block_comptime
instruction
Since ziglang#14819 this test failed with: $ ../../../build/stage3/bin/zig test multi_writer.zig multi_writer.zig:26:57: error: unable to evaluate comptime expression var batch = std.event.Batch(Error!void, self.streams.len, .auto_async).init(); ~~~~^~~~~~~~ referenced by: Writer: multi_writer.zig:19:52 writer: multi_writer.zig:21:36 remaining reference traces hidden; use '-freference-trace' to see all reference traces Thanks @jacobly for hints how to fix this on IRC.
Since #14819 this test failed with: $ ../../../build/stage3/bin/zig test multi_writer.zig multi_writer.zig:26:57: error: unable to evaluate comptime expression var batch = std.event.Batch(Error!void, self.streams.len, .auto_async).init(); ~~~~^~~~~~~~ referenced by: Writer: multi_writer.zig:19:52 writer: multi_writer.zig:21:36 remaining reference traces hidden; use '-freference-trace' to see all reference traces Thanks @jacobly for hints how to fix this on IRC.
The core goal here was to resolve #7056. I achieved that, but I think this also makes AstGen kinda
easier to understand and less error-prone, which is a nice plus.
Rather than trying to emit comptime-evaluated instructions (e.g. calls marked as comptime, inline
loops), whenever in a comptime scope, AstGen now keeps track of whether Sema will (definitely)
be evaluating the current block at compile-time. When transitioning from runtime code into code
which should be comptime (e.g. a
comptime
block, a type annotation), AstGen will wrap it in ablock_comptime
. As an optimization, this wrapper is elided in a few common cases.This is a breaking change. There likely exists code in the wild which (intentionally or not) relies
on the dodgy behaviour outlined in #7056, and will need to be changed. Here are a few particular
points:
Accessing
my_struct.arr.len
wheremy_struct
is runtime and has an array field no longer workswithin a
comptime
block. Whether we want this to work is debatable, but if we do, the bug wasalready present for "real" (i.e. container-level) comptime blocks, so this regression isn't a new
issue. I did have to change a couple bits of code which relied on this behaviour.
comptime return x;
in a function called at runtime will now emit a compile error. This seemsweird at first, but actually makes sense: it's attempted runtime control flow in compile-time
code! After some discussion on Discord, we concluded that it would probably be good for
comptime return
to implicitly make a function comptime-only. This PR doesn't do that, but it'sa potential future improvement.
Result locations are no longer forwarded across
comptime
exprs. Instead, the comptimeexpression is evaluated with no result location, and is then retroactively written to the result
location at maybe-runtime. I'd be impressed if someone found somewhere this matters.
This PR frees up a couple of ZIR tags due to elimination of some instructions which were equivalent
to forced-comptime versions of other instructions. I'll leave it to the core team to decide if they
want to promote some stuff from
Extended
, or just leave them free for future use.This PR does increase the size of generated ZIR, but the change isn't significant in most cases. Below
are the total ZIR bytes for a few (somewhat randomly chosen) files from the compiler and standard
library, pre- and post-change. You'll see that
hash_map.zig
observed by far the biggest change, withmost files sitting around the 1% region.