|
1 | 1 | //! Performs various peephole optimizations.
|
2 | 2 |
|
3 | 3 | use crate::simplify::simplify_duplicate_switch_targets;
|
| 4 | +use rustc_hir::def::DefKind; |
| 5 | +use rustc_index::IndexVec; |
4 | 6 | use rustc_middle::mir::*;
|
5 | 7 | use rustc_middle::ty::layout::ValidityRequirement;
|
6 | 8 | use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
|
7 | 9 | use rustc_span::symbol::Symbol;
|
8 | 10 | use rustc_target::abi::FieldIdx;
|
| 11 | +use rustc_target::abi::FIRST_VARIANT; |
9 | 12 |
|
10 | 13 | pub struct InstSimplify;
|
11 | 14 |
|
@@ -38,6 +41,10 @@ impl<'tcx> MirPass<'tcx> for InstSimplify {
|
38 | 41 | block.terminator.as_mut().unwrap(),
|
39 | 42 | &mut block.statements,
|
40 | 43 | );
|
| 44 | + ctx.simplify_constructor_calls( |
| 45 | + &mut block.terminator.as_mut().unwrap(), |
| 46 | + &mut block.statements, |
| 47 | + ); |
41 | 48 | simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap());
|
42 | 49 | }
|
43 | 50 | }
|
@@ -287,6 +294,57 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
287 | 294 | }
|
288 | 295 | }
|
289 | 296 | }
|
| 297 | + |
| 298 | + fn simplify_constructor_calls( |
| 299 | + &self, |
| 300 | + terminator: &mut Terminator<'tcx>, |
| 301 | + statements: &mut Vec<Statement<'tcx>>, |
| 302 | + ) { |
| 303 | + let TerminatorKind::Call { func, target, destination, args, .. } = &mut terminator.kind |
| 304 | + else { |
| 305 | + return; |
| 306 | + }; |
| 307 | + let Some(target_block) = target else { |
| 308 | + return; |
| 309 | + }; |
| 310 | + let func_ty = func.ty(self.local_decls, self.tcx); |
| 311 | + let ty::FnDef(ctor_id, generics) = *func_ty.kind() else { |
| 312 | + return; |
| 313 | + }; |
| 314 | + let DefKind::Ctor(..) = self.tcx.def_kind(ctor_id) else { |
| 315 | + return; |
| 316 | + }; |
| 317 | + |
| 318 | + let sig = self |
| 319 | + .tcx |
| 320 | + .fn_sig(ctor_id) |
| 321 | + .instantiate(self.tcx, generics) |
| 322 | + .no_bound_vars() |
| 323 | + .expect("LBR in ADT constructor signature"); |
| 324 | + let ty::Adt(adt_def, generics) = sig.output().kind() else { |
| 325 | + bug!("unexpected type for ADT ctor {:?}", sig.output()); |
| 326 | + }; |
| 327 | + let variant_index = if adt_def.is_enum() { |
| 328 | + adt_def.variant_index_with_ctor_id(ctor_id) |
| 329 | + } else { |
| 330 | + FIRST_VARIANT |
| 331 | + }; |
| 332 | + |
| 333 | + let kind = AggregateKind::Adt(adt_def.did(), variant_index, generics, None, None); |
| 334 | + |
| 335 | + let args = std::mem::take(args); |
| 336 | + let fields = IndexVec::from_raw(args); |
| 337 | + |
| 338 | + let statement = Statement { |
| 339 | + kind: StatementKind::Assign(Box::new(( |
| 340 | + *destination, |
| 341 | + Rvalue::Aggregate(Box::new(kind), fields), |
| 342 | + ))), |
| 343 | + source_info: terminator.source_info, |
| 344 | + }; |
| 345 | + statements.push(statement); |
| 346 | + terminator.kind = TerminatorKind::Goto { target: *target_block }; |
| 347 | + } |
290 | 348 | }
|
291 | 349 |
|
292 | 350 | fn intrinsic_assert_panics<'tcx>(
|
|
0 commit comments