Skip to content
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

replace @setRuntimeSafety with @optimizeFor #978

Open
andrewrk opened this issue May 3, 2018 · 1 comment

Comments

Projects
None yet
2 participants
@andrewrk
Copy link
Member

commented May 3, 2018

Communicate intent precisely.

Right now you can use @setRuntimeSafety(false) in Debug and ReleaseSafe modes to allow the optimizer to speed up particular blocks of code. This would make sense to do in a well tested high performance crypto algorithm for example. Or in general the bottlenecks of your library or program.

So the pattern here is that the build mode specifies the default, and you can override it at a per-block (or function) level. Here's a table of the parameters and the defaults that the build modes set:

Parameter Debug ReleaseFast ReleaseSafe ReleaseSmall
LLVM Optimizations - improve speed, harm debugging & compile time -O3 -O3 -Os
Runtime Safety Checks - harm speed, harm size, improve debugging On On

With @setRuntimeSafety we can make a block of code adhere to the principles of Debug even in a ReleaseFast build, and vice versa. ...to some extent - it does not affect optimizations.

But it could! LLVM supports choosing -O3, -Os, or -O0 at least at the function level.

You can probably guess what I'm leading up to here. Really instead of specifically asking to turn off safety, what we really want to communicate to the compiler is what we want to optimize for.

@optimizeFor(comptime mode: BuildMode)

Where BuildMode is already defined as @import("builtin").BuildMode:

pub const Mode = enum {
    Debug,
    ReleaseSafe,
    ReleaseFast,
    ReleaseSmall,
};

And then the other issue we need to solve here is that the same intent should be communicable for types. Zig reserves the right to order fields and insert padding and such for structs, and therefore we should also allow the programmer to tell Zig what to optimize for.

For example Debug might randomly order fields to make sure one does not accidentally depend on field order. ReleaseFast might arrange fields in an order most likely to have better cache performance. ReleaseSmall might sort fields by descending alignment to minimize padding.

One little tidbit: ReleaseSmall is about generated binary size, not runtime memory size. So there is a slight disconnect here. But "small" is definitely something you would potentially want to optimize for in a struct, union, or enum. We can think about how to name the release modes and the optimization targets more coherently.

@alexnask

This comment has been minimized.

Copy link
Contributor

commented May 3, 2018

@andrewrk Just a small correction, I believe the settings I used for ReleaseSmall are equivalent to -Oz.
(The PMBuilder->SizeLevel is 1 for -Os, 2 for -Oz)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.