rustc_trans: don't emit ZST allocas that are only assigned to.
This commit is contained in:
parent
910c4816fd
commit
cb3c4d022a
@ -19,7 +19,6 @@ use rustc::mir::visit::{Visitor, LvalueContext};
|
||||
use rustc::mir::traversal;
|
||||
use common;
|
||||
use super::MirContext;
|
||||
use super::rvalue;
|
||||
|
||||
pub fn lvalue_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
|
||||
let mir = mircx.mir;
|
||||
@ -93,7 +92,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||
|
||||
if let mir::Lvalue::Local(index) = *lvalue {
|
||||
self.mark_assigned(index);
|
||||
if !rvalue::rvalue_creates_operand(rvalue) {
|
||||
if !self.cx.rvalue_creates_operand(rvalue) {
|
||||
self.mark_as_lvalue(index);
|
||||
}
|
||||
} else {
|
||||
|
@ -11,17 +11,16 @@
|
||||
use libc::c_uint;
|
||||
use llvm::{self, ValueRef, BasicBlockRef};
|
||||
use llvm::debuginfo::DIScope;
|
||||
use rustc::ty;
|
||||
use rustc::ty::{self, Ty, TypeFoldable};
|
||||
use rustc::ty::layout::{self, LayoutTyper};
|
||||
use rustc::mir::{self, Mir};
|
||||
use rustc::mir::tcx::LvalueTy;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::infer::TransNormalize;
|
||||
use rustc::ty::TypeFoldable;
|
||||
use session::config::FullDebugInfo;
|
||||
use base;
|
||||
use builder::Builder;
|
||||
use common::{self, CrateContext, C_null, Funclet};
|
||||
use common::{self, CrateContext, Funclet};
|
||||
use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
|
||||
use monomorphize::{self, Instance};
|
||||
use abi::FnType;
|
||||
@ -171,23 +170,12 @@ enum LocalRef<'tcx> {
|
||||
|
||||
impl<'tcx> LocalRef<'tcx> {
|
||||
fn new_operand<'a>(ccx: &CrateContext<'a, 'tcx>,
|
||||
ty: ty::Ty<'tcx>) -> LocalRef<'tcx> {
|
||||
ty: Ty<'tcx>) -> LocalRef<'tcx> {
|
||||
if common::type_is_zero_size(ccx, ty) {
|
||||
// Zero-size temporaries aren't always initialized, which
|
||||
// doesn't matter because they don't contain data, but
|
||||
// we need something in the operand.
|
||||
let llty = type_of::type_of(ccx, ty);
|
||||
let val = if common::type_is_imm_pair(ccx, ty) {
|
||||
let fields = llty.field_types();
|
||||
OperandValue::Pair(C_null(fields[0]), C_null(fields[1]))
|
||||
} else {
|
||||
OperandValue::Immediate(C_null(llty))
|
||||
};
|
||||
let op = OperandRef {
|
||||
val: val,
|
||||
ty: ty
|
||||
};
|
||||
LocalRef::Operand(Some(op))
|
||||
LocalRef::Operand(Some(OperandRef::new_zst(ccx, ty)))
|
||||
} else {
|
||||
LocalRef::Operand(None)
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use rustc::mir::tcx::LvalueTy;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
||||
use base;
|
||||
use common;
|
||||
use common::{self, CrateContext, C_null};
|
||||
use builder::Builder;
|
||||
use value::Value;
|
||||
use type_of;
|
||||
@ -79,6 +79,22 @@ impl<'tcx> fmt::Debug for OperandRef<'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> OperandRef<'tcx> {
|
||||
pub fn new_zst(ccx: &CrateContext<'a, 'tcx>,
|
||||
ty: Ty<'tcx>) -> OperandRef<'tcx> {
|
||||
assert!(common::type_is_zero_size(ccx, ty));
|
||||
let llty = type_of::type_of(ccx, ty);
|
||||
let val = if common::type_is_imm_pair(ccx, ty) {
|
||||
let fields = llty.field_types();
|
||||
OperandValue::Pair(C_null(fields[0]), C_null(fields[1]))
|
||||
} else {
|
||||
OperandValue::Immediate(C_null(llty))
|
||||
};
|
||||
OperandRef {
|
||||
val: val,
|
||||
ty: ty
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts that this operand refers to a scalar and returns
|
||||
/// a reference to its value.
|
||||
pub fn immediate(self) -> ValueRef {
|
||||
|
@ -158,7 +158,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
_ => {
|
||||
assert!(rvalue_creates_operand(rvalue));
|
||||
assert!(self.rvalue_creates_operand(rvalue));
|
||||
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
|
||||
self.store_operand(&bcx, dest.llval, dest.alignment.to_align(), temp);
|
||||
bcx
|
||||
@ -171,7 +171,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
rvalue: &mir::Rvalue<'tcx>)
|
||||
-> (Builder<'a, 'tcx>, OperandRef<'tcx>)
|
||||
{
|
||||
assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
|
||||
assert!(self.rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
|
||||
|
||||
match *rvalue {
|
||||
mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
|
||||
@ -466,8 +466,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
}
|
||||
mir::Rvalue::Repeat(..) |
|
||||
mir::Rvalue::Aggregate(..) => {
|
||||
bug!("cannot generate operand from rvalue {:?}", rvalue);
|
||||
|
||||
// According to `rvalue_creates_operand`, only ZST
|
||||
// aggregate rvalues are allowed to be operands.
|
||||
let ty = rvalue.ty(self.mir, self.ccx.tcx());
|
||||
(bcx, OperandRef::new_zst(self.ccx, self.monomorphize(&ty)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -650,26 +652,29 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
|
||||
OperandValue::Pair(val, of)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool {
|
||||
match *rvalue {
|
||||
mir::Rvalue::Ref(..) |
|
||||
mir::Rvalue::Len(..) |
|
||||
mir::Rvalue::Cast(..) | // (*)
|
||||
mir::Rvalue::BinaryOp(..) |
|
||||
mir::Rvalue::CheckedBinaryOp(..) |
|
||||
mir::Rvalue::UnaryOp(..) |
|
||||
mir::Rvalue::Discriminant(..) |
|
||||
mir::Rvalue::Box(..) |
|
||||
mir::Rvalue::Use(..) => // (*)
|
||||
true,
|
||||
mir::Rvalue::Repeat(..) |
|
||||
mir::Rvalue::Aggregate(..) =>
|
||||
false,
|
||||
pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>) -> bool {
|
||||
match *rvalue {
|
||||
mir::Rvalue::Ref(..) |
|
||||
mir::Rvalue::Len(..) |
|
||||
mir::Rvalue::Cast(..) | // (*)
|
||||
mir::Rvalue::BinaryOp(..) |
|
||||
mir::Rvalue::CheckedBinaryOp(..) |
|
||||
mir::Rvalue::UnaryOp(..) |
|
||||
mir::Rvalue::Discriminant(..) |
|
||||
mir::Rvalue::Box(..) |
|
||||
mir::Rvalue::Use(..) => // (*)
|
||||
true,
|
||||
mir::Rvalue::Repeat(..) |
|
||||
mir::Rvalue::Aggregate(..) => {
|
||||
let ty = rvalue.ty(self.mir, self.ccx.tcx());
|
||||
let ty = self.monomorphize(&ty);
|
||||
common::type_is_zero_size(self.ccx, ty)
|
||||
}
|
||||
}
|
||||
|
||||
// (*) this is only true if the type is suitable
|
||||
}
|
||||
|
||||
// (*) this is only true if the type is suitable
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user