From 418900562cb189e68b21acd49116ed8235646578 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 3 Sep 2025 00:05:50 +0200 Subject: [PATCH] explicitly start `va_list` lifetime --- compiler/rustc_codegen_ssa/src/mir/block.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 4 ++++ tests/codegen-llvm/c-variadic-lifetime.rs | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 tests/codegen-llvm/c-variadic-lifetime.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 5f6976f5d005..6492ef73956b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -520,7 +520,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { LocalRef::Place(va_list) => { bx.va_end(va_list.val.llval); - // Explicitly end the lifetime of the `va_list`, this matters for LLVM. + // Explicitly end the lifetime of the `va_list`, improves LLVM codegen. bx.lifetime_end(va_list.val.llval, va_list.layout.size); } _ => bug!("C-variadic function must have a `VaList` place"), diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 06873313e2ec..6b109e8b8e2f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -438,6 +438,10 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() { let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); + + // Explicitly start the lifetime of the `va_list`, improves LLVM codegen. + bx.lifetime_start(va_list.val.llval, va_list.layout.size); + bx.va_start(va_list.val.llval); return LocalRef::Place(va_list); diff --git a/tests/codegen-llvm/c-variadic-lifetime.rs b/tests/codegen-llvm/c-variadic-lifetime.rs new file mode 100644 index 000000000000..5b2f8af18c81 --- /dev/null +++ b/tests/codegen-llvm/c-variadic-lifetime.rs @@ -0,0 +1,21 @@ +//@ add-core-stubs +//@ compile-flags: -Copt-level=3 +#![feature(c_variadic)] +#![crate_type = "lib"] + +// Check that `%args` explicitly has its lifetime start and end. Being explicit can improve +// instruction and register selection, see e.g. https://github.com/rust-lang/rust/pull/144549 + +#[unsafe(no_mangle)] +unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 { + // CHECK: call void @llvm.lifetime.start.p0(i64 {{[0-9]+}}, ptr nonnull %args) + // CHECK: call void @llvm.va_start.p0(ptr nonnull %args) + + let b = args.arg::(); + let c = args.arg::(); + + a + b + c + + // CHECK: call void @llvm.va_end.p0(ptr nonnull %args) + // CHECK: call void @llvm.lifetime.end.p0(i64 {{[0-9]+}}, ptr nonnull %args) +}