Rollup merge of #59630 - nnethercote:shrink-mir-Statement, r=pnkfelix

Shrink `mir::Statement`.

The `InlineAsm` variant is extremely rare, and `mir::Statement` often
contributes significantly to peak memory usage.
This commit is contained in:
Mazdak Farrokhzad 2019-04-03 04:36:14 +02:00 committed by GitHub
commit d31d80b7d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 48 additions and 47 deletions

View File

@ -4,7 +4,7 @@
use crate::hir::def::{CtorKind, Namespace}; use crate::hir::def::{CtorKind, Namespace};
use crate::hir::def_id::DefId; use crate::hir::def_id::DefId;
use crate::hir::{self, HirId, InlineAsm}; use crate::hir::{self, HirId, InlineAsm as HirInlineAsm};
use crate::mir::interpret::{ConstValue, InterpError, Scalar}; use crate::mir::interpret::{ConstValue, InterpError, Scalar};
use crate::mir::visit::MirVisitable; use crate::mir::visit::MirVisitable;
use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::ieee::{Double, Single};
@ -1735,7 +1735,7 @@ pub struct Statement<'tcx> {
// `Statement` is used a lot. Make sure it doesn't unintentionally get bigger. // `Statement` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::<Statement<'_>>() == 56); static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::<Statement<'_>>() == 48);
impl<'tcx> Statement<'tcx> { impl<'tcx> Statement<'tcx> {
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
@ -1779,12 +1779,9 @@ pub enum StatementKind<'tcx> {
/// End the current live range for the storage of the local. /// End the current live range for the storage of the local.
StorageDead(Local), StorageDead(Local),
/// Executes a piece of inline Assembly. /// Executes a piece of inline Assembly. Stored in a Box to keep the size
InlineAsm { /// of `StatementKind` low.
asm: Box<InlineAsm>, InlineAsm(Box<InlineAsm<'tcx>>),
outputs: Box<[Place<'tcx>]>,
inputs: Box<[(Span, Operand<'tcx>)]>,
},
/// Retag references in the given place, ensuring they got fresh tags. This is /// Retag references in the given place, ensuring they got fresh tags. This is
/// part of the Stacked Borrows model. These statements are currently only interpreted /// part of the Stacked Borrows model. These statements are currently only interpreted
@ -1858,6 +1855,13 @@ pub enum FakeReadCause {
ForLet, ForLet,
} }
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub struct InlineAsm<'tcx> {
pub asm: HirInlineAsm,
pub outputs: Box<[Place<'tcx>]>,
pub inputs: Box<[(Span, Operand<'tcx>)]>,
}
impl<'tcx> Debug for Statement<'tcx> { impl<'tcx> Debug for Statement<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
use self::StatementKind::*; use self::StatementKind::*;
@ -1880,11 +1884,8 @@ impl<'tcx> Debug for Statement<'tcx> {
ref place, ref place,
variant_index, variant_index,
} => write!(fmt, "discriminant({:?}) = {:?}", place, variant_index), } => write!(fmt, "discriminant({:?}) = {:?}", place, variant_index),
InlineAsm { InlineAsm(ref asm) =>
ref asm, write!(fmt, "asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs),
ref outputs,
ref inputs,
} => write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs),
AscribeUserType(ref place, ref variance, ref c_ty) => { AscribeUserType(ref place, ref variance, ref c_ty) => {
write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty) write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
} }
@ -3149,13 +3150,21 @@ EnumTypeFoldableImpl! {
(StatementKind::SetDiscriminant) { place, variant_index }, (StatementKind::SetDiscriminant) { place, variant_index },
(StatementKind::StorageLive)(a), (StatementKind::StorageLive)(a),
(StatementKind::StorageDead)(a), (StatementKind::StorageDead)(a),
(StatementKind::InlineAsm) { asm, outputs, inputs }, (StatementKind::InlineAsm)(a),
(StatementKind::Retag)(kind, place), (StatementKind::Retag)(kind, place),
(StatementKind::AscribeUserType)(a, v, b), (StatementKind::AscribeUserType)(a, v, b),
(StatementKind::Nop), (StatementKind::Nop),
} }
} }
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for InlineAsm<'tcx> {
asm,
outputs,
inputs,
}
}
EnumTypeFoldableImpl! { EnumTypeFoldableImpl! {
impl<'tcx, T> TypeFoldable<'tcx> for ClearCrossCrate<T> { impl<'tcx, T> TypeFoldable<'tcx> for ClearCrossCrate<T> {
(ClearCrossCrate::Clear), (ClearCrossCrate::Clear),

View File

@ -391,15 +391,15 @@ macro_rules! make_mir_visitor {
location location
); );
} }
StatementKind::InlineAsm { outputs, inputs, asm: _ } => { StatementKind::InlineAsm(asm) => {
for output in & $($mutability)? outputs[..] { for output in & $($mutability)? asm.outputs[..] {
self.visit_place( self.visit_place(
output, output,
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput), PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
location location
); );
} }
for (span, input) in & $($mutability)? inputs[..] { for (span, input) in & $($mutability)? asm.inputs[..] {
self.visit_span(span); self.visit_span(span);
self.visit_operand(input, location); self.visit_operand(input, location);
} }

View File

@ -68,13 +68,13 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
bx bx
} }
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { mir::StatementKind::InlineAsm(ref asm) => {
let outputs = outputs.iter().map(|output| { let outputs = asm.outputs.iter().map(|output| {
self.codegen_place(&mut bx, output) self.codegen_place(&mut bx, output)
}).collect(); }).collect();
let input_vals = inputs.iter() let input_vals = asm.inputs.iter()
.fold(Vec::with_capacity(inputs.len()), |mut acc, (span, input)| { .fold(Vec::with_capacity(asm.inputs.len()), |mut acc, (span, input)| {
let op = self.codegen_operand(&mut bx, input); let op = self.codegen_operand(&mut bx, input);
if let OperandValue::Immediate(_) = op.val { if let OperandValue::Immediate(_) = op.val {
acc.push(op.immediate()); acc.push(op.immediate());
@ -85,8 +85,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
acc acc
}); });
if input_vals.len() == inputs.len() { if input_vals.len() == asm.inputs.len() {
let res = bx.codegen_inline_asm(asm, outputs, input_vals); let res = bx.codegen_inline_asm(&asm.asm, outputs, input_vals);
if !res { if !res {
span_err!(bx.sess(), statement.source_info.span, E0668, span_err!(bx.sess(), statement.source_info.span, E0668,
"malformed inline assembly"); "malformed inline assembly");

View File

@ -525,16 +525,12 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
flow_state, flow_state,
); );
} }
StatementKind::InlineAsm { StatementKind::InlineAsm(ref asm) => {
ref asm,
ref outputs,
ref inputs,
} => {
let context = ContextKind::InlineAsm.new(location); let context = ContextKind::InlineAsm.new(location);
for (o, output) in asm.outputs.iter().zip(outputs.iter()) { for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
if o.is_indirect { if o.is_indirect {
// FIXME(eddyb) indirect inline asm outputs should // FIXME(eddyb) indirect inline asm outputs should
// be encoeded through MIR place derefs instead. // be encoded through MIR place derefs instead.
self.access_place( self.access_place(
context, context,
(output, o.span), (output, o.span),
@ -558,7 +554,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
); );
} }
} }
for (_, input) in inputs.iter() { for (_, input) in asm.inputs.iter() {
self.consume_operand(context, (input, span), flow_state); self.consume_operand(context, (input, span), flow_state);
} }
} }

View File

@ -92,16 +92,12 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
JustWrite, JustWrite,
); );
} }
StatementKind::InlineAsm { StatementKind::InlineAsm(ref asm) => {
ref asm,
ref outputs,
ref inputs,
} => {
let context = ContextKind::InlineAsm.new(location); let context = ContextKind::InlineAsm.new(location);
for (o, output) in asm.outputs.iter().zip(outputs.iter()) { for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
if o.is_indirect { if o.is_indirect {
// FIXME(eddyb) indirect inline asm outputs should // FIXME(eddyb) indirect inline asm outputs should
// be encoeded through MIR place derefs instead. // be encoded through MIR place derefs instead.
self.access_place( self.access_place(
context, context,
output, output,
@ -117,7 +113,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
); );
} }
} }
for (_, input) in inputs.iter() { for (_, input) in asm.inputs.iter() {
self.consume_operand(context, input); self.consume_operand(context, input);
} }
} }

View File

@ -188,11 +188,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
block, block,
Statement { Statement {
source_info, source_info,
kind: StatementKind::InlineAsm { kind: StatementKind::InlineAsm(box InlineAsm {
asm: box asm.clone(), asm: asm.clone(),
outputs, outputs,
inputs, inputs,
}, }),
}, },
); );
this.block_context.pop(); this.block_context.pop();

View File

@ -288,8 +288,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'gcx, 'tcx> {
self.kill_borrows_on_place(sets, &Place::Base(PlaceBase::Local(local))); self.kill_borrows_on_place(sets, &Place::Base(PlaceBase::Local(local)));
} }
mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => { mir::StatementKind::InlineAsm(ref asm) => {
for (output, kind) in outputs.iter().zip(&asm.outputs) { for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
if !kind.is_indirect && !kind.is_rw { if !kind.is_indirect && !kind.is_rw {
self.kill_borrows_on_place(sets, output); self.kill_borrows_on_place(sets, output);
} }

View File

@ -272,13 +272,13 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
StatementKind::FakeRead(_, ref place) => { StatementKind::FakeRead(_, ref place) => {
self.create_move_path(place); self.create_move_path(place);
} }
StatementKind::InlineAsm { ref outputs, ref inputs, ref asm } => { StatementKind::InlineAsm(ref asm) => {
for (output, kind) in outputs.iter().zip(&asm.outputs) { for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
if !kind.is_indirect { if !kind.is_indirect {
self.gather_init(output, InitKind::Deep); self.gather_init(output, InitKind::Deep);
} }
} }
for (_, input) in inputs.iter() { for (_, input) in asm.inputs.iter() {
self.gather_operand(input); self.gather_operand(input);
} }
} }