@@ -4,8 +4,7 @@ use rustc_abi::Variants;
4
4
use rustc_data_structures:: fx:: FxHashSet ;
5
5
use rustc_middle:: bug;
6
6
use rustc_middle:: mir:: {
7
- BasicBlock , BasicBlockData , BasicBlocks , Body , Local , Operand , Rvalue , StatementKind ,
8
- TerminatorKind ,
7
+ BasicBlockData , Body , Local , Operand , Rvalue , StatementKind , TerminatorKind ,
9
8
} ;
10
9
use rustc_middle:: ty:: layout:: TyAndLayout ;
11
10
use rustc_middle:: ty:: { Ty , TyCtxt } ;
@@ -125,43 +124,10 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
125
124
unreachable_targets. push ( index) ;
126
125
}
127
126
}
128
- let otherwise_is_empty_unreachable =
129
- body. basic_blocks [ targets. otherwise ( ) ] . is_empty_unreachable ( ) ;
130
- fn check_successors ( basic_blocks : & BasicBlocks < ' _ > , bb : BasicBlock ) -> bool {
131
- // After resolving https://github.com/llvm/llvm-project/issues/78578,
132
- // We can remove this check.
133
- // The main issue here is that `early-tailduplication` causes compile time overhead
134
- // and potential performance problems.
135
- // Simply put, when encounter a switch (indirect branch) statement,
136
- // `early-tailduplication` tries to duplicate the switch branch statement with BB
137
- // into (each) predecessors. This makes CFG very complex.
138
- // We can understand it as it transforms the following code
139
- // ```rust
140
- // match a { ... many cases };
141
- // match b { ... many cases };
142
- // ```
143
- // into
144
- // ```rust
145
- // match a { ... many match b { goto BB cases } }
146
- // ... BB cases
147
- // ```
148
- // Abandon this transformation when it is possible (the best effort)
149
- // to encounter the problem.
150
- let mut successors = basic_blocks[ bb] . terminator ( ) . successors ( ) ;
151
- let Some ( first_successor) = successors. next ( ) else { return true } ;
152
- if successors. next ( ) . is_some ( ) {
153
- return true ;
154
- }
155
- if let TerminatorKind :: SwitchInt { .. } =
156
- & basic_blocks[ first_successor] . terminator ( ) . kind
157
- {
158
- return false ;
159
- } ;
160
- true
161
- }
127
+
162
128
// If and only if there is a variant that does not have a branch set, change the
163
129
// current of otherwise as the variant branch and set otherwise to unreachable. It
164
- // transforms following code
130
+ // transforms the following code
165
131
// ```rust
166
132
// match c {
167
133
// Ordering::Less => 1,
@@ -177,22 +143,16 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
177
143
// Ordering::Greater => 3,
178
144
// }
179
145
// ```
180
- let otherwise_is_last_variant = !otherwise_is_empty_unreachable
181
- && allowed_variants. len ( ) == 1
182
- // Despite the LLVM issue, we hope that small enum can still be transformed.
183
- // This is valuable for both `a <= b` and `if let Some/Ok(v)`.
184
- && ( targets. all_targets ( ) . len ( ) <= 3
185
- || check_successors ( & body. basic_blocks , targets. otherwise ( ) ) ) ;
186
- let replace_otherwise_to_unreachable = otherwise_is_last_variant
187
- || ( !otherwise_is_empty_unreachable && allowed_variants. is_empty ( ) ) ;
188
-
146
+ let replace_otherwise_to_unreachable = allowed_variants. len ( ) <= 1
147
+ && !body. basic_blocks [ targets. otherwise ( ) ] . is_empty_unreachable ( ) ;
189
148
if unreachable_targets. is_empty ( ) && !replace_otherwise_to_unreachable {
190
149
continue ;
191
150
}
192
151
193
152
let unreachable_block = patch. unreachable_no_cleanup_block ( ) ;
194
153
let mut targets = targets. clone ( ) ;
195
154
if replace_otherwise_to_unreachable {
155
+ let otherwise_is_last_variant = !allowed_variants. is_empty ( ) ;
196
156
if otherwise_is_last_variant {
197
157
// We have checked that `allowed_variants` has only one element.
198
158
#[ allow( rustc:: potential_query_instability) ]
0 commit comments