@@ -90,11 +90,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
9090 } ;
9191
9292 for bb in body. basic_blocks . indices ( ) {
93- let old_len = finder. opportunities . len ( ) ;
94- // If we have any const-eval errors discard any opportunities found
95- if finder. start_from_switch ( bb) . is_none ( ) {
96- finder. opportunities . truncate ( old_len) ;
97- }
93+ finder. start_from_switch ( bb) ;
9894 }
9995
10096 let opportunities = finder. opportunities ;
@@ -201,28 +197,26 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
201197
202198 /// Recursion entry point to find threading opportunities.
203199 #[ instrument( level = "trace" , skip( self ) ) ]
204- fn start_from_switch ( & mut self , bb : BasicBlock ) -> Option < ( ) > {
200+ fn start_from_switch ( & mut self , bb : BasicBlock ) {
205201 let bbdata = & self . body [ bb] ;
206202 if bbdata. is_cleanup || self . loop_headers . contains ( bb) {
207- return Some ( ( ) ) ;
203+ return ;
208204 }
209- let Some ( ( discr, targets) ) = bbdata. terminator ( ) . kind . as_switch ( ) else { return Some ( ( ) ) } ;
210- let Some ( discr) = discr. place ( ) else { return Some ( ( ) ) } ;
205+ let Some ( ( discr, targets) ) = bbdata. terminator ( ) . kind . as_switch ( ) else { return } ;
206+ let Some ( discr) = discr. place ( ) else { return } ;
211207 debug ! ( ?discr, ?bb) ;
212208
213209 let discr_ty = discr. ty ( self . body , self . tcx ) . ty ;
214- let Ok ( discr_layout) = self . ecx . layout_of ( discr_ty) else {
215- return Some ( ( ) ) ;
216- } ;
210+ let Ok ( discr_layout) = self . ecx . layout_of ( discr_ty) else { return } ;
217211
218- let Some ( discr) = self . map . find ( discr. as_ref ( ) ) else { return Some ( ( ) ) } ;
212+ let Some ( discr) = self . map . find ( discr. as_ref ( ) ) else { return } ;
219213 debug ! ( ?discr) ;
220214
221215 let cost = CostChecker :: new ( self . tcx , self . typing_env , None , self . body ) ;
222216 let mut state = State :: new_reachable ( ) ;
223217
224218 let conds = if let Some ( ( value, then, else_) ) = targets. as_static_if ( ) {
225- let value = ScalarInt :: try_from_uint ( value, discr_layout. size ) ? ;
219+ let Some ( value) = ScalarInt :: try_from_uint ( value, discr_layout. size ) else { return } ;
226220 self . arena . alloc_from_iter ( [
227221 Condition { value, polarity : Polarity :: Eq , target : then } ,
228222 Condition { value, polarity : Polarity :: Ne , target : else_ } ,
@@ -248,27 +242,27 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
248242 mut state : State < ConditionSet < ' a > > ,
249243 mut cost : CostChecker < ' _ , ' tcx > ,
250244 depth : usize ,
251- ) -> Option < ( ) > {
245+ ) {
252246 // Do not thread through loop headers.
253247 if self . loop_headers . contains ( bb) {
254- return Some ( ( ) ) ;
248+ return ;
255249 }
256250
257251 debug ! ( cost = ?cost. cost( ) ) ;
258252 for ( statement_index, stmt) in
259253 self . body . basic_blocks [ bb] . statements . iter ( ) . enumerate ( ) . rev ( )
260254 {
261255 if self . is_empty ( & state) {
262- return Some ( ( ) ) ;
256+ return ;
263257 }
264258
265259 cost. visit_statement ( stmt, Location { block : bb, statement_index } ) ;
266260 if cost. cost ( ) > MAX_COST {
267- return Some ( ( ) ) ;
261+ return ;
268262 }
269263
270264 // Attempt to turn the `current_condition` on `lhs` into a condition on another place.
271- self . process_statement ( bb, stmt, & mut state) ? ;
265+ self . process_statement ( bb, stmt, & mut state) ;
272266
273267 // When a statement mutates a place, assignments to that place that happen
274268 // above the mutation cannot fulfill a condition.
@@ -280,7 +274,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
280274 }
281275
282276 if self . is_empty ( & state) || depth >= MAX_BACKTRACK {
283- return Some ( ( ) ) ;
277+ return ;
284278 }
285279
286280 let last_non_rec = self . opportunities . len ( ) ;
@@ -293,9 +287,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
293287 match term. kind {
294288 TerminatorKind :: SwitchInt { ref discr, ref targets } => {
295289 self . process_switch_int ( discr, targets, bb, & mut state) ;
296- self . find_opportunity ( pred, state, cost, depth + 1 ) ? ;
290+ self . find_opportunity ( pred, state, cost, depth + 1 ) ;
297291 }
298- _ => self . recurse_through_terminator ( pred, || state, & cost, depth) ? ,
292+ _ => self . recurse_through_terminator ( pred, || state, & cost, depth) ,
299293 }
300294 } else if let & [ ref predecessors @ .., last_pred] = & predecessors[ ..] {
301295 for & pred in predecessors {
@@ -320,13 +314,12 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
320314 let first = & mut new_tos[ 0 ] ;
321315 * first = ThreadingOpportunity { chain : vec ! [ bb] , target : first. target } ;
322316 self . opportunities . truncate ( last_non_rec + 1 ) ;
323- return Some ( ( ) ) ;
317+ return ;
324318 }
325319
326320 for op in self . opportunities [ last_non_rec..] . iter_mut ( ) {
327321 op. chain . push ( bb) ;
328322 }
329- Some ( ( ) )
330323 }
331324
332325 /// Extract the mutated place from a statement.
@@ -440,23 +433,23 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
440433 lhs : PlaceIndex ,
441434 rhs : & Operand < ' tcx > ,
442435 state : & mut State < ConditionSet < ' a > > ,
443- ) -> Option < ( ) > {
436+ ) {
444437 match rhs {
445438 // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
446439 Operand :: Constant ( constant) => {
447- let constant = self
448- . ecx
449- . eval_mir_constant ( & constant. const_ , constant. span , None )
450- . discard_err ( ) ?;
440+ let Some ( constant) =
441+ self . ecx . eval_mir_constant ( & constant. const_ , constant. span , None ) . discard_err ( )
442+ else {
443+ return ;
444+ } ;
451445 self . process_constant ( bb, lhs, constant, state) ;
452446 }
453447 // Transfer the conditions on the copied rhs.
454448 Operand :: Move ( rhs) | Operand :: Copy ( rhs) => {
455- let Some ( rhs) = self . map . find ( rhs. as_ref ( ) ) else { return Some ( ( ) ) } ;
449+ let Some ( rhs) = self . map . find ( rhs. as_ref ( ) ) else { return } ;
456450 state. insert_place_idx ( rhs, lhs, & self . map ) ;
457451 }
458452 }
459- Some ( ( ) )
460453 }
461454
462455 #[ instrument( level = "trace" , skip( self ) ) ]
@@ -466,26 +459,22 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
466459 lhs_place : & Place < ' tcx > ,
467460 rhs : & Rvalue < ' tcx > ,
468461 state : & mut State < ConditionSet < ' a > > ,
469- ) -> Option < ( ) > {
470- let Some ( lhs) = self . map . find ( lhs_place. as_ref ( ) ) else {
471- return Some ( ( ) ) ;
472- } ;
462+ ) {
463+ let Some ( lhs) = self . map . find ( lhs_place. as_ref ( ) ) else { return } ;
473464 match rhs {
474- Rvalue :: Use ( operand) => self . process_operand ( bb, lhs, operand, state) ? ,
465+ Rvalue :: Use ( operand) => self . process_operand ( bb, lhs, operand, state) ,
475466 // Transfer the conditions on the copy rhs.
476- Rvalue :: CopyForDeref ( rhs) => {
477- self . process_operand ( bb, lhs, & Operand :: Copy ( * rhs) , state) ?
478- }
467+ Rvalue :: CopyForDeref ( rhs) => self . process_operand ( bb, lhs, & Operand :: Copy ( * rhs) , state) ,
479468 Rvalue :: Discriminant ( rhs) => {
480- let Some ( rhs) = self . map . find_discr ( rhs. as_ref ( ) ) else { return Some ( ( ) ) } ;
469+ let Some ( rhs) = self . map . find_discr ( rhs. as_ref ( ) ) else { return } ;
481470 state. insert_place_idx ( rhs, lhs, & self . map ) ;
482471 }
483472 // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
484473 Rvalue :: Aggregate ( box kind, operands) => {
485474 let agg_ty = lhs_place. ty ( self . body , self . tcx ) . ty ;
486475 let lhs = match kind {
487476 // Do not support unions.
488- AggregateKind :: Adt ( .., Some ( _) ) => return Some ( ( ) ) ,
477+ AggregateKind :: Adt ( .., Some ( _) ) => return ,
489478 AggregateKind :: Adt ( _, variant_index, ..) if agg_ty. is_enum ( ) => {
490479 if let Some ( discr_target) = self . map . apply ( lhs, TrackElem :: Discriminant )
491480 && let Some ( discr_value) = self
@@ -498,31 +487,33 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
498487 if let Some ( idx) = self . map . apply ( lhs, TrackElem :: Variant ( * variant_index) ) {
499488 idx
500489 } else {
501- return Some ( ( ) ) ;
490+ return ;
502491 }
503492 }
504493 _ => lhs,
505494 } ;
506495 for ( field_index, operand) in operands. iter_enumerated ( ) {
507496 if let Some ( field) = self . map . apply ( lhs, TrackElem :: Field ( field_index) ) {
508- self . process_operand ( bb, field, operand, state) ? ;
497+ self . process_operand ( bb, field, operand, state) ;
509498 }
510499 }
511500 }
512501 // Transfer the conditions on the copy rhs, after inverting the value of the condition.
513502 Rvalue :: UnaryOp ( UnOp :: Not , Operand :: Move ( place) | Operand :: Copy ( place) ) => {
514503 let layout = self . ecx . layout_of ( place. ty ( self . body , self . tcx ) . ty ) . unwrap ( ) ;
515- let Some ( conditions) = state. try_get_idx ( lhs, & self . map ) else { return Some ( ( ) ) } ;
516- let Some ( place) = self . map . find ( place. as_ref ( ) ) else { return Some ( ( ) ) } ;
517- let conds = conditions. map ( self . arena , |mut cond| {
504+ let Some ( conditions) = state. try_get_idx ( lhs, & self . map ) else { return } ;
505+ let Some ( place) = self . map . find ( place. as_ref ( ) ) else { return } ;
506+ let Some ( conds) = conditions. map ( self . arena , |mut cond| {
518507 cond. value = self
519508 . ecx
520509 . unary_op ( UnOp :: Not , & ImmTy :: from_scalar_int ( cond. value , layout) )
521510 . discard_err ( ) ?
522511 . to_scalar_int ( )
523512 . discard_err ( ) ?;
524513 Some ( cond)
525- } ) ?;
514+ } ) else {
515+ return ;
516+ } ;
526517 state. insert_value_idx ( place, conds, & self . map ) ;
527518 }
528519 // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`.
@@ -532,34 +523,38 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
532523 box ( Operand :: Move ( place) | Operand :: Copy ( place) , Operand :: Constant ( value) )
533524 | box ( Operand :: Constant ( value) , Operand :: Move ( place) | Operand :: Copy ( place) ) ,
534525 ) => {
535- let Some ( conditions) = state. try_get_idx ( lhs, & self . map ) else { return Some ( ( ) ) } ;
536- let Some ( place) = self . map . find ( place. as_ref ( ) ) else { return Some ( ( ) ) } ;
526+ let Some ( conditions) = state. try_get_idx ( lhs, & self . map ) else { return } ;
527+ let Some ( place) = self . map . find ( place. as_ref ( ) ) else { return } ;
537528 let equals = match op {
538529 BinOp :: Eq => ScalarInt :: TRUE ,
539530 BinOp :: Ne => ScalarInt :: FALSE ,
540- _ => return Some ( ( ) ) ,
531+ _ => return ,
541532 } ;
542533 if value. const_ . ty ( ) . is_floating_point ( ) {
543534 // Floating point equality does not follow bit-patterns.
544535 // -0.0 and NaN both have special rules for equality,
545536 // and therefore we cannot use integer comparisons for them.
546537 // Avoid handling them, though this could be extended in the future.
547- return Some ( ( ) ) ;
538+ return ;
548539 }
549- let value = value. const_ . try_eval_scalar_int ( self . tcx , self . typing_env ) ?;
550- let conds = conditions. map ( self . arena , |c| {
540+ let Some ( value) = value. const_ . try_eval_scalar_int ( self . tcx , self . typing_env )
541+ else {
542+ return ;
543+ } ;
544+ let Some ( conds) = conditions. map ( self . arena , |c| {
551545 Some ( Condition {
552546 value,
553547 polarity : if c. matches ( equals) { Polarity :: Eq } else { Polarity :: Ne } ,
554548 ..c
555549 } )
556- } ) ?;
550+ } ) else {
551+ return ;
552+ } ;
557553 state. insert_value_idx ( place, conds, & self . map ) ;
558554 }
559555
560556 _ => { }
561557 }
562- Some ( ( ) )
563558 }
564559
565560 #[ instrument( level = "trace" , skip( self ) ) ]
@@ -568,7 +563,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
568563 bb : BasicBlock ,
569564 stmt : & Statement < ' tcx > ,
570565 state : & mut State < ConditionSet < ' a > > ,
571- ) -> Option < ( ) > {
566+ ) {
572567 let register_opportunity = |c : Condition | {
573568 debug ! ( ?bb, ?c. target, "register" ) ;
574569 self . opportunities . push ( ThreadingOpportunity { chain : vec ! [ bb] , target : c. target } )
@@ -581,32 +576,30 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
581576 // If we expect `discriminant(place) ?= A`,
582577 // we have an opportunity if `variant_index ?= A`.
583578 StatementKind :: SetDiscriminant { box place, variant_index } => {
584- let Some ( discr_target) = self . map . find_discr ( place. as_ref ( ) ) else {
585- return Some ( ( ) ) ;
586- } ;
579+ let Some ( discr_target) = self . map . find_discr ( place. as_ref ( ) ) else { return } ;
587580 let enum_ty = place. ty ( self . body , self . tcx ) . ty ;
588581 // `SetDiscriminant` guarantees that the discriminant is now `variant_index`.
589582 // Even if the discriminant write does nothing due to niches, it is UB to set the
590583 // discriminant when the data does not encode the desired discriminant.
591- let discr =
592- self . ecx . discriminant_for_variant ( enum_ty, * variant_index) . discard_err ( ) ?;
593- self . process_immediate ( bb, discr_target, discr, state) ;
584+ let Some ( discr) =
585+ self . ecx . discriminant_for_variant ( enum_ty, * variant_index) . discard_err ( )
586+ else {
587+ return ;
588+ } ;
589+ self . process_immediate ( bb, discr_target, discr, state)
594590 }
595591 // If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`.
596592 StatementKind :: Intrinsic ( box NonDivergingIntrinsic :: Assume (
597593 Operand :: Copy ( place) | Operand :: Move ( place) ,
598594 ) ) => {
599- let Some ( conditions) = state. try_get ( place. as_ref ( ) , & self . map ) else {
600- return Some ( ( ) ) ;
601- } ;
602- conditions. iter_matches ( ScalarInt :: TRUE ) . for_each ( register_opportunity) ;
595+ let Some ( conditions) = state. try_get ( place. as_ref ( ) , & self . map ) else { return } ;
596+ conditions. iter_matches ( ScalarInt :: TRUE ) . for_each ( register_opportunity)
603597 }
604598 StatementKind :: Assign ( box ( lhs_place, rhs) ) => {
605- self . process_assign ( bb, lhs_place, rhs, state) ? ;
599+ self . process_assign ( bb, lhs_place, rhs, state)
606600 }
607601 _ => { }
608602 }
609- Some ( ( ) )
610603 }
611604
612605 #[ instrument( level = "trace" , skip( self , state, cost) ) ]
@@ -617,7 +610,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
617610 state : impl FnOnce ( ) -> State < ConditionSet < ' a > > ,
618611 cost : & CostChecker < ' _ , ' tcx > ,
619612 depth : usize ,
620- ) -> Option < ( ) > {
613+ ) {
621614 let term = self . body . basic_blocks [ bb] . terminator ( ) ;
622615 let place_to_flood = match term. kind {
623616 // We come from a target, so those are not possible.
@@ -632,9 +625,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
632625 | TerminatorKind :: FalseUnwind { .. }
633626 | TerminatorKind :: Yield { .. } => bug ! ( "{term:?} invalid" ) ,
634627 // Cannot reason about inline asm.
635- TerminatorKind :: InlineAsm { .. } => return Some ( ( ) ) ,
628+ TerminatorKind :: InlineAsm { .. } => return ,
636629 // `SwitchInt` is handled specially.
637- TerminatorKind :: SwitchInt { .. } => return Some ( ( ) ) ,
630+ TerminatorKind :: SwitchInt { .. } => return ,
638631 // We can recurse, no thing particular to do.
639632 TerminatorKind :: Goto { .. } => None ,
640633 // Flood the overwritten place, and progress through.
0 commit comments