Skip to content

Commit 9f69c66

Browse files
committed
Optimize codegen of use values that are copy post monomorphization
1 parent b9159e0 commit 9f69c66

File tree

1 file changed

+66
-4
lines changed
  • compiler/rustc_codegen_ssa/src/mir

1 file changed

+66
-4
lines changed

Diff for: compiler/rustc_codegen_ssa/src/mir/mod.rs

+66-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::iter;
33
use rustc_index::IndexVec;
44
use rustc_index::bit_set::DenseBitSet;
55
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
6-
use rustc_middle::mir::{Local, UnwindTerminateReason, traversal};
6+
use rustc_middle::mir::{Body, Local, UnwindTerminateReason, traversal};
77
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout};
88
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
99
use rustc_middle::{bug, mir, span_bug};
@@ -173,7 +173,12 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
173173
let tcx = cx.tcx();
174174
let llfn = cx.get_fn(instance);
175175

176-
let mir = cx.tcx().instance_mir(instance.def);
176+
let mir = tcx.instance_mir(instance.def);
177+
let mir = instance.instantiate_mir_and_normalize_erasing_regions(
178+
tcx,
179+
ty::TypingEnv::fully_monomorphized(),
180+
ty::EarlyBinder::bind(mir.clone()),
181+
);
177182

178183
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
179184
debug!("fn_abi: {:?}", fn_abi);
@@ -183,7 +188,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
183188
return;
184189
}
185190

186-
let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, mir);
191+
let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, &mir);
187192

188193
let start_llbb = Bx::append_block(cx, llfn, "start");
189194
let mut start_bx = Bx::build(cx, start_llbb);
@@ -195,7 +200,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
195200
}
196201

197202
let cleanup_kinds =
198-
base::wants_new_eh_instructions(tcx.sess).then(|| analyze::cleanup_kinds(mir));
203+
base::wants_new_eh_instructions(tcx.sess).then(|| analyze::cleanup_kinds(&mir));
199204

200205
let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> =
201206
mir.basic_blocks
@@ -205,6 +210,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
205210
})
206211
.collect();
207212

213+
let mir = tcx.arena.alloc(optimize_use_clone::<Bx>(cx, mir));
214+
208215
let mut fx = FunctionCx {
209216
instance,
210217
mir,
@@ -311,6 +318,61 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
311318
}
312319
}
313320

321+
// FIXME: Move this function to mir::transform when post-mono MIR passes land.
322+
fn optimize_use_clone<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
323+
cx: &'a Bx::CodegenCx,
324+
mut mir: Body<'tcx>,
325+
) -> Body<'tcx> {
326+
let tcx = cx.tcx();
327+
328+
if tcx.features().ergonomic_clones() {
329+
for bb in mir.basic_blocks.as_mut() {
330+
let mir::TerminatorKind::Call {
331+
args,
332+
destination,
333+
target,
334+
call_source: mir::CallSource::Use,
335+
..
336+
} = &bb.terminator().kind
337+
else {
338+
continue;
339+
};
340+
341+
// CallSource::Use calls always use 1 argument.
342+
assert_eq!(args.len(), 1);
343+
let arg = &args[0];
344+
345+
// These types are easily available from locals, so check that before
346+
// doing DefId lookups to figure out what we're actually calling.
347+
let arg_ty = arg.node.ty(&mir.local_decls, tcx);
348+
349+
let ty::Ref(_region, inner_ty, mir::Mutability::Not) = *arg_ty.kind() else { continue };
350+
351+
if !tcx.type_is_copy_modulo_regions(cx.typing_env(), inner_ty) {
352+
continue;
353+
}
354+
355+
let Some(arg_place) = arg.node.place() else { continue };
356+
357+
let destination_block = target.unwrap();
358+
359+
bb.statements.push(mir::Statement {
360+
source_info: bb.terminator().source_info,
361+
kind: mir::StatementKind::Assign(Box::new((
362+
*destination,
363+
mir::Rvalue::Use(mir::Operand::Copy(
364+
arg_place.project_deeper(&[mir::ProjectionElem::Deref], tcx),
365+
)),
366+
))),
367+
});
368+
369+
bb.terminator_mut().kind = mir::TerminatorKind::Goto { target: destination_block };
370+
}
371+
}
372+
373+
mir
374+
}
375+
314376
/// Produces, for each argument, a `Value` pointing at the
315377
/// argument's value. As arguments are places, these are always
316378
/// indirect.

0 commit comments

Comments
 (0)