@@ -90,11 +90,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
90
90
} ;
91
91
92
92
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) ;
98
94
}
99
95
100
96
let opportunities = finder. opportunities ;
@@ -201,28 +197,26 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
201
197
202
198
/// Recursion entry point to find threading opportunities.
203
199
#[ instrument( level = "trace" , skip( self ) ) ]
204
- fn start_from_switch ( & mut self , bb : BasicBlock ) -> Option < ( ) > {
200
+ fn start_from_switch ( & mut self , bb : BasicBlock ) {
205
201
let bbdata = & self . body [ bb] ;
206
202
if bbdata. is_cleanup || self . loop_headers . contains ( bb) {
207
- return Some ( ( ) ) ;
203
+ return ;
208
204
}
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 } ;
211
207
debug ! ( ?discr, ?bb) ;
212
208
213
209
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 } ;
217
211
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 } ;
219
213
debug ! ( ?discr) ;
220
214
221
215
let cost = CostChecker :: new ( self . tcx , self . typing_env , None , self . body ) ;
222
216
let mut state = State :: new_reachable ( ) ;
223
217
224
218
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 } ;
226
220
self . arena . alloc_from_iter ( [
227
221
Condition { value, polarity : Polarity :: Eq , target : then } ,
228
222
Condition { value, polarity : Polarity :: Ne , target : else_ } ,
@@ -248,27 +242,27 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
248
242
mut state : State < ConditionSet < ' a > > ,
249
243
mut cost : CostChecker < ' _ , ' tcx > ,
250
244
depth : usize ,
251
- ) -> Option < ( ) > {
245
+ ) {
252
246
// Do not thread through loop headers.
253
247
if self . loop_headers . contains ( bb) {
254
- return Some ( ( ) ) ;
248
+ return ;
255
249
}
256
250
257
251
debug ! ( cost = ?cost. cost( ) ) ;
258
252
for ( statement_index, stmt) in
259
253
self . body . basic_blocks [ bb] . statements . iter ( ) . enumerate ( ) . rev ( )
260
254
{
261
255
if self . is_empty ( & state) {
262
- return Some ( ( ) ) ;
256
+ return ;
263
257
}
264
258
265
259
cost. visit_statement ( stmt, Location { block : bb, statement_index } ) ;
266
260
if cost. cost ( ) > MAX_COST {
267
- return Some ( ( ) ) ;
261
+ return ;
268
262
}
269
263
270
264
// 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) ;
272
266
273
267
// When a statement mutates a place, assignments to that place that happen
274
268
// above the mutation cannot fulfill a condition.
@@ -280,7 +274,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
280
274
}
281
275
282
276
if self . is_empty ( & state) || depth >= MAX_BACKTRACK {
283
- return Some ( ( ) ) ;
277
+ return ;
284
278
}
285
279
286
280
let last_non_rec = self . opportunities . len ( ) ;
@@ -293,9 +287,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
293
287
match term. kind {
294
288
TerminatorKind :: SwitchInt { ref discr, ref targets } => {
295
289
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 ) ;
297
291
}
298
- _ => self . recurse_through_terminator ( pred, || state, & cost, depth) ? ,
292
+ _ => self . recurse_through_terminator ( pred, || state, & cost, depth) ,
299
293
}
300
294
} else if let & [ ref predecessors @ .., last_pred] = & predecessors[ ..] {
301
295
for & pred in predecessors {
@@ -320,13 +314,12 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
320
314
let first = & mut new_tos[ 0 ] ;
321
315
* first = ThreadingOpportunity { chain : vec ! [ bb] , target : first. target } ;
322
316
self . opportunities . truncate ( last_non_rec + 1 ) ;
323
- return Some ( ( ) ) ;
317
+ return ;
324
318
}
325
319
326
320
for op in self . opportunities [ last_non_rec..] . iter_mut ( ) {
327
321
op. chain . push ( bb) ;
328
322
}
329
- Some ( ( ) )
330
323
}
331
324
332
325
/// Extract the mutated place from a statement.
@@ -440,23 +433,23 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
440
433
lhs : PlaceIndex ,
441
434
rhs : & Operand < ' tcx > ,
442
435
state : & mut State < ConditionSet < ' a > > ,
443
- ) -> Option < ( ) > {
436
+ ) {
444
437
match rhs {
445
438
// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
446
439
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
+ } ;
451
445
self . process_constant ( bb, lhs, constant, state) ;
452
446
}
453
447
// Transfer the conditions on the copied rhs.
454
448
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 } ;
456
450
state. insert_place_idx ( rhs, lhs, & self . map ) ;
457
451
}
458
452
}
459
- Some ( ( ) )
460
453
}
461
454
462
455
#[ instrument( level = "trace" , skip( self ) ) ]
@@ -466,26 +459,22 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
466
459
lhs_place : & Place < ' tcx > ,
467
460
rhs : & Rvalue < ' tcx > ,
468
461
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 } ;
473
464
match rhs {
474
- Rvalue :: Use ( operand) => self . process_operand ( bb, lhs, operand, state) ? ,
465
+ Rvalue :: Use ( operand) => self . process_operand ( bb, lhs, operand, state) ,
475
466
// 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) ,
479
468
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 } ;
481
470
state. insert_place_idx ( rhs, lhs, & self . map ) ;
482
471
}
483
472
// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
484
473
Rvalue :: Aggregate ( box kind, operands) => {
485
474
let agg_ty = lhs_place. ty ( self . body , self . tcx ) . ty ;
486
475
let lhs = match kind {
487
476
// Do not support unions.
488
- AggregateKind :: Adt ( .., Some ( _) ) => return Some ( ( ) ) ,
477
+ AggregateKind :: Adt ( .., Some ( _) ) => return ,
489
478
AggregateKind :: Adt ( _, variant_index, ..) if agg_ty. is_enum ( ) => {
490
479
if let Some ( discr_target) = self . map . apply ( lhs, TrackElem :: Discriminant )
491
480
&& let Some ( discr_value) = self
@@ -498,31 +487,33 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
498
487
if let Some ( idx) = self . map . apply ( lhs, TrackElem :: Variant ( * variant_index) ) {
499
488
idx
500
489
} else {
501
- return Some ( ( ) ) ;
490
+ return ;
502
491
}
503
492
}
504
493
_ => lhs,
505
494
} ;
506
495
for ( field_index, operand) in operands. iter_enumerated ( ) {
507
496
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) ;
509
498
}
510
499
}
511
500
}
512
501
// Transfer the conditions on the copy rhs, after inverting the value of the condition.
513
502
Rvalue :: UnaryOp ( UnOp :: Not , Operand :: Move ( place) | Operand :: Copy ( place) ) => {
514
503
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| {
518
507
cond. value = self
519
508
. ecx
520
509
. unary_op ( UnOp :: Not , & ImmTy :: from_scalar_int ( cond. value , layout) )
521
510
. discard_err ( ) ?
522
511
. to_scalar_int ( )
523
512
. discard_err ( ) ?;
524
513
Some ( cond)
525
- } ) ?;
514
+ } ) else {
515
+ return ;
516
+ } ;
526
517
state. insert_value_idx ( place, conds, & self . map ) ;
527
518
}
528
519
// We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`.
@@ -532,34 +523,38 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
532
523
box ( Operand :: Move ( place) | Operand :: Copy ( place) , Operand :: Constant ( value) )
533
524
| box ( Operand :: Constant ( value) , Operand :: Move ( place) | Operand :: Copy ( place) ) ,
534
525
) => {
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 } ;
537
528
let equals = match op {
538
529
BinOp :: Eq => ScalarInt :: TRUE ,
539
530
BinOp :: Ne => ScalarInt :: FALSE ,
540
- _ => return Some ( ( ) ) ,
531
+ _ => return ,
541
532
} ;
542
533
if value. const_ . ty ( ) . is_floating_point ( ) {
543
534
// Floating point equality does not follow bit-patterns.
544
535
// -0.0 and NaN both have special rules for equality,
545
536
// and therefore we cannot use integer comparisons for them.
546
537
// Avoid handling them, though this could be extended in the future.
547
- return Some ( ( ) ) ;
538
+ return ;
548
539
}
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| {
551
545
Some ( Condition {
552
546
value,
553
547
polarity : if c. matches ( equals) { Polarity :: Eq } else { Polarity :: Ne } ,
554
548
..c
555
549
} )
556
- } ) ?;
550
+ } ) else {
551
+ return ;
552
+ } ;
557
553
state. insert_value_idx ( place, conds, & self . map ) ;
558
554
}
559
555
560
556
_ => { }
561
557
}
562
- Some ( ( ) )
563
558
}
564
559
565
560
#[ instrument( level = "trace" , skip( self ) ) ]
@@ -568,7 +563,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
568
563
bb : BasicBlock ,
569
564
stmt : & Statement < ' tcx > ,
570
565
state : & mut State < ConditionSet < ' a > > ,
571
- ) -> Option < ( ) > {
566
+ ) {
572
567
let register_opportunity = |c : Condition | {
573
568
debug ! ( ?bb, ?c. target, "register" ) ;
574
569
self . opportunities . push ( ThreadingOpportunity { chain : vec ! [ bb] , target : c. target } )
@@ -581,32 +576,30 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
581
576
// If we expect `discriminant(place) ?= A`,
582
577
// we have an opportunity if `variant_index ?= A`.
583
578
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 } ;
587
580
let enum_ty = place. ty ( self . body , self . tcx ) . ty ;
588
581
// `SetDiscriminant` guarantees that the discriminant is now `variant_index`.
589
582
// Even if the discriminant write does nothing due to niches, it is UB to set the
590
583
// 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)
594
590
}
595
591
// If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`.
596
592
StatementKind :: Intrinsic ( box NonDivergingIntrinsic :: Assume (
597
593
Operand :: Copy ( place) | Operand :: Move ( place) ,
598
594
) ) => {
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)
603
597
}
604
598
StatementKind :: Assign ( box ( lhs_place, rhs) ) => {
605
- self . process_assign ( bb, lhs_place, rhs, state) ? ;
599
+ self . process_assign ( bb, lhs_place, rhs, state)
606
600
}
607
601
_ => { }
608
602
}
609
- Some ( ( ) )
610
603
}
611
604
612
605
#[ instrument( level = "trace" , skip( self , state, cost) ) ]
@@ -617,7 +610,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
617
610
state : impl FnOnce ( ) -> State < ConditionSet < ' a > > ,
618
611
cost : & CostChecker < ' _ , ' tcx > ,
619
612
depth : usize ,
620
- ) -> Option < ( ) > {
613
+ ) {
621
614
let term = self . body . basic_blocks [ bb] . terminator ( ) ;
622
615
let place_to_flood = match term. kind {
623
616
// We come from a target, so those are not possible.
@@ -632,9 +625,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
632
625
| TerminatorKind :: FalseUnwind { .. }
633
626
| TerminatorKind :: Yield { .. } => bug ! ( "{term:?} invalid" ) ,
634
627
// Cannot reason about inline asm.
635
- TerminatorKind :: InlineAsm { .. } => return Some ( ( ) ) ,
628
+ TerminatorKind :: InlineAsm { .. } => return ,
636
629
// `SwitchInt` is handled specially.
637
- TerminatorKind :: SwitchInt { .. } => return Some ( ( ) ) ,
630
+ TerminatorKind :: SwitchInt { .. } => return ,
638
631
// We can recurse, no thing particular to do.
639
632
TerminatorKind :: Goto { .. } => None ,
640
633
// Flood the overwritten place, and progress through.
0 commit comments