@@ -21,116 +21,90 @@ impl MirPass for Deaggregator {
21
21
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
22
22
source : MirSource ,
23
23
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
-
31
24
// Don't run on constant MIR, because trans might not be able to
32
25
// evaluate the modified MIR.
33
26
// FIXME(eddyb) Remove check after miri is merged.
34
27
let id = tcx. hir . as_local_node_id ( source. def_id ) . unwrap ( ) ;
35
28
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 ,
41
32
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
+ }
69
41
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
+ }
75
53
} 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 ;
89
58
}
90
59
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 ! ( )
101
66
} ;
102
67
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
+ } ;
109
85
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
+ } ) ;
130
108
}
131
- debug ! ( "getting variant {:?}" , variant) ;
132
- debug ! ( "for adt_def {:?}" , adt_def) ;
133
- return Some ( i) ;
134
- } ;
135
- None
109
+ }
136
110
}
0 commit comments