Uh oh!
There was an error while loading. Please reload this page.
Eliminate UbCheck for non-standard libraries - #122282
Conversation
rustbot
commented
Mar 10, 2024
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
Uh oh!
There was an error while loading. Please reload this page.
This comment has been minimized.
This comment has been minimized.
Uh oh!
There was an error while loading. Please reload this page.
dianqk
commented
Mar 10, 2024
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
bors
commented
Mar 10, 2024
Eliminate `UbCheck` for non-standard libraries Since only core and std are prebuilt crates, I think it's only necessary to keep UB checks for them. `mir-opt` may not optimize some code due to `UbCheck`. In more complex cases, I'm also not sure that LLVM utilizes `assume` correctly. r? saethlin
bors
commented
Mar 10, 2024
☀️ Try build successful - checks-actions |
This comment has been minimized.
This comment has been minimized.
Uh oh!
There was an error while loading. Please reload this page.
I'd really like to have an example of this, if you think it's happening. I think this other PR of mine should ensure that LLVM never sees the checks when they are not enabled: #121421. But if the problem is that LLVM using I also tried a different kind of approach to eliminate the impact of the checks on MIR optimizations: #121767 I expected to see perf improvements as a result of getting the optimized MIR back to where it was before, but that didn't happen. Hopefully this approach works better 🤞 |
rust-timer
commented
Mar 10, 2024
Finished benchmarking commit (acc30d0): comparison URL. Overall result: ❌✅ regressions and improvements - ACTION NEEDEDBenchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf. Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @bors rollup=never Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Bootstrap: 648.121s -> 643.906s (-0.65%) |
dianqk
commented
Mar 11, 2024
The purpose of this PR come from rust-lang/hashbrown#509. Current LLVM does not handle assume well. (Of course there is a PR that is improving it.) Based on my discussion with @dtcxzyw offline, it would be easier for LLVM to handle instructions than intrinsic functions. We may miss out some optimization. If I can remove x.checked_add(y).unwrap_unchecked() |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Are you saying you're trying to write a MIR optimization or something like one so that rustc emits the LLVM IR that's easier for LLVM to optimize well, and So long as I understand that correctly I'm in favor of this, I just have the comments I left above (and much farther above). Usually attributes are more of a verb or a whole sentence, and |
dianqk
commented
Mar 11, 2024
Yes. See https://rust.godbolt.org/z/YG6YrosEb. We can know
Thanks! I get it. |
saethlin
commented
Mar 11, 2024
Very nice. @bors r+ |
dianqk
commented
Mar 15, 2024
I would expect that A does not get a |
The entire point of these intrinsics is to still make A get UB checks in that case! Here, B is the standard library. If B doesn't want UbCheck in such cases it should just use |
dianqk
commented
Mar 15, 2024
IIUC, this is the current behavior of the master branch. This PR still retains this behavior. This PR will only work on BB inlined from std.
Maybe I got your point. :3 We should consider replacing |
No, the PR does not retain this behavior. MIR-opts will now use the flags of the crate containing the MIR to resolve the intrinsic (except in the standard library), rather than the crate doing the codegen. I'm confused why you would say this PR does not change behavior when the entire point of this PR is to change behavior. Currently, the behavior is as intended for all crates B. After this PR, it only works when B is the standard library. That's changing the documented contract of the intrinsic. The intrinsic is unstable so we can change the contract, but I'm saying the new contract is too fragile and non-local and I proposed an alternative that is IMO better.
That's just a rename, so it changes nothing about our discussion. The first step is to agree on what the intended behavior of the intrinsics should be. I like what they currently are. I understand they should be changed to make mir-opt more effective. I'm okay with changing them but not with the change proposed here, primarily because it can lead to Miri running checks that we document and intend for Miri to never run. The current behavior for
The new behavior is:
That's just not a sensible intrinsic IMO. It can be improved by changing the way Miri enters the picture: making Miri not part of how the intrinsic behaves but part of how it is used. As a side-benefit we also don't need two of these intrinsics any more. |
dianqk
commented
Mar 16, 2024
Indeed, I get it. Perhaps we can wait until |
RalfJung
commented
Mar 17, 2024
I've opened a PR that implements the plan I laid out above: #122629. After that lands, this PR can be resurrected, it then just needs some proper docs changes in the |
… r=<try>
refactor check_{lang,library}_ub: use a single intrinsics
This enacts the plan I laid out [here](rust-lang#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`… r=<try>
refactor check_{lang,library}_ub: use a single intrinsics
This enacts the plan I laid out [here](rust-lang#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`… r=<try>
refactor check_{lang,library}_ub: use a single intrinsics
This enacts the plan I laid out [here](rust-lang#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`… r=<try>
refactor check_{lang,library}_ub: use a single intrinsic
This enacts the plan I laid out [here](rust-lang#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`… r=saethlin
refactor check_{lang,library}_ub: use a single intrinsic
This enacts the plan I laid out [here](rust-lang#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`… r=saethlin
refactor check_{lang,library}_ub: use a single intrinsic
This enacts the plan I laid out [here](rust-lang#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`dianqk
commented
Mar 24, 2024
I've tried to update the document based on the new changes. |
dianqk
commented
Mar 24, 2024
@bors try @rust-timer queue |
rust-timer
commented
Mar 24, 2024
Awaiting bors try build completion. @rustbot label: +S-waiting-on-perf |
I can't reopen this PR because GitHub doesn't allow it. It looks like this The new PR is #122975. |
refactor check_{lang,library}_ub: use a single intrinsic
This enacts the plan I laid out [here](rust-lang/rust#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang/rust#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`RalfJung
commented
Mar 24, 2024
(If you close a PR and then push to a branch, you can't reopen. You can only reopen when the branch is at the exact same commit as when it was closed.) |
dianqk
commented
Mar 24, 2024
I see. Yes, this is the proper procedure. |
… r=saethlin
refactor check_{lang,library}_ub: use a single intrinsic
This enacts the plan I laid out [here](rust-lang#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`refactor check_{lang,library}_ub: use a single intrinsic
This enacts the plan I laid out [here](rust-lang/rust#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang/rust#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`refactor check_{lang,library}_ub: use a single intrinsic
This enacts the plan I laid out [here](rust-lang/rust#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang/rust#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`refactor check_{lang,library}_ub: use a single intrinsic
This enacts the plan I laid out [here](rust-lang/rust#122282 (comment)): use a single intrinsic, called `ub_checks` (in aniticpation of rust-lang/compiler-team#725), that just exposes the value of `debug_assertions` (consistently implemented in both codegen and the interpreter). Put the language vs library UB logic into the library.
This makes it easier to do something like rust-lang/rust#122282 in the future: that just slightly alters the semantics of `ub_checks` (making it more approximating when crates built with different flags are mixed), but it no longer affects whether these checks can happen in Miri or compile-time.
The first commit just moves things around; I don't think these macros and functions belong into `intrinsics.rs` as they are not intrinsics.
r? `@saethlin`
I think it's only necessary to keep UB checks for core and std because only they are prebuilt crates,
mir-optmay not optimize some code due toUbCheck.The purpose of this PR is to allow other passes to treat
UbCheckas constants in MIR for optimization.In more complex cases, I'm also not sure that LLVM utilizes
assumecorrectly.r? saethlin