@@ -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} ;
@@ -173,7 +173,12 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
173
173
let tcx = cx. tcx ( ) ;
174
174
let llfn = cx. get_fn ( instance) ;
175
175
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
+ ) ;
177
182
178
183
let fn_abi = cx. fn_abi_of_instance ( instance, ty:: List :: empty ( ) ) ;
179
184
debug ! ( "fn_abi: {:?}" , fn_abi) ;
@@ -183,7 +188,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
183
188
return ;
184
189
}
185
190
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) ;
187
192
188
193
let start_llbb = Bx :: append_block ( cx, llfn, "start" ) ;
189
194
let mut start_bx = Bx :: build ( cx, start_llbb) ;
@@ -195,7 +200,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
195
200
}
196
201
197
202
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) ) ;
199
204
200
205
let cached_llbbs: IndexVec < mir:: BasicBlock , CachedLlbb < Bx :: BasicBlock > > =
201
206
mir. basic_blocks
@@ -205,6 +210,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
205
210
} )
206
211
. collect ( ) ;
207
212
213
+ let mir = tcx. arena . alloc ( optimize_use_clone :: < Bx > ( cx, mir) ) ;
214
+
208
215
let mut fx = FunctionCx {
209
216
instance,
210
217
mir,
@@ -311,6 +318,61 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
311
318
}
312
319
}
313
320
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
+
314
376
/// Produces, for each argument, a `Value` pointing at the
315
377
/// argument's value. As arguments are places, these are always
316
378
/// indirect.
0 commit comments