@@ -15,10 +15,11 @@ use rustc_middle::mir::visit::{
15
15
use rustc_middle:: mir:: * ;
16
16
use rustc_middle:: ty:: layout:: { LayoutError , LayoutOf , LayoutOfHelpers , TyAndLayout } ;
17
17
use rustc_middle:: ty:: { self , GenericArgs , Instance , ParamEnv , Ty , TyCtxt , TypeVisitableExt } ;
18
- use rustc_span:: { def_id:: DefId , Span , DUMMY_SP } ;
18
+ use rustc_span:: { def_id:: DefId , Span } ;
19
19
use rustc_target:: abi:: { self , Align , HasDataLayout , Size , TargetDataLayout } ;
20
20
use rustc_target:: spec:: abi:: Abi as CallAbi ;
21
21
22
+ use crate :: dataflow_const_prop:: Patch ;
22
23
use crate :: MirPass ;
23
24
use rustc_const_eval:: interpret:: {
24
25
self , compile_time_machine, AllocId , ConstAllocation , ConstValue , FnArg , Frame , ImmTy ,
@@ -120,6 +121,8 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
120
121
optimization_finder. visit_basic_block_data ( bb, data) ;
121
122
}
122
123
124
+ optimization_finder. patch . visit_body_preserves_cfg ( body) ;
125
+
123
126
trace ! ( "ConstProp done for {:?}" , def_id) ;
124
127
}
125
128
}
@@ -302,6 +305,7 @@ struct ConstPropagator<'mir, 'tcx> {
302
305
tcx : TyCtxt < ' tcx > ,
303
306
param_env : ParamEnv < ' tcx > ,
304
307
local_decls : & ' mir IndexSlice < Local , LocalDecl < ' tcx > > ,
308
+ patch : Patch < ' tcx > ,
305
309
}
306
310
307
311
impl < ' tcx > LayoutOfHelpers < ' tcx > for ConstPropagator < ' _ , ' tcx > {
@@ -385,7 +389,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
385
389
ecx. frame_mut ( ) . locals [ local] . make_live_uninit ( ) ;
386
390
}
387
391
388
- ConstPropagator { ecx, tcx, param_env, local_decls : & dummy_body. local_decls }
392
+ let patch = Patch :: new ( tcx) ;
393
+ ConstPropagator { ecx, tcx, param_env, local_decls : & dummy_body. local_decls , patch }
389
394
}
390
395
391
396
fn get_const ( & self , place : Place < ' tcx > ) -> Option < OpTy < ' tcx > > {
@@ -422,12 +427,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
422
427
ecx. machine . written_only_inside_own_block_locals . remove ( & local) ;
423
428
}
424
429
425
- fn propagate_operand ( & mut self , operand : & mut Operand < ' tcx > ) {
426
- if let Some ( place) = operand. place ( ) && let Some ( op) = self . replace_with_const ( place) {
427
- * operand = op;
428
- }
429
- }
430
-
431
430
fn check_rvalue ( & mut self , rvalue : & Rvalue < ' tcx > ) -> Option < ( ) > {
432
431
// Perform any special handling for specific Rvalue types.
433
432
// Generally, checks here fall into one of two categories:
@@ -543,16 +542,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
543
542
}
544
543
}
545
544
546
- /// Creates a new `Operand::Constant` from a `Scalar` value
547
- fn operand_from_scalar ( & self , scalar : Scalar , ty : Ty < ' tcx > ) -> Operand < ' tcx > {
548
- Operand :: Constant ( Box :: new ( Constant {
549
- span : DUMMY_SP ,
550
- user_ty : None ,
551
- literal : ConstantKind :: from_scalar ( self . tcx , scalar, ty) ,
552
- } ) )
553
- }
554
-
555
- fn replace_with_const ( & mut self , place : Place < ' tcx > ) -> Option < Operand < ' tcx > > {
545
+ fn replace_with_const ( & mut self , place : Place < ' tcx > ) -> Option < ConstantKind < ' tcx > > {
556
546
// This will return None if the above `const_prop` invocation only "wrote" a
557
547
// type whose creation requires no write. E.g. a generator whose initial state
558
548
// consists solely of uninitialized memory (so it doesn't capture any locals).
@@ -568,7 +558,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
568
558
let Right ( imm) = imm else { return None } ;
569
559
match * imm {
570
560
Immediate :: Scalar ( scalar) if scalar. try_to_int ( ) . is_ok ( ) => {
571
- Some ( self . operand_from_scalar ( scalar, value. layout . ty ) )
561
+ Some ( ConstantKind :: from_scalar ( self . tcx , scalar, value. layout . ty ) )
572
562
}
573
563
Immediate :: ScalarPair ( l, r) if l. try_to_int ( ) . is_ok ( ) && r. try_to_int ( ) . is_ok ( ) => {
574
564
let alloc = self
@@ -578,15 +568,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
578
568
} )
579
569
. ok ( ) ?;
580
570
581
- let literal = ConstantKind :: Val (
571
+ Some ( ConstantKind :: Val (
582
572
ConstValue :: ByRef { alloc, offset : Size :: ZERO } ,
583
573
value. layout . ty ,
584
- ) ;
585
- Some ( Operand :: Constant ( Box :: new ( Constant {
586
- span : DUMMY_SP ,
587
- user_ty : None ,
588
- literal,
589
- } ) ) )
574
+ ) )
590
575
}
591
576
// Scalars or scalar pairs that contain undef values are assumed to not have
592
577
// successfully evaluated and are thus not propagated.
@@ -728,40 +713,29 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
728
713
}
729
714
}
730
715
731
- impl < ' tcx > MutVisitor < ' tcx > for ConstPropagator < ' _ , ' tcx > {
732
- fn tcx ( & self ) -> TyCtxt < ' tcx > {
733
- self . tcx
734
- }
735
-
736
- fn visit_operand ( & mut self , operand : & mut Operand < ' tcx > , location : Location ) {
716
+ impl < ' tcx > Visitor < ' tcx > for ConstPropagator < ' _ , ' tcx > {
717
+ fn visit_operand ( & mut self , operand : & Operand < ' tcx > , location : Location ) {
737
718
self . super_operand ( operand, location) ;
738
- self . propagate_operand ( operand)
719
+ if let Some ( place) = operand. place ( ) && let Some ( value) = self . replace_with_const ( place) {
720
+ self . patch . before_effect . insert ( ( location, place) , value) ;
721
+ }
739
722
}
740
723
741
- fn process_projection_elem (
724
+ fn visit_projection_elem (
742
725
& mut self ,
726
+ _: PlaceRef < ' tcx > ,
743
727
elem : PlaceElem < ' tcx > ,
744
- _: Location ,
745
- ) -> Option < PlaceElem < ' tcx > > {
728
+ _: PlaceContext ,
729
+ location : Location ,
730
+ ) {
746
731
if let PlaceElem :: Index ( local) = elem
747
- && let Some ( value) = self . get_const ( local. into ( ) )
748
- && let Some ( imm) = value. as_mplace_or_imm ( ) . right ( )
749
- && let Immediate :: Scalar ( scalar) = * imm
750
- && let Ok ( offset) = scalar. to_target_usize ( & self . tcx )
751
- && let Some ( min_length) = offset. checked_add ( 1 )
732
+ && let Some ( value) = self . replace_with_const ( local. into ( ) )
752
733
{
753
- Some ( PlaceElem :: ConstantIndex { offset, min_length, from_end : false } )
754
- } else {
755
- None
734
+ self . patch . before_effect . insert ( ( location, local. into ( ) ) , value) ;
756
735
}
757
736
}
758
737
759
- fn visit_assign (
760
- & mut self ,
761
- place : & mut Place < ' tcx > ,
762
- rvalue : & mut Rvalue < ' tcx > ,
763
- location : Location ,
764
- ) {
738
+ fn visit_assign ( & mut self , place : & Place < ' tcx > , rvalue : & Rvalue < ' tcx > , location : Location ) {
765
739
self . super_assign ( place, rvalue, location) ;
766
740
767
741
let Some ( ( ) ) = self . check_rvalue ( rvalue) else { return } ;
@@ -778,7 +752,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
778
752
{
779
753
trace ! ( "skipping replace of Rvalue::Use({:?} because it is already a const" , c) ;
780
754
} else if let Some ( operand) = self . replace_with_const ( * place) {
781
- * rvalue = Rvalue :: Use ( operand) ;
755
+ self . patch . assignments . insert ( location , operand) ;
782
756
}
783
757
} else {
784
758
// Const prop failed, so erase the destination, ensuring that whatever happens
@@ -802,7 +776,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
802
776
}
803
777
}
804
778
805
- fn visit_statement ( & mut self , statement : & mut Statement < ' tcx > , location : Location ) {
779
+ fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
806
780
trace ! ( "visit_statement: {:?}" , statement) ;
807
781
808
782
// We want to evaluate operands before any change to the assigned-to value,
@@ -846,7 +820,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
846
820
}
847
821
}
848
822
849
- fn visit_basic_block_data ( & mut self , block : BasicBlock , data : & mut BasicBlockData < ' tcx > ) {
823
+ fn visit_basic_block_data ( & mut self , block : BasicBlock , data : & BasicBlockData < ' tcx > ) {
850
824
self . super_basic_block_data ( block, data) ;
851
825
852
826
// We remove all Locals which are restricted in propagation to their containing blocks and
0 commit comments