3
3
4
4
use rustc:: hir:: def:: DefKind ;
5
5
use rustc:: mir:: {
6
- Constant , Location , Place , PlaceBase , Mir , Operand , Rvalue , Local ,
6
+ AggregateKind , Constant , Location , Place , PlaceBase , Mir , Operand , Rvalue , Local ,
7
7
NullOp , UnOp , StatementKind , Statement , LocalKind , Static , StaticKind ,
8
8
TerminatorKind , Terminator , ClearCrossCrate , SourceInfo , BinOp , ProjectionElem ,
9
9
SourceScope , SourceScopeLocalData , LocalDecl , Promoted ,
10
10
} ;
11
- use rustc:: mir:: visit:: { Visitor , PlaceContext , MutatingUseContext , NonMutatingUseContext } ;
11
+ use rustc:: mir:: visit:: {
12
+ Visitor , PlaceContext , MutatingUseContext , MutVisitor , NonMutatingUseContext ,
13
+ } ;
12
14
use rustc:: mir:: interpret:: { InterpError , Scalar , GlobalId , EvalResult } ;
13
15
use rustc:: ty:: { self , Instance , ParamEnv , Ty , TyCtxt } ;
14
- use syntax :: source_map :: DUMMY_SP ;
16
+ use syntax_pos :: { Span , DUMMY_SP } ;
15
17
use rustc:: ty:: subst:: InternalSubsts ;
16
18
use rustc_data_structures:: indexed_vec:: IndexVec ;
17
19
use rustc:: ty:: layout:: {
18
20
LayoutOf , TyLayout , LayoutError ,
19
21
HasTyCtxt , TargetDataLayout , HasDataLayout ,
20
22
} ;
21
23
22
- use crate :: interpret:: { InterpretCx , ScalarMaybeUndef , Immediate , OpTy , ImmTy , MemoryKind } ;
24
+ use crate :: interpret:: { self , InterpretCx , ScalarMaybeUndef , Immediate , OpTy , ImmTy , MemoryKind } ;
23
25
use crate :: const_eval:: {
24
26
CompileTimeInterpreter , error_to_const_error, eval_promoted, mk_eval_cx,
25
27
} ;
@@ -497,6 +499,53 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
497
499
} ,
498
500
}
499
501
}
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
+ }
500
549
}
501
550
502
551
fn type_size_of < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
@@ -560,10 +609,10 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
560
609
}
561
610
}
562
611
563
- impl < ' b , ' a , ' tcx > Visitor < ' tcx > for ConstPropagator < ' b , ' a , ' tcx > {
612
+ impl < ' b , ' a , ' tcx > MutVisitor < ' tcx > for ConstPropagator < ' b , ' a , ' tcx > {
564
613
fn visit_constant (
565
614
& mut self ,
566
- constant : & Constant < ' tcx > ,
615
+ constant : & mut Constant < ' tcx > ,
567
616
location : Location ,
568
617
) {
569
618
trace ! ( "visit_constant: {:?}" , constant) ;
@@ -573,11 +622,11 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
573
622
574
623
fn visit_statement (
575
624
& mut self ,
576
- statement : & Statement < ' tcx > ,
625
+ statement : & mut Statement < ' tcx > ,
577
626
location : Location ,
578
627
) {
579
628
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 {
581
630
let place_ty: Ty < ' tcx > = place
582
631
. ty ( & self . local_decls , self . tcx )
583
632
. ty ;
@@ -589,6 +638,10 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
589
638
trace ! ( "storing {:?} to {:?}" , value, local) ;
590
639
assert ! ( self . places[ local] . is_none( ) ) ;
591
640
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
+ }
592
645
}
593
646
}
594
647
}
@@ -599,7 +652,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
599
652
600
653
fn visit_terminator (
601
654
& mut self ,
602
- terminator : & Terminator < ' tcx > ,
655
+ terminator : & mut Terminator < ' tcx > ,
603
656
location : Location ,
604
657
) {
605
658
self . super_terminator ( terminator, location) ;
0 commit comments