Repository navigation
Treat union fields as aliasing each other in value_analysis - #163425
Conversation
|
Thanks for the pull request, and welcome! The Rust Project has assigned @dingxiangfei2009 (or someone else) to review your changes, you should hear from them (or someone else) within the next two weeks. Please see the contribution instructions and our LLM policy for more information. Why was this reviewer chosen?The reviewer was selected based on:
|
|
Hey @TaKO8Ki @dingxiangfei2009 could you kindly review this PR? Thanks |
@ojuschugh1 please read again this comment and allow some time to a reviewer to get to this pull request (worth reminding that many of us review patches on a voluntary basis). thanks |
Sorry about that, I'll give it time. Thanks for the reminder. |
|
|
||
| // CHECK-LABEL: fn main( | ||
| fn main() { | ||
| // CHECK: debug a => [[a:_.*]]; |
There was a problem hiding this comment.
| // CHECK: debug a => [[a:_.*]]; |
It doesn't make sense to look at debuginfo in a regression test for a miscompile.
There was a problem hiding this comment.
Sure, i will remove it. Thanks
| // CHECK: [[a]] = copy ({{_.*}}.0: u8); | ||
| let a = unsafe { u.a }; // should not be propagated |
There was a problem hiding this comment.
Instead of this, make the function not main, make the crate-type a lib, and return u.a from the function. That should make it rather easy to write the FileCheck that looks for a copy from the union field to the return place.
There was a problem hiding this comment.
Done, it's a lib crate now with read_other_field returning u.a, and the check is _0 = copy ({{_.*}}.0: u8). Thanks
| // CHECK: ({{_.*}}.1: u8) = const 5_u8; | ||
| // CHECK-NOT: ({{_.*}}.1: u8) = const 5_u8; |
There was a problem hiding this comment.
This is only checking that we didn't produce a particular miscompile, it's not checking that the intended pattern is intact. Look through the MIR before and after JumpThreading when things miscompile to understand what structure we are trying to avoid optimizing, and try to write a test for that.
There was a problem hiding this comment.
Right, with the bug bb1 and bb2 stop jumping to bb3 and go to copies of it that jump straight to bb4/bb5, so the second switchInt is left unreachable. The checks now pin the two goto -> bb3 edges and the write followed by the second switchInt in bb3.
d0f65b4 to
49e02a2
Compare
|
There are a few nevers in the merge queue so I'm checking to see if it's reasonable to roll this up @bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Treat union fields as aliasing each other in value_analysis
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (ed6d54b): comparison URL. Overall result: ✅ improvements - no action neededBenchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf. @bors rollup=never rustc-perf Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -0.6%, secondary 2.5%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (secondary -1.2%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis perf run didn't have relevant results for this metric. Bootstrap: 490.047s -> 489.473s (-0.12%) |
|
@bors r+ rollup=never note="unexpected perf improvement" |
|
@bors rollup=iffy |
…uwer Rollup of 4 perf-sensitive pull requests Successful merges: - #163425 (Treat union fields as aliasing each other in value_analysis) - #164074 (Avoid cloning impl trait AST nodes in late resolution) - #164089 (Implement `clone_from` for `BorrowckDomain`) - #164150 (Reserve more capacity for Symbol interner)
Rollup merge of #163425 - ojuschugh1:jump-threading-fix, r=saethlin Treat union fields as aliasing each other in value_analysis Fixes #161898 The problem was that `for_each_aliasing_place` only considered enum variants and the discriminant as aliasing, so writing to one union field left the state of the other fields alone. JumpThreading then threaded the second `switchInt` on `u.a` using the value from before `u.b = 5`, and DataflowConstProp folded the read of `u.a` to a stale constant in the same way. Union field places have only been in the map since #127087 began collecting places syntactically; before that `iter_fields` skipped unions. I made `for_each_aliasing_place` flood everything under a union as soon as the walk reaches it, since all non-ZST union fields start at offset 0 and overlap. The alternative of not registering places below unions would also work but loses threading on union reads with no write in between. Added a mir-opt test for each pass.
|
Note This PR was benchmarked as part of triage of its containing rollup: triage URL. Finished benchmarking commit (e89ad72): comparison URL. Overall result: ✅ improvements - no action needed@rustbot label: -perf-regression Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (secondary 2.5%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 1.8%, secondary -3.5%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary 0.1%, secondary 0.1%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Artifact size: 406.63 MiB -> 406.92 MiB (0.07%) |
|
Thanks @saethlin for the review, the comments on the tests were really helpful. Thanks to everyone else involved too. |
Fixes #161898
The problem was that
for_each_aliasing_placeonly considered enum variants and the discriminant as aliasing, so writing to one union field left the state of the other fields alone. JumpThreading then threaded the secondswitchIntonu.ausing the value from beforeu.b = 5, and DataflowConstProp folded the read ofu.ato a stale constant in the same way. Union field places have only been in the map since #127087 began collecting places syntactically; before thatiter_fieldsskipped unions.I made
for_each_aliasing_placeflood everything under a union as soon as the walk reaches it, since all non-ZST union fields start at offset 0 and overlap. The alternative of not registering places below unions would also work but loses threading on union reads with no write in between.Added a mir-opt test for each pass.