Skip to content

Commit 048f122

Browse files
committed
Also evaluate TY consts.
1 parent 9b71592 commit 048f122

File tree

2 files changed

+51
-67
lines changed

2 files changed

+51
-67
lines changed

compiler/rustc_mir_transform/src/const_prop.rs

Lines changed: 49 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_middle::mir::visit::{
1616
use rustc_middle::mir::*;
1717
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
1818
use rustc_middle::ty::InternalSubsts;
19-
use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
19+
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
2020
use rustc_span::{def_id::DefId, Span};
2121
use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout};
2222
use rustc_target::spec::abi::Abi as CallAbi;
@@ -625,21 +625,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
625625

626626
fn replace_with_const(
627627
&mut self,
628-
rval: &mut Rvalue<'tcx>,
629628
value: &OpTy<'tcx>,
630629
source_info: SourceInfo,
631-
) {
632-
if let Rvalue::Use(Operand::Constant(c)) = rval {
633-
match c.literal {
634-
ConstantKind::Ty(c) if matches!(c.kind(), ConstKind::Unevaluated(..)) => {}
635-
_ => {
636-
trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
637-
return;
638-
}
639-
}
640-
}
641-
642-
trace!("attempting to replace {:?} with {:?}", rval, value);
630+
) -> Option<Operand<'tcx>> {
631+
trace!("attempting to replace with {:?}", value);
643632
if let Err(e) = self.ecx.const_validate_operand(
644633
value,
645634
vec![],
@@ -649,64 +638,56 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
649638
CtfeValidationMode::Regular,
650639
) {
651640
trace!("validation error, attempt failed: {:?}", e);
652-
return;
641+
return None;
653642
}
654643

655644
// FIXME> figure out what to do when read_immediate_raw fails
656645
let imm = self.ecx.read_immediate_raw(value).ok();
657646

658-
if let Some(Right(imm)) = imm {
659-
match *imm {
660-
interpret::Immediate::Scalar(scalar) => {
661-
*rval = Rvalue::Use(self.operand_from_scalar(
662-
scalar,
663-
value.layout.ty,
664-
source_info.span,
665-
));
666-
}
667-
Immediate::ScalarPair(..) => {
668-
// Found a value represented as a pair. For now only do const-prop if the type
669-
// of `rvalue` is also a tuple with two scalars.
670-
// FIXME: enable the general case stated above ^.
671-
let ty = value.layout.ty;
672-
// Only do it for tuples
673-
if let ty::Tuple(types) = ty.kind() {
674-
// Only do it if tuple is also a pair with two scalars
675-
if let [ty1, ty2] = types[..] {
676-
let ty_is_scalar = |ty| {
677-
self.ecx.layout_of(ty).ok().map(|layout| layout.abi.is_scalar())
678-
== Some(true)
679-
};
680-
let alloc = if ty_is_scalar(ty1) && ty_is_scalar(ty2) {
681-
let alloc = self
682-
.ecx
683-
.intern_with_temp_alloc(value.layout, |ecx, dest| {
684-
ecx.write_immediate(*imm, dest)
685-
})
686-
.unwrap();
687-
Some(alloc)
688-
} else {
689-
None
690-
};
691-
692-
if let Some(alloc) = alloc {
693-
// Assign entire constant in a single statement.
694-
// We can't use aggregates, as we run after the aggregate-lowering `MirPhase`.
695-
let const_val = ConstValue::ByRef { alloc, offset: Size::ZERO };
696-
let literal = ConstantKind::Val(const_val, ty);
697-
*rval = Rvalue::Use(Operand::Constant(Box::new(Constant {
698-
span: source_info.span,
699-
user_ty: None,
700-
literal,
701-
})));
702-
}
703-
}
704-
}
647+
let Right(imm) = imm? else { return None };
648+
match *imm {
649+
interpret::Immediate::Scalar(scalar) => {
650+
Some(self.operand_from_scalar(scalar, value.layout.ty, source_info.span))
651+
}
652+
Immediate::ScalarPair(..) => {
653+
// Found a value represented as a pair. For now only do const-prop if the type
654+
// of `rvalue` is also a tuple with two scalars.
655+
// FIXME: enable the general case stated above ^.
656+
let ty = value.layout.ty;
657+
// Only do it for tuples
658+
let ty::Tuple(types) = ty.kind() else { return None };
659+
// Only do it if tuple is also a pair with two scalars
660+
if let [ty1, ty2] = types[..] {
661+
let ty_is_scalar = |ty| {
662+
self.ecx.layout_of(ty).ok().map(|layout| layout.abi.is_scalar())
663+
== Some(true)
664+
};
665+
let alloc = if ty_is_scalar(ty1) && ty_is_scalar(ty2) {
666+
self.ecx
667+
.intern_with_temp_alloc(value.layout, |ecx, dest| {
668+
ecx.write_immediate(*imm, dest)
669+
})
670+
.unwrap()
671+
} else {
672+
return None;
673+
};
674+
675+
// Assign entire constant in a single statement.
676+
// We can't use aggregates, as we run after the aggregate-lowering `MirPhase`.
677+
let const_val = ConstValue::ByRef { alloc, offset: Size::ZERO };
678+
let literal = ConstantKind::Val(const_val, ty);
679+
Some(Operand::Constant(Box::new(Constant {
680+
span: source_info.span,
681+
user_ty: None,
682+
literal,
683+
})))
684+
} else {
685+
None
705686
}
706-
// Scalars or scalar pairs that contain undef values are assumed to not have
707-
// successfully evaluated and are thus not propagated.
708-
_ => {}
709687
}
688+
// Scalars or scalar pairs that contain undef values are assumed to not have
689+
// successfully evaluated and are thus not propagated.
690+
_ => None,
710691
}
711692
}
712693

@@ -899,7 +880,9 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
899880
// consists solely of uninitialized memory (so it doesn't capture any locals).
900881
if let Some(ref value) = self.get_const(place) && self.should_const_prop(value) {
901882
trace!("replacing {:?} with {:?}", rval, value);
902-
self.replace_with_const(rval, value, source_info);
883+
if let Some(operand) = self.replace_with_const(value, source_info) {
884+
*rval = Rvalue::Use(operand);
885+
}
903886
if can_const_prop == ConstPropMode::FullConstProp
904887
|| can_const_prop == ConstPropMode::OnlyInsideOwnBlock
905888
{

tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88

99
bb0: {
1010
StorageLive(_1); // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
11-
_1 = const _; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
11+
- _1 = const _; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
1212
- switchInt(move _1) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
13+
+ _1 = const false; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
1314
+ switchInt(const false) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
1415
}
1516

0 commit comments

Comments
 (0)