diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 3bdfc1db913a4..46248d75b2822 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -4,10 +4,13 @@ use std::{fmt, mem}; use either::{Either, Left, Right}; use hir::CRATE_HIR_ID; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::Lock; use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; +use rustc_middle::mir::ConstValue; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers, @@ -47,6 +50,9 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// The recursion limit (cached from `tcx.recursion_limit(())`) pub recursion_limit: Limit, + + pub const_cache: + Lock, TyAndLayout<'tcx>, Span), OpTy<'tcx, M::Provenance>>>, } // The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread @@ -440,6 +446,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { param_env, memory: Memory::new(), recursion_limit: tcx.recursion_limit(), + const_cache: Lock::new(FxHashMap::default()), } } diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 255dd1eba97f2..eaa551f378692 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -748,6 +748,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }) }; let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?; + let span = self.cur_span(); + if let Some(op) = self.const_cache.lock().get(&(val_val, layout, span)).cloned() { + return Ok(op); + } let imm = match val_val { mir::ConstValue::Indirect { alloc_id, offset } => { // We rely on mutability being set correctly in that allocation to prevent writes @@ -764,7 +768,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Immediate::new_slice(self.global_base_pointer(ptr)?.into(), meta, self) } }; - Ok(OpTy { op: Operand::Immediate(imm), layout }) + let res = OpTy { op: Operand::Immediate(imm), layout }; + self.const_cache.lock().insert((val_val, layout, span), res.clone()); + Ok(res) } }