Apply `noalias`, `nonnull`, `dereferenceable`, and `align` attributes unconditionally.

We've done measurements with Miri and have determined that `noalias` shouldn't
break code. The requirements that allow us to add dereferenceable and align
have been long documented in the standard library documentation.
This commit is contained in:
Patrick Walton 2022-11-17 15:24:39 -08:00 committed by Erik Desjardins
parent 74dd3cb159
commit 21b8815b6c
2 changed files with 11 additions and 18 deletions

View File

@ -307,24 +307,17 @@ fn adjust_for_rust_scalar<'tcx>(
attrs.set(ArgAttribute::ReadOnly);
}
}
}
// If this is the argument to `drop_in_place`, the contents of which we fully control as the
// compiler, then we may be able to mark that argument `noalias`. Currently, we're conservative
// and do so only if `drop_in_place` results in a direct call to the programmer's `drop` method.
// The `drop` method requires `&mut self`, so we're effectively just propagating the `noalias`
// guarantee from `drop` upward to `drop_in_place` in this case.
// compiler, then we mark this argument as `noalias`, aligned, and dereferenceable. (The
// standard library documents the necessary requirements to uphold these attributes for code
// that calls this method directly.) This can enable better optimizations, such as argument
// promotion.
if is_drop_target {
match *layout.ty.kind() {
ty::RawPtr(inner) => {
if let ty::Adt(adt_def, _) = inner.ty.kind() {
if adt_def.destructor(cx.tcx()).is_some() {
debug!("marking drop_in_place argument as noalias");
attrs.set(ArgAttribute::NoAlias);
}
}
}
_ => bug!("drop target isn't a raw pointer"),
attrs.set(ArgAttribute::NonNull);
attrs.pointee_size = pointee.size;
attrs.pointee_align = Some(pointee.align);
}
}
}

View File

@ -4,7 +4,7 @@
use std::hint::black_box;
// CHECK: define{{.*}}drop_in_place{{.*}}Foo{{.*}}({{.*}}noalias{{.*}})
// CHECK: define{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}Foo{{.*}}({{.*}}noalias {{.*}} align 4 dereferenceable(12){{.*}})
#[repr(C)]
pub struct Foo {