@@ -31,8 +31,9 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
3131 let mut excluded = excluded_locals ( body) ;
3232 let typing_env = body. typing_env ( tcx) ;
3333 loop {
34+ add_type_based_exclusions ( tcx, & mut excluded, body) ;
3435 debug ! ( ?excluded) ;
35- let escaping = escaping_locals ( tcx , & excluded, body) ;
36+ let escaping = escaping_locals ( & excluded, body) ;
3637 debug ! ( ?escaping) ;
3738 let replacements = compute_flattening ( tcx, typing_env, body, escaping) ;
3839 debug ! ( ?replacements) ;
@@ -55,18 +56,13 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
5556 }
5657}
5758
58- /// Identify all locals that are not eligible for SROA.
59- ///
60- /// There are 3 cases:
61- /// - the aggregated local is used or passed to other code (function parameters and arguments);
62- /// - the locals is a union or an enum;
63- /// - the local's address is taken, and thus the relative addresses of the fields are observable to
64- /// client code.
65- fn escaping_locals < ' tcx > (
59+ /// Also exclude locals whose types are ineligible for SRoA because of
60+ /// implementation restrictions (whether here or in codegen later).
61+ fn add_type_based_exclusions < ' tcx > (
6662 tcx : TyCtxt < ' tcx > ,
67- excluded : & DenseBitSet < Local > ,
63+ excluded : & mut DenseBitSet < Local > ,
6864 body : & Body < ' tcx > ,
69- ) -> DenseBitSet < Local > {
65+ ) {
7066 let is_excluded_ty = |ty : Ty < ' tcx > | {
7167 if ty. is_union ( ) || ty. is_enum ( ) {
7268 return true ;
@@ -86,10 +82,25 @@ fn escaping_locals<'tcx>(
8682 false
8783 } ;
8884
85+ for ( local, decl) in body. local_decls ( ) . iter_enumerated ( ) {
86+ if is_excluded_ty ( decl. ty ) {
87+ excluded. insert ( local) ;
88+ }
89+ }
90+ }
91+
92+ /// Identify all locals that are not eligible for SROA.
93+ ///
94+ /// There are 3 cases:
95+ /// - the aggregated local is used or passed to other code (function parameters and arguments);
96+ /// - the locals is a union or an enum;
97+ /// - the local's address is taken, and thus the relative addresses of the fields are observable to
98+ /// client code.
99+ fn escaping_locals < ' tcx > ( excluded : & DenseBitSet < Local > , body : & Body < ' tcx > ) -> DenseBitSet < Local > {
89100 let mut set = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
90101 set. insert_range ( RETURN_PLACE ..=Local :: from_usize ( body. arg_count ) ) ;
91- for ( local, decl ) in body. local_decls ( ) . iter_enumerated ( ) {
92- if excluded. contains ( local) || is_excluded_ty ( decl . ty ) {
102+ for local in body. local_decls ( ) . indices ( ) {
103+ if excluded. contains ( local) {
93104 set. insert ( local) ;
94105 }
95106 }
0 commit comments