@@ -6,6 +6,8 @@ use rustc_middle::ty::util::IntTypeExt;
6
6
use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
7
7
use rustc_session:: Session ;
8
8
9
+ use crate :: patch:: MirPatch ;
10
+
9
11
/// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large
10
12
/// enough discrepancy between them.
11
13
///
@@ -41,31 +43,34 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
41
43
let mut alloc_cache = FxHashMap :: default ( ) ;
42
44
let typing_env = body. typing_env ( tcx) ;
43
45
44
- let blocks = body. basic_blocks . as_mut ( ) ;
45
- let local_decls = & mut body. local_decls ;
46
+ let mut patch = MirPatch :: new ( body) ;
46
47
47
- for bb in blocks {
48
- bb . expand_statements ( |st| {
48
+ for ( block , data ) in body . basic_blocks . as_mut ( ) . iter_enumerated_mut ( ) {
49
+ for ( statement_index , st ) in data . statements . iter_mut ( ) . enumerate ( ) {
49
50
let StatementKind :: Assign ( box (
50
51
lhs,
51
52
Rvalue :: Use ( Operand :: Copy ( rhs) | Operand :: Move ( rhs) ) ,
52
53
) ) = & st. kind
53
54
else {
54
- return None ;
55
+ continue ;
55
56
} ;
56
57
57
- let ty = lhs . ty ( local_decls , tcx ) . ty ;
58
+ let location = Location { block , statement_index } ;
58
59
59
- let ( adt_def, num_variants, alloc_id) =
60
- self . candidate ( tcx, typing_env, ty, & mut alloc_cache) ?;
60
+ let ty = lhs. ty ( & body. local_decls , tcx) . ty ;
61
61
62
- let source_info = st. source_info ;
63
- let span = source_info. span ;
62
+ let Some ( ( adt_def, num_variants, alloc_id) ) =
63
+ self . candidate ( tcx, typing_env, ty, & mut alloc_cache)
64
+ else {
65
+ continue ;
66
+ } ;
67
+
68
+ let span = st. source_info . span ;
64
69
65
70
let tmp_ty = Ty :: new_array ( tcx, tcx. types . usize , num_variants as u64 ) ;
66
- let size_array_local = local_decls . push ( LocalDecl :: new ( tmp_ty, span) ) ;
67
- let store_live =
68
- Statement { source_info , kind : StatementKind :: StorageLive ( size_array_local) } ;
71
+ let size_array_local = patch . new_temp ( tmp_ty, span) ;
72
+
73
+ let store_live = StatementKind :: StorageLive ( size_array_local) ;
69
74
70
75
let place = Place :: from ( size_array_local) ;
71
76
let constant_vals = ConstOperand {
@@ -77,108 +82,63 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
77
82
) ,
78
83
} ;
79
84
let rval = Rvalue :: Use ( Operand :: Constant ( Box :: new ( constant_vals) ) ) ;
80
- let const_assign =
81
- Statement { source_info, kind : StatementKind :: Assign ( Box :: new ( ( place, rval) ) ) } ;
82
-
83
- let discr_place = Place :: from (
84
- local_decls. push ( LocalDecl :: new ( adt_def. repr ( ) . discr_type ( ) . to_ty ( tcx) , span) ) ,
85
- ) ;
86
- let store_discr = Statement {
87
- source_info,
88
- kind : StatementKind :: Assign ( Box :: new ( (
89
- discr_place,
90
- Rvalue :: Discriminant ( * rhs) ,
91
- ) ) ) ,
92
- } ;
93
-
94
- let discr_cast_place =
95
- Place :: from ( local_decls. push ( LocalDecl :: new ( tcx. types . usize , span) ) ) ;
96
- let cast_discr = Statement {
97
- source_info,
98
- kind : StatementKind :: Assign ( Box :: new ( (
99
- discr_cast_place,
100
- Rvalue :: Cast (
101
- CastKind :: IntToInt ,
102
- Operand :: Copy ( discr_place) ,
103
- tcx. types . usize ,
104
- ) ,
105
- ) ) ) ,
106
- } ;
107
-
108
- let size_place =
109
- Place :: from ( local_decls. push ( LocalDecl :: new ( tcx. types . usize , span) ) ) ;
110
- let store_size = Statement {
111
- source_info,
112
- kind : StatementKind :: Assign ( Box :: new ( (
113
- size_place,
114
- Rvalue :: Use ( Operand :: Copy ( Place {
115
- local : size_array_local,
116
- projection : tcx
117
- . mk_place_elems ( & [ PlaceElem :: Index ( discr_cast_place. local ) ] ) ,
118
- } ) ) ,
119
- ) ) ) ,
120
- } ;
121
-
122
- let dst =
123
- Place :: from ( local_decls. push ( LocalDecl :: new ( Ty :: new_mut_ptr ( tcx, ty) , span) ) ) ;
124
- let dst_ptr = Statement {
125
- source_info,
126
- kind : StatementKind :: Assign ( Box :: new ( (
127
- dst,
128
- Rvalue :: RawPtr ( RawPtrKind :: Mut , * lhs) ,
129
- ) ) ) ,
130
- } ;
85
+ let const_assign = StatementKind :: Assign ( Box :: new ( ( place, rval) ) ) ;
86
+
87
+ let discr_place =
88
+ Place :: from ( patch. new_temp ( adt_def. repr ( ) . discr_type ( ) . to_ty ( tcx) , span) ) ;
89
+ let store_discr =
90
+ StatementKind :: Assign ( Box :: new ( ( discr_place, Rvalue :: Discriminant ( * rhs) ) ) ) ;
91
+
92
+ let discr_cast_place = Place :: from ( patch. new_temp ( tcx. types . usize , span) ) ;
93
+ let cast_discr = StatementKind :: Assign ( Box :: new ( (
94
+ discr_cast_place,
95
+ Rvalue :: Cast ( CastKind :: IntToInt , Operand :: Copy ( discr_place) , tcx. types . usize ) ,
96
+ ) ) ) ;
97
+
98
+ let size_place = Place :: from ( patch. new_temp ( tcx. types . usize , span) ) ;
99
+ let store_size = StatementKind :: Assign ( Box :: new ( (
100
+ size_place,
101
+ Rvalue :: Use ( Operand :: Copy ( Place {
102
+ local : size_array_local,
103
+ projection : tcx. mk_place_elems ( & [ PlaceElem :: Index ( discr_cast_place. local ) ] ) ,
104
+ } ) ) ,
105
+ ) ) ) ;
106
+
107
+ let dst = Place :: from ( patch. new_temp ( Ty :: new_mut_ptr ( tcx, ty) , span) ) ;
108
+ let dst_ptr =
109
+ StatementKind :: Assign ( Box :: new ( ( dst, Rvalue :: RawPtr ( RawPtrKind :: Mut , * lhs) ) ) ) ;
131
110
132
111
let dst_cast_ty = Ty :: new_mut_ptr ( tcx, tcx. types . u8 ) ;
133
- let dst_cast_place =
134
- Place :: from ( local_decls. push ( LocalDecl :: new ( dst_cast_ty, span) ) ) ;
135
- let dst_cast = Statement {
136
- source_info,
137
- kind : StatementKind :: Assign ( Box :: new ( (
138
- dst_cast_place,
139
- Rvalue :: Cast ( CastKind :: PtrToPtr , Operand :: Copy ( dst) , dst_cast_ty) ,
140
- ) ) ) ,
141
- } ;
112
+ let dst_cast_place = Place :: from ( patch. new_temp ( dst_cast_ty, span) ) ;
113
+ let dst_cast = StatementKind :: Assign ( Box :: new ( (
114
+ dst_cast_place,
115
+ Rvalue :: Cast ( CastKind :: PtrToPtr , Operand :: Copy ( dst) , dst_cast_ty) ,
116
+ ) ) ) ;
142
117
143
- let src =
144
- Place :: from ( local_decls. push ( LocalDecl :: new ( Ty :: new_imm_ptr ( tcx, ty) , span) ) ) ;
145
- let src_ptr = Statement {
146
- source_info,
147
- kind : StatementKind :: Assign ( Box :: new ( (
148
- src,
149
- Rvalue :: RawPtr ( RawPtrKind :: Const , * rhs) ,
150
- ) ) ) ,
151
- } ;
118
+ let src = Place :: from ( patch. new_temp ( Ty :: new_imm_ptr ( tcx, ty) , span) ) ;
119
+ let src_ptr =
120
+ StatementKind :: Assign ( Box :: new ( ( src, Rvalue :: RawPtr ( RawPtrKind :: Const , * rhs) ) ) ) ;
152
121
153
122
let src_cast_ty = Ty :: new_imm_ptr ( tcx, tcx. types . u8 ) ;
154
- let src_cast_place =
155
- Place :: from ( local_decls. push ( LocalDecl :: new ( src_cast_ty, span) ) ) ;
156
- let src_cast = Statement {
157
- source_info,
158
- kind : StatementKind :: Assign ( Box :: new ( (
159
- src_cast_place,
160
- Rvalue :: Cast ( CastKind :: PtrToPtr , Operand :: Copy ( src) , src_cast_ty) ,
161
- ) ) ) ,
162
- } ;
123
+ let src_cast_place = Place :: from ( patch. new_temp ( src_cast_ty, span) ) ;
124
+ let src_cast = StatementKind :: Assign ( Box :: new ( (
125
+ src_cast_place,
126
+ Rvalue :: Cast ( CastKind :: PtrToPtr , Operand :: Copy ( src) , src_cast_ty) ,
127
+ ) ) ) ;
163
128
164
- let deinit_old =
165
- Statement { source_info, kind : StatementKind :: Deinit ( Box :: new ( dst) ) } ;
166
-
167
- let copy_bytes = Statement {
168
- source_info,
169
- kind : StatementKind :: Intrinsic ( Box :: new (
170
- NonDivergingIntrinsic :: CopyNonOverlapping ( CopyNonOverlapping {
171
- src : Operand :: Copy ( src_cast_place) ,
172
- dst : Operand :: Copy ( dst_cast_place) ,
173
- count : Operand :: Copy ( size_place) ,
174
- } ) ,
175
- ) ) ,
176
- } ;
129
+ let deinit_old = StatementKind :: Deinit ( Box :: new ( dst) ) ;
130
+
131
+ let copy_bytes = StatementKind :: Intrinsic ( Box :: new (
132
+ NonDivergingIntrinsic :: CopyNonOverlapping ( CopyNonOverlapping {
133
+ src : Operand :: Copy ( src_cast_place) ,
134
+ dst : Operand :: Copy ( dst_cast_place) ,
135
+ count : Operand :: Copy ( size_place) ,
136
+ } ) ,
137
+ ) ) ;
177
138
178
- let store_dead =
179
- Statement { source_info, kind : StatementKind :: StorageDead ( size_array_local) } ;
139
+ let store_dead = StatementKind :: StorageDead ( size_array_local) ;
180
140
181
- let iter = [
141
+ let stmts = [
182
142
store_live,
183
143
const_assign,
184
144
store_discr,
@@ -191,14 +151,16 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
191
151
deinit_old,
192
152
copy_bytes,
193
153
store_dead,
194
- ]
195
- . into_iter ( ) ;
154
+ ] ;
155
+ for stmt in stmts {
156
+ patch. add_statement ( location, stmt) ;
157
+ }
196
158
197
159
st. make_nop ( ) ;
198
-
199
- Some ( iter)
200
- } ) ;
160
+ }
201
161
}
162
+
163
+ patch. apply ( body) ;
202
164
}
203
165
204
166
fn is_required ( & self ) -> bool {
0 commit comments