about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-08-02 12:57:27 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-08-02 12:57:27 +0200
commit6c9b90d06a455af08da7ea66977dc4d7d1b4ce1b (patch)
treea1b43fb6e6140ce7384bdaf2a439e6b4d287c4aa /src
parentf8fa574864a5bd54752fc198438f8c53a8ed5ef0 (diff)
downloadrust-6c9b90d06a455af08da7ea66977dc4d7d1b4ce1b.tar.gz
rust-6c9b90d06a455af08da7ea66977dc4d7d1b4ce1b.zip
Be a little more clever about picking columns to match on in trans_alt
This should result in slightly more efficient matching of 'complex'
patterns with multiple discriminants in them.
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/trans_alt.rs38
1 files changed, 34 insertions, 4 deletions
diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs
index 899ba437cb1..755dc860793 100644
--- a/src/comp/middle/trans_alt.rs
+++ b/src/comp/middle/trans_alt.rs
@@ -228,7 +228,37 @@ fn any_box_pat(m: &match, col: uint) -> bool {
 }
 
 type exit_node = {bound: bind_map, from: BasicBlockRef, to: BasicBlockRef};
-type mk_fail = fn() -> BasicBlockRef ;
+type mk_fail = fn() -> BasicBlockRef;
+
+fn pick_col(m: &match) -> uint {
+    let scores = ivec::init_elt_mut(0u, ivec::len(m.(0).pats));
+    for br: match_branch in m {
+        let i = 0u;
+        for p: @ast::pat in br.pats {
+            alt p.node {
+              ast::pat_lit(_) | ast::pat_tag(_, _) { scores.(i) += 1u; }
+              _ {}
+            }
+            i += 1u;
+        }
+    }
+    let max_score = 0u;
+    let best_col = 0u;
+    let i = 0u;
+    for score: uint in scores {
+        // Irrefutable columns always go first, they'd only be duplicated in
+        // the branches.
+        if score == 0u { ret i; }
+        // If no irrefutable ones are found, we pick the one with the biggest
+        // branching factor.
+        if score > max_score {
+            max_score = score;
+            best_col = i;
+        }
+        i += 1u;
+    }
+    ret best_col;
+}
 
 fn compile_submatch(bcx: @block_ctxt, m: &match, vals: ValueRef[],
                     f: &mk_fail, exits: &mutable exit_node[]) {
@@ -239,10 +269,10 @@ fn compile_submatch(bcx: @block_ctxt, m: &match, vals: ValueRef[],
         ret;
     }
 
-    // FIXME maybe be clever about picking a column.
-    let col = 0u;
+    let col = pick_col(m);
     let val = vals.(col);
-    let vals_left = ivec::slice(vals, 1u, ivec::len(vals));
+    let vals_left = ivec::slice(vals, 0u, col) +
+        ivec::slice(vals, col + 1u, ivec::len(vals));
     let ccx = bcx.fcx.lcx.ccx;
     let pat_id = 0;
     for br: match_branch  in m {