@@ -21,116 +21,90 @@ impl MirPass for Deaggregator {
2121 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
2222 source : MirSource ,
2323 mir : & mut Mir < ' tcx > ) {
24- let node_path = tcx. item_path_str ( source. def_id ) ;
25- debug ! ( "running on: {:?}" , node_path) ;
26- // we only run when mir_opt_level > 2
27- if tcx. sess . opts . debugging_opts . mir_opt_level <= 2 {
28- return ;
29- }
30-
3124 // Don't run on constant MIR, because trans might not be able to
3225 // evaluate the modified MIR.
3326 // FIXME(eddyb) Remove check after miri is merged.
3427 let id = tcx. hir . as_local_node_id ( source. def_id ) . unwrap ( ) ;
3528 match ( tcx. hir . body_owner_kind ( id) , source. promoted ) {
36- ( hir:: BodyOwnerKind :: Fn , None ) => { } ,
37- _ => return
38- }
39- // In fact, we might not want to trigger in other cases.
40- // Ex: when we could use SROA. See issue #35259
29+ ( _, Some ( _) ) |
30+ ( hir:: BodyOwnerKind :: Const , _) |
31+ ( hir:: BodyOwnerKind :: Static ( _) , _) => return ,
4132
42- for bb in mir. basic_blocks_mut ( ) {
43- let mut curr: usize = 0 ;
44- while let Some ( idx) = get_aggregate_statement_index ( curr, & bb. statements ) {
45- // do the replacement
46- debug ! ( "removing statement {:?}" , idx) ;
47- let src_info = bb. statements [ idx] . source_info ;
48- let suffix_stmts = bb. statements . split_off ( idx+1 ) ;
49- let orig_stmt = bb. statements . pop ( ) . unwrap ( ) ;
50- let ( lhs, rhs) = match orig_stmt. kind {
51- StatementKind :: Assign ( ref lhs, ref rhs) => ( lhs, rhs) ,
52- _ => span_bug ! ( src_info. span, "expected assign, not {:?}" , orig_stmt) ,
53- } ;
54- let ( agg_kind, operands) = match rhs {
55- & Rvalue :: Aggregate ( ref agg_kind, ref operands) => ( agg_kind, operands) ,
56- _ => span_bug ! ( src_info. span, "expected aggregate, not {:?}" , rhs) ,
57- } ;
58- let ( adt_def, variant, substs) = match * * agg_kind {
59- AggregateKind :: Adt ( adt_def, variant, substs, None )
60- => ( adt_def, variant, substs) ,
61- _ => span_bug ! ( src_info. span, "expected struct, not {:?}" , rhs) ,
62- } ;
63- let n = bb. statements . len ( ) ;
64- bb. statements . reserve ( n + operands. len ( ) + suffix_stmts. len ( ) ) ;
65- for ( i, op) in operands. iter ( ) . enumerate ( ) {
66- let ref variant_def = adt_def. variants [ variant] ;
67- let ty = variant_def. fields [ i] . ty ( tcx, substs) ;
68- let rhs = Rvalue :: Use ( op. clone ( ) ) ;
33+ ( hir:: BodyOwnerKind :: Fn , _) => {
34+ if tcx. is_const_fn ( source. def_id ) {
35+ // Don't run on const functions, as, again, trans might not be able to evaluate
36+ // the optimized IR.
37+ return
38+ }
39+ }
40+ }
6941
70- let lhs_cast = if adt_def. is_enum ( ) {
71- Place :: Projection ( Box :: new ( PlaceProjection {
72- base : lhs. clone ( ) ,
73- elem : ProjectionElem :: Downcast ( adt_def, variant) ,
74- } ) )
42+ let ( basic_blocks, local_decls) = mir. basic_blocks_and_local_decls_mut ( ) ;
43+ let local_decls = & * local_decls;
44+ for bb in basic_blocks {
45+ bb. expand_statements ( |stmt| {
46+ // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
47+ if let StatementKind :: Assign ( _, ref rhs) = stmt. kind {
48+ if let Rvalue :: Aggregate ( ref kind, _) = * rhs {
49+ // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
50+ if let AggregateKind :: Array ( _) = * * kind {
51+ return None ;
52+ }
7553 } else {
76- lhs. clone ( )
77- } ;
78-
79- let lhs_proj = Place :: Projection ( Box :: new ( PlaceProjection {
80- base : lhs_cast,
81- elem : ProjectionElem :: Field ( Field :: new ( i) , ty) ,
82- } ) ) ;
83- let new_statement = Statement {
84- source_info : src_info,
85- kind : StatementKind :: Assign ( lhs_proj, rhs) ,
86- } ;
87- debug ! ( "inserting: {:?} @ {:?}" , new_statement, idx + i) ;
88- bb. statements . push ( new_statement) ;
54+ return None ;
55+ }
56+ } else {
57+ return None ;
8958 }
9059
91- // if the aggregate was an enum, we need to set the discriminant
92- if adt_def. is_enum ( ) {
93- let set_discriminant = Statement {
94- kind : StatementKind :: SetDiscriminant {
95- place : lhs. clone ( ) ,
96- variant_index : variant,
97- } ,
98- source_info : src_info,
99- } ;
100- bb. statements . push ( set_discriminant) ;
60+ let stmt = stmt. replace_nop ( ) ;
61+ let source_info = stmt. source_info ;
62+ let ( mut lhs, kind, operands) = match stmt. kind {
63+ StatementKind :: Assign ( lhs, Rvalue :: Aggregate ( kind, operands) )
64+ => ( lhs, kind, operands) ,
65+ _ => bug ! ( )
10166 } ;
10267
103- curr = bb. statements . len ( ) ;
104- bb. statements . extend ( suffix_stmts) ;
105- }
106- }
107- }
108- }
68+ let mut set_discriminant = None ;
69+ let active_field_index = match * kind {
70+ AggregateKind :: Adt ( adt_def, variant_index, _, active_field_index) => {
71+ if adt_def. is_enum ( ) {
72+ set_discriminant = Some ( Statement {
73+ kind : StatementKind :: SetDiscriminant {
74+ place : lhs. clone ( ) ,
75+ variant_index,
76+ } ,
77+ source_info,
78+ } ) ;
79+ lhs = lhs. downcast ( adt_def, variant_index) ;
80+ }
81+ active_field_index
82+ }
83+ _ => None
84+ } ;
10985
110- fn get_aggregate_statement_index < ' a , ' tcx , ' b > ( start : usize ,
111- statements : & Vec < Statement < ' tcx > > )
112- -> Option < usize > {
113- for i in start..statements. len ( ) {
114- let ref statement = statements[ i] ;
115- let rhs = match statement. kind {
116- StatementKind :: Assign ( _, ref rhs) => rhs,
117- _ => continue ,
118- } ;
119- let ( kind, operands) = match rhs {
120- & Rvalue :: Aggregate ( ref kind, ref operands) => ( kind, operands) ,
121- _ => continue ,
122- } ;
123- let ( adt_def, variant) = match * * kind {
124- AggregateKind :: Adt ( adt_def, variant, _, None ) => ( adt_def, variant) ,
125- _ => continue ,
126- } ;
127- if operands. len ( ) == 0 {
128- // don't deaggregate ()
129- continue ;
86+ Some ( operands. into_iter ( ) . enumerate ( ) . map ( move |( i, op) | {
87+ let lhs_field = if let AggregateKind :: Array ( _) = * kind {
88+ // FIXME(eddyb) `offset` should be u64.
89+ let offset = i as u32 ;
90+ assert_eq ! ( offset as usize , i) ;
91+ lhs. clone ( ) . elem ( ProjectionElem :: ConstantIndex {
92+ offset,
93+ // FIXME(eddyb) `min_length` doesn't appear to be used.
94+ min_length : offset + 1 ,
95+ from_end : false
96+ } )
97+ } else {
98+ let ty = op. ty ( local_decls, tcx) ;
99+ let field = Field :: new ( active_field_index. unwrap_or ( i) ) ;
100+ lhs. clone ( ) . field ( field, ty)
101+ } ;
102+ Statement {
103+ source_info,
104+ kind : StatementKind :: Assign ( lhs_field, Rvalue :: Use ( op) ) ,
105+ }
106+ } ) . chain ( set_discriminant) )
107+ } ) ;
130108 }
131- debug ! ( "getting variant {:?}" , variant) ;
132- debug ! ( "for adt_def {:?}" , adt_def) ;
133- return Some ( i) ;
134- } ;
135- None
109+ }
136110}
0 commit comments