diff options
| author | Ulrik Sverdrup <bluss@users.noreply.github.com> | 2016-12-09 16:28:54 +0100 |
|---|---|---|
| committer | Ulrik Sverdrup <bluss@users.noreply.github.com> | 2016-12-09 18:16:38 +0100 |
| commit | fbc3f11fc18a626ba9b9f6bc52de4fc5ef75154b (patch) | |
| tree | dc4bed62f9b5e72c0d973211cb66b574ffe60377 /src/librustc_mir | |
| parent | dedd9850841f20880b6318ce9cbe60e2b205b6a9 (diff) | |
| download | rust-fbc3f11fc18a626ba9b9f6bc52de4fc5ef75154b.tar.gz rust-fbc3f11fc18a626ba9b9f6bc52de4fc5ef75154b.zip | |
mir: Reinstate while loop in deaggregator pass
A previous commit must have removed the `while let` loop here by mistake; for each basic block, it should find and deaggregate multiple statements in their index order, and the `curr` index tracks the progress through the block. This fixes both the case of deaggregating statements in separate basic blocks (preserving `curr` could prevent that) as well as multiple times in the same block (missing loop prevented that).
Diffstat (limited to 'src/librustc_mir')
| -rw-r--r-- | src/librustc_mir/transform/deaggregator.rs | 117 |
1 files changed, 58 insertions, 59 deletions
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index fcdeae6d6c0..e13c8e02137 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -36,71 +36,70 @@ impl<'tcx> MirPass<'tcx> for Deaggregator { // In fact, we might not want to trigger in other cases. // Ex: when we could use SROA. See issue #35259 - let mut curr: usize = 0; for bb in mir.basic_blocks_mut() { - let idx = match get_aggregate_statement_index(curr, &bb.statements) { - Some(idx) => idx, - None => continue, - }; - // do the replacement - debug!("removing statement {:?}", idx); - let src_info = bb.statements[idx].source_info; - let suffix_stmts = bb.statements.split_off(idx+1); - let orig_stmt = bb.statements.pop().unwrap(); - let (lhs, rhs) = match orig_stmt.kind { - StatementKind::Assign(ref lhs, ref rhs) => (lhs, rhs), - _ => span_bug!(src_info.span, "expected assign, not {:?}", orig_stmt), - }; - let (agg_kind, operands) = match rhs { - &Rvalue::Aggregate(ref agg_kind, ref operands) => (agg_kind, operands), - _ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs), - }; - let (adt_def, variant, substs) = match agg_kind { - &AggregateKind::Adt(adt_def, variant, substs, None) => (adt_def, variant, substs), - _ => span_bug!(src_info.span, "expected struct, not {:?}", rhs), - }; - let n = bb.statements.len(); - bb.statements.reserve(n + operands.len() + suffix_stmts.len()); - for (i, op) in operands.iter().enumerate() { - let ref variant_def = adt_def.variants[variant]; - let ty = variant_def.fields[i].ty(tcx, substs); - let rhs = Rvalue::Use(op.clone()); - - let lhs_cast = if adt_def.variants.len() > 1 { - Lvalue::Projection(Box::new(LvalueProjection { - base: lhs.clone(), - elem: ProjectionElem::Downcast(adt_def, variant), - })) - } else { - lhs.clone() + let mut curr: usize = 0; + while let Some(idx) = get_aggregate_statement_index(curr, &bb.statements) { + // do the replacement + debug!("removing statement {:?}", idx); + let src_info = bb.statements[idx].source_info; + let suffix_stmts = bb.statements.split_off(idx+1); + let orig_stmt = bb.statements.pop().unwrap(); + let (lhs, rhs) = match orig_stmt.kind { + StatementKind::Assign(ref lhs, ref rhs) => (lhs, rhs), + _ => span_bug!(src_info.span, "expected assign, not {:?}", orig_stmt), }; - - let lhs_proj = Lvalue::Projection(Box::new(LvalueProjection { - base: lhs_cast, - elem: ProjectionElem::Field(Field::new(i), ty), - })); - let new_statement = Statement { - source_info: src_info, - kind: StatementKind::Assign(lhs_proj, rhs), + let (agg_kind, operands) = match rhs { + &Rvalue::Aggregate(ref agg_kind, ref operands) => (agg_kind, operands), + _ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs), }; - debug!("inserting: {:?} @ {:?}", new_statement, idx + i); - bb.statements.push(new_statement); - } + let (adt_def, variant, substs) = match agg_kind { + &AggregateKind::Adt(adt_def, variant, substs, None) + => (adt_def, variant, substs), + _ => span_bug!(src_info.span, "expected struct, not {:?}", rhs), + }; + let n = bb.statements.len(); + bb.statements.reserve(n + operands.len() + suffix_stmts.len()); + for (i, op) in operands.iter().enumerate() { + let ref variant_def = adt_def.variants[variant]; + let ty = variant_def.fields[i].ty(tcx, substs); + let rhs = Rvalue::Use(op.clone()); - // if the aggregate was an enum, we need to set the discriminant - if adt_def.variants.len() > 1 { - let set_discriminant = Statement { - kind: StatementKind::SetDiscriminant { - lvalue: lhs.clone(), - variant_index: variant, - }, - source_info: src_info, + let lhs_cast = if adt_def.variants.len() > 1 { + Lvalue::Projection(Box::new(LvalueProjection { + base: lhs.clone(), + elem: ProjectionElem::Downcast(adt_def, variant), + })) + } else { + lhs.clone() + }; + + let lhs_proj = Lvalue::Projection(Box::new(LvalueProjection { + base: lhs_cast, + elem: ProjectionElem::Field(Field::new(i), ty), + })); + let new_statement = Statement { + source_info: src_info, + kind: StatementKind::Assign(lhs_proj, rhs), + }; + debug!("inserting: {:?} @ {:?}", new_statement, idx + i); + bb.statements.push(new_statement); + } + + // if the aggregate was an enum, we need to set the discriminant + if adt_def.variants.len() > 1 { + let set_discriminant = Statement { + kind: StatementKind::SetDiscriminant { + lvalue: lhs.clone(), + variant_index: variant, + }, + source_info: src_info, + }; + bb.statements.push(set_discriminant); }; - bb.statements.push(set_discriminant); - }; - curr = bb.statements.len(); - bb.statements.extend(suffix_stmts); + curr = bb.statements.len(); + bb.statements.extend(suffix_stmts); + } } } } |
