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

debug-assert ptr sanity in ptr::write #69509

Merged
merged 4 commits into from
Mar 20, 2020

Conversation

RalfJung
Copy link
Member

@RalfJung RalfJung commented Feb 27, 2020

This is a re-submission of the parts that we removed from #69208 due to "interesting" test failures.

Fixes #53871
r? @Mark-Simulacrum @eddyb

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 27, 2020
@RalfJung
Copy link
Member Author

RalfJung commented Feb 27, 2020

As @eddyb suggested I tried ./x.py test --stage 1 src/test/codegen --target i686-unknown-linux-gnu, and was indeed able to reproduce the failure:

/home/r/src/rust/rustc.3/src/test/codegen/repeat-trusted-len.rs:16:11: error: CHECK: expected string not found in input
// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false)
          ^
/home/r/src/rust/rustc.3/build/x86_64-unknown-linux-gnu/test/codegen/repeat-trusted-len/repeat-trusted-len.ll:17:33: note: scanning from here
define void @repeat_take_collect(%"alloc::vec::Vec<u8>"* noalias nocapture sret dereferenceable(12)) unnamed_addr #1 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
                                ^
/home/r/src/rust/rustc.3/build/x86_64-unknown-linux-gnu/test/codegen/repeat-trusted-len/repeat-trusted-len.ll:17:33: note: with "USIZE" equal to "i32"
define void @repeat_take_collect(%"alloc::vec::Vec<u8>"* noalias nocapture sret dereferenceable(12)) unnamed_addr #1 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
                                ^
/home/r/src/rust/rustc.3/build/x86_64-unknown-linux-gnu/test/codegen/repeat-trusted-len/repeat-trusted-len.ll:17:33: note: with "USIZE" equal to "i32"
define void @repeat_take_collect(%"alloc::vec::Vec<u8>"* noalias nocapture sret dereferenceable(12)) unnamed_addr #1 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
                                ^
/home/r/src/rust/rustc.3/build/x86_64-unknown-linux-gnu/test/codegen/repeat-trusted-len/repeat-trusted-len.ll:30:2: note: possible intended match here
 tail call void @llvm.memset.p0i8.i64(i8* nonnull align 1 %1, i8 42, i64 100000, i1 false) #4, !noalias !11
 ^

If I read this correctly, then the codegen test expected memset.p0i8.i32 but we actually get memset.p0i8.i64. That's odd, for sure, but shouldn't be bad -- right?

With the fix I just pushed, this locally passes both on 64bit and 32bit (Linux each time; the wasm32 target doesn't work as I am missing emcc at least).

@eddyb
Copy link
Member

eddyb commented Feb 27, 2020

Maybe we should ignore that distinction in the test? Seems really weird though.
Any chance you're using u64 at any point instead of usize in the check you're adding?

cc @nagisa @nikic @hanna-kruppe

@RalfJung
Copy link
Member Author

Maybe we should ignore that distinction in the test?

Yeah, I think that's what I am doing in the last commit I pushed here.

Any chance you're using u64 at any point instead of usize in the check you're adding?

I can't see a u64 anywhere:

https://github.com/rust-lang/rust/blob/693b4d3075e7d48d9402876b12bef376d7aa2f1f/src/libcore/intrinsics.rs#L1421-L1423

https://github.com/rust-lang/rust/blob/693b4d3075e7d48d9402876b12bef376d7aa2f1f/src/libcore/ptr/const_ptr.rs#L28-L32

@eddyb
Copy link
Member

eddyb commented Feb 27, 2020

Yeah, I think that's what I am doing in the last commit I pushed here

You're hardcoding the (weird) i64, I'm saying we can just ignore those parts of the line with {{.*}}. Oh and you removed [[USIZE]], so you can probably remove the part of the test that only exists to bind USIZE to a pointer-sized integer.

@RalfJung
Copy link
Member Author

RalfJung commented Feb 27, 2020

Oh I see. Well let's see what others think before I do further edits here.

Oh and you removed [[USIZE]], so you can probably remove the part of the test that only exists to bind USIZE to a pointer-sized integer.

Ah, that's how this works. :D

@eddyb
Copy link
Member

eddyb commented Feb 27, 2020

Apropos of nothing, I just realized I want a way in config.toml to only enable debug assertions in the compiler, but not libcore.
I was wondering how my local build has become slower relative to nightly, and these kinds of assertions seem responsible.

I don't even want debug assertions (IMO rustc itself should never use them, just in case they affect soundness, but that's orthogonal), it's just that debug logging is gated on it.

@RalfJung
Copy link
Member Author

these kinds of assertions seem responsible.

Would be interesting to see this confirmed. There aren't that many, really, and I feel like LLVM ought to be able to optimize most of them away -- but maybe it is not as good at that as it could be.

IMO rustc itself should never use them, just in case they affect soundness, but that's orthogonal.

We use them in the Miri engine for some checks that have non-trivial cost, so we don't want to slow down release builds with those sanity checks.

@eddyb
Copy link
Member

eddyb commented Feb 27, 2020

There aren't that many, really, and I feel like LLVM ought to be able to optimize most of them away

Not if e.g. functions operating on raw pointers aren't inlined into functions that operate on references, or if said inlining happens to lose some information.
Not to mention that the checks themselves may impede inlining - it's a whole rat's nest.

For the record the worst I've seen so far is a slowdown of 2.4x for one crate, between nightly and a local build (using the times in the cargo -Z timings report), but it's not uniform, suggesting it affects some parts of rustc worse (or that the culprit is actually debug! calls having their arguments evaluated, because that was sadly changed at some point - this makes me think we should consider forking log).

We use them in the Miri engine for some checks that have non-trivial cost, so we don't want to slow down release builds with those sanity checks.

Hopefully they're really hard to trigger by screwing up elsewhere, especially from other parts of the compiler.
Or maybe they're more relevant to runtime miri than CTFE, I guess.

However, if you do get the chance to measure any of them, and it happens to be not that impactful perf-wise, please change it to a regular assert!.

@RalfJung
Copy link
Member Author

For the record the worst I've seen so far is a slowdown of 2.4x for one crate, between nightly and a local build

Ouch. Well if you think these raw-ptr related debug assertions have significant impact on this (would be good to get that explicitly tested), I'm okay removing them. I figured they would be a nice safety net but it might just be too expensive.

If you give me a benchmark, I might find some time to test this.

@eddyb
Copy link
Member

eddyb commented Feb 27, 2020

Ouch. Well if you think these raw-ptr related debug assertions have significant impact on this (would be good to get that explicitly tested), I'm okay removing them. I figured they would be a nice safety net but it might just be too expensive.

I'd prefer to keep them but for me to be able to turn debug-assertions off in libstd, just so I get as close as possible to the expected nightly performance.

But due to the variation in slowdown between different crates being compiled I'm starting to suspect debug! logging which doesn't check RUSTC_LOG before computing the format args (but is completely gated by cfg(debug_assertions), so when they're disabled it doesn't compute the format args).

@eddyb
Copy link
Member

eddyb commented Feb 27, 2020

If you give me a benchmark, I might find some time to test this.

Just found a non-project-specific crate in those builds: serde, with a ~1.9x slowdown.

@Mark-Simulacrum
Copy link
Member

r? @eddyb on this one I think

@RalfJung RalfJung force-pushed the debug-assert-write branch 2 times, most recently from 7f53150 to 9d43ebf Compare March 12, 2020 19:13
@RalfJung
Copy link
Member Author

@eddyb

You're hardcoding the (weird) i64, I'm saying we can just ignore those parts of the line with {{.*}}. Oh and you removed [[USIZE]], so you can probably remove the part of the test that only exists to bind USIZE to a pointer-sized integer.

I did these adjustments. I hope the test looks good now. :)

Comment on lines 81 to 82
// give space for 2 copies of `Big` + 256 "misc" bytes.
if stack_usage > mem::size_of::<Big>() * 2 + 256 {
Copy link
Member

@eddyb eddyb Mar 12, 2020

Choose a reason for hiding this comment

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

Could this constant be binary searched so it's less than double the previous value?

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought powers of two were nice, but sure. ;)

Copy link
Member Author

Choose a reason for hiding this comment

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

208 is the smallest value that works for me.
But I am a bit worried it might be larger for other platforms / architectures.

Copy link
Member

Choose a reason for hiding this comment

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

We don't support a target with larger sizes/alignments than x64 I don't think.

Copy link
Member

@eddyb eddyb Mar 12, 2020

Choose a reason for hiding this comment

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

Oh nevermind, they could less efficient in their stack usage even if the types aren't larger.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah that's what I meant.

@eddyb
Copy link
Member

eddyb commented Mar 12, 2020

Pinging @nagisa @nikic @hanna-kruppe again, any reason we'd end up with a @llvm.memset.p0i8.i64 call on 32-bit target? See #69509 (comment).

I thought the llvm.memset size parameter was always a pointer-sized integer.

EDIT: we can merge this PR without solving that but I'm curious why it might even happen.

@hanna-kruppe
Copy link
Contributor

No plausible reason for that comes to mind. It's not just very weird in itself, it's also very spooky that the changes in this PR have such an effect.

@hanna-kruppe
Copy link
Contributor

I don't have the bandwidth for it currently, but it would be great if someone could:

  • reproduce this with a plain rustc invocation (no test suite shenanigans)
  • try to minimize the test case (so that it still contains a memset with i64 size on a 32b target)
  • check where the memset with i64 size is introduced (rustc's initial IR or during optimizations)

@bors bors added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Mar 18, 2020
@Centril
Copy link
Contributor

Centril commented Mar 19, 2020

@bors p=3

@bors
Copy link
Contributor

bors commented Mar 19, 2020

⌛ Testing commit c95f08a with merge 7202bc73630dad1231bfee91ad11aaec8f537ef5...

@bors
Copy link
Contributor

bors commented Mar 20, 2020

💔 Test failed - checks-azure

@bors bors 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 Mar 20, 2020
@Dylan-DPC-zz
Copy link

Looks spurious to me

@bors retry

@bors bors 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 Mar 20, 2020
@bors
Copy link
Contributor

bors commented Mar 20, 2020

⌛ Testing commit c95f08a with merge fc65ff9d482d99e59c4274c00865bbe924fbfa04...

@bors
Copy link
Contributor

bors commented Mar 20, 2020

💔 Test failed - checks-azure

@bors bors 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 Mar 20, 2020
@RalfJung
Copy link
Member Author

extracting D:\a\1\s\build\cache\2020-01-31\rustfmt-nightly-i686-pc-windows-gnu.tar.gz
    Updating crates.io index
error: failed to get `cc` as a dependency of package `bootstrap v0.0.0 (D:\a\1\s\src\bootstrap)`

Caused by:
  failed to fetch `https://github.com/rust-lang/crates.io-index`

@bors retry

@bors bors 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 Mar 20, 2020
@bors
Copy link
Contributor

bors commented Mar 20, 2020

⌛ Testing commit c95f08a with merge ba06223814d736f19b8a4853d708eebb6a67feb0...

@Centril
Copy link
Contributor

Centril commented Mar 20, 2020

@bors retry yielding

@bors
Copy link
Contributor

bors commented Mar 20, 2020

⌛ Testing commit c95f08a with merge dd53a2af944fe834c7c8b15b3cebaa513fc47af6...

@JohnTitor
Copy link
Member

@bors retry yield rollup

@bors
Copy link
Contributor

bors commented Mar 20, 2020

⌛ Testing commit c95f08a with merge 1057dc9...

@bors
Copy link
Contributor

bors commented Mar 20, 2020

☀️ Test successful - checks-azure
Approved by: eddyb
Pushing 1057dc9 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Mar 20, 2020
@bors bors merged commit 1057dc9 into rust-lang:master Mar 20, 2020
@RalfJung RalfJung deleted the debug-assert-write branch March 21, 2020 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add debug assertions to raw pointer methods testing for unaligned/NULL pointers
9 participants