refactor(mir-transform): Merge can_be_overridden, is_required and is_enabled into one - #160015
refactor(mir-transform): Merge can_be_overridden, is_required and is_enabled into one#160015clubby789 wants to merge 1 commit into
can_be_overridden, is_required and is_enabled into one#160015Conversation
|
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt Some changes occurred in coverage instrumentation. cc @Zalathar |
|
|
|
Thanks for helping with the cleanup!
The two have slightly different semantics though, don't they? So I think we need a 3-variant enum here: passes that are actually required (as they implement parts of the MIR semantics), passes that are optional but not "optimizations", and passes that are truly just optimizations. An actually required pass should have an That still spreads the logic across both |
FWIW I had started doing this until I realized that |
This comment has been minimized.
This comment has been minimized.
Thinking a bit more about this... one way we could represent this is with an enum like this: enum PassEnabled {
/// This pass implements a mandatory lowering step, either to implement parts of the MIR semantics
/// or to bring MIR into a shape that is easier to deal with for later passes / codegen.
/// Passes using this cannot be disable via any means. They must not remove any UB.
Required,
/// This pass is optional, it can be controlled via `-Zmir-enable-passes`.
Optional {
/// Whether the pass should be enabled in this compilation session by default,
/// i.e., before applying `-Zmir-enable-passes` or `#[optimize(...)]`.
default_enabled: bool,
/// Whether this is an optimization pass. Only optimization passes are disabled by
/// `#[optimize(none)]`. A pass can be optional without being an optimization pass,
/// e.g. if it just adds extra debug checks that one can anyway also turn off.
optimization: bool,
}
}One could then have a few convenient constructors for the typical cases to make this less verbose. What I am missing in this proposal is a way to explicitly mark an optimization as "I promise not to remove UB". Maybe that should also be a field on /// If this is `true`, then the pass promises that *if `mir_opt_level() == 0`*, it will not remove any UB.
/// Passes that set this to `false` automatically get disabled at MIR optimization level 0.
preserves_ub: bool, |
7099c7f to
5a391ab
Compare
|
I wrote up an approach revolving around the below enum, with EDIT: Folded together /// Rules outlining when this pass may be overridden or suppressed.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum PassPolicy {
/// Part of MIR semantics and must run, even in Miri.
/// Such passes must therefore never remove UB, and should come with a comment justifying
/// why they must always run.
Required,
/// Not an optimization, but may be configured by `-Zmir-enable-passes`.
Optional {
/// Whether this pass should be enabled by default in this session in the absence of
/// an explicit `-Zmir-enable-passes`.
enabled_by_default: bool,
},
/// An optimization pass, which may also be suppressed by `#[optimize(none)]`.
Optimization {
/// Whether this pass should be enabled by default in this session in the absence of
/// an explicit `-Zmir-enable-passes` or `#[optimize]` attribute.
enabled_by_default: bool,
},
} |
5a391ab to
a94264c
Compare
can_be_overridden and is_requiredcan_be_overridden, is_required and is_enabled into one
This comment has been minimized.
This comment has been minimized.
|
That should also work. Not sure how many "optional" passes we have and whether the UB removal question even makes sense for them.
|
a94264c to
61676eb
Compare
#128657 and #134082 both merged at similar times, and added two similar flags to the
MirPasstraitcan_be_overridden: Controls if-Zmir-enable-passescan enable/disable a pass; only set tofalseforForceInlineis_required: Controls if#[optimize(none)]should suppress a pass; set to explicitlytrue/falseacross all passes based on which appeared to be unconditionally enabled at the timeThis adds some redundancy, so this PR merges both into `can_be_overridden`: - removes cases of `is_required(&self) -> bool { true }` - replaces `is_required(&self) -> bool { false }` with `can_be_overridden(&self) -> bool { true }`Also, previously,
-Zmir-enable-passestook precedence, but now#[optimize(none)]does, as the latter is more local.This merges both functions as well as
is_enabledinto a singlePassPolicyenumr? @RalfJung