@@ -423,6 +423,84 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
423423 None
424424 }
425425
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+
426504 #[ instrument( level = "trace" , skip( self ) ) ]
427505 fn process_statement (
428506 & mut self ,
@@ -472,95 +550,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
472550 conditions. iter_matches ( ScalarInt :: TRUE ) . for_each ( register_opportunity) ;
473551 }
474552 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) ?;
564554 }
565555 _ => { }
566556 }
0 commit comments