@@ -31,8 +31,9 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
31
31
let mut excluded = excluded_locals ( body) ;
32
32
let typing_env = body. typing_env ( tcx) ;
33
33
loop {
34
+ add_type_based_exclusions ( tcx, & mut excluded, body) ;
34
35
debug ! ( ?excluded) ;
35
- let escaping = escaping_locals ( tcx , & excluded, body) ;
36
+ let escaping = escaping_locals ( & excluded, body) ;
36
37
debug ! ( ?escaping) ;
37
38
let replacements = compute_flattening ( tcx, typing_env, body, escaping) ;
38
39
debug ! ( ?replacements) ;
@@ -55,18 +56,13 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
55
56
}
56
57
}
57
58
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 > (
66
62
tcx : TyCtxt < ' tcx > ,
67
- excluded : & DenseBitSet < Local > ,
63
+ excluded : & mut DenseBitSet < Local > ,
68
64
body : & Body < ' tcx > ,
69
- ) -> DenseBitSet < Local > {
65
+ ) {
70
66
let is_excluded_ty = |ty : Ty < ' tcx > | {
71
67
if ty. is_union ( ) || ty. is_enum ( ) {
72
68
return true ;
@@ -86,10 +82,28 @@ fn escaping_locals<'tcx>(
86
82
false
87
83
} ;
88
84
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 > (
100
+ excluded : & DenseBitSet < Local > ,
101
+ body : & Body < ' tcx > ,
102
+ ) -> DenseBitSet < Local > {
89
103
let mut set = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
90
104
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 ) {
105
+ for local in body. local_decls ( ) . indices ( ) {
106
+ if excluded. contains ( local) {
93
107
set. insert ( local) ;
94
108
}
95
109
}
0 commit comments