about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-09-06 15:21:42 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-09-06 15:23:03 -0700
commitee4ba4490d1f49c8aef12a5194a4e9b50dfc87fa (patch)
treee2a152ae8565824181eba9e4c86911cd4d968fe5 /src/rustc
parentfe9f0556d28e99417cef022c7486fe01440906f0 (diff)
downloadrust-ee4ba4490d1f49c8aef12a5194a4e9b50dfc87fa.tar.gz
rust-ee4ba4490d1f49c8aef12a5194a4e9b50dfc87fa.zip
Issue #3402: Load immediate rvalues right away
Should lead to smaller stack frames, hopefully reducing
the perf hits we saw
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/trans/datum.rs74
-rw-r--r--src/rustc/middle/trans/expr.rs12
2 files changed, 73 insertions, 13 deletions
diff --git a/src/rustc/middle/trans/datum.rs b/src/rustc/middle/trans/datum.rs
index 4f3591d99ca..d6338eb8565 100644
--- a/src/rustc/middle/trans/datum.rs
+++ b/src/rustc/middle/trans/datum.rs
@@ -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 to_appropriate_llval(bcx: block) -> ValueRef {
+    fn appropriate_mode() -> DatumMode {
         /*!
          *
-         * Yields something that is by value if the type is immediate
-         * and by ref otherwise. */
+         * 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) {
-            self.to_value_llval(bcx)
+            ByValue
         } else if ty::type_is_immediate(self.ty) {
-            self.to_value_llval(bcx)
+            ByValue
         } else {
-            self.to_ref_llval(bcx)
+            ByRef
+        }
+    }
+
+    fn to_appropriate_llval(bcx: block) -> ValueRef {
+        /*!
+         *
+         * Yields an llvalue with the `appropriate_mode()`. */
+
+        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)
         }
     }
 
diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs
index 8b2acf1c0b5..1e9c36b1e7e 100644
--- a/src/rustc/middle/trans/expr.rs
+++ b/src/rustc/middle/trans/expr.rs
@@ -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};
             }