Skip to content

Commit 792d485

Browse files
authored
Rollup merge of rust-lang#74507 - lcnr:const-prop-into-op, r=oli-obk
add `visit_operand` to const prop r? @oli-obk
2 parents 45f2730 + d257bac commit 792d485

File tree

16 files changed

+261
-89
lines changed

16 files changed

+261
-89
lines changed

src/librustc_mir/transform/const_prop.rs

+50-62
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,34 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
582582
Some(())
583583
}
584584

585+
fn propagate_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
586+
match *operand {
587+
Operand::Copy(l) | Operand::Move(l) => {
588+
if let Some(value) = self.get_const(l) {
589+
if self.should_const_prop(value) {
590+
// FIXME(felix91gr): this code only handles `Scalar` cases.
591+
// For now, we're not handling `ScalarPair` cases because
592+
// doing so here would require a lot of code duplication.
593+
// We should hopefully generalize `Operand` handling into a fn,
594+
// and use it to do const-prop here and everywhere else
595+
// where it makes sense.
596+
if let interpret::Operand::Immediate(interpret::Immediate::Scalar(
597+
ScalarMaybeUninit::Scalar(scalar),
598+
)) = *value
599+
{
600+
*operand = self.operand_from_scalar(
601+
scalar,
602+
value.layout.ty,
603+
self.source_info.unwrap().span,
604+
);
605+
}
606+
}
607+
}
608+
}
609+
Operand::Constant(ref mut ct) => self.visit_constant(ct, location),
610+
}
611+
}
612+
585613
fn const_prop(
586614
&mut self,
587615
rvalue: &Rvalue<'tcx>,
@@ -905,6 +933,16 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
905933
}
906934
}
907935

936+
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
937+
// Only const prop copies and moves on `mir_opt_level=3` as doing so
938+
// currently increases compile time.
939+
if self.tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
940+
self.super_operand(operand, location)
941+
} else {
942+
self.propagate_operand(operand, location)
943+
}
944+
}
945+
908946
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
909947
trace!("visit_constant: {:?}", constant);
910948
self.super_constant(constant, location);
@@ -1072,18 +1110,13 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
10721110
}
10731111
}
10741112
}
1075-
TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => {
1076-
if let Some(value) = self.eval_operand(&discr, source_info) {
1077-
if self.should_const_prop(value) {
1078-
if let ScalarMaybeUninit::Scalar(scalar) =
1079-
self.ecx.read_scalar(value).unwrap()
1080-
{
1081-
*discr = self.operand_from_scalar(scalar, switch_ty, source_info.span);
1082-
}
1083-
}
1084-
}
1113+
TerminatorKind::SwitchInt { ref mut discr, .. } => {
1114+
// FIXME: This is currently redundant with `visit_operand`, but sadly
1115+
// always visiting operands currently causes a perf regression in LLVM codegen, so
1116+
// `visit_operand` currently only runs for propagates places for `mir_opt_level=3`.
1117+
self.propagate_operand(discr, location)
10851118
}
1086-
// None of these have Operands to const-propagate
1119+
// None of these have Operands to const-propagate.
10871120
TerminatorKind::Goto { .. }
10881121
| TerminatorKind::Resume
10891122
| TerminatorKind::Abort
@@ -1096,61 +1129,16 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
10961129
| TerminatorKind::FalseEdge { .. }
10971130
| TerminatorKind::FalseUnwind { .. }
10981131
| TerminatorKind::InlineAsm { .. } => {}
1099-
// Every argument in our function calls can be const propagated.
1100-
TerminatorKind::Call { ref mut args, .. } => {
1101-
let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level;
1102-
// Constant Propagation into function call arguments is gated
1103-
// under mir-opt-level 2, because LLVM codegen gives performance
1104-
// regressions with it.
1105-
if mir_opt_level >= 2 {
1106-
for opr in args {
1107-
/*
1108-
The following code would appear to be incomplete, because
1109-
the function `Operand::place()` returns `None` if the
1110-
`Operand` is of the variant `Operand::Constant`. In this
1111-
context however, that variant will never appear. This is why:
1112-
1113-
When constructing the MIR, all function call arguments are
1114-
copied into `Locals` of `LocalKind::Temp`. At least, all arguments
1115-
that are not unsized (Less than 0.1% are unsized. See #71170
1116-
to learn more about those).
1117-
1118-
This means that, conversely, all `Operands` found as function call
1119-
arguments are of the variant `Operand::Copy`. This allows us to
1120-
simplify our handling of `Operands` in this case.
1121-
*/
1122-
if let Some(l) = opr.place() {
1123-
if let Some(value) = self.get_const(l) {
1124-
if self.should_const_prop(value) {
1125-
// FIXME(felix91gr): this code only handles `Scalar` cases.
1126-
// For now, we're not handling `ScalarPair` cases because
1127-
// doing so here would require a lot of code duplication.
1128-
// We should hopefully generalize `Operand` handling into a fn,
1129-
// and use it to do const-prop here and everywhere else
1130-
// where it makes sense.
1131-
if let interpret::Operand::Immediate(
1132-
interpret::Immediate::Scalar(ScalarMaybeUninit::Scalar(
1133-
scalar,
1134-
)),
1135-
) = *value
1136-
{
1137-
*opr = self.operand_from_scalar(
1138-
scalar,
1139-
value.layout.ty,
1140-
source_info.span,
1141-
);
1142-
}
1143-
}
1144-
}
1145-
}
1146-
}
1147-
}
1148-
}
1132+
// Every argument in our function calls have already been propagated in `visit_operand`.
1133+
//
1134+
// NOTE: because LLVM codegen gives performance regressions with it, so this is gated
1135+
// on `mir_opt_level=3`.
1136+
TerminatorKind::Call { .. } => {}
11491137
}
11501138

11511139
// We remove all Locals which are restricted in propagation to their containing blocks and
11521140
// which were modified in the current block.
1153-
// Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const`
1141+
// Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const`.
11541142
let mut locals = std::mem::take(&mut self.ecx.machine.written_only_inside_own_block_locals);
11551143
for &local in locals.iter() {
11561144
Self::remove_const(&mut self.ecx, local);

src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff

+13-1
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,25 @@
6464
+ // mir::Constant
6565
+ // + span: $DIR/array_index.rs:5:18: 5:33
6666
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
67-
+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
67+
+ assert(const true, "index out of bounds: the len is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
6868
+ // ty::Const
6969
+ // + ty: bool
7070
+ // + val: Value(Scalar(0x01))
7171
+ // mir::Constant
7272
+ // + span: $DIR/array_index.rs:5:18: 5:33
7373
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
74+
+ // ty::Const
75+
+ // + ty: usize
76+
+ // + val: Value(Scalar(0x00000004))
77+
+ // mir::Constant
78+
+ // + span: $DIR/array_index.rs:5:18: 5:33
79+
+ // + literal: Const { ty: usize, val: Value(Scalar(0x00000004)) }
80+
+ // ty::Const
81+
+ // + ty: usize
82+
+ // + val: Value(Scalar(0x00000002))
83+
+ // mir::Constant
84+
+ // + span: $DIR/array_index.rs:5:18: 5:33
85+
+ // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) }
7486
}
7587

7688
bb1: {

src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff

+13-1
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,25 @@
6464
+ // mir::Constant
6565
+ // + span: $DIR/array_index.rs:5:18: 5:33
6666
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
67-
+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
67+
+ assert(const true, "index out of bounds: the len is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
6868
+ // ty::Const
6969
+ // + ty: bool
7070
+ // + val: Value(Scalar(0x01))
7171
+ // mir::Constant
7272
+ // + span: $DIR/array_index.rs:5:18: 5:33
7373
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
74+
+ // ty::Const
75+
+ // + ty: usize
76+
+ // + val: Value(Scalar(0x0000000000000004))
77+
+ // mir::Constant
78+
+ // + span: $DIR/array_index.rs:5:18: 5:33
79+
+ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000004)) }
80+
+ // ty::Const
81+
+ // + ty: usize
82+
+ // + val: Value(Scalar(0x0000000000000002))
83+
+ // mir::Constant
84+
+ // + span: $DIR/array_index.rs:5:18: 5:33
85+
+ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) }
7486
}
7587

7688
bb1: {

src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff

+26-6
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,22 @@
3838
- // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
3939
+ // + span: $DIR/bad_op_div_by_zero.rs:5:18: 5:19
4040
// + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
41+
- assert(!move _4, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
4142
+ _4 = const true; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
43+
// ty::Const
44+
+ // + ty: bool
45+
+ // + val: Value(Scalar(0x01))
46+
+ // mir::Constant
47+
+ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
48+
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
49+
+ assert(!const true, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
4250
+ // ty::Const
4351
+ // + ty: bool
4452
+ // + val: Value(Scalar(0x01))
4553
+ // mir::Constant
4654
+ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
4755
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
48-
assert(!move _4, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
49-
// ty::Const
56+
+ // ty::Const
5057
// + ty: i32
5158
// + val: Value(Scalar(0x00000001))
5259
// mir::Constant
@@ -90,29 +97,42 @@
9097
- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
9198
- assert(!move _7, "attempt to compute `{} / {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
9299
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
93-
+ assert(!const false, "attempt to compute `{} / {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
94-
+ // ty::Const
100+
+ assert(!const false, "attempt to compute `{} / {}` which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
101+
// ty::Const
95102
+ // + ty: bool
96103
+ // + val: Value(Scalar(0x00))
97104
+ // mir::Constant
98105
+ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
99106
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
100-
// ty::Const
107+
+ // ty::Const
101108
// + ty: i32
102109
// + val: Value(Scalar(0x00000001))
103110
// mir::Constant
104111
// + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:15
105112
// + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
113+
+ // ty::Const
114+
+ // + ty: i32
115+
+ // + val: Value(Scalar(0x00000000))
116+
+ // mir::Constant
117+
+ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
118+
+ // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
106119
}
107120

108121
bb2: {
109-
_2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
122+
- _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
123+
+ _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
110124
// ty::Const
111125
// + ty: i32
112126
// + val: Value(Scalar(0x00000001))
113127
// mir::Constant
114128
// + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:15
115129
// + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
130+
+ // ty::Const
131+
+ // + ty: i32
132+
+ // + val: Value(Scalar(0x00000000))
133+
+ // mir::Constant
134+
+ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
135+
+ // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
116136
StorageDead(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
117137
_0 = const (); // scope 0 at $DIR/bad_op_div_by_zero.rs:3:11: 6:2
118138
// ty::Const

0 commit comments

Comments
 (0)