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)
}
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 {
/*!
*
* Yields the value itself. */
match self.mode {
ByValue => self.val,
ByRef => Load(bcx, self.val)
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
C_nil()
} 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
@ -405,25 +426,52 @@ impl Datum {
match self.mode {
ByRef => self.val,
ByValue => {
let slot = alloc_ty(bcx, self.ty);
Store(bcx, self.val, slot);
slot
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
C_null(T_ptr(type_of::type_of(bcx.ccx(), self.ty)))
} 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 {
/*!
*
* Yields something that is by value if the type is immediate
* and by ref otherwise. */
* Yields an llvalue with the `appropriate_mode()`. */
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
self.to_value_llval(bcx)
} else if ty::type_is_immediate(self.ty) {
self.to_value_llval(bcx)
} else {
self.to_ref_llval(bcx)
match self.appropriate_mode() {
ByValue => self.to_value_llval(bcx),
ByRef => 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 {
let scratch = scratch_datum(bcx, ty, false);
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);
return DatumBlock {bcx: bcx, datum: scratch};
}