Chez Phase 1 close-out: truthy? elision + end-to-end compute bench (jolt-nkcb)
Elide the redundant jolt-truthy? wrapper on an :if test that provably yields a Scheme boolean (a native comparison/not, or a boolean const). Sound because jolt-truthy? of #t/#f is identity. The hot fib/mandelbrot tests are all comparisons, so this is a direct ceiling lever: fib(30) end-to-end 24.0 -> 14.4 ms. Add bench-pipeline.janet (JOLT_CHEZ_BENCH=1, opt-in) timing fib(30) + mandelbrot(200) through the real pipeline vs the spike ceiling. Mandelbrot 200 runs at 87 ms, at/below the 98 ms generic-flonum ceiling - the substrate ceiling is reached end-to-end. fib sits at 2x its hand-flonum ceiling; the residual is jolt's all-double number model (typed fl*/fx* emission is Phase 4). Compile-only is total for the compute subset (every form emits; Chez has no interpreter fallback). Full parity unchanged at 1534/2494, 0 new divergences.
This commit is contained in:
parent
af680ed106
commit
e98afcad13
5 changed files with 181 additions and 4 deletions
|
|
@ -382,6 +382,27 @@
|
|||
(string "(jolt-invoke " (emit fnode) " " (string/join args " ") ")")
|
||||
(string "(" (emit fnode) " " (string/join args " ") ")")))
|
||||
|
||||
# Native-op Scheme procedures that return a genuine Scheme boolean (#t/#f), so an
|
||||
# :if test built from them needs no jolt-truthy? wrapper (jolt-nkcb). Comparisons
|
||||
# and `not` are #t/#f; the numeric/collection predicates bottom out in fx=?/>/etc.
|
||||
(def- bool-returning-ops
|
||||
{"<" true "<=" true ">" true ">=" true "jolt=" true "jolt-not" true
|
||||
"jolt-even?" true "jolt-odd?" true "jolt-pos?" true "jolt-neg?" true
|
||||
"jolt-zero?" true "jolt-empty?" true "jolt-contains?" true})
|
||||
|
||||
# Does this IR node emit to an expression that yields a Scheme boolean? Used to
|
||||
# drop the redundant jolt-truthy? on an :if test — sound because jolt-truthy? of
|
||||
# #t/#f is the identity. Conservative: only a boolean const or an :invoke that
|
||||
# lowers to a bool-returning native op (any other shape keeps the wrapper).
|
||||
(defn- returns-scheme-bool? [node]
|
||||
(def node (nn node))
|
||||
(cond
|
||||
(and (= :const (get node :op)) (boolean? (get node :val))) true
|
||||
(= :invoke (get node :op))
|
||||
(let [nop (native-op (nn (get node :fn)) (length (vv (get node :args))))]
|
||||
(truthy? (and nop (get bool-returning-ops nop))))
|
||||
false))
|
||||
|
||||
(set emit (fn emit [node]
|
||||
(def node (nn node))
|
||||
(case (get node :op)
|
||||
|
|
@ -400,8 +421,10 @@
|
|||
(string "(var-deref " (chez-str-lit (get node :ns)) " "
|
||||
(chez-str-lit (get node :name)) ")")))
|
||||
:host (errorf "emit: unsupported host ref `%s` (no host interop on Chez yet)" (get node :name))
|
||||
:if (string "(if (jolt-truthy? " (emit (get node :test)) ") "
|
||||
(emit (get node :then)) " " (emit (get node :else)) ")")
|
||||
:if (let [test (get node :test)
|
||||
t (if (returns-scheme-bool? test) (emit test)
|
||||
(string "(jolt-truthy? " (emit test) ")"))]
|
||||
(string "(if " t " " (emit (get node :then)) " " (emit (get node :else)) ")"))
|
||||
:do (string "(begin "
|
||||
(string/join (map emit (vv (get node :statements))) " ")
|
||||
(if (empty? (vv (get node :statements))) "" " ")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue