Skip to content

Commit 7f68fd8

Browse files
committed
Auto merge of #60597 - wesleywiser:const_prop, r=<try>
Do some simple constant propagation in the ConstProp pass r? @oli-obk I added a few test cases. Let me know if you think there should be more.
2 parents 55c48b4 + 95fd4c6 commit 7f68fd8

File tree

4 files changed

+146
-9
lines changed

4 files changed

+146
-9
lines changed

src/librustc_mir/transform/const_prop.rs

+55-9
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
44
use rustc::hir::def::DefKind;
55
use 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+
};
1214
use rustc::mir::interpret::{InterpError, Scalar, GlobalId, EvalResult};
1315
use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
1416
use syntax::source_map::DUMMY_SP;
@@ -19,7 +21,7 @@ use rustc::ty::layout::{
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};
2325
use crate::const_eval::{
2426
CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
2527
};
@@ -497,6 +499,46 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
497499
},
498500
}
499501
}
502+
503+
fn operand_from_scalar(&self, scalar: Scalar, ty: Ty<'tcx>) -> Operand<'tcx> {
504+
Operand::Constant(Box::new(
505+
Constant {
506+
span: DUMMY_SP,
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>) {
518+
if let interpret::Operand::Immediate(im) = *value {
519+
match im {
520+
interpret::Immediate::Scalar(ScalarMaybeUndef::Scalar(scalar)) => {
521+
*rval = Rvalue::Use(self.operand_from_scalar(scalar, value.layout.ty));
522+
},
523+
Immediate::ScalarPair(
524+
ScalarMaybeUndef::Scalar(one),
525+
ScalarMaybeUndef::Scalar(two)
526+
) => {
527+
let ty = &value.layout.ty.sty;
528+
if let ty::Tuple(substs) = ty {
529+
*rval = Rvalue::Aggregate(
530+
Box::new(AggregateKind::Tuple),
531+
vec![
532+
self.operand_from_scalar(one, substs[0].expect_ty()),
533+
self.operand_from_scalar(two, substs[1].expect_ty()),
534+
],
535+
);
536+
}
537+
},
538+
_ => { }
539+
}
540+
}
541+
}
500542
}
501543

502544
fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -560,10 +602,10 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
560602
}
561603
}
562604

563-
impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
605+
impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
564606
fn visit_constant(
565607
&mut self,
566-
constant: &Constant<'tcx>,
608+
constant: &mut Constant<'tcx>,
567609
location: Location,
568610
) {
569611
trace!("visit_constant: {:?}", constant);
@@ -573,12 +615,12 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
573615

574616
fn visit_statement(
575617
&mut self,
576-
statement: &Statement<'tcx>,
618+
statement: &mut Statement<'tcx>,
577619
location: Location,
578620
) {
579621
trace!("visit_statement: {:?}", statement);
580-
if let StatementKind::Assign(ref place, ref rval) = statement.kind {
581-
let place_ty: Ty<'tcx> = place
622+
if let StatementKind::Assign(ref place, ref mut rval) = statement.kind {
623+
let place_ty: ty::Ty<'tcx> = place
582624
.ty(&self.local_decls, self.tcx)
583625
.ty;
584626
if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
@@ -589,6 +631,10 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
589631
trace!("storing {:?} to {:?}", value, local);
590632
assert!(self.places[local].is_none());
591633
self.places[local] = Some(value);
634+
635+
if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 {
636+
self.replace_with_const(rval, value);
637+
}
592638
}
593639
}
594640
}
@@ -599,7 +645,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
599645

600646
fn visit_terminator(
601647
&mut self,
602-
terminator: &Terminator<'tcx>,
648+
terminator: &mut Terminator<'tcx>,
603649
location: Location,
604650
) {
605651
self.super_terminator(terminator, location);
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
fn main() {
2+
let x: u32 = [0, 1, 2, 3][2];
3+
}
4+
5+
// END RUST SOURCE
6+
// START rustc.main.ConstProp.before.mir
7+
// bb0: {
8+
// ...
9+
// _2 = [const 0u32, const 1u32, const 2u32, const 3u32];
10+
// ...
11+
// _3 = const 2usize;
12+
// _4 = const 4usize;
13+
// _5 = Lt(_3, _4);
14+
// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
15+
// }
16+
// bb1: {
17+
// _1 = _2[_3];
18+
// ...
19+
// return;
20+
// }
21+
// END rustc.main.ConstProp.before.mir
22+
// START rustc.main.ConstProp.after.mir
23+
// bb0: {
24+
// ...
25+
// _5 = const true;
26+
// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
27+
// }
28+
// bb1: {
29+
// _1 = _2[_3];
30+
// ...
31+
// return;
32+
// }
33+
// END rustc.main.ConstProp.after.mir
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: -C overflow-checks=on
2+
3+
fn main() {
4+
let x: u32 = 1 + 1;
5+
}
6+
7+
// END RUST SOURCE
8+
// START rustc.main.ConstProp.before.mir
9+
// bb0: {
10+
// ...
11+
// _2 = CheckedAdd(const 1u32, const 1u32);
12+
// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1;
13+
// }
14+
// END rustc.main.ConstProp.before.mir
15+
// START rustc.main.ConstProp.after.mir
16+
// bb0: {
17+
// ...
18+
// _2 = (const 2u32, const false);
19+
// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1;
20+
// }
21+
// END rustc.main.ConstProp.after.mir
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
fn test() -> &'static [u32] {
2+
&[1, 2]
3+
}
4+
5+
fn main() {
6+
let x = test()[0];
7+
}
8+
9+
// END RUST SOURCE
10+
// START rustc.main.ConstProp.before.mir
11+
// bb1: {
12+
// ...
13+
// _3 = const 0usize;
14+
// _4 = Len((*_2));
15+
// _5 = Lt(_3, _4);
16+
// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2;
17+
// }
18+
// bb2: {
19+
// _1 = (*_2)[_3];
20+
// ...
21+
// return;
22+
// }
23+
// END rustc.main.ConstProp.before.mir
24+
// START rustc.main.ConstProp.after.mir
25+
// bb0: {
26+
// ...
27+
// _3 = const 0usize;
28+
// _4 = Len((*_2));
29+
// _5 = Lt(_3, _4);
30+
// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2;
31+
// }
32+
// bb2: {
33+
// _1 = (*_2)[_3];
34+
// ...
35+
// return;
36+
// }
37+
// END rustc.main.ConstProp.after.mir

0 commit comments

Comments
 (0)