Skip to content

Commit dd9a526

Browse files
committed
rustc_mir: handle all aggregate kinds in the deaggregator.
1 parent 893663e commit dd9a526

File tree

3 files changed

+70
-84
lines changed

3 files changed

+70
-84
lines changed

src/librustc_mir/transform/deaggregator.rs

Lines changed: 68 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -44,98 +44,85 @@ impl MirPass for Deaggregator {
4444
return;
4545
}
4646

47-
for bb in mir.basic_blocks_mut() {
48-
let mut curr: usize = 0;
49-
while let Some(idx) = get_aggregate_statement_index(curr, &bb.statements) {
50-
// do the replacement
51-
debug!("removing statement {:?}", idx);
52-
let src_info = bb.statements[idx].source_info;
53-
let suffix_stmts = bb.statements.split_off(idx+1);
47+
let can_deaggregate = |statement: &Statement| {
48+
if let StatementKind::Assign(_, ref rhs) = statement.kind {
49+
if let Rvalue::Aggregate(..) = *rhs {
50+
return true;
51+
}
52+
}
53+
54+
false
55+
};
56+
57+
let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut();
58+
for bb in basic_blocks {
59+
let mut start = 0;
60+
while let Some(i) = bb.statements[start..].iter().position(&can_deaggregate) {
61+
let i = start + i;
62+
63+
// FIXME(eddyb) this is probably more expensive than it should be.
64+
// Ideally we'd move the block's statements all at once.
65+
let suffix_stmts = bb.statements.split_off(i + 1);
5466
let orig_stmt = bb.statements.pop().unwrap();
55-
let (lhs, rhs) = match orig_stmt.kind {
56-
StatementKind::Assign(ref lhs, ref rhs) => (lhs, rhs),
57-
_ => span_bug!(src_info.span, "expected assign, not {:?}", orig_stmt),
58-
};
59-
let (agg_kind, operands) = match rhs {
60-
&Rvalue::Aggregate(ref agg_kind, ref operands) => (agg_kind, operands),
61-
_ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs),
67+
let source_info = orig_stmt.source_info;
68+
let (mut lhs, kind, operands) = match orig_stmt.kind {
69+
StatementKind::Assign(lhs, Rvalue::Aggregate(kind, operands))
70+
=> (lhs, kind, operands),
71+
_ => bug!()
6272
};
63-
let (adt_def, variant, substs) = match **agg_kind {
64-
AggregateKind::Adt(adt_def, variant, substs, None)
65-
=> (adt_def, variant, substs),
66-
_ => span_bug!(src_info.span, "expected struct, not {:?}", rhs),
73+
74+
let mut set_discriminant = None;
75+
let active_field_index = match *kind {
76+
AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
77+
if adt_def.is_enum() {
78+
set_discriminant = Some(Statement {
79+
kind: StatementKind::SetDiscriminant {
80+
place: lhs.clone(),
81+
variant_index,
82+
},
83+
source_info,
84+
});
85+
lhs = lhs.downcast(adt_def, variant_index);
86+
}
87+
active_field_index
88+
}
89+
_ => None
6790
};
68-
let n = bb.statements.len();
69-
bb.statements.reserve(n + operands.len() + suffix_stmts.len());
70-
for (i, op) in operands.iter().enumerate() {
71-
let ref variant_def = adt_def.variants[variant];
72-
let ty = variant_def.fields[i].ty(tcx, substs);
73-
let rhs = Rvalue::Use(op.clone());
7491

75-
let lhs_cast = if adt_def.is_enum() {
76-
Place::Projection(Box::new(PlaceProjection {
77-
base: lhs.clone(),
78-
elem: ProjectionElem::Downcast(adt_def, variant),
79-
}))
80-
} else {
81-
lhs.clone()
82-
};
92+
let new_total_count = bb.statements.len() +
93+
operands.len() +
94+
(set_discriminant.is_some() as usize) +
95+
suffix_stmts.len();
96+
bb.statements.reserve(new_total_count);
8397

84-
let lhs_proj = Place::Projection(Box::new(PlaceProjection {
85-
base: lhs_cast,
86-
elem: ProjectionElem::Field(Field::new(i), ty),
87-
}));
88-
let new_statement = Statement {
89-
source_info: src_info,
90-
kind: StatementKind::Assign(lhs_proj, rhs),
98+
for (j, op) in operands.into_iter().enumerate() {
99+
let lhs_field = if let AggregateKind::Array(_) = *kind {
100+
// FIXME(eddyb) `offset` should be u64.
101+
let offset = j as u32;
102+
assert_eq!(offset as usize, j);
103+
lhs.clone().elem(ProjectionElem::ConstantIndex {
104+
offset,
105+
// FIXME(eddyb) `min_length` doesn't appear to be used.
106+
min_length: offset + 1,
107+
from_end: false
108+
})
109+
} else {
110+
let ty = op.ty(local_decls, tcx);
111+
let field = Field::new(active_field_index.unwrap_or(j));
112+
lhs.clone().field(field, ty)
91113
};
92-
debug!("inserting: {:?} @ {:?}", new_statement, idx + i);
93-
bb.statements.push(new_statement);
114+
bb.statements.push(Statement {
115+
source_info,
116+
kind: StatementKind::Assign(lhs_field, Rvalue::Use(op)),
117+
});
94118
}
95119

96-
// if the aggregate was an enum, we need to set the discriminant
97-
if adt_def.is_enum() {
98-
let set_discriminant = Statement {
99-
kind: StatementKind::SetDiscriminant {
100-
place: lhs.clone(),
101-
variant_index: variant,
102-
},
103-
source_info: src_info,
104-
};
105-
bb.statements.push(set_discriminant);
106-
};
120+
// If the aggregate was an enum, we need to set the discriminant.
121+
bb.statements.extend(set_discriminant);
107122

108-
curr = bb.statements.len();
123+
start = bb.statements.len();
109124
bb.statements.extend(suffix_stmts);
110125
}
111126
}
112127
}
113128
}
114-
115-
fn get_aggregate_statement_index<'a, 'tcx, 'b>(start: usize,
116-
statements: &Vec<Statement<'tcx>>)
117-
-> Option<usize> {
118-
for i in start..statements.len() {
119-
let ref statement = statements[i];
120-
let rhs = match statement.kind {
121-
StatementKind::Assign(_, ref rhs) => rhs,
122-
_ => continue,
123-
};
124-
let (kind, operands) = match rhs {
125-
&Rvalue::Aggregate(ref kind, ref operands) => (kind, operands),
126-
_ => continue,
127-
};
128-
let (adt_def, variant) = match **kind {
129-
AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant),
130-
_ => continue,
131-
};
132-
if operands.len() == 0 {
133-
// don't deaggregate ()
134-
continue;
135-
}
136-
debug!("getting variant {:?}", variant);
137-
debug!("for adt_def {:?}", adt_def);
138-
return Some(i);
139-
};
140-
None
141-
}

src/test/mir-opt/copy_propagation_arg.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ fn main() {
7878
// bb1: {
7979
// StorageDead(_3);
8080
// _1 = const 5u8;
81-
// _0 = ();
8281
// return;
8382
// }
8483
// END rustc.bar.CopyPropagation.before.mir
@@ -100,7 +99,6 @@ fn main() {
10099
// _2 = _1;
101100
// _1 = move _2;
102101
// StorageDead(_2);
103-
// _0 = ();
104102
// return;
105103
// }
106104
// END rustc.baz.CopyPropagation.before.mir

src/test/mir-opt/deaggregator_test_multiple.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ fn main() {
5252
// ((_4 as A).0: i32) = move _5;
5353
// discriminant(_4) = 0;
5454
// ...
55-
// _0 = [move _2, move _4];
55+
// _0[0 of 1] = move _2;
56+
// _0[1 of 2] = move _4;
5657
// ...
5758
// return;
5859
// }

0 commit comments

Comments
 (0)