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:
parent
fe9f0556d2
commit
ee4ba4490d
2 changed files with 75 additions and 15 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue