Skip to content

Commit 576a61d

Browse files
Auto merge of #149366 - cjgillot:gvn-primitive, r=<try>
Gvn primitive
2 parents 1be6b13 + 1a22aee commit 576a61d

19 files changed

+110
-111
lines changed

compiler/rustc_middle/src/mir/consts.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,11 @@ impl<'tcx> Const<'tcx> {
495495
/// Return true if any evaluation of this constant always returns the same value,
496496
/// taking into account even pointer identity tests.
497497
pub fn is_deterministic(&self) -> bool {
498+
// Primitive types cannot contain provenance and always have the same value.
499+
if self.ty().is_primitive() {
500+
return true;
501+
}
502+
498503
// Some constants may generate fresh allocations for pointers they contain,
499504
// so using the same constant twice can yield two different results.
500505
// Notably, valtrees purposefully generate new allocations.
@@ -504,24 +509,19 @@ impl<'tcx> Const<'tcx> {
504509
// A valtree may be a reference. Valtree references correspond to a
505510
// different allocation each time they are evaluated. Valtrees for primitive
506511
// types are fine though.
507-
ty::ConstKind::Value(cv) => cv.ty.is_primitive(),
508-
ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
512+
ty::ConstKind::Value(..)
513+
| ty::ConstKind::Expr(..)
514+
| ty::ConstKind::Unevaluated(..)
509515
// This can happen if evaluation of a constant failed. The result does not matter
510516
// much since compilation is doomed.
511-
ty::ConstKind::Error(..) => false,
517+
| ty::ConstKind::Error(..) => false,
512518
// Should not appear in runtime MIR.
513519
ty::ConstKind::Infer(..)
514520
| ty::ConstKind::Bound(..)
515521
| ty::ConstKind::Placeholder(..) => bug!(),
516522
},
517523
Const::Unevaluated(..) => false,
518-
Const::Val(
519-
ConstValue::Slice { .. }
520-
| ConstValue::ZeroSized
521-
| ConstValue::Scalar(_)
522-
| ConstValue::Indirect { .. },
523-
_,
524-
) => true,
524+
Const::Val(..) => true,
525525
}
526526
}
527527
}

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,16 +1007,16 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
10071007
operand: &mut Operand<'tcx>,
10081008
location: Location,
10091009
) -> Option<VnIndex> {
1010-
match *operand {
1011-
Operand::Constant(ref constant) => Some(self.insert_constant(constant.const_)),
1010+
let value = match *operand {
1011+
Operand::Constant(ref constant) => self.insert_constant(constant.const_),
10121012
Operand::Copy(ref mut place) | Operand::Move(ref mut place) => {
1013-
let value = self.simplify_place_value(place, location)?;
1014-
if let Some(const_) = self.try_as_constant(value) {
1015-
*operand = Operand::Constant(Box::new(const_));
1016-
}
1017-
Some(value)
1013+
self.simplify_place_value(place, location)?
10181014
}
1015+
};
1016+
if let Some(const_) = self.try_as_constant(value) {
1017+
*operand = Operand::Constant(Box::new(const_));
10191018
}
1019+
Some(value)
10201020
}
10211021

10221022
#[instrument(level = "trace", skip(self), ret)]
@@ -1791,14 +1791,28 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
17911791

17921792
/// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR.
17931793
fn try_as_constant(&mut self, index: VnIndex) -> Option<ConstOperand<'tcx>> {
1794-
// This was already constant in MIR, do not change it. If the constant is not
1795-
// deterministic, adding an additional mention of it in MIR will not give the same value as
1796-
// the former mention.
1797-
if let Value::Constant { value, disambiguator: None } = self.get(index) {
1798-
debug_assert!(value.is_deterministic());
1794+
let value = self.get(index);
1795+
1796+
// This was already an *evaluated* constant in MIR, do not change it.
1797+
if let Value::Constant { value, disambiguator: None } = value
1798+
&& let Const::Val(..) = value
1799+
{
17991800
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
18001801
}
18011802

1803+
if let Some(value) = self.try_as_evaluated_constant(index) {
1804+
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
1805+
}
1806+
1807+
// We failed to provide an evaluated form, fallback to using the unevaluated constant.
1808+
if let Value::Constant { value, disambiguator: None } = value {
1809+
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
1810+
}
1811+
1812+
None
1813+
}
1814+
1815+
fn try_as_evaluated_constant(&mut self, index: VnIndex) -> Option<Const<'tcx>> {
18021816
let op = self.eval_to_const(index)?;
18031817
if op.layout.is_unsized() {
18041818
// Do not attempt to propagate unsized locals.
@@ -1812,8 +1826,7 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
18121826
// FIXME: remove this hack once https://github.com/rust-lang/rust/issues/79738 is fixed.
18131827
assert!(!value.may_have_provenance(self.tcx, op.layout.size));
18141828

1815-
let const_ = Const::Val(value, op.layout.ty);
1816-
Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_ })
1829+
Some(Const::Val(value, op.layout.ty))
18171830
}
18181831

18191832
/// Construct a place which holds the same value as `index` and for which all locals strictly

tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
- StorageLive(_2);
2323
+ nop;
2424
StorageLive(_3);
25-
_4 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind unreachable];
25+
- _4 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind unreachable];
26+
+ _4 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> [return: bb1, unwind unreachable];
2627
}
2728

2829
bb1: {

tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
- StorageLive(_2);
2323
+ nop;
2424
StorageLive(_3);
25-
_4 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind continue];
25+
- _4 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind continue];
26+
+ _4 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> [return: bb1, unwind continue];
2627
}
2728

2829
bb1: {

tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
StorageLive(_20);
4848
StorageLive(_21);
4949
_21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
50-
_20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG);
50+
_20 = BitAnd(move _21, const 2097152_u32);
5151
StorageDead(_21);
5252
_4 = Ne(move _20, const 0_u32);
5353
StorageDead(_20);
@@ -72,7 +72,7 @@
7272
StorageLive(_22);
7373
StorageLive(_23);
7474
_23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
75-
_22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
75+
_22 = BitAnd(move _23, const 268435456_u32);
7676
StorageDead(_23);
7777
switchInt(move _22) -> [0: bb10, otherwise: bb11];
7878
}

tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
StorageLive(_20);
4848
StorageLive(_21);
4949
_21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
50-
_20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG);
50+
_20 = BitAnd(move _21, const 2097152_u32);
5151
StorageDead(_21);
5252
_4 = Ne(move _20, const 0_u32);
5353
StorageDead(_20);
@@ -72,7 +72,7 @@
7272
StorageLive(_22);
7373
StorageLive(_23);
7474
_23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
75-
_22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
75+
_22 = BitAnd(move _23, const 268435456_u32);
7676
StorageDead(_23);
7777
switchInt(move _22) -> [0: bb10, otherwise: bb11];
7878
}

tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
StorageLive(_20);
4848
StorageLive(_21);
4949
_21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
50-
_20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG);
50+
_20 = BitAnd(move _21, const 2097152_u32);
5151
StorageDead(_21);
5252
_4 = Ne(move _20, const 0_u32);
5353
StorageDead(_20);
@@ -72,7 +72,7 @@
7272
StorageLive(_22);
7373
StorageLive(_23);
7474
_23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
75-
_22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
75+
_22 = BitAnd(move _23, const 268435456_u32);
7676
StorageDead(_23);
7777
switchInt(move _22) -> [0: bb10, otherwise: bb11];
7878
}

tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
StorageLive(_20);
4848
StorageLive(_21);
4949
_21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
50-
_20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG);
50+
_20 = BitAnd(move _21, const 2097152_u32);
5151
StorageDead(_21);
5252
_4 = Ne(move _20, const 0_u32);
5353
StorageDead(_20);
@@ -72,7 +72,7 @@
7272
StorageLive(_22);
7373
StorageLive(_23);
7474
_23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
75-
_22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
75+
_22 = BitAnd(move _23, const 268435456_u32);
7676
StorageDead(_23);
7777
switchInt(move _22) -> [0: bb10, otherwise: bb11];
7878
}

tests/mir-opt/gvn_const_eval_polymorphic.no_optimize.GVN.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
let mut _0: bool;
66

77
bb0: {
8-
_0 = Eq(const no_optimize::<T>::{constant#0}, const no_optimize::<T>::{constant#1});
8+
- _0 = Eq(const no_optimize::<T>::{constant#0}, const no_optimize::<T>::{constant#1});
9+
+ _0 = Eq(const no_optimize::<T>::{constant#0}, const true);
910
return;
1011
}
1112
}

tests/mir-opt/gvn_const_eval_polymorphic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn optimize_false<T>() -> bool {
5151
// EMIT_MIR gvn_const_eval_polymorphic.no_optimize.GVN.diff
5252
fn no_optimize<T>() -> bool {
5353
// CHECK-LABEL: fn no_optimize(
54-
// CHECK: _0 = Eq(const no_optimize::<T>::{constant#0}, const no_optimize::<T>::{constant#1});
54+
// CHECK: _0 = Eq(const no_optimize::<T>::{constant#0}, const true);
5555
// CHECK-NEXT: return;
5656
(const { type_name_contains_i32(&generic::<T>) }) == const { true }
5757
}

0 commit comments

Comments
 (0)