@@ -96,8 +96,10 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching {
9696 ) ;
9797
9898 let mut allowed_variants = if let Ok ( layout) = layout {
99+ // Find allowed variants based on uninhabited.
99100 variant_discriminants ( & layout, discriminant_ty, tcx)
100101 } else if let Some ( variant_range) = discriminant_ty. variant_range ( tcx) {
102+ // If there are some generics, we can still get the allowed variants.
101103 variant_range
102104 . map ( |variant| {
103105 discriminant_ty. discriminant_for_variant ( tcx, variant) . unwrap ( ) . val
@@ -124,6 +126,23 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching {
124126 fn check_successors ( basic_blocks : & BasicBlocks < ' _ > , bb : BasicBlock ) -> bool {
125127 // After resolving https://github.com/llvm/llvm-project/issues/78578,
126128 // We can remove this check.
129+ // The main issue here is that `early-tailduplication` causes compile time overhead
130+ // and potential performance problems.
131+ // Simply put, when encounter a switch (indirect branch) statement,
132+ // `early-tailduplication` tries to duplicate the switch branch statement with BB
133+ // into (each) predecessors. This makes CFG very complex.
134+ // We can understand it as it transforms the following code
135+ // ```rust
136+ // match a { ... many cases };
137+ // match b { ... many cases };
138+ // ```
139+ // into
140+ // ```rust
141+ // match a { ... many match b { goto BB cases } }
142+ // ... BB cases
143+ // ```
144+ // Abandon this transformation when it is possible (the best effort)
145+ // to encounter the problem.
127146 let mut successors = basic_blocks[ bb] . terminator ( ) . successors ( ) ;
128147 let Some ( first_successor) = successors. next ( ) else { return true } ;
129148 if successors. next ( ) . is_some ( ) {
@@ -136,6 +155,24 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching {
136155 } ;
137156 true
138157 }
158+ // If and only if there is a variant that does not have a branch set,
159+ // change the current of otherwise as the variant branch and set otherwise to unreachable.
160+ // It transforms following code
161+ // ```rust
162+ // match c {
163+ // Ordering::Less => 1,
164+ // Ordering::Equal => 2,
165+ // _ => 3,
166+ // }
167+ // ```
168+ // to
169+ // ```rust
170+ // match c {
171+ // Ordering::Less => 1,
172+ // Ordering::Equal => 2,
173+ // Ordering::Greater => 3,
174+ // }
175+ // ```
139176 let otherwise_is_last_variant = !otherwise_is_empty_unreachable
140177 && allowed_variants. len ( ) == 1
141178 && check_successors ( & body. basic_blocks , targets. otherwise ( ) ) ;
@@ -150,6 +187,7 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching {
150187 let mut targets = targets. clone ( ) ;
151188 if replace_otherwise_to_unreachable {
152189 if otherwise_is_last_variant {
190+ // We have checked that `allowed_variants` has only one element.
153191 #[ allow( rustc:: potential_query_instability) ]
154192 let last_variant = * allowed_variants. iter ( ) . next ( ) . unwrap ( ) ;
155193 targets. add_target ( last_variant, targets. otherwise ( ) ) ;
0 commit comments