@@ -66,8 +66,8 @@ impl SimplifyCfg {
6666 }
6767}
6868
69- pub ( super ) fn simplify_cfg ( body : & mut Body < ' _ > ) {
70- CfgSimplifier :: new ( body) . simplify ( ) ;
69+ pub ( super ) fn simplify_cfg < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
70+ CfgSimplifier :: new ( tcx , body) . simplify ( ) ;
7171 remove_dead_blocks ( body) ;
7272
7373 // FIXME: Should probably be moved into some kind of pass manager
@@ -79,9 +79,9 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
7979 self . name ( )
8080 }
8181
82- fn run_pass ( & self , _ : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
82+ fn run_pass ( & self , tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
8383 debug ! ( "SimplifyCfg({:?}) - simplifying {:?}" , self . name( ) , body. source) ;
84- simplify_cfg ( body) ;
84+ simplify_cfg ( tcx , body) ;
8585 }
8686
8787 fn is_required ( & self ) -> bool {
@@ -90,12 +90,13 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
9090}
9191
9292struct CfgSimplifier < ' a , ' tcx > {
93+ preserve_switch_reads : bool ,
9394 basic_blocks : & ' a mut IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
9495 pred_count : IndexVec < BasicBlock , u32 > ,
9596}
9697
9798impl < ' a , ' tcx > CfgSimplifier < ' a , ' tcx > {
98- fn new ( body : & ' a mut Body < ' tcx > ) -> Self {
99+ fn new ( tcx : TyCtxt < ' tcx > , body : & ' a mut Body < ' tcx > ) -> Self {
99100 let mut pred_count = IndexVec :: from_elem ( 0u32 , & body. basic_blocks ) ;
100101
101102 // we can't use mir.predecessors() here because that counts
@@ -110,9 +111,13 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
110111 }
111112 }
112113
114+ // Preserve `SwitchInt` reads on the phase transition from Built -> Analysis(Initial)
115+ // or if `-Zmir-preserve-ub`.
116+ let preserve_switch_reads =
117+ matches ! ( body. phase, MirPhase :: Built ) | tcx. sess . opts . unstable_opts . mir_preserve_ub ;
113118 let basic_blocks = body. basic_blocks_mut ( ) ;
114119
115- CfgSimplifier { basic_blocks, pred_count }
120+ CfgSimplifier { preserve_switch_reads , basic_blocks, pred_count }
116121 }
117122
118123 fn simplify ( mut self ) {
@@ -253,9 +258,15 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
253258
254259 // turn a branch with all successors identical to a goto
255260 fn simplify_branch ( & mut self , terminator : & mut Terminator < ' tcx > ) -> bool {
256- match terminator. kind {
257- TerminatorKind :: SwitchInt { .. } => { }
258- _ => return false ,
261+ // Removing a `SwitchInt` terminator may remove reads that result in UB,
262+ // so we must not apply this optimization before borrowck or when
263+ // `-Zmir-preserve-ub` is set.
264+ if self . preserve_switch_reads {
265+ return false ;
266+ }
267+
268+ let TerminatorKind :: SwitchInt { .. } = terminator. kind else {
269+ return false ;
259270 } ;
260271
261272 let first_succ = {
0 commit comments