Skip to content

Commit 284f94f

Browse files
committed
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 #90595.
2 parents cb3752d + 976267b commit 284f94f

File tree

7 files changed

+33
-4
lines changed

7 files changed

+33
-4
lines changed

compiler/rustc_codegen_llvm/src/abi.rs

+13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::attributes;
22
use crate::builder::Builder;
33
use crate::context::CodegenCx;
44
use crate::llvm::{self, Attribute, AttributePlace};
5+
use crate::llvm_util;
56
use crate::type_::Type;
67
use crate::type_of::LayoutLlvmExt;
78
use crate::value::Value;
@@ -425,6 +426,18 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
425426
cx.type_array(cx.type_i8(), self.ret.layout.size.bytes()),
426427
);
427428
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[sret]);
429+
if cx.sess().opts.optimize != config::OptLevel::No
430+
&& llvm_util::get_version() >= (18, 0, 0)
431+
{
432+
attributes::apply_to_llfn(
433+
llfn,
434+
llvm::AttributePlace::Argument(i),
435+
&[
436+
llvm::AttributeKind::Writable.create_attr(cx.llcx),
437+
llvm::AttributeKind::DeadOnUnwind.create_attr(cx.llcx),
438+
],
439+
);
440+
}
428441
}
429442
PassMode::Cast { cast, pad_i32: _ } => {
430443
cast.attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+2
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ pub enum AttributeKind {
200200
AllocAlign = 39,
201201
SanitizeSafeStack = 40,
202202
FnRetThunkExtern = 41,
203+
Writable = 42,
204+
DeadOnUnwind = 43,
203205
}
204206

205207
/// LLVMIntPredicate

compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ enum LLVMRustAttribute {
9191
AllocAlign = 39,
9292
SanitizeSafeStack = 40,
9393
FnRetThunkExtern = 41,
94+
Writable = 42,
95+
DeadOnUnwind = 43,
9496
};
9597

9698
typedef struct OpaqueRustString *RustStringRef;

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,16 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
312312
return Attribute::SafeStack;
313313
case FnRetThunkExtern:
314314
return Attribute::FnRetThunkExtern;
315+
#if LLVM_VERSION_GE(18, 0)
316+
case Writable:
317+
return Attribute::Writable;
318+
case DeadOnUnwind:
319+
return Attribute::DeadOnUnwind;
320+
#else
321+
case Writable:
322+
case DeadOnUnwind:
323+
report_fatal_error("Not supported on this LLVM version");
324+
#endif
315325
}
316326
report_fatal_error("bad AttributeKind");
317327
}

tests/codegen/function-arguments.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
197197
x
198198
}
199199

200-
// CHECK: @struct_return(ptr noalias nocapture noundef sret([32 x i8]) align 4 dereferenceable(32){{( %_0)?}})
200+
// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias nocapture noundef{{( writable)?}} sret([32 x i8]) align 4 dereferenceable(32){{( %_0)?}})
201201
#[no_mangle]
202202
pub fn struct_return() -> S {
203203
S {

tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ pub struct IntDoubleInt {
260260
#[no_mangle]
261261
pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
262262

263-
// CHECK: define void @f_ret_int_double_int_s(ptr noalias nocapture noundef sret([24 x i8]) align 8 dereferenceable(24) %_0)
263+
// 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)
264264
#[no_mangle]
265265
pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
266266
IntDoubleInt { a: 1, b: 2., c: 3 }

tests/codegen/maybeuninit-rvo.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
//@ compile-flags: -O
2+
//@ needs-unwind
3+
//@ min-llvm-version: 18
24
#![feature(c_unwind)]
35
#![crate_type = "lib"]
46

@@ -23,8 +25,8 @@ extern "C-unwind" {
2325
}
2426

2527
pub fn new_from_uninit_unwind() -> Foo {
26-
// CHECK-LABEL: new_from_uninit
27-
// CHECK: call void @llvm.memcpy.
28+
// CHECK-LABEL: new_from_uninit_unwind
29+
// CHECK-NOT: call void @llvm.memcpy.
2830
let mut x = std::mem::MaybeUninit::uninit();
2931
unsafe {
3032
init_unwind(x.as_mut_ptr());

0 commit comments

Comments
 (0)