type-fold.scm 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. ;;; Abstract constant folding on CPS
  2. ;;; Copyright (C) 2014, 2015, 2017, 2018 Free Software Foundation, Inc.
  3. ;;;
  4. ;;; This library is free software: you can redistribute it and/or modify
  5. ;;; it under the terms of the GNU Lesser General Public License as
  6. ;;; published by the Free Software Foundation, either version 3 of the
  7. ;;; License, or (at your option) any later version.
  8. ;;;
  9. ;;; This library is distributed in the hope that it will be useful, but
  10. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;; Lesser General Public License for more details.
  13. ;;;
  14. ;;; You should have received a copy of the GNU Lesser General Public
  15. ;;; License along with this program. If not, see
  16. ;;; <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;;;
  19. ;;; This pass uses the abstract interpretation provided by type analysis
  20. ;;; to fold constant values and type predicates. It is most profitably
  21. ;;; run after CSE, to take advantage of scalar replacement.
  22. ;;;
  23. ;;; Code:
  24. (define-module (language cps type-fold)
  25. #:use-module (ice-9 match)
  26. #:use-module (language cps)
  27. #:use-module (language cps utils)
  28. #:use-module (language cps renumber)
  29. #:use-module (language cps types)
  30. #:use-module (language cps with-cps)
  31. #:use-module (language cps intmap)
  32. #:use-module (language cps intset)
  33. #:use-module (system base target)
  34. #:export (type-fold))
  35. ;; Branch folders.
  36. (define &scalar-types
  37. (logior &fixnum &bignum &flonum &char &special-immediate))
  38. (define *branch-folders* (make-hash-table))
  39. (define-syntax-rule (define-branch-folder op f)
  40. (hashq-set! *branch-folders* 'op f))
  41. (define-syntax-rule (define-branch-folder-alias to from)
  42. (hashq-set! *branch-folders* 'to (hashq-ref *branch-folders* 'from)))
  43. (define-syntax-rule (define-unary-branch-folder* (op param arg min max)
  44. body ...)
  45. (define-branch-folder op (lambda (param arg min max) body ...)))
  46. (define-syntax-rule (define-unary-branch-folder (op arg min max) body ...)
  47. (define-unary-branch-folder* (op param arg min max) body ...))
  48. (define-syntax-rule (define-binary-branch-folder (op arg0 min0 max0
  49. arg1 min1 max1)
  50. body ...)
  51. (define-branch-folder op (lambda (param arg0 min0 max0 arg1 min1 max1) body ...)))
  52. (define-syntax-rule (define-special-immediate-predicate-folder op imin imax)
  53. (define-unary-branch-folder (op type min max)
  54. (let ((type* (logand type &special-immediate)))
  55. (cond
  56. ((zero? (logand type &special-immediate)) (values #t #f))
  57. ((eqv? type &special-immediate)
  58. (cond
  59. ((or (< imax min) (< max imin)) (values #t #f))
  60. ((<= imin min max imax) (values #t #t))
  61. (else (values #f #f))))
  62. (else (values #f #f))))))
  63. (define-special-immediate-predicate-folder eq-nil? &nil &nil)
  64. (define-special-immediate-predicate-folder eq-eol? &null &null)
  65. (define-special-immediate-predicate-folder eq-false? &false &false)
  66. (define-special-immediate-predicate-folder eq-true? &true &true)
  67. (define-special-immediate-predicate-folder unspecified? &unspecified &unspecified)
  68. (define-special-immediate-predicate-folder undefined? &undefined &undefined)
  69. (define-special-immediate-predicate-folder eof-object? &eof &eof)
  70. (define-special-immediate-predicate-folder null? &null &nil)
  71. (define-special-immediate-predicate-folder false? &nil &false)
  72. (define-special-immediate-predicate-folder nil? &null &false) ;; &nil in middle
  73. (define-syntax-rule (define-unary-type-predicate-folder op &type)
  74. (define-unary-branch-folder (op type min max)
  75. (let ((type* (logand type &type)))
  76. (cond
  77. ((zero? type*) (values #t #f))
  78. ((eqv? type type*) (values #t #t))
  79. (else (values #f #f))))))
  80. (define-unary-branch-folder (heap-object? type min max)
  81. (define &immediate-types (logior &fixnum &char &special-immediate))
  82. (cond
  83. ((zero? (logand type &immediate-types)) (values #t #t))
  84. ((type<=? type &immediate-types) (values #t #f))
  85. (else (values #f #f))))
  86. (define-unary-branch-folder (heap-number? type min max)
  87. (define &types (logior &bignum &flonum &fraction &complex))
  88. (cond
  89. ((zero? (logand type &types)) (values #t #f))
  90. ((type<=? type &types) (values #t #t))
  91. (else (values #f #f))))
  92. ;; All the cases that are in compile-bytecode.
  93. (define-unary-type-predicate-folder fixnum? &fixnum)
  94. (define-unary-type-predicate-folder bignum? &bignum)
  95. (define-unary-type-predicate-folder pair? &pair)
  96. (define-unary-type-predicate-folder symbol? &symbol)
  97. (define-unary-type-predicate-folder variable? &box)
  98. (define-unary-type-predicate-folder mutable-vector? &mutable-vector)
  99. (define-unary-type-predicate-folder immutable-vector? &immutable-vector)
  100. (define-unary-type-predicate-folder struct? &struct)
  101. (define-unary-type-predicate-folder string? &string)
  102. (define-unary-type-predicate-folder number? &number)
  103. (define-unary-type-predicate-folder char? &char)
  104. (define-unary-branch-folder (vector? type min max)
  105. (cond
  106. ((zero? (logand type &vector)) (values #t #f))
  107. ((type<=? type &vector) (values #t #t))
  108. (else (values #f #f))))
  109. (define-binary-branch-folder (eq? type0 min0 max0 type1 min1 max1)
  110. (cond
  111. ((or (zero? (logand type0 type1)) (< max0 min1) (< max1 min0))
  112. (values #t #f))
  113. ((and (eqv? type0 type1)
  114. (eqv? min0 min1 max0 max1)
  115. (zero? (logand type0 (1- type0)))
  116. (not (zero? (logand type0 &scalar-types))))
  117. (values #t #t))
  118. (else
  119. (values #f #f))))
  120. (define-branch-folder-alias heap-numbers-equal? eq?)
  121. (define (compare-exact-ranges min0 max0 min1 max1)
  122. (and (cond ((< max0 min1) '<)
  123. ((> min0 max1) '>)
  124. ((= min0 max0 min1 max1) '=)
  125. ((<= max0 min1) '<=)
  126. ((>= min0 max1) '>=)
  127. (else #f))))
  128. (define-binary-branch-folder (< type0 min0 max0 type1 min1 max1)
  129. (if (type<=? (logior type0 type1) &exact-number)
  130. (case (compare-exact-ranges min0 max0 min1 max1)
  131. ((<) (values #t #t))
  132. ((= >= >) (values #t #f))
  133. (else (values #f #f)))
  134. (values #f #f)))
  135. (define-binary-branch-folder (u64-< type0 min0 max0 type1 min1 max1)
  136. (case (compare-exact-ranges min0 max0 min1 max1)
  137. ((<) (values #t #t))
  138. ((= >= >) (values #t #f))
  139. (else (values #f #f))))
  140. (define-branch-folder-alias s64-< u64-<)
  141. ;; We currently cannot define branch folders for floating point
  142. ;; comparison ops like the commented one below because we can't prove
  143. ;; there are no nans involved.
  144. ;;
  145. ;; (define-branch-folder-alias f64-< <)
  146. (define-binary-branch-folder (<= type0 min0 max0 type1 min1 max1)
  147. (if (type<=? (logior type0 type1) &exact-number)
  148. (case (compare-exact-ranges min0 max0 min1 max1)
  149. ((< <= =) (values #t #t))
  150. ((>) (values #t #f))
  151. (else (values #f #f)))
  152. (values #f #f)))
  153. (define-unary-branch-folder* (u64-imm-= c type min max)
  154. (cond
  155. ((= c min max) (values #t #t))
  156. ((<= min c max) (values #f #f))
  157. (else (values #t #f))))
  158. (define-branch-folder-alias s64-imm-= u64-imm-=)
  159. (define-unary-branch-folder* (u64-imm-< c type min max)
  160. (cond
  161. ((< max c) (values #t #t))
  162. ((>= min c) (values #t #f))
  163. (else (values #f #f))))
  164. (define-branch-folder-alias s64-imm-< u64-imm-<)
  165. (define-unary-branch-folder* (imm-u64-< c type min max)
  166. (cond
  167. ((< c min) (values #t #t))
  168. ((>= c max) (values #t #f))
  169. (else (values #f #f))))
  170. (define-branch-folder-alias imm-s64-< imm-u64-<)
  171. (define-binary-branch-folder (= type0 min0 max0 type1 min1 max1)
  172. (cond
  173. ((not (type<=? (logior type0 type1) &exact-number))
  174. (values #f #f))
  175. ((zero? (logand type0 type1))
  176. ;; If both values are exact but of different types, they are not
  177. ;; equal.
  178. (values #t #f))
  179. (else
  180. (case (compare-exact-ranges min0 max0 min1 max1)
  181. ((=) (values #t #t))
  182. ((< >) (values #t #f))
  183. (else (values #f #f))))))
  184. (define-binary-branch-folder (u64-= type0 min0 max0 type1 min1 max1)
  185. (case (compare-exact-ranges min0 max0 min1 max1)
  186. ((=) (values #t #t))
  187. ((< >) (values #t #f))
  188. (else (values #f #f))))
  189. (define-branch-folder-alias s64-= u64-=)
  190. ;; Convert e.g. rsh to rsh/immediate.
  191. (define *primcall-macro-reducers* (make-hash-table))
  192. (define-syntax-rule (define-primcall-macro-reducer op f)
  193. (hashq-set! *primcall-macro-reducers* 'op f))
  194. (define-syntax-rule (define-unary-primcall-macro-reducer (op cps k src
  195. arg type min max)
  196. body ...)
  197. (define-primcall-macro-reducer op
  198. (lambda (cps k src param arg type min max)
  199. body ...)))
  200. (define-syntax-rule (define-binary-primcall-macro-reducer
  201. (op cps k src
  202. arg0 type0 min0 max0
  203. arg1 type1 min1 max1)
  204. body ...)
  205. (define-primcall-macro-reducer op
  206. (lambda (cps k src param arg0 type0 min0 max0 arg1 type1 min1 max1)
  207. body ...)))
  208. (define-binary-primcall-macro-reducer (mul cps k src
  209. arg0 type0 min0 max0
  210. arg1 type1 min1 max1)
  211. (cond
  212. ((and (type<=? type0 &exact-integer) (= min0 max0))
  213. (with-cps cps
  214. (build-term
  215. ($continue k src ($primcall 'mul/immediate min0 (arg1))))))
  216. ((and (type<=? type1 &exact-integer) (= min1 max1))
  217. (with-cps cps
  218. (build-term
  219. ($continue k src ($primcall 'mul/immediate min1 (arg0))))))
  220. (else
  221. (with-cps cps #f))))
  222. (define-binary-primcall-macro-reducer (lsh cps k src
  223. arg0 type0 min0 max0
  224. arg1 type1 min1 max1)
  225. (cond
  226. ((= min1 max1)
  227. (with-cps cps
  228. (build-term
  229. ($continue k src ($primcall 'lsh/immediate min1 (arg0))))))
  230. (else
  231. (with-cps cps #f))))
  232. (define-binary-primcall-macro-reducer (rsh cps k src
  233. arg0 type0 min0 max0
  234. arg1 type1 min1 max1)
  235. (cond
  236. ((= min1 max1)
  237. (with-cps cps
  238. (build-term
  239. ($continue k src ($primcall 'rsh/immediate min1 (arg0))))))
  240. (else
  241. (with-cps cps #f))))
  242. ;; Strength reduction.
  243. (define *primcall-reducers* (make-hash-table))
  244. (define-syntax-rule (define-primcall-reducer op f)
  245. (hashq-set! *primcall-reducers* 'op f))
  246. (define-syntax-rule (define-unary-primcall-reducer (op cps k src param
  247. arg type min max)
  248. body ...)
  249. (define-primcall-reducer op
  250. (lambda (cps k src param arg type min max)
  251. body ...)))
  252. (define-syntax-rule (define-binary-primcall-reducer (op cps k src param
  253. arg0 type0 min0 max0
  254. arg1 type1 min1 max1)
  255. body ...)
  256. (define-primcall-reducer op
  257. (lambda (cps k src param arg0 type0 min0 max0 arg1 type1 min1 max1)
  258. body ...)))
  259. (define-unary-primcall-reducer (mul/immediate cps k src constant
  260. arg type min max)
  261. (cond
  262. ((not (type<=? type &number))
  263. (with-cps cps #f))
  264. ((eqv? constant -1)
  265. ;; (* arg -1) -> (- 0 arg)
  266. (with-cps cps
  267. ($ (with-cps-constants ((zero 0))
  268. (build-term
  269. ($continue k src ($primcall 'sub #f (zero arg))))))))
  270. ((and (eqv? constant 0) (type<=? type &exact-number))
  271. ;; (* arg 0) -> 0 if arg is exact
  272. (with-cps cps
  273. (build-term ($continue k src ($const 0)))))
  274. ((eqv? constant 1)
  275. ;; (* arg 1) -> arg
  276. (with-cps cps
  277. (build-term ($continue k src ($values (arg))))))
  278. ((eqv? constant 2)
  279. ;; (* arg 2) -> (+ arg arg)
  280. (with-cps cps
  281. (build-term ($continue k src ($primcall 'add #f (arg arg))))))
  282. ((and (type<=? type &exact-integer)
  283. (positive? constant)
  284. (zero? (logand constant (1- constant))))
  285. ;; (* arg power-of-2) -> (lsh arg (log2 power-of-2))
  286. (let ((n (let lp ((bits 0) (constant constant))
  287. (if (= constant 1) bits (lp (1+ bits) (ash constant -1))))))
  288. (with-cps cps
  289. (build-term ($continue k src ($primcall 'lsh/immediate n (arg)))))))
  290. (else
  291. (with-cps cps #f))))
  292. (define-binary-primcall-reducer (logbit? cps k src param
  293. arg0 type0 min0 max0
  294. arg1 type1 min1 max1)
  295. (define (compute-mask cps kmask src)
  296. (if (eq? min0 max0)
  297. (with-cps cps
  298. (build-term
  299. ($continue kmask src ($const (ash 1 min0)))))
  300. (with-cps cps
  301. ($ (with-cps-constants ((one 1))
  302. (letv n)
  303. (letk kn ($kargs ('n) (n)
  304. ($continue kmask src
  305. ($primcall 'lsh #f (one n)))))
  306. (build-term
  307. ($continue kn src ($primcall 'untag-fixnum #f (arg0)))))))))
  308. (cond
  309. ((and (type<=? type0 &exact-integer)
  310. (<= 0 min0 (target-most-positive-fixnum))
  311. (<= 0 max0 (target-most-positive-fixnum)))
  312. (with-cps cps
  313. (letv mask res u64)
  314. (letk kt ($kargs () () ($continue k src ($const #t))))
  315. (letk kf ($kargs () () ($continue k src ($const #f))))
  316. (letk ku64 ($kargs (#f) (u64)
  317. ($branch kt kf src 's64-imm-= 0 (u64))))
  318. (letk kand ($kargs (#f) (res)
  319. ($continue ku64 src ($primcall 'untag-fixnum #f (res)))))
  320. (letk kmask ($kargs (#f) (mask)
  321. ($continue kand src
  322. ($primcall 'logand #f (mask arg1)))))
  323. ($ (compute-mask kmask src))))
  324. (else
  325. (with-cps cps #f))))
  326. (define-unary-primcall-reducer (u64->scm cps k src constant arg type min max)
  327. (cond
  328. ((<= max (target-most-positive-fixnum))
  329. (with-cps cps
  330. (letv s64)
  331. (letk ks64 ($kargs ('s64) (s64)
  332. ($continue k src
  333. ($primcall 'tag-fixnum #f (s64)))))
  334. (build-term
  335. ($continue ks64 src
  336. ($primcall 'u64->s64 #f (arg))))))
  337. (else
  338. (with-cps cps #f))))
  339. (define-unary-primcall-reducer (s64->scm cps k src constant arg type min max)
  340. (cond
  341. ((<= (target-most-negative-fixnum) min max (target-most-positive-fixnum))
  342. (with-cps cps
  343. (build-term
  344. ($continue k src
  345. ($primcall 'tag-fixnum #f (arg))))))
  346. (else
  347. (with-cps cps #f))))
  348. (define-unary-primcall-reducer (scm->s64 cps k src constant arg type min max)
  349. (cond
  350. ((and (type<=? type &exact-integer)
  351. (<= (target-most-negative-fixnum) min max (target-most-positive-fixnum)))
  352. (with-cps cps
  353. (build-term
  354. ($continue k src
  355. ($primcall 'untag-fixnum #f (arg))))))
  356. (else
  357. (with-cps cps #f))))
  358. (define-unary-primcall-reducer (scm->u64 cps k src constant arg type min max)
  359. (cond
  360. ((and (type<=? type &exact-integer)
  361. (<= 0 min max (target-most-positive-fixnum)))
  362. (with-cps cps
  363. (letv s64)
  364. (letk ks64 ($kargs ('s64) (s64)
  365. ($continue k src
  366. ($primcall 's64->u64 #f (s64)))))
  367. (build-term
  368. ($continue ks64 src
  369. ($primcall 'untag-fixnum #f (arg))))))
  370. (else
  371. (with-cps cps #f))))
  372. ;;
  373. (define (local-type-fold start end cps)
  374. (define (scalar-value type val)
  375. (cond
  376. ((eqv? type &fixnum) val)
  377. ((eqv? type &bignum) val)
  378. ((eqv? type &flonum) (exact->inexact val))
  379. ((eqv? type &char) (integer->char val))
  380. ((eqv? type &special-immediate)
  381. (cond
  382. ((eqv? val &null) '())
  383. ((eqv? val &nil) #nil)
  384. ((eqv? val &false) #f)
  385. ((eqv? val &true) #t)
  386. ((eqv? val &unspecified) *unspecified*)
  387. ;; FIXME: &undefined here
  388. ((eqv? val &eof) the-eof-object)
  389. (else (error "unhandled immediate" val))))
  390. (else (error "unhandled type" type val))))
  391. (let ((types (infer-types cps start)))
  392. (define (fold-primcall cps label names vars k src op param args def)
  393. (call-with-values (lambda () (lookup-post-type types label def 0))
  394. (lambda (type min max)
  395. (and (not (zero? type))
  396. (zero? (logand type (1- type)))
  397. (zero? (logand type (lognot &scalar-types)))
  398. (eqv? min max)
  399. (let ((val (scalar-value type min)))
  400. ;; (pk 'folded src op args val)
  401. (with-cps cps
  402. (letv v*)
  403. (letk k* ($kargs (#f) (v*)
  404. ($continue k src ($const val))))
  405. ;; Rely on DCE to elide this expression, if
  406. ;; possible.
  407. (setk label
  408. ($kargs names vars
  409. ($continue k* src ($primcall op param args))))))))))
  410. (define (transform-primcall f cps label names vars k src op param args)
  411. (and f
  412. (match args
  413. ((arg0)
  414. (call-with-values (lambda () (lookup-pre-type types label arg0))
  415. (lambda (type0 min0 max0)
  416. (call-with-values (lambda ()
  417. (f cps k src param arg0 type0 min0 max0))
  418. (lambda (cps term)
  419. (and term
  420. (with-cps cps
  421. (setk label ($kargs names vars ,term)))))))))
  422. ((arg0 arg1)
  423. (call-with-values (lambda () (lookup-pre-type types label arg0))
  424. (lambda (type0 min0 max0)
  425. (call-with-values (lambda () (lookup-pre-type types label arg1))
  426. (lambda (type1 min1 max1)
  427. (call-with-values (lambda ()
  428. (f cps k src param arg0 type0 min0 max0
  429. arg1 type1 min1 max1))
  430. (lambda (cps term)
  431. (and term
  432. (with-cps cps
  433. (setk label ($kargs names vars ,term)))))))))))
  434. (_ #f))))
  435. (define (reduce-primcall cps label names vars k src op param args)
  436. (cond
  437. ((transform-primcall (hashq-ref *primcall-macro-reducers* op)
  438. cps label names vars k src op param args)
  439. => (lambda (cps)
  440. (match (intmap-ref cps label)
  441. (($ $kargs names vars
  442. ($ $continue k src ($ $primcall op param args)))
  443. (reduce-primcall cps label names vars k src op param args)))))
  444. ((transform-primcall (hashq-ref *primcall-reducers* op)
  445. cps label names vars k src op param args))
  446. (else cps)))
  447. (define (fold-unary-branch cps label names vars kf kt src op param arg)
  448. (and=>
  449. (hashq-ref *branch-folders* op)
  450. (lambda (folder)
  451. (call-with-values (lambda () (lookup-pre-type types label arg))
  452. (lambda (type min max)
  453. (call-with-values (lambda () (folder param type min max))
  454. (lambda (f? v)
  455. ;; (when f? (pk 'folded-unary-branch label op arg v))
  456. (and f?
  457. (with-cps cps
  458. (setk label
  459. ($kargs names vars
  460. ($continue (if v kt kf) src
  461. ($values ())))))))))))))
  462. (define (fold-binary-branch cps label names vars kf kt src op param arg0 arg1)
  463. (and=>
  464. (hashq-ref *branch-folders* op)
  465. (lambda (folder)
  466. (call-with-values (lambda () (lookup-pre-type types label arg0))
  467. (lambda (type0 min0 max0)
  468. (call-with-values (lambda () (lookup-pre-type types label arg1))
  469. (lambda (type1 min1 max1)
  470. (call-with-values (lambda ()
  471. (folder param type0 min0 max0 type1 min1 max1))
  472. (lambda (f? v)
  473. ;; (when f? (pk 'folded-binary-branch label op arg0 arg1 v))
  474. (and f?
  475. (with-cps cps
  476. (setk label
  477. ($kargs names vars
  478. ($continue (if v kt kf) src
  479. ($values ())))))))))))))))
  480. (define (visit-primcall cps label names vars k src op param args)
  481. ;; We might be able to fold primcalls that define a value.
  482. (match (intmap-ref cps k)
  483. (($ $kargs (_) (def))
  484. (or (fold-primcall cps label names vars k src op param args def)
  485. (reduce-primcall cps label names vars k src op param args)))
  486. (_
  487. (reduce-primcall cps label names vars k src op param args))))
  488. (define (visit-branch cps label names vars kf kt src op param args)
  489. ;; We might be able to fold primcalls that branch.
  490. (match args
  491. ((x)
  492. (or (fold-unary-branch cps label names vars kf kt src op param x)
  493. cps))
  494. ((x y)
  495. (or (fold-binary-branch cps label names vars kf kt src op param x y)
  496. cps))))
  497. (let lp ((label start) (cps cps))
  498. (if (<= label end)
  499. (lp (1+ label)
  500. (match (intmap-ref cps label)
  501. (($ $kargs names vars ($ $continue k src
  502. ($ $primcall op param args)))
  503. (visit-primcall cps label names vars k src op param args))
  504. (($ $kargs names vars ($ $branch kf kt src op param args))
  505. (visit-branch cps label names vars kf kt src op param args))
  506. (_ cps)))
  507. cps))))
  508. (define (fold-functions-in-renumbered-program f conts seed)
  509. (let* ((conts (persistent-intmap conts))
  510. (end (1+ (intmap-prev conts))))
  511. (let lp ((label 0) (seed seed))
  512. (if (eqv? label end)
  513. seed
  514. (match (intmap-ref conts label)
  515. (($ $kfun src meta self tail clause)
  516. (lp (1+ tail) (f label tail seed))))))))
  517. (define (type-fold conts)
  518. ;; Type analysis wants a program whose labels are sorted.
  519. (let ((conts (renumber conts)))
  520. (with-fresh-name-state conts
  521. (persistent-intmap
  522. (fold-functions-in-renumbered-program local-type-fold conts conts)))))