Unbox ^double record field reads (#231)
A record field tagged ^double now reads back as a flonum and feeds the numeric pass, so hintless arithmetic over those fields lowers to fl-ops — the leaf-numeric analog of the ^Vec3 nested-field hints. Combined with the whole-program :double param inference, a vec3-dot over a ^double-fielded record unboxes end to end with no per-fn hints. records.ss: a ^double field tag passes through resolution, and the ctor (and a mutable-field set!) coerce a ^double field to a flonum — JVM primitive-field parity (jolt returned an exact 1, not 1.0, before), and what makes reading the field back as :double sound for an fl-op. types.clj: field-type-from-tag maps "double" -> :double, and a keyword/get lookup whose result is :double annotates the node :num-read :double. numeric.clj reads that annotation and classifies the field read as a :double operand, so the enclosing arithmetic specializes — the read itself keeps its jrec-field-at/jolt-get emit. run-fieldnum.ss gate: ctor coercion (int field -> flonum), field-field arithmetic emitting fl*/fl+, and an untagged field staying generic. make test / shakesmoke green, selfhost holds, 0 new divergences. Co-authored-by: Yogthos <yogthos@gmail.com>
This commit is contained in:
parent
8ae45057d6
commit
4671e1b67e
6 changed files with 292 additions and 180 deletions
|
|
@ -156,6 +156,10 @@
|
|||
node1 (assoc node :args argnodes)
|
||||
n (count ars)]
|
||||
(cond
|
||||
;; a field read the structural inference proved is a flonum (a ^double record
|
||||
;; field) is a :double operand — so (* (:x v) (:x v)) unboxes. The read itself
|
||||
;; isn't lowered here; it keeps its keyword/jrec-field-at emit.
|
||||
(= :double (get node :num-read)) [:double node1]
|
||||
;; a call to a var with a declared numeric return (^double/^long) yields that
|
||||
;; kind, so an accumulator over the result types. The call itself isn't an
|
||||
;; arithmetic op to lower — its body already coerces the return.
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
(cond
|
||||
(or (nil? tag) (<= depth 0)) :any
|
||||
(= tag "num") :num
|
||||
(= tag "double") :double ; a ^double field reads back as a flonum
|
||||
:else (let [e (get shapes tag)]
|
||||
(if e (record-type-from-entry e depth shapes) :any))))
|
||||
(defn- record-type-from-entry [rs depth shapes]
|
||||
|
|
@ -224,9 +225,13 @@
|
|||
mt (ty mr)
|
||||
msub (if (struct-safe? mt) (mark-struct (nd mr) mt) (nd mr))
|
||||
ft (field-type mt (get fnode :val))
|
||||
dr (when (= n 2) (infer (nth args 1) tenv env))]
|
||||
[(if dr (join ft (ty dr)) ft)
|
||||
(assoc node :args (if dr [msub (nd dr)] [msub]))]))
|
||||
dr (when (= n 2) (infer (nth args 1) tenv env))
|
||||
rt (if dr (join ft (ty dr)) ft)
|
||||
node' (assoc node :args (if dr [msub (nd dr)] [msub]))]
|
||||
;; a flonum field read is a :double operand for the numeric pass (fl-ops); the
|
||||
;; lookup itself still emits as a keyword/jrec-field-at read, this only feeds
|
||||
;; its kind up so (* (:x v) (:x v)) over a ^double-fielded record unboxes.
|
||||
[rt (if (= rt :double) (assoc node' :num-read :double) node')]))
|
||||
|
||||
(defn- infer-get-lookup
|
||||
"(get m :k [default]): the keyword-lookup result type, when the key is a constant
|
||||
|
|
@ -237,9 +242,10 @@
|
|||
msub (if (struct-safe? mt) (mark-struct (nd mr) mt) (nd mr))
|
||||
kr (infer (nth args 1) tenv env)
|
||||
ft (field-type mt (get (nth args 1) :val))
|
||||
dr (when (= n 3) (infer (nth args 2) tenv env))]
|
||||
[(if dr (join ft (ty dr)) ft)
|
||||
(assoc node :args (if dr [msub (nd kr) (nd dr)] [msub (nd kr)]))]))
|
||||
dr (when (= n 3) (infer (nth args 2) tenv env))
|
||||
rt (if dr (join ft (ty dr)) ft)
|
||||
node' (assoc node :args (if dr [msub (nd kr) (nd dr)] [msub (nd kr)]))]
|
||||
[rt (if (= rt :double) (assoc node' :num-read :double) node')]))
|
||||
|
||||
(defn- infer-reduce-hof
|
||||
"reduce over a typed vector with a fn-literal: seed the closure's accumulator
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue