Issue #3402: Load immediate rvalues right away

Should lead to smaller stack frames, hopefully reducing
the perf hits we saw
This commit is contained in:
Niko Matsakis 2012-09-06 15:21:42 -07:00
parent fe9f0556d2
commit ee4ba4490d
2 changed files with 75 additions and 15 deletions

View file

@ -373,18 +373,39 @@ impl Datum {
self.source) self.source)
} }
fn to_value_datum(bcx: block) -> Datum {
/*!
*
* Yields a by-ref form of this datum. This may involve
* creation of a temporary stack slot. The value returned by
* this function is not separately rooted from this datum, so
* it will not live longer than the current datum. */
match self.mode {
ByValue => self,
ByRef => {
Datum {val: self.to_value_llval(bcx), mode: ByValue,
ty: self.ty, source: FromRvalue}
}
}
}
fn to_value_llval(bcx: block) -> ValueRef { fn to_value_llval(bcx: block) -> ValueRef {
/*! /*!
* *
* Yields the value itself. */ * Yields the value itself. */
match self.mode { if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
ByValue => self.val, C_nil()
ByRef => Load(bcx, self.val) } else {
match self.mode {
ByValue => self.val,
ByRef => Load(bcx, self.val)
}
} }
} }
fn to_ref(bcx: block) -> Datum { fn to_ref_datum(bcx: block) -> Datum {
/*! /*!
* *
* Yields a by-ref form of this datum. This may involve * Yields a by-ref form of this datum. This may involve
@ -405,25 +426,52 @@ impl Datum {
match self.mode { match self.mode {
ByRef => self.val, ByRef => self.val,
ByValue => { ByValue => {
let slot = alloc_ty(bcx, self.ty); if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
Store(bcx, self.val, slot); C_null(T_ptr(type_of::type_of(bcx.ccx(), self.ty)))
slot } else {
let slot = alloc_ty(bcx, self.ty);
Store(bcx, self.val, slot);
slot
}
} }
} }
} }
fn appropriate_mode() -> DatumMode {
/*!
*
* Indicates the "appropriate" mode for this value,
* which is either by ref or by value, depending
* on whether type is iimmediate or what. */
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
ByValue
} else if ty::type_is_immediate(self.ty) {
ByValue
} else {
ByRef
}
}
fn to_appropriate_llval(bcx: block) -> ValueRef { fn to_appropriate_llval(bcx: block) -> ValueRef {
/*! /*!
* *
* Yields something that is by value if the type is immediate * Yields an llvalue with the `appropriate_mode()`. */
* and by ref otherwise. */
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) { match self.appropriate_mode() {
self.to_value_llval(bcx) ByValue => self.to_value_llval(bcx),
} else if ty::type_is_immediate(self.ty) { ByRef => self.to_ref_llval(bcx)
self.to_value_llval(bcx) }
} else { }
self.to_ref_llval(bcx)
fn to_appropriate_datum(bcx: block) -> Datum {
/*!
*
* Yields a datum with the `appropriate_mode()`. */
match self.appropriate_mode() {
ByValue => self.to_value_datum(bcx),
ByRef => self.to_ref_datum(bcx)
} }
} }

View file

@ -206,6 +206,18 @@ fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
} else { } else {
let scratch = scratch_datum(bcx, ty, false); let scratch = scratch_datum(bcx, ty, false);
bcx = trans_rvalue_dps(bcx, expr, SaveIn(scratch.val)); bcx = trans_rvalue_dps(bcx, expr, SaveIn(scratch.val));
// Note: this is not obviously a good idea. It causes
// immediate values to be loaded immediately after a
// return from a call or other similar expression,
// which in turn leads to alloca's having shorter
// lifetimes and hence larger stack frames. However,
// in turn it can lead to more register pressure.
// Still, in practice it seems to increase
// performance, since we have fewer problems with
// morestack churn.
let scratch = scratch.to_appropriate_datum(bcx);
scratch.add_clean(bcx); scratch.add_clean(bcx);
return DatumBlock {bcx: bcx, datum: scratch}; return DatumBlock {bcx: bcx, datum: scratch};
} }