From a174d65709744f9d88fbf8807a605f7ac15c2255 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Wed, 22 Jun 2022 11:24:34 +0200 Subject: Added llvm lifetime annotations to function call argument temporaries. The goal of this change is to ensure that llvm will do stack slot optimization on these temporaries. This ensures that in code like: ```rust const A: [u8; 1024] = [0; 1024]; fn copy_const() { f(A); f(A); } ``` we only use 1024 bytes of stack space, instead of 2048 bytes. --- compiler/rustc_codegen_ssa/src/mir/block.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_codegen_ssa') diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index db348f2bdd5..10d8de48f66 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -132,6 +132,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { llargs: &[Bx::Value], destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, cleanup: Option, + argument_tmps: &[PlaceRef<'tcx, ::Value>], ) { // If there is a cleanup block and the function we're calling can unwind, then // do an invoke, otherwise do a call. @@ -172,6 +173,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { if let Some((ret_dest, target)) = destination { bx.switch_to_block(fx.llbb(target)); fx.set_debug_loc(bx, self.terminator.source_info); + for tmp in argument_tmps { + bx.lifetime_end(tmp.llval, tmp.layout.size); + } fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret); } } else { @@ -186,6 +190,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } if let Some((ret_dest, target)) = destination { + for tmp in argument_tmps { + bx.lifetime_end(tmp.llval, tmp.layout.size); + } fx.store_return(bx, ret_dest, &fn_abi.ret, llret); self.funclet_br(fx, bx, target); } else { @@ -415,6 +422,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { args, Some((ReturnDest::Nothing, target)), unwind, + &[], ); } @@ -492,7 +500,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (fn_abi, llfn) = common::build_langcall(&bx, Some(span), lang_item); // Codegen the actual panic invoke/call. - helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); + helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup, &[]); } fn codegen_abort_terminator( @@ -508,7 +516,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (fn_abi, llfn) = common::build_langcall(&bx, Some(span), LangItem::PanicNoUnwind); // Codegen the actual panic invoke/call. - helper.do_call(self, &mut bx, fn_abi, llfn, &[], None, None); + helper.do_call(self, &mut bx, fn_abi, llfn, &[], None, None, &[]); } /// Returns `true` if this is indeed a panic intrinsic and codegen is done. @@ -579,6 +587,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &[msg.0, msg.1, location], target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)), cleanup, + &[], ); } else { // a NOP @@ -786,6 +795,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (args, None) }; + let mut argument_tmps = vec![]; 'make_args: for (i, arg) in first_args.iter().enumerate() { let mut op = self.codegen_operand(&mut bx, arg); @@ -851,8 +861,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (&mir::Operand::Copy(_), Ref(_, None, _)) | (&mir::Operand::Constant(_), Ref(_, None, _)) => { let tmp = PlaceRef::alloca(&mut bx, op.layout); + bx.lifetime_start(tmp.llval, tmp.layout.size); op.val.store(&mut bx, tmp); op.val = Ref(tmp.llval, None, tmp.align); + argument_tmps.push(tmp); } _ => {} } @@ -925,6 +937,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &llargs, target.as_ref().map(|&target| (ret_dest, target)), cleanup, + &argument_tmps, ); bx.switch_to_block(bb_fail); @@ -942,6 +955,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &llargs, target.as_ref().map(|&target| (ret_dest, target)), cleanup, + &argument_tmps, ); } -- cgit 1.4.1-3-g733a5 From 8f529aba8688f26b601ef733951379718d345ee7 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Sat, 25 Jun 2022 16:36:11 +0200 Subject: Improved naming for copied constant arguments vector. --- compiler/rustc_codegen_ssa/src/mir/block.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'compiler/rustc_codegen_ssa') diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 10d8de48f66..0503d723240 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { llargs: &[Bx::Value], destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, cleanup: Option, - argument_tmps: &[PlaceRef<'tcx, ::Value>], + copied_constant_arguments: &[PlaceRef<'tcx, ::Value>], ) { // If there is a cleanup block and the function we're calling can unwind, then // do an invoke, otherwise do a call. @@ -173,7 +173,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { if let Some((ret_dest, target)) = destination { bx.switch_to_block(fx.llbb(target)); fx.set_debug_loc(bx, self.terminator.source_info); - for tmp in argument_tmps { + for tmp in copied_constant_arguments { bx.lifetime_end(tmp.llval, tmp.layout.size); } fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret); @@ -190,7 +190,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } if let Some((ret_dest, target)) = destination { - for tmp in argument_tmps { + for tmp in copied_constant_arguments { bx.lifetime_end(tmp.llval, tmp.layout.size); } fx.store_return(bx, ret_dest, &fn_abi.ret, llret); @@ -795,7 +795,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (args, None) }; - let mut argument_tmps = vec![]; + let mut copied_constant_arguments = vec![]; 'make_args: for (i, arg) in first_args.iter().enumerate() { let mut op = self.codegen_operand(&mut bx, arg); @@ -864,7 +864,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.lifetime_start(tmp.llval, tmp.layout.size); op.val.store(&mut bx, tmp); op.val = Ref(tmp.llval, None, tmp.align); - argument_tmps.push(tmp); + copied_constant_arguments.push(tmp); } _ => {} } @@ -937,7 +937,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &llargs, target.as_ref().map(|&target| (ret_dest, target)), cleanup, - &argument_tmps, + &copied_constant_arguments, ); bx.switch_to_block(bb_fail); @@ -955,7 +955,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &llargs, target.as_ref().map(|&target| (ret_dest, target)), cleanup, - &argument_tmps, + &copied_constant_arguments, ); } -- cgit 1.4.1-3-g733a5