Skip to content

Commit 0ffc4a4

Browse files
authored
Merge pull request #1580 from herbie-fp/spec-split
Parse spec directly
2 parents 65090f0 + 021ae4a commit 0ffc4a4

7 files changed

Lines changed: 103 additions & 37 deletions

File tree

src/api/run.rkt

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"../reports/pages.rkt"
77
"../reports/timeline.rkt"
88
"../syntax/read.rkt"
9+
"../syntax/sugar.rkt"
910
"../syntax/platform.rkt"
1011
"../syntax/types.rkt"
1112
"../syntax/load-platform.rkt"
@@ -17,13 +18,41 @@
1718
"sandbox.rkt"
1819
"server.rkt")
1920

20-
(provide make-report)
21+
(provide make-report
22+
rerun-report)
23+
24+
(define (extract-test row)
25+
(define vars (table-row-vars row))
26+
(define repr (get-representation (table-row-precision row)))
27+
(define var-reprs (map (curryr cons repr) vars))
28+
(define ctx (context vars repr (map (const repr) vars)))
29+
(test (table-row-name row)
30+
(table-row-identifier row)
31+
(table-row-vars row)
32+
(fpcore->prog (table-row-input row) ctx)
33+
(fpcore->prog (table-row-output row) ctx)
34+
(table-row-target-prog row)
35+
(fpcore->spec (table-row-spec row))
36+
(fpcore->spec (table-row-pre row))
37+
(representation-name repr)
38+
(for/list ([(k v) (in-dict var-reprs)])
39+
(cons k (representation-name v)))))
2140

2241
(define (make-report bench-dirs #:dir dir #:threads threads)
2342
(activate-platform! (*platform-name*))
2443
(define tests (sort (append-map load-tests bench-dirs) string-ci<? #:key test-name))
2544
(run-tests tests #:dir dir #:threads threads))
2645

46+
(define (rerun-report json-file #:dir dir #:threads threads)
47+
(define data (call-with-input-file json-file read-datafile))
48+
(define tests (map extract-test (report-info-tests data)))
49+
(activate-platform! (*platform-name*))
50+
(*flags* (report-info-flags data))
51+
(set-seed! (report-info-seed data))
52+
(*num-points* (report-info-points data))
53+
(*num-iterations* (report-info-iterations data))
54+
(run-tests tests #:dir dir #:threads threads))
55+
2756
(define (read-json-files info dir name)
2857
(filter identity
2958
(for/list ([res (report-info-tests info)])

src/api/sandbox.rkt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@
6565
(error 'get-alternatives "cannnot run without a pcontext"))
6666

6767
(define-values (train-pcontext test-pcontext) (partition-pcontext joint-pcontext))
68-
(define alternatives (run-improve! (test-input test) (test-spec test) (*context*) train-pcontext))
68+
(define initial-expr
69+
(if (equal? (prog->spec (test-input test)) (test-spec test))
70+
(test-input test)
71+
(approx (test-spec test) (test-input test))))
72+
(define alternatives (run-improve! initial-expr (test-spec test) (*context*) train-pcontext))
6973

7074
;; compute error/cost for input expression
7175
(define start-expr (test-input test))
@@ -134,8 +138,8 @@
134138

135139
(define (get-sample test)
136140
(random) ;; Tick the random number generator, for backwards compatibility
137-
(define specification (prog->spec (or (test-spec test) (test-input test))))
138-
(define precondition (prog->spec (test-pre test)))
141+
(define specification (test-spec test))
142+
(define precondition (test-pre test))
139143
(define-values (batch brfs) (progs->batch (list specification)))
140144
(define sample
141145
(parameterize ([*num-points* (+ (*num-points*) (*reeval-pts*))])

src/core/preprocess.rkt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,7 @@
5757
(cons `(sort ,a ,b) (replace-vars `((,a . ,b) (,b . ,a)) spec))))
5858

5959
;; See https://pavpanchekha.com/blog/symmetric-expressions.html
60-
(define (find-preprocessing expr ctx)
61-
(define spec (prog->spec expr))
62-
60+
(define (find-preprocessing spec ctx)
6361
;; identities
6462
(define identities
6563
(append (make-even-identities spec ctx)

src/syntax/platform.rkt

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
prog->spec
3838
batch-to-spec!
3939
get-fpcore-impl
40+
impl->fpcore
4041
reset-fpcore-op-cache!
4142
(struct-out $platform)
4243
;; Platform API
@@ -196,11 +197,16 @@
196197
(apply cost-proc (map loop args itypes))]))))
197198

198199
;; Extracts the `fpcore` field of an operator implementation
199-
;; as a property dictionary and expression.
200+
;; as a property dictionary and operation.
200201
(define (impl->fpcore impl)
201-
(match (impl-info impl 'fpcore)
202-
[(list '! props ... body) (values (props->dict props) body)]
203-
[body (values '() body)]))
202+
(define-values (props body)
203+
(match (impl-info impl 'fpcore)
204+
[(list '! props ... body) (values (props->dict props) body)]
205+
[body (values '() body)]))
206+
(values props
207+
(if (symbol? body)
208+
(list body)
209+
body)))
204210

205211
(define/reset op-hash #f)
206212

@@ -215,12 +221,8 @@
215221
(define h (make-hash))
216222
(for ([impl (in-list (platform-impls (*active-platform*)))])
217223
(define-values (_ expr) (impl->fpcore impl))
218-
(define expr*
219-
(if (symbol? expr)
220-
(list expr)
221-
expr))
222-
(when (list? expr*)
223-
(hash-update! h (car expr*) (curry cons impl) '())))
224+
(when (list? expr)
225+
(hash-update! h (car expr) (curry cons impl) '())))
224226
(op-hash h))
225227

226228
; gather all implementations that have the same spec, input representations,
@@ -230,12 +232,8 @@
230232
(for ([impl (in-list (hash-ref (op-hash) op '()))]
231233
#:when (equal? ireprs (impl-info impl 'itype)))
232234
(define-values (prop-dict* expr) (impl->fpcore impl))
233-
(define expr*
234-
(if (symbol? expr)
235-
(list expr)
236-
expr)) ; Handle named constants
237235
(define pattern (cons op (map (lambda (_) (gensym)) ireprs)))
238-
(when (and (subset? prop-dict* prop-dict) (pattern-match pattern expr*))
236+
(when (and (subset? prop-dict* prop-dict) (pattern-match pattern expr))
239237
(sow impl)))))
240238
; check that we have any matching impls
241239
(cond

src/syntax/read.rkt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@
173173

174174
;; inline and desugar
175175
(define body* (fpcore->prog body ctx))
176-
(define pre* (fpcore->prog (dict-ref prop-dict ':pre 'TRUE) ctx))
176+
(define pre* (fpcore->spec (dict-ref prop-dict ':pre 'TRUE)))
177177

178178
(define targets
179179
(for/list ([(key val) (in-dict prop-dict)]
@@ -188,11 +188,13 @@
188188
(fpcore->prog val ctx)
189189
(cons val #t))])))
190190

191-
(define spec (fpcore->prog (dict-ref prop-dict ':spec body) ctx))
191+
(define spec-src (dict-ref prop-dict ':spec body))
192+
(define spec (fpcore->spec spec-src))
192193

193194
;; Named fpcores become platform operators
194195
(when (and func-name (*register-named-fpcore-operators?*))
195-
(register-fpcore-operator! func-name (struct-copy context ctx [repr output-repr]) body* spec))
196+
(define spec* (fpcore->prog spec-src ctx))
197+
(register-fpcore-operator! func-name (struct-copy context ctx [repr output-repr]) body* spec*))
196198
(check-unused-variables var-names body* pre*)
197199
(check-weird-variables var-names)
198200

src/syntax/sugar.rkt

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@
6464
"syntax.rkt"
6565
"types.rkt")
6666

67-
(provide fpcore->prog
67+
(provide fpcore->spec
68+
fpcore->prog
6869
prog->fpcore)
6970

7071
;; Local copies to avoid depending on core/programs.rkt.
@@ -85,6 +86,18 @@
8586
[(approx impl spec) (approx (loop impl) (loop spec))]
8687
[(list op args ...) (cons op (map loop args))])))
8788

89+
(define (fpcore-extension-spec expr)
90+
(define specs
91+
(remove-duplicates (filter identity
92+
(for/list ([impl (in-list (platform-impls (*active-platform*)))])
93+
(define-values (_ body) (impl->fpcore impl))
94+
(define subst (pattern-match (expand-expr body) expr))
95+
(and subst (pattern-substitute (impl-info impl 'spec) subst))))))
96+
(match specs
97+
['() #f]
98+
[(list spec) spec]
99+
[_ (error 'fpcore->spec "ambiguous platform specs for `~a`: ~a" expr specs)]))
100+
88101
;; Expression pre-processing for normalizing expressions.
89102
;; Used for conversion from FPCore to other IRs.
90103
(define (expand-expr expr)
@@ -146,12 +159,34 @@
146159
; applications
147160
[`(,op ,args ...) `(,op ,@(map (curryr loop env) args))]
148161
; constants
149-
[(? operator-exists? op) (list expr)]
162+
[(? operator-exists? op) (list op)]
150163
; variables
151164
[(? symbol?) (dict-ref env expr expr)]
152165
; other
153166
[_ expr])))
154167

168+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
169+
;; FPCore -> LSpec
170+
171+
(define (fpcore->spec prog)
172+
(let loop ([expr (expand-expr prog)])
173+
(match expr
174+
[(? number?)
175+
(match expr
176+
[(or +inf.0 -inf.0 +nan.0) expr]
177+
[(? exact?) expr]
178+
[_ (inexact->exact expr)])]
179+
[(? symbol?) expr]
180+
[(list '! _ ... body) (loop body)]
181+
[(list 'cast arg) (loop arg)]
182+
[(list op args ...)
183+
(define args* (map loop args))
184+
(define expr* `(,op ,@args*))
185+
(match (fpcore-extension-spec expr*)
186+
[#f expr*]
187+
[(== expr*) expr*]
188+
[spec (loop spec)])])))
189+
155190
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
156191
;; FPCore -> LImpl
157192

@@ -169,11 +204,8 @@
169204
(define ireprs (map (lambda (arg) (repr-of arg ctx)) args))
170205
(define impl (assert-fpcore-impl op prop-dict ireprs))
171206
(define vars (impl-info impl 'vars))
172-
(define pattern
173-
(match (impl-info impl 'fpcore)
174-
[(list '! _ ... body) body]
175-
[body body]))
176-
(define subst (pattern-match pattern (cons op args)))
207+
(define-values (_ body) (impl->fpcore impl))
208+
(define subst (pattern-match body (cons op args)))
177209
(pattern-substitute (cons impl vars) subst))
178210

179211
;; Translates from FPCore to an LImpl.
@@ -209,11 +241,8 @@
209241
(define idx-repr (repr-of idx* ctx))
210242
(define impl (assert-fpcore-impl 'ref prop-dict (list arr-repr idx-repr)))
211243
(define vars (impl-info impl 'vars))
212-
(define pattern
213-
(match (impl-info impl 'fpcore)
214-
[(list '! _ ... body) body]
215-
[body body]))
216-
(define subst (pattern-match pattern (list 'ref arr* idx*)))
244+
(define-values (_ body) (impl->fpcore impl))
245+
(define subst (pattern-match body (list 'ref arr* idx*)))
217246
(pattern-substitute (cons impl vars) subst)]
218247
[(list op args ...)
219248
(define args* (map (lambda (arg) (loop arg prop-dict)) args))

src/syntax/test-syntax.rkt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
(require "syntax.rkt"
44
"platform.rkt"
5+
"sugar.rkt"
56
"types.rkt")
67

78
(module+ test
@@ -24,4 +25,9 @@
2425
'+.f64)
2526
(check-equal? (get-impl 'sin '((:precision . binary64)) (list f64)) 'sin.f64)
2627

28+
; fpcore->spec
29+
(check-equal? (fpcore->spec '(log1p x)) '(log (+ 1 x)))
30+
(check-equal? (fpcore->spec '(hypot x y)) '(sqrt (+ (* x x) (* y y))))
31+
(check-equal? (fpcore->spec '(fma x y z)) '(+ (* x y) z))
32+
2733
(void))

0 commit comments

Comments
 (0)