Skip to content

Emit llvm dereferenceable in more cases on newer LLVM versions - #158863

Merged
rust-bors[bot] merged 3 commits into
rust-lang:mainfrom
WaffleLapkin:nonofree
Oct 2, 2026
Merged

rust-bors[bot] merged 3 commits into
rust-lang:mainfrom
WaffleLapkin:nonofree

Conversation

@WaffleLapkin

@WaffleLapkin WaffleLapkin commented Jul 6, 2026 •

Copy link
Copy Markdown
Member

View all comments

On llvm >= 23 emit dereferenceable even without nofree, since llvm/llvm-project#204795 makes dereferenceable act "at a point" / not imply nofree.

Additionally restrict dereferenceable to &Freeze / &mut Unpin / Box<Unpin, _> only (this is only relevant for llvm >= 23 as otherwise !Freeze/!Unpin suppress nofree and as such dereferenceable).

r? nikic

I thought this will be a bit harder change, but since your refactoring in #156281 it's actually trivial ^^'

Draft because I don't think this can be tested prior to LLVM update. I'm also not sure if the version check I did is the appropriate one...

cc @RalfJung

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 6, 2026

@nikic nikic left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we should wait until the LLVM 23 upgrade so we can properly test this.

View changes since this review

Comment thread compiler/rustc_codegen_llvm/src/abi.rs Outdated
@RalfJung

RalfJung commented Jul 7, 2026

Copy link
Copy Markdown
Member

With LLVM 23 we can also put dereferenceable on &Cell arguments, on &mut !Unpin arguments, and on &T/&mut T return types for all T. Does this PR do all that?

@WaffleLapkin

WaffleLapkin commented Jul 7, 2026 •

Copy link
Copy Markdown
Member Author

@RalfJung yes. What currently stops dereferenceable from being applied to &!Freeze and &mut !Unpin arguments, and references in return types, is that in all these cases we don't set NoFree:

// NoFree is not valid on return values. If it were, it would mean something like
// "will not be freed until the end of the program", which is generally not valid for
// references.
let no_free = !is_return
&& match kind {
// Non-frozen shared references are not necessarily dereferenceable for the
// entire duration of the function
// (see <https://github.com/rust-lang/rust/pull/98017>).
PointerKind::SharedRef { frozen } => frozen,
// Mutable references to potentially self-referential types are not necessarily
// dereferenceable for the entire duration of the function
// (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>).
PointerKind::MutableRef { unpin } => unpin,
// Box may be deallocated during execution of the function.
PointerKind::Box { .. } => false,
};
if no_free {
attrs.set(ArgAttribute::NoFree);
}

With NoFree no longer being required, they will all become dereferenceable.

I suppose another way to put this is that rustc already uses dereferenceable-at-a-point semantics since #156281, and applies dereferenceable-at-a-point everywhere it's valid. The only check that prevents llvm dereferenceable from being applied in cases you mentioned, is the one that I'm changing in this PR.

@RalfJung

RalfJung commented Jul 7, 2026

Copy link
Copy Markdown
Member

Nice, that's what I was hoping for. :)

This will be much easier to review once we actually have LLVM 23 and can look at the codegen test diff.

@WaffleLapkin
WaffleLapkin marked this pull request as ready for review August 6, 2026 10:25
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 6, 2026
Comment thread tests/codegen-llvm/drop-in-place-noalias.rs Outdated

@RalfJung RalfJung left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread tests/codegen-llvm/function-arguments.rs Outdated
Comment on lines 126 to 128
// This one is *not* `noalias` because it might be self-referential.
// It is also not `dereferenceable` due to
// It is also not `dereferenceable` prior to LLVM23 due to
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>.

@WaffleLapkin WaffleLapkin Aug 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RalfJung I'm confused by this. You said applying dereferenceable on &!Freeze / &mut !Unpin should be fine now, but rust-lang/unsafe-code-guidelines#381 seems to disagree with that. Was there some kind of update since that issue was written or am I missing something else?

View changes since the review

@RalfJung RalfJung Aug 6, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah... good point. I had forgotten about this. This also relates to an old LLVM semantics question that never got resolved.

In the end the question is what dereferenceable really means to LLVM. Does it mean "this memory is in-bounds of some allocation" or does it mean "pretend we did a byte-type read here". The former is fine, Miri checks that. The latter is not fine as that read can affect the aliasing model (and the data race model, but LLVM ~defines that problem away and this is not our worst crime on the memory model side so we hope it's fine).

So what is unambiguously correct is to add dereferenceable to &i32 and &mut i32 return types, and to Box<i32> arguments and return types. But for !Freeze or !Unpin things are indeed less clear.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to PR such that it only emits dereferenceable in cases when miri performs implicit reads. #158863 (comment).

@WaffleLapkin

Copy link
Copy Markdown
Member Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 6, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 6, 2026
Emit llvm dereferenceable in more cases on newer LLVM versions
@rust-log-analyzer

This comment has been minimized.

@rust-bors

rust-bors Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 69d43e7 (69d43e79223ff1e0056f7f333df9005f685ab5ae)
Base parent: b070f45 (b070f45ad92ed45b20e57d9483a21657d0d00715)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (69d43e7): comparison URL.

Overall result: ❌ regressions - please read:

Benchmarking 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.

Next, please: If you can, justify the regressions found in this try perf run in writing along with @rustbot label: +perf-regression-triaged. If not, fix the regressions and do another perf run. Neutral or positive results will clear the label automatically.

@bors rollup=never rustc-perf
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.3% [2.2%, 2.5%] 6
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary 4.3%, secondary -1.8%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
4.3% [4.3%, 4.3%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-1.8% [-1.8%, -1.8%] 1
All ❌✅ (primary) 4.3% [4.3%, 4.3%] 1

Cycles

Results (primary -2.4%, secondary 4.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
4.1% [2.8%, 5.3%] 2
Improvements ✅
(primary)
-2.4% [-2.4%, -2.4%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -2.4% [-2.4%, -2.4%] 1

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 459.982s -> 458.725s (-0.27%)
Artifact size: 398.64 MiB -> 399.05 MiB (0.10%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Aug 6, 2026
@WaffleLapkin

Copy link
Copy Markdown
Member Author

Regression feels like noise to me. match-stress regresses in check profile too, which can't be caused by llvm codegen changes here... Unless the match checking in rustc is being optimized worse somehow, in which case I'm not sure what can be done about it.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Oct 2, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Oct 2, 2026
Emit llvm dereferenceable in more cases on newer LLVM versions
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Oct 2, 2026
Emit llvm dereferenceable in more cases on newer LLVM versions





On llvm >= 23 emit `dereferenceable` even without `nofree`, since llvm/llvm-project#204795 makes `dereferenceable` act "at a point" / not imply `nofree`.

Additionally restrict `dereferenceable` to `&Freeze` / `&mut Unpin` / `Box<Unpin, _>` only (this is only relevant for `llvm >= 23` as otherwise `!Freeze`/`!Unpin` suppress `nofree` and as such `dereferenceable`).

r? nikic

I thought this will be a bit harder change, but since your refactoring in #156281 it's actually trivial ^^'

Draft because I don't think this can be tested prior to LLVM update. I'm also not sure if the version check I did is the appropriate one...

cc @RalfJung
@rust-bors

rust-bors Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: d93ffcb (d93ffcb6db3c311b076c80aaf29921b0137b6152)
Base parent: dba8825 (dba8825fe50879b22129271fb865944e384f7cce)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (d93ffcb): comparison URL.

Overall result: ❌ regressions - no action needed

Benchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up.

@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.1% [0.1%, 0.1%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (secondary 1.8%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
1.8% [1.8%, 1.8%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Cycles

Results (primary 2.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.0% [2.0%, 2.0%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.0% [2.0%, 2.0%] 1

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 490.969s -> 489.48s (-0.30%)
Artifact size: 408.65 MiB -> 408.69 MiB (0.01%)

@rustbot rustbot removed S-waiting-on-perf Status: Waiting on a perf run to be completed. perf-regression Performance regression. labels Oct 2, 2026
@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job test-i686-gnu-nopt-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)

@rust-bors rust-bors Bot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Oct 2, 2026
@rust-bors

rust-bors Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

💔 Test for b5e0884 failed: CI. Failed job:

@JonathanBrouwer

Copy link
Copy Markdown
Member

@bors try jobs=test-i686-gnu-nopt-1
@bors retry

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Oct 2, 2026
Emit llvm dereferenceable in more cases on newer LLVM versions


try-job: test-i686-gnu-nopt-1
@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 2, 2026
@rust-bors

This comment has been minimized.

@rust-bors

rust-bors Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 522b387 (522b387cd60b742a30f2a65b6fb510af3ea07e56)
Base parent: c165834 (c1658342b0ea7eab61db1960082668c77f553522)

@rust-bors rust-bors Bot added merged-by-bors This PR was explicitly merged by bors. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Oct 2, 2026
@rust-bors

rust-bors Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

☀️ Test successful - CI
Approved by: RalfJung
Duration: 3h 8m 54s
Pushing da51be1 to main...

@rust-bors
rust-bors Bot merged commit da51be1 into rust-lang:main Oct 2, 2026
16 checks passed
@rustbot rustbot added this to the 1.101.0 milestone Oct 2, 2026
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor
What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing c165834 (parent) -> da51be1 (this PR)

Test differences

Show 26 test diffs

Stage 1

  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM22: [missing] -> pass (J1)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM22: [missing] -> pass (J1)
  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM22: [missing] -> ignore (ignored when the LLVM version (23.1.1) is newer than majorversion 22) (J2)
  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM23: [missing] -> pass (J2)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM22: [missing] -> ignore (ignored when the LLVM version (23.1.1) is newer than majorversion 22) (J2)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM23: [missing] -> pass (J2)
  • [codegen] tests/codegen-llvm/function-arguments.rs: pass -> [missing] (J6)
  • [codegen] tests/codegen-llvm/llvm-writable.rs: pass -> [missing] (J6)
  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM23: [missing] -> ignore (ignored when the LLVM version 22.1.2 is older than 23.0.0) (J7)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM23: [missing] -> ignore (ignored when the LLVM version 22.1.2 is older than 23.0.0) (J7)
  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM23: [missing] -> ignore (ignored when the LLVM version 21.1.2 is older than 23.0.0) (J8)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM23: [missing] -> ignore (ignored when the LLVM version 21.1.2 is older than 23.0.0) (J8)

Stage 2

  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM23: [missing] -> ignore (ignored when the LLVM version 21.1.2 is older than 23.0.0) (J0)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM23: [missing] -> ignore (ignored when the LLVM version 21.1.2 is older than 23.0.0) (J0)
  • [codegen] tests/codegen-llvm/function-arguments.rs: pass -> [missing] (J3)
  • [codegen] tests/codegen-llvm/llvm-writable.rs: pass -> [missing] (J3)
  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM23: [missing] -> ignore (ignored when the LLVM version 22.1.2 is older than 23.0.0) (J4)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM23: [missing] -> ignore (ignored when the LLVM version 22.1.2 is older than 23.0.0) (J4)
  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM22: [missing] -> ignore (ignored when the LLVM version (23.1.1) is newer than majorversion 22) (J5)
  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM23: [missing] -> pass (J5)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM22: [missing] -> ignore (ignored when the LLVM version (23.1.1) is newer than majorversion 22) (J5)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM23: [missing] -> pass (J5)
  • [codegen] tests/codegen-llvm/function-arguments.rs#LLVM22: [missing] -> pass (J9)
  • [codegen] tests/codegen-llvm/llvm-writable.rs#LLVM22: [missing] -> pass (J9)

Additionally, 2 doctest diffs were found. These are ignored, as they are noisy.

Job group index

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard da51be10c32bd6d06a2eb348bce844435739ed90 --output-dir test-dashboard

And then open test-dashboard/index.html in your browser to see an overview of all executed tests.

Job duration changes

  1. dist-i686-msvc: 34m 11s -> 51m 43s (+51.3%)
  2. test-x86_64-gnu-stdlib-semver-check: 18m 3s -> 8m 58s (-50.3%)
  3. dist-various-1: 34m 35s -> 50m 8s (+45.0%)
  4. dist-ohos-x86_64: 58m 18s -> 1h 23m (+42.7%)
  5. optional-test-x86_64-gnu-autodiff: 59m 46s -> 34m 43s (-41.9%)
  6. test-x86_64-gnu-gcc: 1h 26m -> 53m 1s (-38.7%)
  7. dist-ohos-aarch64: 57m 42s -> 1h 19m (+38.6%)
  8. test-x86_64-msvc-ext2: 1h 24m -> 1h 53m (+34.2%)
  9. test-aarch64-apple-macos-26-2: 2h 13m -> 2h 59m (+34.2%)
  10. dist-sparcv9-solaris: 1h 45m -> 1h 9m (-34.1%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (da51be1): comparison URL.

Overall result: ❌ regressions - no action needed

@rustbot label: -perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.1% [0.1%, 0.1%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

This perf run didn't have relevant results for this metric.

Cycles

Results (secondary 3.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
3.1% [3.1%, 3.1%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Binary size

Results (primary -0.0%, secondary -0.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.0% [-0.1%, -0.0%] 29
Improvements ✅
(secondary)
-0.0% [-0.1%, -0.0%] 8
All ❌✅ (primary) -0.0% [-0.1%, -0.0%] 29

Bootstrap: 491.121s -> 488.784s (-0.48%)
Artifact size: 408.64 MiB -> 408.61 MiB (-0.01%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. merged-by-bors This PR was explicitly merged by bors. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants