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