33
44use rustc:: hir:: def:: DefKind ;
55use rustc:: mir:: {
6- Constant , Location , Place , PlaceBase , Mir , Operand , Rvalue , Local ,
6+ AggregateKind , Constant , Location , Place , PlaceBase , Mir , Operand , Rvalue , Local ,
77 NullOp , UnOp , StatementKind , Statement , LocalKind , Static , StaticKind ,
88 TerminatorKind , Terminator , ClearCrossCrate , SourceInfo , BinOp , ProjectionElem ,
99 SourceScope , SourceScopeLocalData , LocalDecl , Promoted ,
1010} ;
11- use rustc:: mir:: visit:: { Visitor , PlaceContext , MutatingUseContext , NonMutatingUseContext } ;
11+ use rustc:: mir:: visit:: {
12+ Visitor , PlaceContext , MutatingUseContext , MutVisitor , NonMutatingUseContext ,
13+ } ;
1214use rustc:: mir:: interpret:: { InterpError , Scalar , GlobalId , EvalResult } ;
1315use rustc:: ty:: { self , Instance , ParamEnv , Ty , TyCtxt } ;
14- use syntax :: source_map :: DUMMY_SP ;
16+ use syntax_pos :: { Span , DUMMY_SP } ;
1517use rustc:: ty:: subst:: InternalSubsts ;
1618use rustc_data_structures:: indexed_vec:: IndexVec ;
1719use rustc:: ty:: layout:: {
1820 LayoutOf , TyLayout , LayoutError ,
1921 HasTyCtxt , TargetDataLayout , HasDataLayout ,
2022} ;
2123
22- use crate :: interpret:: { InterpretCx , ScalarMaybeUndef , Immediate , OpTy , ImmTy , MemoryKind } ;
24+ use crate :: interpret:: { self , InterpretCx , ScalarMaybeUndef , Immediate , OpTy , ImmTy , MemoryKind } ;
2325use crate :: const_eval:: {
2426 CompileTimeInterpreter , error_to_const_error, eval_promoted, mk_eval_cx,
2527} ;
@@ -497,6 +499,53 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
497499 } ,
498500 }
499501 }
502+
503+ fn operand_from_scalar ( & self , scalar : Scalar , ty : Ty < ' tcx > , span : Span ) -> Operand < ' tcx > {
504+ Operand :: Constant ( Box :: new (
505+ Constant {
506+ span,
507+ ty,
508+ user_ty : None ,
509+ literal : self . tcx . mk_const ( ty:: Const :: from_scalar (
510+ scalar,
511+ ty,
512+ ) )
513+ }
514+ ) )
515+ }
516+
517+ fn replace_with_const ( & self , rval : & mut Rvalue < ' tcx > , value : Const < ' tcx > , span : Span ) {
518+ self . ecx . validate_operand (
519+ value,
520+ vec ! [ ] ,
521+ None ,
522+ true ,
523+ ) . expect ( "value should already be a valid const" ) ;
524+
525+ if let interpret:: Operand :: Immediate ( im) = * value {
526+ match im {
527+ interpret:: Immediate :: Scalar ( ScalarMaybeUndef :: Scalar ( scalar) ) => {
528+ * rval = Rvalue :: Use ( self . operand_from_scalar ( scalar, value. layout . ty , span) ) ;
529+ } ,
530+ Immediate :: ScalarPair (
531+ ScalarMaybeUndef :: Scalar ( one) ,
532+ ScalarMaybeUndef :: Scalar ( two)
533+ ) => {
534+ let ty = & value. layout . ty . sty ;
535+ if let ty:: Tuple ( substs) = ty {
536+ * rval = Rvalue :: Aggregate (
537+ Box :: new ( AggregateKind :: Tuple ) ,
538+ vec ! [
539+ self . operand_from_scalar( one, substs[ 0 ] . expect_ty( ) , span) ,
540+ self . operand_from_scalar( two, substs[ 1 ] . expect_ty( ) , span) ,
541+ ] ,
542+ ) ;
543+ }
544+ } ,
545+ _ => { }
546+ }
547+ }
548+ }
500549}
501550
502551fn type_size_of < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
@@ -560,10 +609,10 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
560609 }
561610}
562611
563- impl < ' b , ' a , ' tcx > Visitor < ' tcx > for ConstPropagator < ' b , ' a , ' tcx > {
612+ impl < ' b , ' a , ' tcx > MutVisitor < ' tcx > for ConstPropagator < ' b , ' a , ' tcx > {
564613 fn visit_constant (
565614 & mut self ,
566- constant : & Constant < ' tcx > ,
615+ constant : & mut Constant < ' tcx > ,
567616 location : Location ,
568617 ) {
569618 trace ! ( "visit_constant: {:?}" , constant) ;
@@ -573,11 +622,11 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
573622
574623 fn visit_statement (
575624 & mut self ,
576- statement : & Statement < ' tcx > ,
625+ statement : & mut Statement < ' tcx > ,
577626 location : Location ,
578627 ) {
579628 trace ! ( "visit_statement: {:?}" , statement) ;
580- if let StatementKind :: Assign ( ref place, ref rval) = statement. kind {
629+ if let StatementKind :: Assign ( ref place, ref mut rval) = statement. kind {
581630 let place_ty: Ty < ' tcx > = place
582631 . ty ( & self . local_decls , self . tcx )
583632 . ty ;
@@ -589,6 +638,10 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
589638 trace ! ( "storing {:?} to {:?}" , value, local) ;
590639 assert ! ( self . places[ local] . is_none( ) ) ;
591640 self . places [ local] = Some ( value) ;
641+
642+ if self . tcx . sess . opts . debugging_opts . mir_opt_level >= 2 {
643+ self . replace_with_const ( rval, value, statement. source_info . span ) ;
644+ }
592645 }
593646 }
594647 }
@@ -599,7 +652,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
599652
600653 fn visit_terminator (
601654 & mut self ,
602- terminator : & Terminator < ' tcx > ,
655+ terminator : & mut Terminator < ' tcx > ,
603656 location : Location ,
604657 ) {
605658 self . super_terminator ( terminator, location) ;
0 commit comments