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

View File

@ -4,7 +4,7 @@
use std::hint::black_box; 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)] #[repr(C)]
pub struct Foo { pub struct Foo {