mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #121298 - nikic:writable, r=cuviper
Set writable and dead_on_unwind attributes for sret arguments Set the `writable` and `dead_on_unwind` attributes for `sret` arguments. This allows call slot optimization to remove more memcpy's. See https://llvm.org/docs/LangRef.html#parameter-attributes for the specification of these attributes. In short, the statement we're making here is that: * The return slot is writable. * The return slot will not be read if the function unwinds. Fixes https://github.com/rust-lang/rust/issues/90595.
This commit is contained in:
commit
284f94f9c0
@ -2,6 +2,7 @@ use crate::attributes;
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::llvm::{self, Attribute, AttributePlace};
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use crate::value::Value;
|
||||
@ -425,6 +426,18 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
cx.type_array(cx.type_i8(), self.ret.layout.size.bytes()),
|
||||
);
|
||||
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[sret]);
|
||||
if cx.sess().opts.optimize != config::OptLevel::No
|
||||
&& llvm_util::get_version() >= (18, 0, 0)
|
||||
{
|
||||
attributes::apply_to_llfn(
|
||||
llfn,
|
||||
llvm::AttributePlace::Argument(i),
|
||||
&[
|
||||
llvm::AttributeKind::Writable.create_attr(cx.llcx),
|
||||
llvm::AttributeKind::DeadOnUnwind.create_attr(cx.llcx),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
PassMode::Cast { cast, pad_i32: _ } => {
|
||||
cast.attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
|
||||
|
@ -200,6 +200,8 @@ pub enum AttributeKind {
|
||||
AllocAlign = 39,
|
||||
SanitizeSafeStack = 40,
|
||||
FnRetThunkExtern = 41,
|
||||
Writable = 42,
|
||||
DeadOnUnwind = 43,
|
||||
}
|
||||
|
||||
/// LLVMIntPredicate
|
||||
|
@ -91,6 +91,8 @@ enum LLVMRustAttribute {
|
||||
AllocAlign = 39,
|
||||
SanitizeSafeStack = 40,
|
||||
FnRetThunkExtern = 41,
|
||||
Writable = 42,
|
||||
DeadOnUnwind = 43,
|
||||
};
|
||||
|
||||
typedef struct OpaqueRustString *RustStringRef;
|
||||
|
@ -312,6 +312,16 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
|
||||
return Attribute::SafeStack;
|
||||
case FnRetThunkExtern:
|
||||
return Attribute::FnRetThunkExtern;
|
||||
#if LLVM_VERSION_GE(18, 0)
|
||||
case Writable:
|
||||
return Attribute::Writable;
|
||||
case DeadOnUnwind:
|
||||
return Attribute::DeadOnUnwind;
|
||||
#else
|
||||
case Writable:
|
||||
case DeadOnUnwind:
|
||||
report_fatal_error("Not supported on this LLVM version");
|
||||
#endif
|
||||
}
|
||||
report_fatal_error("bad AttributeKind");
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
|
||||
x
|
||||
}
|
||||
|
||||
// CHECK: @struct_return(ptr noalias nocapture noundef sret([32 x i8]) align 4 dereferenceable(32){{( %_0)?}})
|
||||
// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias nocapture noundef{{( writable)?}} sret([32 x i8]) align 4 dereferenceable(32){{( %_0)?}})
|
||||
#[no_mangle]
|
||||
pub fn struct_return() -> S {
|
||||
S {
|
||||
|
@ -260,7 +260,7 @@ pub struct IntDoubleInt {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
|
||||
|
||||
// CHECK: define void @f_ret_int_double_int_s(ptr noalias nocapture noundef sret([24 x i8]) align 8 dereferenceable(24) %_0)
|
||||
// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias nocapture noundef{{( writable)?}} sret([24 x i8]) align 8 dereferenceable(24) %_0)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
|
||||
IntDoubleInt { a: 1, b: 2., c: 3 }
|
||||
|
@ -1,4 +1,6 @@
|
||||
//@ compile-flags: -O
|
||||
//@ needs-unwind
|
||||
//@ min-llvm-version: 18
|
||||
#![feature(c_unwind)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
@ -23,8 +25,8 @@ extern "C-unwind" {
|
||||
}
|
||||
|
||||
pub fn new_from_uninit_unwind() -> Foo {
|
||||
// CHECK-LABEL: new_from_uninit
|
||||
// CHECK: call void @llvm.memcpy.
|
||||
// CHECK-LABEL: new_from_uninit_unwind
|
||||
// CHECK-NOT: call void @llvm.memcpy.
|
||||
let mut x = std::mem::MaybeUninit::uninit();
|
||||
unsafe {
|
||||
init_unwind(x.as_mut_ptr());
|
||||
|
Loading…
Reference in New Issue
Block a user