about summary refs log tree commit diff
path: root/src/librustc_mir/transform
diff options
context:
space:
mode:
authorUlrik Sverdrup <bluss@users.noreply.github.com>2016-12-09 16:28:54 +0100
committerUlrik Sverdrup <bluss@users.noreply.github.com>2016-12-09 18:16:38 +0100
commitfbc3f11fc18a626ba9b9f6bc52de4fc5ef75154b (patch)
treedc4bed62f9b5e72c0d973211cb66b574ffe60377 /src/librustc_mir/transform
parentdedd9850841f20880b6318ce9cbe60e2b205b6a9 (diff)
downloadrust-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/transform')
-rw-r--r--src/librustc_mir/transform/deaggregator.rs117
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);
+            }
         }
     }
 }