@@ -3,7 +3,7 @@ use std::iter;
3
3
use rustc_index:: IndexVec ;
4
4
use rustc_index:: bit_set:: DenseBitSet ;
5
5
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} ;
7
7
use rustc_middle:: ty:: layout:: { FnAbiOf , HasTyCtxt , HasTypingEnv , TyAndLayout } ;
8
8
use rustc_middle:: ty:: { self , Instance , Ty , TyCtxt , TypeFoldable , TypeVisitableExt } ;
9
9
use rustc_middle:: { bug, mir, span_bug} ;
@@ -170,19 +170,29 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
170
170
) {
171
171
assert ! ( !instance. args. has_infer( ) ) ;
172
172
173
+ let tcx = cx. tcx ( ) ;
173
174
let llfn = cx. get_fn ( instance) ;
174
175
175
- let mir = cx . tcx ( ) . instance_mir ( instance. def ) ;
176
+ let mut mir = tcx. instance_mir ( instance. def ) ;
176
177
177
178
let fn_abi = cx. fn_abi_of_instance ( instance, ty:: List :: empty ( ) ) ;
178
179
debug ! ( "fn_abi: {:?}" , fn_abi) ;
179
180
180
- if cx . tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) . flags . contains ( CodegenFnAttrFlags :: NAKED ) {
181
+ if tcx. codegen_fn_attrs ( instance. def_id ( ) ) . flags . contains ( CodegenFnAttrFlags :: NAKED ) {
181
182
crate :: mir:: naked_asm:: codegen_naked_asm :: < Bx > ( cx, & mir, instance) ;
182
183
return ;
183
184
}
184
185
185
- let debug_context = cx. create_function_debug_context ( instance, fn_abi, llfn, mir) ;
186
+ if tcx. features ( ) . ergonomic_clones ( ) {
187
+ let monomorphized_mir = instance. instantiate_mir_and_normalize_erasing_regions (
188
+ tcx,
189
+ ty:: TypingEnv :: fully_monomorphized ( ) ,
190
+ ty:: EarlyBinder :: bind ( mir. clone ( ) ) ,
191
+ ) ;
192
+ mir = tcx. arena . alloc ( optimize_use_clone :: < Bx > ( cx, monomorphized_mir) ) ;
193
+ }
194
+
195
+ let debug_context = cx. create_function_debug_context ( instance, fn_abi, llfn, & mir) ;
186
196
187
197
let start_llbb = Bx :: append_block ( cx, llfn, "start" ) ;
188
198
let mut start_bx = Bx :: build ( cx, start_llbb) ;
@@ -194,7 +204,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
194
204
}
195
205
196
206
let cleanup_kinds =
197
- base:: wants_new_eh_instructions ( cx . tcx ( ) . sess ) . then ( || analyze:: cleanup_kinds ( mir) ) ;
207
+ base:: wants_new_eh_instructions ( tcx. sess ) . then ( || analyze:: cleanup_kinds ( & mir) ) ;
198
208
199
209
let cached_llbbs: IndexVec < mir:: BasicBlock , CachedLlbb < Bx :: BasicBlock > > =
200
210
mir. basic_blocks
@@ -217,7 +227,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
217
227
cleanup_kinds,
218
228
landing_pads : IndexVec :: from_elem ( None , & mir. basic_blocks ) ,
219
229
funclets : IndexVec :: from_fn_n ( |_| None , mir. basic_blocks . len ( ) ) ,
220
- cold_blocks : find_cold_blocks ( cx . tcx ( ) , mir) ,
230
+ cold_blocks : find_cold_blocks ( tcx, mir) ,
221
231
locals : locals:: Locals :: empty ( ) ,
222
232
debug_context,
223
233
per_local_var_debug_info : None ,
@@ -233,7 +243,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
233
243
fx. compute_per_local_var_debug_info ( & mut start_bx) . unzip ( ) ;
234
244
fx. per_local_var_debug_info = per_local_var_debug_info;
235
245
236
- let traversal_order = traversal:: mono_reachable_reverse_postorder ( mir, cx . tcx ( ) , instance) ;
246
+ let traversal_order = traversal:: mono_reachable_reverse_postorder ( mir, tcx, instance) ;
237
247
let memory_locals = analyze:: non_ssa_locals ( & fx, & traversal_order) ;
238
248
239
249
// Allocate variable and temp allocas
@@ -310,6 +320,61 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
310
320
}
311
321
}
312
322
323
+ // FIXME: Move this function to mir::transform when post-mono MIR passes land.
324
+ fn optimize_use_clone < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
325
+ cx : & ' a Bx :: CodegenCx ,
326
+ mut mir : Body < ' tcx > ,
327
+ ) -> Body < ' tcx > {
328
+ let tcx = cx. tcx ( ) ;
329
+
330
+ if tcx. features ( ) . ergonomic_clones ( ) {
331
+ for bb in mir. basic_blocks . as_mut ( ) {
332
+ let mir:: TerminatorKind :: Call {
333
+ args,
334
+ destination,
335
+ target,
336
+ call_source : mir:: CallSource :: Use ,
337
+ ..
338
+ } = & bb. terminator ( ) . kind
339
+ else {
340
+ continue ;
341
+ } ;
342
+
343
+ // CallSource::Use calls always use 1 argument.
344
+ assert_eq ! ( args. len( ) , 1 ) ;
345
+ let arg = & args[ 0 ] ;
346
+
347
+ // These types are easily available from locals, so check that before
348
+ // doing DefId lookups to figure out what we're actually calling.
349
+ let arg_ty = arg. node . ty ( & mir. local_decls , tcx) ;
350
+
351
+ let ty:: Ref ( _region, inner_ty, mir:: Mutability :: Not ) = * arg_ty. kind ( ) else { continue } ;
352
+
353
+ if !tcx. type_is_copy_modulo_regions ( cx. typing_env ( ) , inner_ty) {
354
+ continue ;
355
+ }
356
+
357
+ let Some ( arg_place) = arg. node . place ( ) else { continue } ;
358
+
359
+ let destination_block = target. unwrap ( ) ;
360
+
361
+ bb. statements . push ( mir:: Statement {
362
+ source_info : bb. terminator ( ) . source_info ,
363
+ kind : mir:: StatementKind :: Assign ( Box :: new ( (
364
+ * destination,
365
+ mir:: Rvalue :: Use ( mir:: Operand :: Copy (
366
+ arg_place. project_deeper ( & [ mir:: ProjectionElem :: Deref ] , tcx) ,
367
+ ) ) ,
368
+ ) ) ) ,
369
+ } ) ;
370
+
371
+ bb. terminator_mut ( ) . kind = mir:: TerminatorKind :: Goto { target : destination_block } ;
372
+ }
373
+ }
374
+
375
+ mir
376
+ }
377
+
313
378
/// Produces, for each argument, a `Value` pointing at the
314
379
/// argument's value. As arguments are places, these are always
315
380
/// indirect.
0 commit comments