@@ -354,6 +354,50 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
354354 None
355355 }
356356
357+ /// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
358+ #[ instrument( level = "trace" , skip( self ) ) ]
359+ fn process_constant (
360+ & mut self ,
361+ bb : BasicBlock ,
362+ lhs : PlaceIndex ,
363+ constant : OpTy < ' tcx > ,
364+ state : & mut State < ConditionSet < ' a > > ,
365+ ) {
366+ self . map . for_each_projection_value (
367+ lhs,
368+ constant,
369+ & mut |elem, op| match elem {
370+ TrackElem :: Field ( idx) => self . ecx . project_field ( op, idx. as_usize ( ) ) . ok ( ) ,
371+ TrackElem :: Variant ( idx) => self . ecx . project_downcast ( op, idx) . ok ( ) ,
372+ TrackElem :: Discriminant => {
373+ let variant = self . ecx . read_discriminant ( op) . ok ( ) ?;
374+ let discr_value =
375+ self . ecx . discriminant_for_variant ( op. layout . ty , variant) . ok ( ) ?;
376+ Some ( discr_value. into ( ) )
377+ }
378+ TrackElem :: DerefLen => {
379+ let op: OpTy < ' _ > = self . ecx . deref_pointer ( op) . ok ( ) ?. into ( ) ;
380+ let len_usize = op. len ( & self . ecx ) . ok ( ) ?;
381+ let layout =
382+ self . tcx . layout_of ( self . param_env . and ( self . tcx . types . usize ) ) . unwrap ( ) ;
383+ Some ( ImmTy :: from_uint ( len_usize, layout) . into ( ) )
384+ }
385+ } ,
386+ & mut |place, op| {
387+ if let Some ( conditions) = state. try_get_idx ( place, self . map )
388+ && let Ok ( imm) = self . ecx . read_immediate_raw ( op)
389+ && let Some ( imm) = imm. right ( )
390+ && let Immediate :: Scalar ( Scalar :: Int ( int) ) = * imm
391+ {
392+ conditions. iter_matches ( int) . for_each ( |c : Condition | {
393+ self . opportunities
394+ . push ( ThreadingOpportunity { chain : vec ! [ bb] , target : c. target } )
395+ } )
396+ }
397+ } ,
398+ ) ;
399+ }
400+
357401 #[ instrument( level = "trace" , skip( self ) ) ]
358402 fn process_operand (
359403 & mut self ,
@@ -366,43 +410,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
366410 // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
367411 Operand :: Constant ( constant) => {
368412 let constant = self . ecx . eval_mir_constant ( & constant. const_ , None , None ) . ok ( ) ?;
369- self . map . for_each_projection_value (
370- lhs,
371- constant,
372- & mut |elem, op| match elem {
373- TrackElem :: Field ( idx) => self . ecx . project_field ( op, idx. as_usize ( ) ) . ok ( ) ,
374- TrackElem :: Variant ( idx) => self . ecx . project_downcast ( op, idx) . ok ( ) ,
375- TrackElem :: Discriminant => {
376- let variant = self . ecx . read_discriminant ( op) . ok ( ) ?;
377- let discr_value =
378- self . ecx . discriminant_for_variant ( op. layout . ty , variant) . ok ( ) ?;
379- Some ( discr_value. into ( ) )
380- }
381- TrackElem :: DerefLen => {
382- let op: OpTy < ' _ > = self . ecx . deref_pointer ( op) . ok ( ) ?. into ( ) ;
383- let len_usize = op. len ( & self . ecx ) . ok ( ) ?;
384- let layout = self
385- . tcx
386- . layout_of ( self . param_env . and ( self . tcx . types . usize ) )
387- . unwrap ( ) ;
388- Some ( ImmTy :: from_uint ( len_usize, layout) . into ( ) )
389- }
390- } ,
391- & mut |place, op| {
392- if let Some ( conditions) = state. try_get_idx ( place, self . map )
393- && let Ok ( imm) = self . ecx . read_immediate_raw ( op)
394- && let Some ( imm) = imm. right ( )
395- && let Immediate :: Scalar ( Scalar :: Int ( int) ) = * imm
396- {
397- conditions. iter_matches ( int) . for_each ( |c : Condition | {
398- self . opportunities . push ( ThreadingOpportunity {
399- chain : vec ! [ bb] ,
400- target : c. target ,
401- } )
402- } )
403- }
404- } ,
405- ) ;
413+ self . process_constant ( bb, lhs, constant, state) ;
406414 }
407415 // Transfer the conditions on the copied rhs.
408416 Operand :: Move ( rhs) | Operand :: Copy ( rhs) => {
0 commit comments