diff options
| author | bors <bors@rust-lang.org> | 2023-10-29 14:50:53 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-10-29 14:50:53 +0000 |
| commit | 83c9732e0c7e1cae5f039677da4c51ee1d9b19b0 (patch) | |
| tree | 05a5ad6943e6dfd98522bf54b83b9fa18386190a /compiler/rustc_const_eval/src | |
| parent | 160fd3ceb5143100d4e06f324b02af1f9e786372 (diff) | |
| parent | 24be43356e31d6b0ee2ec8bf912c0a325f236a1d (diff) | |
| download | rust-83c9732e0c7e1cae5f039677da4c51ee1d9b19b0.tar.gz rust-83c9732e0c7e1cae5f039677da4c51ee1d9b19b0.zip | |
Auto merge of #116270 - cjgillot:gvn-aggregate, r=oli-obk,RalfJung
See through aggregates in GVN
This PR is extracted from https://github.com/rust-lang/rust/pull/111344
The first 2 commit are cleanups to avoid repeated work. I propose to stop removing useless assignments as part of this pass, and let a later `SimplifyLocals` do it. This makes tests easier to read (among others).
The next 3 commits add a constant folding mechanism to the GVN pass, presented in https://github.com/rust-lang/rust/pull/116012. ~This pass is designed to only use global allocations, to avoid any risk of accidental modification of the stored state.~
The following commits implement opportunistic simplifications, in particular:
- projections of aggregates: `MyStruct { x: a }.x` gets replaced by `a`, works with enums too;
- projections of arrays: `[a, b][0]` becomes `a`;
- projections of repeat expressions: `[a; N][x]` becomes `a`;
- transform arrays of equal operands into a repeat rvalue.
Fixes https://github.com/rust-lang/miri/issues/3090
r? `@oli-obk`
Diffstat (limited to 'compiler/rustc_const_eval/src')
7 files changed, 58 insertions, 9 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 8dab45d65ee..fd173670374 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -1,7 +1,8 @@ //! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines). -use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; -use rustc_middle::{mir, ty}; +use rustc_middle::mir; +use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt}; +use rustc_middle::ty::{self, Ty}; use rustc_target::abi::{self, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; @@ -244,11 +245,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn discriminant_for_variant( &self, - layout: TyAndLayout<'tcx>, + ty: Ty<'tcx>, variant: VariantIdx, ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { - let discr_layout = self.layout_of(layout.ty.discriminant_ty(*self.tcx))?; - let discr_value = match layout.ty.discriminant_for_variant(*self.tcx, variant) { + let discr_layout = self.layout_of(ty.discriminant_ty(*self.tcx))?; + let discr_value = match ty.discriminant_for_variant(*self.tcx, variant) { Some(discr) => { // This type actually has discriminants. assert_eq!(discr.ty, discr_layout.ty); diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index fd89e34204f..3d90e95c09c 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -450,6 +450,42 @@ pub fn intern_const_alloc_recursive< Ok(()) } +/// Intern `ret`. This function assumes that `ret` references no other allocation. +#[instrument(level = "debug", skip(ecx))] +pub fn intern_const_alloc_for_constprop< + 'mir, + 'tcx: 'mir, + T, + M: CompileTimeMachine<'mir, 'tcx, T>, +>( + ecx: &mut InterpCx<'mir, 'tcx, M>, + alloc_id: AllocId, +) -> InterpResult<'tcx, ()> { + // Move allocation to `tcx`. + let Some((_, mut alloc)) = ecx.memory.alloc_map.remove(&alloc_id) else { + // Pointer not found in local memory map. It is either a pointer to the global + // map, or dangling. + if ecx.tcx.try_get_global_alloc(alloc_id).is_none() { + throw_ub!(DeadLocal) + } + // The constant is already in global memory. Do nothing. + return Ok(()); + }; + + alloc.mutability = Mutability::Not; + + // We are not doing recursive interning, so we don't currently support provenance. + // (If this assertion ever triggers, we should just implement a + // proper recursive interning loop.) + assert!(alloc.provenance().ptrs().is_empty()); + + // Link the alloc id to the actual allocation + let alloc = ecx.tcx.mk_const_alloc(alloc); + ecx.tcx.set_alloc_id_memory(alloc_id, alloc); + + Ok(()) +} + impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> InterpCx<'mir, 'tcx, M> { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index c97207a61ac..c48857fcf3c 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -218,7 +218,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::discriminant_value => { let place = self.deref_pointer(&args[0])?; let variant = self.read_discriminant(&place)?; - let discr = self.discriminant_for_variant(place.layout, variant)?; + let discr = self.discriminant_for_variant(place.layout.ty, variant)?; self.write_immediate(*discr, dest)?; } sym::exact_div => { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index d7c7e279849..16905e93bf1 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1011,7 +1011,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Pr } /// Returns whether the allocation has provenance anywhere in the range of the `AllocRef`. - pub(crate) fn has_provenance(&self) -> bool { + pub fn has_provenance(&self) -> bool { !self.alloc.provenance().range_empty(self.range, &self.tcx) } } diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 13664456987..7d286d103ad 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -21,7 +21,9 @@ mod visitor; pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here pub use self::eval_context::{Frame, FrameInfo, InterpCx, StackPopCleanup}; -pub use self::intern::{intern_const_alloc_recursive, InternKind}; +pub use self::intern::{ + intern_const_alloc_for_constprop, intern_const_alloc_recursive, InternKind, +}; pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump}; pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; pub use self::operand::{ImmTy, Immediate, OpTy, Readable}; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 6716888290d..255dd1eba97 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -169,6 +169,16 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { ImmTy { imm: val.into(), layout } } + #[inline] + pub fn from_scalar_pair(a: Scalar<Prov>, b: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self { + debug_assert!( + matches!(layout.abi, Abi::ScalarPair(..)), + "`ImmTy::from_scalar_pair` on non-scalar-pair layout" + ); + let imm = Immediate::ScalarPair(a, b); + ImmTy { imm, layout } + } + #[inline(always)] pub fn from_immediate(imm: Immediate<Prov>, layout: TyAndLayout<'tcx>) -> Self { debug_assert!( diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 79cbda545f1..8c34d05042b 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -297,7 +297,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Discriminant(place) => { let op = self.eval_place_to_op(place, None)?; let variant = self.read_discriminant(&op)?; - let discr = self.discriminant_for_variant(op.layout, variant)?; + let discr = self.discriminant_for_variant(op.layout.ty, variant)?; self.write_immediate(*discr, &dest)?; } } |
