@@ -423,6 +423,84 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
423
423
None
424
424
}
425
425
426
+ #[ instrument( level = "trace" , skip( self ) ) ]
427
+ fn process_assign (
428
+ & mut self ,
429
+ bb : BasicBlock ,
430
+ lhs_place : & Place < ' tcx > ,
431
+ rhs : & Rvalue < ' tcx > ,
432
+ state : & mut State < ConditionSet < ' a > > ,
433
+ ) -> Option < !> {
434
+ let lhs = self . map . find ( lhs_place. as_ref ( ) ) ?;
435
+ match rhs {
436
+ Rvalue :: Use ( operand) => self . process_operand ( bb, lhs, operand, state) ?,
437
+ // Transfer the conditions on the copy rhs.
438
+ Rvalue :: CopyForDeref ( rhs) => {
439
+ self . process_operand ( bb, lhs, & Operand :: Copy ( * rhs) , state) ?
440
+ }
441
+ Rvalue :: Discriminant ( rhs) => {
442
+ let rhs = self . map . find_discr ( rhs. as_ref ( ) ) ?;
443
+ state. insert_place_idx ( rhs, lhs, self . map ) ;
444
+ }
445
+ // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
446
+ Rvalue :: Aggregate ( box ref kind, ref operands) => {
447
+ let agg_ty = lhs_place. ty ( self . body , self . tcx ) . ty ;
448
+ let lhs = match kind {
449
+ // Do not support unions.
450
+ AggregateKind :: Adt ( .., Some ( _) ) => return None ,
451
+ AggregateKind :: Adt ( _, variant_index, ..) if agg_ty. is_enum ( ) => {
452
+ if let Some ( discr_target) = self . map . apply ( lhs, TrackElem :: Discriminant )
453
+ && let Ok ( discr_value) =
454
+ self . ecx . discriminant_for_variant ( agg_ty, * variant_index)
455
+ {
456
+ self . process_immediate ( bb, discr_target, discr_value, state) ;
457
+ }
458
+ self . map . apply ( lhs, TrackElem :: Variant ( * variant_index) ) ?
459
+ }
460
+ _ => lhs,
461
+ } ;
462
+ for ( field_index, operand) in operands. iter_enumerated ( ) {
463
+ if let Some ( field) = self . map . apply ( lhs, TrackElem :: Field ( field_index) ) {
464
+ self . process_operand ( bb, field, operand, state) ;
465
+ }
466
+ }
467
+ }
468
+ // Transfer the conditions on the copy rhs, after inversing polarity.
469
+ Rvalue :: UnaryOp ( UnOp :: Not , Operand :: Move ( place) | Operand :: Copy ( place) ) => {
470
+ let conditions = state. try_get_idx ( lhs, self . map ) ?;
471
+ let place = self . map . find ( place. as_ref ( ) ) ?;
472
+ let conds = conditions. map ( self . arena , Condition :: inv) ;
473
+ state. insert_value_idx ( place, conds, self . map ) ;
474
+ }
475
+ // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`.
476
+ // Create a condition on `rhs ?= B`.
477
+ Rvalue :: BinaryOp (
478
+ op,
479
+ box ( Operand :: Move ( place) | Operand :: Copy ( place) , Operand :: Constant ( value) )
480
+ | box ( Operand :: Constant ( value) , Operand :: Move ( place) | Operand :: Copy ( place) ) ,
481
+ ) => {
482
+ let conditions = state. try_get_idx ( lhs, self . map ) ?;
483
+ let place = self . map . find ( place. as_ref ( ) ) ?;
484
+ let equals = match op {
485
+ BinOp :: Eq => ScalarInt :: TRUE ,
486
+ BinOp :: Ne => ScalarInt :: FALSE ,
487
+ _ => return None ,
488
+ } ;
489
+ let value = value. const_ . normalize ( self . tcx , self . param_env ) . try_to_scalar_int ( ) ?;
490
+ let conds = conditions. map ( self . arena , |c| Condition {
491
+ value,
492
+ polarity : if c. matches ( equals) { Polarity :: Eq } else { Polarity :: Ne } ,
493
+ ..c
494
+ } ) ;
495
+ state. insert_value_idx ( place, conds, self . map ) ;
496
+ }
497
+
498
+ _ => { }
499
+ }
500
+
501
+ None
502
+ }
503
+
426
504
#[ instrument( level = "trace" , skip( self ) ) ]
427
505
fn process_statement (
428
506
& mut self ,
@@ -472,95 +550,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
472
550
conditions. iter_matches ( ScalarInt :: TRUE ) . for_each ( register_opportunity) ;
473
551
}
474
552
StatementKind :: Assign ( box ( lhs_place, rhs) ) => {
475
- if let Some ( lhs) = self . map . find ( lhs_place. as_ref ( ) ) {
476
- match rhs {
477
- Rvalue :: Use ( operand) => self . process_operand ( bb, lhs, operand, state) ?,
478
- // Transfer the conditions on the copy rhs.
479
- Rvalue :: CopyForDeref ( rhs) => {
480
- self . process_operand ( bb, lhs, & Operand :: Copy ( * rhs) , state) ?
481
- }
482
- Rvalue :: Discriminant ( rhs) => {
483
- let rhs = self . map . find_discr ( rhs. as_ref ( ) ) ?;
484
- state. insert_place_idx ( rhs, lhs, self . map ) ;
485
- }
486
- // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
487
- Rvalue :: Aggregate ( box ref kind, ref operands) => {
488
- let agg_ty = lhs_place. ty ( self . body , self . tcx ) . ty ;
489
- let lhs = match kind {
490
- // Do not support unions.
491
- AggregateKind :: Adt ( .., Some ( _) ) => return None ,
492
- AggregateKind :: Adt ( _, variant_index, ..) if agg_ty. is_enum ( ) => {
493
- if let Some ( discr_target) =
494
- self . map . apply ( lhs, TrackElem :: Discriminant )
495
- && let Ok ( discr_value) = self
496
- . ecx
497
- . discriminant_for_variant ( agg_ty, * variant_index)
498
- {
499
- self . process_immediate (
500
- bb,
501
- discr_target,
502
- discr_value,
503
- state,
504
- ) ;
505
- }
506
- self . map . apply ( lhs, TrackElem :: Variant ( * variant_index) ) ?
507
- }
508
- _ => lhs,
509
- } ;
510
- for ( field_index, operand) in operands. iter_enumerated ( ) {
511
- if let Some ( field) =
512
- self . map . apply ( lhs, TrackElem :: Field ( field_index) )
513
- {
514
- self . process_operand ( bb, field, operand, state) ;
515
- }
516
- }
517
- }
518
- // Transfer the conditions on the copy rhs, after inversing polarity.
519
- Rvalue :: UnaryOp ( UnOp :: Not , Operand :: Move ( place) | Operand :: Copy ( place) ) => {
520
- let conditions = state. try_get_idx ( lhs, self . map ) ?;
521
- let place = self . map . find ( place. as_ref ( ) ) ?;
522
- let conds = conditions. map ( self . arena , Condition :: inv) ;
523
- state. insert_value_idx ( place, conds, self . map ) ;
524
- }
525
- // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`.
526
- // Create a condition on `rhs ?= B`.
527
- Rvalue :: BinaryOp (
528
- op,
529
- box (
530
- Operand :: Move ( place) | Operand :: Copy ( place) ,
531
- Operand :: Constant ( value) ,
532
- )
533
- | box (
534
- Operand :: Constant ( value) ,
535
- Operand :: Move ( place) | Operand :: Copy ( place) ,
536
- ) ,
537
- ) => {
538
- let conditions = state. try_get_idx ( lhs, self . map ) ?;
539
- let place = self . map . find ( place. as_ref ( ) ) ?;
540
- let equals = match op {
541
- BinOp :: Eq => ScalarInt :: TRUE ,
542
- BinOp :: Ne => ScalarInt :: FALSE ,
543
- _ => return None ,
544
- } ;
545
- let value = value
546
- . const_
547
- . normalize ( self . tcx , self . param_env )
548
- . try_to_scalar_int ( ) ?;
549
- let conds = conditions. map ( self . arena , |c| Condition {
550
- value,
551
- polarity : if c. matches ( equals) {
552
- Polarity :: Eq
553
- } else {
554
- Polarity :: Ne
555
- } ,
556
- ..c
557
- } ) ;
558
- state. insert_value_idx ( place, conds, self . map ) ;
559
- }
560
-
561
- _ => { }
562
- }
563
- }
553
+ self . process_assign ( bb, lhs_place, rhs, state) ?;
564
554
}
565
555
_ => { }
566
556
}
0 commit comments