<p dir="ltr">Thanks Matthew!</p>
<div class="gmail_quote">On Feb 23, 2014 5:01 PM,  <<a href="mailto:mflatt@racket-lang.org">mflatt@racket-lang.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
mflatt has updated `master' from e0a1a40fd4 to 22617b7800.<br>
  <a href="http://git.racket-lang.org/plt/e0a1a40fd4..22617b7800" target="_blank">http://git.racket-lang.org/plt/e0a1a40fd4..22617b7800</a><br>
<br>
=====[ One Commit ]=====================================================<br>
Directory summary:<br>
  42.2% pkgs/racket-pkgs/racket-test/tests/racket/<br>
  57.7% racket/src/racket/src/<br>
<br>
~~~~~~~~~~<br>
<br>
22617b7 Matthew Flatt <<a href="mailto:mflatt@racket-lang.org">mflatt@racket-lang.org</a>> 2014-02-23 14:56<br>
:<br>
| JIT: enable unboxing in branches of `if` and end of `begin`<br>
|<br>
| When both branches of an `if` form can produce unboxed results, then<br>
| allow the unboxed result. Similarly, allow a `begin` form's last<br>
| expression to be unboxed.<br>
:<br>
  M racket/src/racket/src/jitarith.c                  | 18 ++++++++++-<br>
  M racket/src/racket/src/jit.c                       | 19 ++++++++++++<br>
  M racket/src/racket/src/jitstate.c                  |  1 +<br>
  M racket/src/racket/src/optimize.c                  | 14 +++++++++<br>
  M racket/src/racket/src/validate.c                  |  7 ++---<br>
  M .../racket-test/tests/racket/optimize.rktl        | 32 ++++++++++++++++++++<br>
<br>
=====[ Overall Diff ]===================================================<br>
<br>
pkgs/racket-pkgs/racket-test/tests/racket/optimize.rktl<br>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
--- OLD/pkgs/racket-pkgs/racket-test/tests/racket/optimize.rktl<br>
+++ NEW/pkgs/racket-pkgs/racket-test/tests/racket/optimize.rktl<br>
@@ -3244,6 +3244,38 @@<br>
             (phase1-eval)))<br>
 (test #t syntax? (f))<br>
<br>
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<br>
+;; Check unboxing through conditionals<br>
+<br>
+(let ()<br>
+  (define (check pred t1 e1)<br>
+    (define v (* 2.0 (if (eval (pred 7.0))<br>
+                         (eval (t1 7.0))<br>
+                         (eval (e1 7.0)))))<br>
+    (test v (eval `(lambda (arg)<br>
+                     (let ([x (if ,(pred 'arg)<br>
+                                  ,(t1 'arg)<br>
+                                  ,(e1 'arg))])<br>
+                       (fl+ x x))))<br>
+          7.0)<br>
+    (test v (eval `(lambda (arg)<br>
+                     (fl* 2.0 (if ,(pred 'arg)<br>
+                                  ,(t1 'arg)<br>
+                                  ,(e1 'arg)))))<br>
+          7.0))<br>
+  (for ([pred (in-list (list<br>
+                        (lambda (arg) `(negative? ,arg))<br>
+                        (lambda (arg) `(positive? ,arg))<br>
+                        (lambda (arg) `(even? (fl* ,arg ,arg)))))])<br>
+    (for ([t1 (in-list (list<br>
+                        (lambda (arg) `(fl+ ,arg 8.0))<br>
+                        (lambda (arg) `(fl- (fl+ ,arg 8.0) 1.0))))])<br>
+      (for ([e1 (in-list (list (lambda (arg) `(fl* 8.0 ,arg))<br>
+                               (lambda (arg) `(begin<br>
+                                                (display "")<br>
+                                                (fl* 8.0 ,arg)))))])<br>
+        (check pred t1 e1)))))<br>
+<br>
 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<br>
<br>
<br>
<br>
racket/src/racket/src/jit.c<br>
~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
--- OLD/racket/src/racket/src/jit.c<br>
+++ NEW/racket/src/racket/src/jit.c<br>
@@ -1641,6 +1641,8 @@ static int generate_branch(Scheme_Object *obj, mz_jit_state *jitter, int is_tail<br>
   Branch_Info for_this_branch;<br>
   GC_CAN_IGNORE Branch_Info_Addr addrs[NUM_QUICK_INFO_ADDRS];<br>
   GC_CAN_IGNORE jit_insn *ref2;<br>
+  mz_jit_unbox_state ubs;<br>
+  int ubd, save_ubd;<br>
   int pushed_marks;<br>
   int nsrs, nsrs1, g1, g2, amt, need_sync, flostack, flostack_pos;<br>
   int else_is_empty = 0, i, can_chain_branch, chain_true, chain_false, old_self_pos;<br>
@@ -1709,6 +1711,8 @@ static int generate_branch(Scheme_Object *obj, mz_jit_state *jitter, int is_tail<br>
<br>
   mz_rs_sync();<br>
<br>
+  scheme_mz_unbox_save(jitter, &ubs);<br>
+<br>
   if (!scheme_generate_inlined_test(jitter, branch->test, then_short_ok, &for_this_branch, need_sync)) {<br>
     CHECK_LIMIT();<br>
     generate_non_tail_with_branch(branch->test, jitter, 0, 1, 0, &for_this_branch);<br>
@@ -1719,6 +1723,9 @@ static int generate_branch(Scheme_Object *obj, mz_jit_state *jitter, int is_tail<br>
   }<br>
   CHECK_LIMIT();<br>
<br>
+  save_ubd = jitter->unbox_depth;<br>
+  scheme_mz_unbox_restore(jitter, &ubs);<br>
+<br>
   /* True branch */<br>
   scheme_mz_runstack_saved(jitter);<br>
   flostack = scheme_mz_flostack_save(jitter, &flostack_pos);<br>
@@ -1786,6 +1793,10 @@ static int generate_branch(Scheme_Object *obj, mz_jit_state *jitter, int is_tail<br>
   if (old_self_pos != jitter->self_pos)<br>
     scheme_signal_error("internal error: self position moved across branch");<br>
<br>
+  ubd = jitter->unbox_depth;<br>
+  jitter->unbox_depth = save_ubd;<br>
+  scheme_mz_unbox_restore(jitter, &ubs);<br>
+<br>
   /* False branch */<br>
   mz_SET_REG_STATUS_VALID(0);<br>
   scheme_mz_runstack_saved(jitter);<br>
@@ -1843,6 +1854,9 @@ static int generate_branch(Scheme_Object *obj, mz_jit_state *jitter, int is_tail<br>
<br>
   END_JIT_DATA(12);<br>
<br>
+  if (ubd != jitter->unbox_depth)<br>
+    scheme_signal_error("internal error: different unbox depth for branches");<br>
+<br>
   /* Return result */<br>
<br>
   if ((g1 == 2) && (g2 == 2))<br>
@@ -2600,10 +2614,13 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w<br>
     {<br>
       Scheme_Sequence *seq = (Scheme_Sequence *)obj;<br>
       int cnt = seq->count, i;<br>
+      mz_jit_unbox_state ubs;<br>
       START_JIT_DATA();<br>
<br>
       LOG_IT(("begin\n"));<br>
<br>
+      scheme_mz_unbox_save(jitter, &ubs);<br>
+<br>
       for (i = 0; i < cnt - 1; i++) {<br>
        scheme_generate_non_tail(seq->array[i], jitter, 1, 1, 1);<br>
        CHECK_LIMIT();<br>
@@ -2611,6 +2628,8 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w<br>
<br>
       END_JIT_DATA(11);<br>
<br>
+      scheme_mz_unbox_restore(jitter, &ubs);<br>
+<br>
       return scheme_generate(seq->array[cnt - 1], jitter, is_tail, wcm_may_replace,<br>
                              multi_ok, orig_target, for_branch);<br>
     }<br>
<br>
racket/src/racket/src/jitarith.c<br>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
--- OLD/racket/src/racket/src/jitarith.c<br>
+++ NEW/racket/src/racket/src/jitarith.c<br>
@@ -283,7 +283,7 @@ int scheme_can_unbox_inline(Scheme_Object *obj, int fuel, int regs, int unsafely<br>
   }<br>
 }<br>
<br>
-int scheme_can_unbox_directly(Scheme_Object *obj, int extfl)<br>
+int can_unbox_directly(Scheme_Object *obj, int extfl, int bfuel)<br>
 /* Used only when !can_unbox_inline(). Detects safe operations that<br>
    produce flonums when they don't raise an exception, and that the JIT<br>
    supports directly unboxing. */<br>
@@ -348,12 +348,28 @@ int scheme_can_unbox_directly(Scheme_Object *obj, int extfl)<br>
     case scheme_letrec_type:<br>
       obj = ((Scheme_Letrec *)obj)->body;<br>
       break;<br>
+    case scheme_branch_type:<br>
+      if (!bfuel)<br>
+        return 0;<br>
+      bfuel--;<br>
+      if (!can_unbox_directly(((Scheme_Branch_Rec *)obj)->tbranch, extfl, bfuel))<br>
+        return 0;<br>
+      obj = ((Scheme_Branch_Rec *)obj)->fbranch;<br>
+      break;<br>
+    case scheme_sequence_type:<br>
+      obj = ((Scheme_Sequence *)obj)->array[((Scheme_Sequence *)obj)->count - 1];<br>
+      break;<br>
     default:<br>
       return 0;<br>
     }<br>
   }<br>
 }<br>
<br>
+int scheme_can_unbox_directly(Scheme_Object *obj, int extfl)<br>
+{<br>
+  return can_unbox_directly(obj, extfl, 3);<br>
+}<br>
+<br>
 static jit_insn *generate_arith_slow_path(mz_jit_state *jitter, Scheme_Object *rator,<br>
                                          jit_insn **_ref, jit_insn **_ref4,<br>
                                           Branch_Info *for_branch, int branch_short,<br>
<br>
racket/src/racket/src/jitstate.c<br>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
--- OLD/racket/src/racket/src/jitstate.c<br>
+++ NEW/racket/src/racket/src/jitstate.c<br>
@@ -805,6 +805,7 @@ void scheme_mz_unbox_save(mz_jit_state *jitter, mz_jit_unbox_state *r)<br>
   }<br>
<br>
 void scheme_mz_unbox_restore(mz_jit_state *jitter, mz_jit_unbox_state *r)<br>
+/* can be called multipel times for an `r` by generate_branch() */<br>
 {<br>
   jitter->unbox = r->unbox;<br>
 #ifdef MZ_LONG_DOUBLE<br>
<br>
racket/src/racket/src/optimize.c<br>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
--- OLD/racket/src/racket/src/optimize.c<br>
+++ NEW/racket/src/racket/src/optimize.c<br>
@@ -1971,6 +1971,20 @@ static int expr_produces_local_type(Scheme_Object *expr, int fuel)<br>
         return produces_local_type(app->rator, 2);<br>
       }<br>
       break;<br>
+    case scheme_branch_type:<br>
+      {<br>
+        Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)expr;<br>
+        return (expr_produces_local_type(b->tbranch, fuel / 2)<br>
+                && expr_produces_local_type(b->fbranch, fuel / 2));<br>
+      }<br>
+      break;<br>
+    case scheme_sequence_type:<br>
+      {<br>
+        Scheme_Sequence *seq = (Scheme_Sequence *)expr;<br>
+<br>
+        expr = seq->array[seq->count-1];<br>
+        break;<br>
+      }<br>
     case scheme_compiled_let_void_type:<br>
       {<br>
         Scheme_Let_Header *lh = (Scheme_Let_Header *)expr;<br>
<br>
racket/src/racket/src/validate.c<br>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
--- OLD/racket/src/racket/src/validate.c<br>
+++ NEW/racket/src/racket/src/validate.c<br>
@@ -1621,7 +1621,8 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,<br>
       int cnt;<br>
       int i, r;<br>
<br>
-      no_typed(need_local_type, port);<br>
+      if (type != scheme_sequence_type)<br>
+        no_typed(need_local_type, port);<br>
<br>
       cnt = seq->count;<br>
<br>
@@ -1642,8 +1643,6 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,<br>
       Scheme_Branch_Rec *b;<br>
       int vc_pos, vc_ncpos, r;<br>
<br>
-      no_typed(need_local_type, port);<br>
-<br>
       b = (Scheme_Branch_Rec *)expr;<br>
       r = validate_expr(port, b->test, stack, tls, depth, letlimit, delta,<br>
                         num_toplevels, num_stxes, num_lifts, tl_use_map,<br>
@@ -1660,7 +1659,7 @@ static int validate_expr(Mz_CPort *port, Scheme_Object *expr,<br>
       r = validate_expr(port, b->tbranch, stack, tls, depth, letlimit, delta,<br>
                         num_toplevels, num_stxes, num_lifts, tl_use_map,<br>
                         tl_state, tl_timestamp,<br>
-                        NULL, 0, result_ignored, vc, tailpos, 0, procs,<br>
+                        NULL, 0, result_ignored, vc, tailpos, need_local_type, procs,<br>
                         expected_results, NULL);<br>
       result = validate_join_seq(result, r);<br>
<br>
</blockquote></div>