From 470e4562a10d2ba9001ea427e5a7e4b9c2342f02 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 21 Jun 2018 13:20:58 +1000 Subject: [PATCH 1/2] Inline some hot `abi` methods. --- src/librustc_target/abi/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 7ff04df623399..b74a2b18f8de2 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -208,6 +208,7 @@ pub trait HasDataLayout: Copy { } impl<'a> HasDataLayout for &'a TargetDataLayout { + #[inline] fn data_layout(&self) -> &TargetDataLayout { self } @@ -240,10 +241,12 @@ impl Size { } } + #[inline] pub fn bytes(self) -> u64 { self.raw } + #[inline] pub fn bits(self) -> u64 { self.bytes().checked_mul(8).unwrap_or_else(|| { panic!("Size::bits: {} bytes in bits doesn't fit in u64", self.bytes()) @@ -289,6 +292,7 @@ impl Size { impl Add for Size { type Output = Size; + #[inline] fn add(self, other: Size) -> Size { Size::from_bytes(self.bytes().checked_add(other.bytes()).unwrap_or_else(|| { panic!("Size::add: {} + {} doesn't fit in u64", self.bytes(), other.bytes()) @@ -298,6 +302,7 @@ impl Add for Size { impl Sub for Size { type Output = Size; + #[inline] fn sub(self, other: Size) -> Size { Size::from_bytes(self.bytes().checked_sub(other.bytes()).unwrap_or_else(|| { panic!("Size::sub: {} - {} would result in negative size", self.bytes(), other.bytes()) @@ -314,6 +319,7 @@ impl Mul for u64 { impl Mul for Size { type Output = Size; + #[inline] fn mul(self, count: u64) -> Size { match self.bytes().checked_mul(count) { Some(bytes) => Size::from_bytes(bytes), @@ -374,18 +380,22 @@ impl Align { }) } + #[inline] pub fn abi(self) -> u64 { 1 << self.abi_pow2 } + #[inline] pub fn pref(self) -> u64 { 1 << self.pref_pow2 } + #[inline] pub fn abi_bits(self) -> u64 { self.abi() * 8 } + #[inline] pub fn pref_bits(self) -> u64 { self.pref() * 8 } From b9c95e47c0c89dc78dbc4562beb0b2a62be41e16 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 21 Jun 2018 15:16:18 +1000 Subject: [PATCH 2/2] Introduce `write_values_to_ptr()`. This greatly speeds up the compilation of large constant arrays, such as this one: > const TEST_DATA: [u8; 32 * 1024 * 1024] = [42; 32 * 1024 * 1024]; --- src/librustc/mir/interpret/value.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 69 ++++++++++++++++++++-- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 9e3d4e60603ec..3e0402069283d 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -124,7 +124,7 @@ impl<'tcx> Scalar { bits: layout.offset(bits as u64, i.bytes())? as u128, defined: pointer_size, }) - } + } } Scalar::Ptr(ptr) => ptr.offset(i, layout).map(Scalar::Ptr), } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index ea667273ecead..8f694bd57b788 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -586,16 +586,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M ) } }; - let elem_size = self.layout_of(elem_ty)?.size; let value = self.eval_operand(operand)?.value; let (dest, dest_align) = self.force_allocation(dest)?.to_ptr_align(); - // FIXME: speed up repeat filling - for i in 0..length { - let elem_dest = dest.ptr_offset(elem_size * i as u64, &self)?; - self.write_value_to_ptr(value, elem_dest, dest_align, elem_ty)?; - } + self.write_values_to_ptr(value, length, dest, dest_align, elem_ty)?; } Len(ref place) => { @@ -1257,6 +1252,68 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } } + pub fn write_values_to_ptr( + &mut self, + value: Value, + length: u64, + dest: Scalar, + dest_align: Align, + dest_ty: Ty<'tcx>, + ) -> EvalResult<'tcx> { + let layout = self.layout_of(dest_ty)?; + let elem_size = layout.size; + trace!("write_value_to_ptr: {:#?}, {}, {:#?}", value, dest_ty, layout); + match value { + Value::ByRef(ptr, align) => { + let align_min = align.min(layout.align); + let dest_align_min = dest_align.min(layout.align); + // FIXME: speed up repeat filling + for i in 0..length { + let elem_dest = dest.ptr_offset(elem_size * i, &self)?; + self.memory.copy(ptr, align_min, elem_dest, dest_align_min, layout.size, + false)?; + } + Ok(()) + } + Value::Scalar(scalar) => { + let signed = match layout.abi { + layout::Abi::Scalar(ref scal) => match scal.value { + layout::Primitive::Int(_, signed) => signed, + _ => false, + }, + _ => match scalar { + Scalar::Bits { defined: 0, .. } => false, + _ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout), + } + }; + // FIXME: speed up repeat filling + for i in 0..length { + let elem_dest = dest.ptr_offset(elem_size * i, &self)?; + self.memory.write_scalar(elem_dest, dest_align, scalar, layout.size, signed)?; + } + Ok(()) + } + Value::ScalarPair(a_val, b_val) => { + let (a, b) = match layout.abi { + layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value), + _ => bug!("write_value_to_ptr: invalid ScalarPair layout: {:#?}", layout) + }; + let (a_size, b_size) = (a.size(&self), b.size(&self)); + let b_offset = a_size.abi_align(b.align(&self)); + // FIXME: speed up repeat filling + for i in 0..length { + let elem_dest = dest.ptr_offset(elem_size * i, &self)?; + let a_ptr = elem_dest; + let b_ptr = elem_dest.ptr_offset(b_offset, &self)?.into(); + // TODO: What about signedess? + self.memory.write_scalar(a_ptr, dest_align, a_val, a_size, false)?; + self.memory.write_scalar(b_ptr, dest_align, b_val, b_size, false)?; + } + Ok(()) + } + } + } + fn ensure_valid_value(&self, val: Scalar, ty: Ty<'tcx>) -> EvalResult<'tcx> { match ty.sty { ty::TyBool => val.to_bool().map(|_| ()),