Skip to content

Commit 54c81ac

Browse files
committed
in a Use statement, exploit the fact that type and hence layout are the same for LHS and RHS
1 parent 8ad4047 commit 54c81ac

File tree

3 files changed

+44
-15
lines changed

3 files changed

+44
-15
lines changed

src/librustc_mir/interpret/operand.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,22 @@ impl<'tcx> OpTy<'tcx> {
189189
}
190190
}
191191

192+
// Use the existing layout if given (but sanity check in debug mode),
193+
// or compute the layout.
194+
#[inline(always)]
195+
fn from_known_layout<'tcx>(
196+
layout: Option<TyLayout<'tcx>>,
197+
compute: impl FnOnce() -> EvalResult<'tcx, TyLayout<'tcx>>
198+
) -> EvalResult<'tcx, TyLayout<'tcx>> {
199+
match layout {
200+
None => compute(),
201+
Some(layout) => {
202+
debug_assert_eq!(layout.ty, compute()?.ty);
203+
Ok(layout)
204+
}
205+
}
206+
}
207+
192208
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
193209
/// Try reading a value in memory; this is interesting particularily for ScalarPair.
194210
/// Return None if the layout does not permit loading this as a value.
@@ -377,21 +393,25 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
377393
}
378394

379395
// Evaluate a place with the goal of reading from it. This lets us sometimes
380-
// avoid allocations.
396+
// avoid allocations. If you already know the layout, you can pass it in
397+
// to avoid looking it up again.
381398
fn eval_place_to_op(
382399
&mut self,
383400
mir_place: &mir::Place<'tcx>,
401+
layout: Option<TyLayout<'tcx>>,
384402
) -> EvalResult<'tcx, OpTy<'tcx>> {
385403
use rustc::mir::Place::*;
386404
Ok(match *mir_place {
387405
Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
388406
Local(local) => {
389407
let op = *self.frame().locals[local].access()?;
390-
OpTy { op, layout: self.layout_of_local(self.cur_frame(), local)? }
408+
let layout = from_known_layout(layout,
409+
|| self.layout_of_local(self.cur_frame(), local))?;
410+
OpTy { op, layout }
391411
},
392412

393413
Projection(ref proj) => {
394-
let op = self.eval_place_to_op(&proj.base)?;
414+
let op = self.eval_place_to_op(&proj.base, None)?;
395415
self.operand_projection(op, &proj.elem)?
396416
}
397417

@@ -406,17 +426,25 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
406426
}
407427

408428
/// Evaluate the operand, returning a place where you can then find the data.
409-
pub fn eval_operand(&mut self, mir_op: &mir::Operand<'tcx>) -> EvalResult<'tcx, OpTy<'tcx>> {
429+
/// if you already know the layout, you can save two some table lookups
430+
/// by passing it in here.
431+
pub fn eval_operand(
432+
&mut self,
433+
mir_op: &mir::Operand<'tcx>,
434+
layout: Option<TyLayout<'tcx>>,
435+
) -> EvalResult<'tcx, OpTy<'tcx>> {
410436
use rustc::mir::Operand::*;
411437
let op = match *mir_op {
412438
// FIXME: do some more logic on `move` to invalidate the old location
413439
Copy(ref place) |
414440
Move(ref place) =>
415-
self.eval_place_to_op(place)?,
441+
self.eval_place_to_op(place, layout)?,
416442

417443
Constant(ref constant) => {
418-
let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs());
419-
let layout = self.layout_of(ty)?;
444+
let layout = from_known_layout(layout, || {
445+
let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs());
446+
self.layout_of(ty)
447+
})?;
420448
let op = self.const_value_to_op(constant.literal.val)?;
421449
OpTy { op, layout }
422450
}
@@ -431,7 +459,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
431459
ops: &[mir::Operand<'tcx>],
432460
) -> EvalResult<'tcx, Vec<OpTy<'tcx>>> {
433461
ops.into_iter()
434-
.map(|op| self.eval_operand(op))
462+
.map(|op| self.eval_operand(op, None))
435463
.collect()
436464
}
437465

@@ -473,7 +501,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
473501
&mut self,
474502
op: &mir::Operand<'tcx>,
475503
) -> EvalResult<'tcx, ValTy<'tcx>> {
476-
let op = self.eval_operand(op)?;
504+
let op = self.eval_operand(op, None)?;
477505
self.read_value(op)
478506
}
479507
pub fn eval_operand_and_read_scalar(

src/librustc_mir/interpret/step.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
141141
use rustc::mir::Rvalue::*;
142142
match *rvalue {
143143
Use(ref operand) => {
144-
let op = self.eval_operand(operand)?;
144+
// Avoid recomputing the layout
145+
let op = self.eval_operand(operand, Some(dest.layout))?;
145146
self.copy_op(op, dest)?;
146147
}
147148

@@ -187,7 +188,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
187188
};
188189

189190
for (i, operand) in operands.iter().enumerate() {
190-
let op = self.eval_operand(operand)?;
191+
let op = self.eval_operand(operand, None)?;
191192
// Ignore zero-sized fields.
192193
if !op.layout.is_zst() {
193194
let field_index = active_field_index.unwrap_or(i);
@@ -198,7 +199,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
198199
}
199200

200201
Repeat(ref operand, _) => {
201-
let op = self.eval_operand(operand)?;
202+
let op = self.eval_operand(operand, None)?;
202203
let dest = self.force_allocation(dest)?;
203204
let length = dest.len();
204205

@@ -260,7 +261,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
260261

261262
Cast(kind, ref operand, cast_ty) => {
262263
debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest.layout.ty);
263-
let src = self.eval_operand(operand)?;
264+
let src = self.eval_operand(operand, None)?;
264265
self.cast(src, kind, dest)?;
265266
}
266267

src/librustc_mir/interpret/terminator/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
3636
ref targets,
3737
..
3838
} => {
39-
let discr_val = self.eval_operand(discr)?;
39+
let discr_val = self.eval_operand(discr, None)?;
4040
let discr = self.read_value(discr_val)?;
4141
trace!("SwitchInt({:?})", *discr);
4242

@@ -70,7 +70,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
7070
None => None,
7171
};
7272

73-
let func = self.eval_operand(func)?;
73+
let func = self.eval_operand(func, None)?;
7474
let (fn_def, sig) = match func.layout.ty.sty {
7575
ty::TyFnPtr(sig) => {
7676
let fn_ptr = self.read_scalar(func)?.to_ptr()?;

0 commit comments

Comments
 (0)