dfg.scm 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  1. ;;; Continuation-passing style (CPS) intermediate language (IL)
  2. ;; Copyright (C) 2013, 2014 Free Software Foundation, Inc.
  3. ;;;; This library is free software; you can redistribute it and/or
  4. ;;;; modify it under the terms of the GNU Lesser General Public
  5. ;;;; License as published by the Free Software Foundation; either
  6. ;;;; version 3 of the License, or (at your option) any later version.
  7. ;;;;
  8. ;;;; This library is distributed in the hope that it will be useful,
  9. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. ;;;; Lesser General Public License for more details.
  12. ;;;;
  13. ;;;; You should have received a copy of the GNU Lesser General Public
  14. ;;;; License along with this library; if not, write to the Free Software
  15. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. ;;; Commentary:
  17. ;;;
  18. ;;; Many passes rely on a local or global static analysis of a function.
  19. ;;; This module implements a simple data-flow graph (DFG) analysis,
  20. ;;; tracking the definitions and uses of variables and continuations.
  21. ;;; It also builds a table of continuations and scope links, to be able
  22. ;;; to easily determine if one continuation is in the scope of another,
  23. ;;; and to get to the expression inside a continuation.
  24. ;;;
  25. ;;; Note that the data-flow graph of continuation labels is a
  26. ;;; control-flow graph.
  27. ;;;
  28. ;;; We currently don't expose details of the DFG type outside this
  29. ;;; module, preferring to only expose accessors. That may change in the
  30. ;;; future but it seems to work for now.
  31. ;;;
  32. ;;; Code:
  33. (define-module (language cps dfg)
  34. #:use-module (ice-9 match)
  35. #:use-module (srfi srfi-1)
  36. #:use-module (srfi srfi-9)
  37. #:use-module (srfi srfi-26)
  38. #:use-module (language cps)
  39. #:export (build-cont-table
  40. build-local-cont-table
  41. lookup-cont
  42. compute-dfg
  43. dfg-cont-table
  44. lookup-def
  45. lookup-uses
  46. lookup-predecessors
  47. lookup-successors
  48. lookup-block-scope
  49. find-call
  50. call-expression
  51. find-expression
  52. find-defining-expression
  53. find-constant-value
  54. continuation-bound-in?
  55. variable-free-in?
  56. constant-needs-allocation?
  57. control-point?
  58. lookup-bound-syms
  59. ;; Control flow analysis.
  60. analyze-control-flow
  61. cfa-k-idx cfa-k-count cfa-k-sym cfa-predecessors
  62. ;; Data flow analysis.
  63. compute-live-variables
  64. dfa-k-idx dfa-k-sym dfa-k-count dfa-k-in dfa-k-out
  65. dfa-var-idx dfa-var-name dfa-var-sym dfa-var-count
  66. print-dfa))
  67. (define (build-cont-table fun)
  68. (fold-conts (lambda (k cont table)
  69. (hashq-set! table k cont)
  70. table)
  71. (make-hash-table)
  72. fun))
  73. (define (build-local-cont-table cont)
  74. (fold-local-conts (lambda (k cont table)
  75. (hashq-set! table k cont)
  76. table)
  77. (make-hash-table)
  78. cont))
  79. (define (lookup-cont sym conts)
  80. (let ((res (hashq-ref conts sym)))
  81. (unless res
  82. (error "Unknown continuation!" sym (hash-fold acons '() conts)))
  83. res))
  84. ;; Data-flow graph for CPS: both for values and continuations.
  85. (define-record-type $dfg
  86. (make-dfg conts blocks use-maps)
  87. dfg?
  88. ;; hash table of sym -> $kif, $kargs, etc
  89. (conts dfg-cont-table)
  90. ;; hash table of sym -> $block
  91. (blocks dfg-blocks)
  92. ;; hash table of sym -> $use-map
  93. (use-maps dfg-use-maps))
  94. (define-record-type $use-map
  95. (make-use-map name sym def uses)
  96. use-map?
  97. (name use-map-name)
  98. (sym use-map-sym)
  99. (def use-map-def)
  100. (uses use-map-uses set-use-map-uses!))
  101. (define-record-type $block
  102. (%make-block scope scope-level preds succs)
  103. block?
  104. (scope block-scope set-block-scope!)
  105. (scope-level block-scope-level set-block-scope-level!)
  106. (preds block-preds set-block-preds!)
  107. (succs block-succs set-block-succs!))
  108. (define (make-block scope scope-level)
  109. (%make-block scope scope-level '() '()))
  110. ;; Some analyses assume that the only relevant set of nodes is the set
  111. ;; that is reachable from some start node. Others need to include nodes
  112. ;; that are reachable from an end node as well, or all nodes in a
  113. ;; function. In that case pass an appropriate implementation of
  114. ;; fold-all-conts, as analyze-control-flow does.
  115. (define (reverse-post-order k0 get-successors fold-all-conts)
  116. (let ((order '())
  117. (visited? (make-hash-table)))
  118. (let visit ((k k0))
  119. (hashq-set! visited? k #t)
  120. (for-each (lambda (k)
  121. (unless (hashq-ref visited? k)
  122. (visit k)))
  123. (get-successors k))
  124. (set! order (cons k order)))
  125. (list->vector (fold-all-conts
  126. (lambda (k seed)
  127. (if (hashq-ref visited? k)
  128. seed
  129. (begin
  130. (hashq-set! visited? k #t)
  131. (cons k seed))))
  132. order))))
  133. (define (make-block-mapping order)
  134. (let ((mapping (make-hash-table)))
  135. (let lp ((n 0))
  136. (when (< n (vector-length order))
  137. (hashq-set! mapping (vector-ref order n) n)
  138. (lp (1+ n))))
  139. mapping))
  140. (define (convert-predecessors order get-predecessors)
  141. (let ((preds-vec (make-vector (vector-length order) #f)))
  142. (let lp ((n 0))
  143. (when (< n (vector-length order))
  144. (vector-set! preds-vec n (get-predecessors (vector-ref order n)))
  145. (lp (1+ n))))
  146. preds-vec))
  147. ;; Control-flow analysis.
  148. (define-record-type $cfa
  149. (make-cfa k-map order preds)
  150. cfa?
  151. ;; Hash table mapping k-sym -> k-idx
  152. (k-map cfa-k-map)
  153. ;; Vector of k-idx -> k-sym, in reverse post order
  154. (order cfa-order)
  155. ;; Vector of k-idx -> list of k-idx
  156. (preds cfa-preds))
  157. (define* (cfa-k-idx cfa k
  158. #:key (default (lambda (k)
  159. (error "unknown k" k))))
  160. (or (hashq-ref (cfa-k-map cfa) k)
  161. (default k)))
  162. (define (cfa-k-count cfa)
  163. (vector-length (cfa-order cfa)))
  164. (define (cfa-k-sym cfa n)
  165. (vector-ref (cfa-order cfa) n))
  166. (define (cfa-predecessors cfa n)
  167. (vector-ref (cfa-preds cfa) n))
  168. (define-inlinable (vector-push! vec idx val)
  169. (let ((v vec) (i idx))
  170. (vector-set! v i (cons val (vector-ref v i)))))
  171. (define (compute-reachable cfa dfg)
  172. "Given the forward control-flow analysis in CFA, compute and return
  173. the continuations that may be reached if flow reaches a continuation N.
  174. Returns a vector of bitvectors. The given CFA should be a forward CFA,
  175. for quickest convergence."
  176. (let* ((k-count (cfa-k-count cfa))
  177. ;; Vector of bitvectors, indicating that continuation N can
  178. ;; reach a set M...
  179. (reachable (make-vector k-count #f))
  180. ;; Vector of lists, indicating that continuation N can directly
  181. ;; reach continuations M...
  182. (succs (make-vector k-count '())))
  183. ;; All continuations are reachable from themselves.
  184. (let lp ((n 0))
  185. (when (< n k-count)
  186. (let ((bv (make-bitvector k-count #f)))
  187. (bitvector-set! bv n #t)
  188. (vector-set! reachable n bv)
  189. (lp (1+ n)))))
  190. ;; Initialize successor lists.
  191. (let lp ((n 0))
  192. (when (< n k-count)
  193. (for-each (lambda (succ)
  194. (vector-push! succs n (cfa-k-idx cfa succ)))
  195. (block-succs (lookup-block (cfa-k-sym cfa n)
  196. (dfg-blocks dfg))))
  197. (lp (1+ n))))
  198. ;; Iterate cfa backwards, to converge quickly.
  199. (let ((tmp (make-bitvector k-count #f)))
  200. (let lp ((n k-count) (changed? #f))
  201. (cond
  202. ((zero? n)
  203. (if changed?
  204. (lp 0 #f)
  205. reachable))
  206. (else
  207. (let ((n (1- n)))
  208. (bitvector-fill! tmp #f)
  209. (for-each (lambda (succ)
  210. (bit-set*! tmp (vector-ref reachable succ) #t))
  211. (vector-ref succs n))
  212. (bitvector-set! tmp n #t)
  213. (bit-set*! tmp (vector-ref reachable n) #f)
  214. (cond
  215. ((bit-position #t tmp 0)
  216. (bit-set*! (vector-ref reachable n) tmp #t)
  217. (lp n #t))
  218. (else
  219. (lp n changed?))))))))))
  220. (define (find-prompts cfa dfg)
  221. "Find the prompts in CFA, and return them as a list of PROMPT-INDEX,
  222. HANDLER-INDEX pairs."
  223. (let lp ((n 0) (prompts '()))
  224. (cond
  225. ((= n (cfa-k-count cfa))
  226. (reverse prompts))
  227. (else
  228. (match (lookup-cont (cfa-k-sym cfa n) (dfg-cont-table dfg))
  229. (($ $kargs names syms body)
  230. (match (find-expression body)
  231. (($ $prompt escape? tag handler)
  232. (lp (1+ n) (acons n (cfa-k-idx cfa handler) prompts)))
  233. (_ (lp (1+ n) prompts))))
  234. (_ (lp (1+ n) prompts)))))))
  235. (define (compute-interval cfa dfg reachable start end)
  236. "Compute and return the set of continuations that may be reached from
  237. START, inclusive, but not reached by END, exclusive. Returns a
  238. bitvector."
  239. (let ((body (make-bitvector (cfa-k-count cfa) #f)))
  240. (bit-set*! body (vector-ref reachable start) #t)
  241. (bit-set*! body (vector-ref reachable end) #f)
  242. body))
  243. (define (find-prompt-bodies cfa dfg)
  244. "Find all the prompts in CFA, and compute the set of continuations
  245. that is reachable from the prompt bodies but not from the corresponding
  246. handler. Returns a list of PROMPT, HANDLER, BODY lists, where the BODY
  247. is a bitvector."
  248. (match (find-prompts cfa dfg)
  249. (() '())
  250. (((prompt . handler) ...)
  251. (let ((reachable (compute-reachable cfa dfg)))
  252. (map (lambda (prompt handler)
  253. ;; FIXME: It isn't correct to use all continuations
  254. ;; reachable from the prompt, because that includes
  255. ;; continuations outside the prompt body. This point is
  256. ;; moot if the handler's control flow joins with the the
  257. ;; body, as is usually but not always the case.
  258. ;;
  259. ;; One counter-example is when the handler contifies an
  260. ;; infinite loop; in that case we compute a too-large
  261. ;; prompt body. This error is currently innocuous, but
  262. ;; we should fix it at some point.
  263. ;;
  264. ;; The fix is to end the body at the corresponding "pop"
  265. ;; primcall, if any.
  266. (let ((body (compute-interval cfa dfg reachable prompt handler)))
  267. (list prompt handler body)))
  268. prompt handler)))))
  269. (define* (visit-prompt-control-flow cfa dfg f #:key complete?)
  270. "For all prompts in CFA, invoke F with arguments PROMPT, HANDLER, and
  271. BODY for each body continuation in the prompt."
  272. (for-each
  273. (match-lambda
  274. ((prompt handler body)
  275. (define (out-or-back-edge? n)
  276. ;; Most uses of visit-prompt-control-flow don't need every body
  277. ;; continuation, and would be happy getting called only for
  278. ;; continuations that postdominate the rest of the body. Unless
  279. ;; you pass #:complete? #t, we only invoke F on continuations
  280. ;; that can leave the body, or on back-edges in loops.
  281. ;;
  282. ;; You would think that looking for the final "pop" primcall
  283. ;; would be sufficient, but that is incorrect; it's possible for
  284. ;; a loop in the prompt body to be contified, and that loop need
  285. ;; not continue to the pop if it never terminates. The pop could
  286. ;; even be removed by DCE, in that case.
  287. (or-map (lambda (succ)
  288. (let ((succ (cfa-k-idx cfa succ)))
  289. (or (not (bitvector-ref body succ))
  290. (<= succ n))))
  291. (block-succs (lookup-block (cfa-k-sym cfa n)
  292. (dfg-blocks dfg)))))
  293. (let lp ((n 0))
  294. (let ((n (bit-position #t body n)))
  295. (when n
  296. (when (or complete? (out-or-back-edge? n))
  297. (f prompt handler n))
  298. (lp (1+ n)))))))
  299. (find-prompt-bodies cfa dfg)))
  300. (define* (analyze-control-flow fun dfg #:key reverse? add-handler-preds?)
  301. (define (build-cfa kentry block-succs block-preds forward-cfa)
  302. (define (block-accessor accessor)
  303. (lambda (k)
  304. (accessor (lookup-block k (dfg-blocks dfg)))))
  305. (define (reachable-preds mapping accessor)
  306. ;; It's possible for a predecessor to not be in the mapping, if
  307. ;; the predecessor is not reachable from the entry node.
  308. (lambda (k)
  309. (filter-map (cut hashq-ref mapping <>)
  310. ((block-accessor accessor) k))))
  311. (let* ((order (reverse-post-order
  312. kentry
  313. (block-accessor block-succs)
  314. (if forward-cfa
  315. (lambda (f seed)
  316. (let lp ((n (cfa-k-count forward-cfa)) (seed seed))
  317. (if (zero? n)
  318. seed
  319. (lp (1- n)
  320. (f (cfa-k-sym forward-cfa (1- n)) seed)))))
  321. (lambda (f seed) seed))))
  322. (k-map (make-block-mapping order))
  323. (preds (convert-predecessors order
  324. (reachable-preds k-map block-preds)))
  325. (cfa (make-cfa k-map order preds)))
  326. (when add-handler-preds?
  327. ;; Any expression in the prompt body could cause an abort to the
  328. ;; handler. This code adds links from every block in the prompt
  329. ;; body to the handler. This causes all values used by the
  330. ;; handler to be seen as live in the prompt body, as indeed they
  331. ;; are.
  332. (let ((forward-cfa (or forward-cfa cfa)))
  333. (visit-prompt-control-flow
  334. forward-cfa dfg
  335. (lambda (prompt handler body)
  336. (define (renumber n)
  337. (if (eq? forward-cfa cfa)
  338. n
  339. (cfa-k-idx cfa (cfa-k-sym forward-cfa n))))
  340. (let ((handler (renumber handler))
  341. (body (renumber body)))
  342. (if reverse?
  343. (vector-push! preds body handler)
  344. (vector-push! preds handler body)))))))
  345. cfa))
  346. (match fun
  347. (($ $fun src meta free
  348. ($ $cont kentry
  349. (and entry
  350. ($ $kentry self ($ $cont ktail tail) clauses))))
  351. (if reverse?
  352. (build-cfa ktail block-preds block-succs
  353. (analyze-control-flow fun dfg #:reverse? #f
  354. #:add-handler-preds? #f))
  355. (build-cfa kentry block-succs block-preds #f)))))
  356. ;; Dominator analysis.
  357. (define-record-type $dominator-analysis
  358. (make-dominator-analysis cfa idoms dom-levels loop-header irreducible)
  359. dominator-analysis?
  360. ;; The corresponding $cfa
  361. (cfa dominator-analysis-cfa)
  362. ;; Vector of k-idx -> k-idx
  363. (idoms dominator-analysis-idoms)
  364. ;; Vector of k-idx -> dom-level
  365. (dom-levels dominator-analysis-dom-levels)
  366. ;; Vector of k-idx -> k-idx or -1
  367. (loop-header dominator-analysis-loop-header)
  368. ;; Vector of k-idx -> true or false value
  369. (irreducible dominator-analysis-irreducible))
  370. (define (compute-dom-levels idoms)
  371. (let ((dom-levels (make-vector (vector-length idoms) #f)))
  372. (define (compute-dom-level n)
  373. (or (vector-ref dom-levels n)
  374. (let ((dom-level (1+ (compute-dom-level (vector-ref idoms n)))))
  375. (vector-set! dom-levels n dom-level)
  376. dom-level)))
  377. (vector-set! dom-levels 0 0)
  378. (let lp ((n 0))
  379. (when (< n (vector-length idoms))
  380. (compute-dom-level n)
  381. (lp (1+ n))))
  382. dom-levels))
  383. (define (compute-idoms preds)
  384. (let ((idoms (make-vector (vector-length preds) 0)))
  385. (define (common-idom d0 d1)
  386. ;; We exploit the fact that a reverse post-order is a topological
  387. ;; sort, and so the idom of a node is always numerically less than
  388. ;; the node itself.
  389. (cond
  390. ((= d0 d1) d0)
  391. ((< d0 d1) (common-idom d0 (vector-ref idoms d1)))
  392. (else (common-idom (vector-ref idoms d0) d1))))
  393. (define (compute-idom preds)
  394. (match preds
  395. (() 0)
  396. ((pred . preds)
  397. (let lp ((idom pred) (preds preds))
  398. (match preds
  399. (() idom)
  400. ((pred . preds)
  401. (lp (common-idom idom pred) preds)))))))
  402. ;; This is the iterative O(n^2) fixpoint algorithm, originally from
  403. ;; Allen and Cocke ("Graph-theoretic constructs for program flow
  404. ;; analysis", 1972). See the discussion in Cooper, Harvey, and
  405. ;; Kennedy's "A Simple, Fast Dominance Algorithm", 2001.
  406. (let iterate ((n 0) (changed? #f))
  407. (cond
  408. ((< n (vector-length preds))
  409. (let ((idom (vector-ref idoms n))
  410. (idom* (compute-idom (vector-ref preds n))))
  411. (cond
  412. ((eqv? idom idom*)
  413. (iterate (1+ n) changed?))
  414. (else
  415. (vector-set! idoms n idom*)
  416. (iterate (1+ n) #t)))))
  417. (changed?
  418. (iterate 0 #f))
  419. (else idoms)))))
  420. ;; Compute a vector containing, for each node, a list of the nodes that
  421. ;; it immediately dominates. These are the "D" edges in the DJ tree.
  422. (define (compute-dom-edges idoms)
  423. (let ((doms (make-vector (vector-length idoms) '())))
  424. (let lp ((n 0))
  425. (when (< n (vector-length idoms))
  426. (let ((idom (vector-ref idoms n)))
  427. (vector-push! doms idom n))
  428. (lp (1+ n))))
  429. doms))
  430. ;; Compute a vector containing, for each node, a list of the successors
  431. ;; of that node that are not dominated by that node. These are the "J"
  432. ;; edges in the DJ tree.
  433. (define (compute-join-edges preds idoms)
  434. (define (dominates? n1 n2)
  435. (or (= n1 n2)
  436. (and (< n1 n2)
  437. (dominates? n1 (vector-ref idoms n2)))))
  438. (let ((joins (make-vector (vector-length idoms) '())))
  439. (let lp ((n 0))
  440. (when (< n (vector-length preds))
  441. (for-each (lambda (pred)
  442. (unless (dominates? pred n)
  443. (vector-push! joins pred n)))
  444. (vector-ref preds n))
  445. (lp (1+ n))))
  446. joins))
  447. ;; Compute a vector containing, for each node, a list of the back edges
  448. ;; to that node. If a node is not the entry of a reducible loop, that
  449. ;; list is empty.
  450. (define (compute-reducible-back-edges joins idoms)
  451. (define (dominates? n1 n2)
  452. (or (= n1 n2)
  453. (and (< n1 n2)
  454. (dominates? n1 (vector-ref idoms n2)))))
  455. (let ((back-edges (make-vector (vector-length idoms) '())))
  456. (let lp ((n 0))
  457. (when (< n (vector-length joins))
  458. (for-each (lambda (succ)
  459. (when (dominates? succ n)
  460. (vector-push! back-edges succ n)))
  461. (vector-ref joins n))
  462. (lp (1+ n))))
  463. back-edges))
  464. ;; Compute the levels in the dominator tree at which there are
  465. ;; irreducible loops, as an integer. If a bit N is set in the integer,
  466. ;; that indicates that at level N in the dominator tree, there is at
  467. ;; least one irreducible loop.
  468. (define (compute-irreducible-dom-levels doms joins idoms dom-levels)
  469. (define (dominates? n1 n2)
  470. (or (= n1 n2)
  471. (and (< n1 n2)
  472. (dominates? n1 (vector-ref idoms n2)))))
  473. (let ((pre-order (make-vector (vector-length doms) #f))
  474. (last-pre-order (make-vector (vector-length doms) #f))
  475. (res 0)
  476. (count 0))
  477. ;; Is MAYBE-PARENT an ancestor of N on the depth-first spanning tree
  478. ;; computed from the DJ graph? See Havlak 1997, "Nesting of
  479. ;; Reducible and Irreducible Loops".
  480. (define (ancestor? a b)
  481. (let ((w (vector-ref pre-order a))
  482. (v (vector-ref pre-order b)))
  483. (and (<= w v)
  484. (<= v (vector-ref last-pre-order w)))))
  485. ;; Compute depth-first spanning tree of DJ graph.
  486. (define (recurse n)
  487. (unless (vector-ref pre-order n)
  488. (visit n)))
  489. (define (visit n)
  490. ;; Pre-order visitation index.
  491. (vector-set! pre-order n count)
  492. (set! count (1+ count))
  493. (for-each recurse (vector-ref doms n))
  494. (for-each recurse (vector-ref joins n))
  495. ;; Pre-order visitation index of last descendant.
  496. (vector-set! last-pre-order (vector-ref pre-order n) (1- count)))
  497. (visit 0)
  498. (let lp ((n 0))
  499. (when (< n (vector-length joins))
  500. (for-each (lambda (succ)
  501. ;; If this join edge is not a loop back edge but it
  502. ;; does go to an ancestor on the DFST of the DJ
  503. ;; graph, then we have an irreducible loop.
  504. (when (and (not (dominates? succ n))
  505. (ancestor? succ n))
  506. (set! res (logior (ash 1 (vector-ref dom-levels succ))))))
  507. (vector-ref joins n))
  508. (lp (1+ n))))
  509. res))
  510. (define (compute-nodes-by-level dom-levels)
  511. (let* ((max-level (let lp ((n 0) (max-level 0))
  512. (if (< n (vector-length dom-levels))
  513. (lp (1+ n) (max (vector-ref dom-levels n) max-level))
  514. max-level)))
  515. (nodes-by-level (make-vector (1+ max-level) '())))
  516. (let lp ((n (1- (vector-length dom-levels))))
  517. (when (>= n 0)
  518. (vector-push! nodes-by-level (vector-ref dom-levels n) n)
  519. (lp (1- n))))
  520. nodes-by-level))
  521. ;; Collect all predecessors to the back-nodes that are strictly
  522. ;; dominated by the loop header, and mark them as belonging to the loop.
  523. ;; If they already have a loop header, that means they are either in a
  524. ;; nested loop, or they have already been visited already.
  525. (define (mark-loop-body header back-nodes preds idoms loop-headers)
  526. (define (strictly-dominates? n1 n2)
  527. (and (< n1 n2)
  528. (let ((idom (vector-ref idoms n2)))
  529. (or (= n1 idom)
  530. (strictly-dominates? n1 idom)))))
  531. (define (visit node)
  532. (when (strictly-dominates? header node)
  533. (cond
  534. ((vector-ref loop-headers node) => visit)
  535. (else
  536. (vector-set! loop-headers node header)
  537. (for-each visit (vector-ref preds node))))))
  538. (for-each visit back-nodes))
  539. (define (mark-irreducible-loops level idoms dom-levels loop-headers)
  540. ;; FIXME: Identify strongly-connected components that are >= LEVEL in
  541. ;; the dominator tree, and somehow mark them as irreducible.
  542. (warn 'irreducible-loops-at-level level))
  543. ;; "Identifying Loops Using DJ Graphs" by Sreedhar, Gao, and Lee, ACAPS
  544. ;; Technical Memo 98, 1995.
  545. (define (identify-loops preds idoms dom-levels)
  546. (let* ((doms (compute-dom-edges idoms))
  547. (joins (compute-join-edges preds idoms))
  548. (back-edges (compute-reducible-back-edges joins idoms))
  549. (irreducible-levels
  550. (compute-irreducible-dom-levels doms joins idoms dom-levels))
  551. (loop-headers (make-vector (vector-length preds) #f))
  552. (nodes-by-level (compute-nodes-by-level dom-levels)))
  553. (let lp ((level (1- (vector-length nodes-by-level))))
  554. (when (>= level 0)
  555. (for-each (lambda (n)
  556. (let ((edges (vector-ref back-edges n)))
  557. (unless (null? edges)
  558. (mark-loop-body n edges preds idoms loop-headers))))
  559. (vector-ref nodes-by-level level))
  560. (when (logbit? level irreducible-levels)
  561. (mark-irreducible-loops level idoms dom-levels loop-headers))
  562. (lp (1- level))))
  563. loop-headers))
  564. (define (analyze-dominators cfa)
  565. (match cfa
  566. (($ $cfa k-map order preds)
  567. (let* ((idoms (compute-idoms preds))
  568. (dom-levels (compute-dom-levels idoms))
  569. (loop-headers (identify-loops preds idoms dom-levels)))
  570. (make-dominator-analysis cfa idoms dom-levels loop-headers #f)))))
  571. ;; Compute the maximum fixed point of the data-flow constraint problem.
  572. ;;
  573. ;; This always completes, as the graph is finite and the in and out sets
  574. ;; are complete semi-lattices. If the graph is reducible and the blocks
  575. ;; are sorted in reverse post-order, this completes in a maximum of LC +
  576. ;; 2 iterations, where LC is the loop connectedness number. See Hecht
  577. ;; and Ullman, "Analysis of a simple algorithm for global flow
  578. ;; problems", POPL 1973, or the recent summary in "Notes on graph
  579. ;; algorithms used in optimizing compilers", Offner 2013.
  580. (define (compute-maximum-fixed-point preds inv outv killv genv union?)
  581. (define (bitvector-copy! dst src)
  582. (bitvector-fill! dst #f)
  583. (bit-set*! dst src #t))
  584. (define (bitvector-meet! accum src)
  585. (bit-set*! accum src union?))
  586. (let lp ((n 0) (changed? #f))
  587. (cond
  588. ((< n (vector-length preds))
  589. (let ((in (vector-ref inv n))
  590. (out (vector-ref outv n))
  591. (kill (vector-ref killv n))
  592. (gen (vector-ref genv n)))
  593. (let ((out-count (or changed? (bit-count #t out))))
  594. (for-each
  595. (lambda (pred)
  596. (bitvector-meet! in (vector-ref outv pred)))
  597. (vector-ref preds n))
  598. (bitvector-copy! out in)
  599. (for-each (cut bitvector-set! out <> #f) kill)
  600. (for-each (cut bitvector-set! out <> #t) gen)
  601. (lp (1+ n)
  602. (or changed? (not (eqv? out-count (bit-count #t out))))))))
  603. (changed?
  604. (lp 0 #f)))))
  605. ;; Data-flow analysis.
  606. (define-record-type $dfa
  607. (make-dfa cfa var-map names syms in out)
  608. dfa?
  609. ;; CFA, for its reverse-post-order numbering
  610. (cfa dfa-cfa)
  611. ;; Hash table mapping var-sym -> var-idx
  612. (var-map dfa-var-map)
  613. ;; Vector of var-idx -> name
  614. (names dfa-names)
  615. ;; Vector of var-idx -> var-sym
  616. (syms dfa-syms)
  617. ;; Vector of k-idx -> bitvector
  618. (in dfa-in)
  619. ;; Vector of k-idx -> bitvector
  620. (out dfa-out))
  621. (define (dfa-k-idx dfa k)
  622. (cfa-k-idx (dfa-cfa dfa) k))
  623. (define (dfa-k-sym dfa idx)
  624. (cfa-k-sym (dfa-cfa dfa) idx))
  625. (define (dfa-k-count dfa)
  626. (cfa-k-count (dfa-cfa dfa)))
  627. (define (dfa-var-idx dfa var)
  628. (or (hashq-ref (dfa-var-map dfa) var)
  629. (error "unknown var" var)))
  630. (define (dfa-var-name dfa idx)
  631. (vector-ref (dfa-names dfa) idx))
  632. (define (dfa-var-sym dfa idx)
  633. (vector-ref (dfa-syms dfa) idx))
  634. (define (dfa-var-count dfa)
  635. (vector-length (dfa-syms dfa)))
  636. (define (dfa-k-in dfa idx)
  637. (vector-ref (dfa-in dfa) idx))
  638. (define (dfa-k-out dfa idx)
  639. (vector-ref (dfa-out dfa) idx))
  640. (define (compute-live-variables fun dfg)
  641. (define (make-variable-mapping use-maps)
  642. (let ((mapping (make-hash-table))
  643. (n 0))
  644. (hash-for-each (lambda (sym use-map)
  645. (hashq-set! mapping sym n)
  646. (set! n (1+ n)))
  647. use-maps)
  648. (values mapping n)))
  649. (call-with-values (lambda () (make-variable-mapping (dfg-use-maps dfg)))
  650. (lambda (var-map nvars)
  651. (let* ((cfa (analyze-control-flow fun dfg #:reverse? #t
  652. #:add-handler-preds? #t))
  653. (syms (make-vector nvars #f))
  654. (names (make-vector nvars #f))
  655. (usev (make-vector (cfa-k-count cfa) '()))
  656. (defv (make-vector (cfa-k-count cfa) '()))
  657. (live-in (make-vector (cfa-k-count cfa) #f))
  658. (live-out (make-vector (cfa-k-count cfa) #f)))
  659. ;; Initialize syms, names, defv, and usev.
  660. (hash-for-each
  661. (lambda (sym use-map)
  662. (match use-map
  663. (($ $use-map name sym def uses)
  664. (let ((v (or (hashq-ref var-map sym)
  665. (error "unknown var" sym))))
  666. (vector-set! syms v sym)
  667. (vector-set! names v name)
  668. (for-each (lambda (def)
  669. (vector-push! defv (cfa-k-idx cfa def) v))
  670. (block-preds (lookup-block def (dfg-blocks dfg))))
  671. (for-each (lambda (use)
  672. (vector-push! usev (cfa-k-idx cfa use) v))
  673. uses)))))
  674. (dfg-use-maps dfg))
  675. ;; Initialize live-in and live-out sets.
  676. (let lp ((n 0))
  677. (when (< n (vector-length live-out))
  678. (vector-set! live-in n (make-bitvector nvars #f))
  679. (vector-set! live-out n (make-bitvector nvars #f))
  680. (lp (1+ n))))
  681. ;; Liveness is a reverse data-flow problem, so we give
  682. ;; compute-maximum-fixed-point a reversed graph, swapping in
  683. ;; for out, and usev for defv. Note that since we are using
  684. ;; a reverse CFA, cfa-preds are actually successors, and
  685. ;; continuation 0 is ktail.
  686. (compute-maximum-fixed-point (cfa-preds cfa)
  687. live-out live-in defv usev #t)
  688. (make-dfa cfa var-map names syms live-in live-out)))))
  689. (define (print-dfa dfa)
  690. (match dfa
  691. (($ $dfa cfa var-map names syms in out)
  692. (define (print-var-set bv)
  693. (let lp ((n 0))
  694. (let ((n (bit-position #t bv n)))
  695. (when n
  696. (format #t " ~A" (vector-ref syms n))
  697. (lp (1+ n))))))
  698. (let lp ((n 0))
  699. (when (< n (cfa-k-count cfa))
  700. (format #t "~A:\n" (cfa-k-sym cfa n))
  701. (format #t " in:")
  702. (print-var-set (vector-ref in n))
  703. (newline)
  704. (format #t " out:")
  705. (print-var-set (vector-ref out n))
  706. (newline)
  707. (lp (1+ n)))))))
  708. (define (visit-fun fun conts blocks use-maps global?)
  709. (define (add-def! name sym def-k)
  710. (unless def-k
  711. (error "Term outside labelled continuation?"))
  712. (hashq-set! use-maps sym (make-use-map name sym def-k '())))
  713. (define (add-use! sym use-k)
  714. (match (hashq-ref use-maps sym)
  715. (#f (error "Symbol out of scope?" sym))
  716. ((and use-map ($ $use-map name sym def uses))
  717. (set-use-map-uses! use-map (cons use-k uses)))))
  718. (define* (declare-block! label cont parent
  719. #:optional (level
  720. (1+ (lookup-scope-level parent blocks))))
  721. (hashq-set! conts label cont)
  722. (hashq-set! blocks label (make-block parent level)))
  723. (define (link-blocks! pred succ)
  724. (let ((pred-block (hashq-ref blocks pred))
  725. (succ-block (hashq-ref blocks succ)))
  726. (unless (and pred-block succ-block)
  727. (error "internal error" pred-block succ-block))
  728. (set-block-succs! pred-block (cons succ (block-succs pred-block)))
  729. (set-block-preds! succ-block (cons pred (block-preds succ-block)))))
  730. (define (visit exp exp-k)
  731. (define (def! name sym)
  732. (add-def! name sym exp-k))
  733. (define (use! sym)
  734. (add-use! sym exp-k))
  735. (define (use-k! k)
  736. (link-blocks! exp-k k))
  737. (define (recur exp)
  738. (visit exp exp-k))
  739. (match exp
  740. (($ $letk (($ $cont k cont) ...) body)
  741. ;; Set up recursive environment before visiting cont bodies.
  742. (for-each (lambda (cont k)
  743. (declare-block! k cont exp-k))
  744. cont k)
  745. (for-each visit cont k)
  746. (recur body))
  747. (($ $kargs names syms body)
  748. (for-each def! names syms)
  749. (recur body))
  750. (($ $kif kt kf)
  751. (use-k! kt)
  752. (use-k! kf))
  753. (($ $kreceive arity k)
  754. (use-k! k))
  755. (($ $letrec names syms funs body)
  756. (unless global?
  757. (error "$letrec should not be present when building a local DFG"))
  758. (for-each def! names syms)
  759. (for-each (cut visit-fun <> conts blocks use-maps global?) funs)
  760. (visit body exp-k))
  761. (($ $continue k src exp)
  762. (use-k! k)
  763. (match exp
  764. (($ $call proc args)
  765. (use! proc)
  766. (for-each use! args))
  767. (($ $primcall name args)
  768. (for-each use! args))
  769. (($ $values args)
  770. (for-each use! args))
  771. (($ $prompt escape? tag handler)
  772. (use! tag)
  773. (use-k! handler))
  774. (($ $fun)
  775. (when global?
  776. (visit-fun exp conts blocks use-maps global?)))
  777. (_ #f)))))
  778. (match fun
  779. (($ $fun src meta free
  780. ($ $cont kentry
  781. (and entry
  782. ($ $kentry self ($ $cont ktail tail) clauses))))
  783. (declare-block! kentry entry #f 0)
  784. (add-def! #f self kentry)
  785. (declare-block! ktail tail kentry)
  786. (for-each
  787. (match-lambda
  788. (($ $cont kclause
  789. (and clause ($ $kclause arity ($ $cont kbody body))))
  790. (declare-block! kclause clause kentry)
  791. (link-blocks! kentry kclause)
  792. (declare-block! kbody body kclause)
  793. (link-blocks! kclause kbody)
  794. (visit body kbody)))
  795. clauses))))
  796. (define* (compute-dfg fun #:key (global? #t))
  797. (let* ((conts (make-hash-table))
  798. (blocks (make-hash-table))
  799. (use-maps (make-hash-table)))
  800. (visit-fun fun conts blocks use-maps global?)
  801. (make-dfg conts blocks use-maps)))
  802. (define (lookup-block k blocks)
  803. (let ((res (hashq-ref blocks k)))
  804. (unless res
  805. (error "Unknown continuation!" k (hash-fold acons '() blocks)))
  806. res))
  807. (define (lookup-scope-level k blocks)
  808. (match (lookup-block k blocks)
  809. (($ $block _ scope-level) scope-level)))
  810. (define (lookup-use-map sym use-maps)
  811. (let ((res (hashq-ref use-maps sym)))
  812. (unless res
  813. (error "Unknown lexical!" sym (hash-fold acons '() use-maps)))
  814. res))
  815. (define (lookup-def sym dfg)
  816. (match dfg
  817. (($ $dfg conts blocks use-maps)
  818. (match (lookup-use-map sym use-maps)
  819. (($ $use-map name sym def uses)
  820. def)))))
  821. (define (lookup-uses sym dfg)
  822. (match dfg
  823. (($ $dfg conts blocks use-maps)
  824. (match (lookup-use-map sym use-maps)
  825. (($ $use-map name sym def uses)
  826. uses)))))
  827. (define (lookup-block-scope k dfg)
  828. (block-scope (lookup-block k (dfg-blocks dfg))))
  829. (define (lookup-predecessors k dfg)
  830. (match (lookup-block k (dfg-blocks dfg))
  831. (($ $block _ _ preds succs) preds)))
  832. (define (lookup-successors k dfg)
  833. (match (lookup-block k (dfg-blocks dfg))
  834. (($ $block _ _ preds succs) succs)))
  835. (define (find-defining-term sym dfg)
  836. (match (lookup-predecessors (lookup-def sym dfg) dfg)
  837. ((def-exp-k)
  838. (lookup-cont def-exp-k (dfg-cont-table dfg)))
  839. (else #f)))
  840. (define (find-call term)
  841. (match term
  842. (($ $kargs names syms body) (find-call body))
  843. (($ $letk conts body) (find-call body))
  844. (($ $letrec names syms funs body) (find-call body))
  845. (($ $continue) term)))
  846. (define (call-expression call)
  847. (match call
  848. (($ $continue k src exp) exp)))
  849. (define (find-expression term)
  850. (call-expression (find-call term)))
  851. (define (find-defining-expression sym dfg)
  852. (match (find-defining-term sym dfg)
  853. (#f #f)
  854. (($ $kreceive) #f)
  855. (($ $kclause) #f)
  856. (term (find-expression term))))
  857. (define (find-constant-value sym dfg)
  858. (match (find-defining-expression sym dfg)
  859. (($ $const val)
  860. (values #t val))
  861. (($ $continue k src ($ $void))
  862. (values #t *unspecified*))
  863. (else
  864. (values #f #f))))
  865. (define (constant-needs-allocation? sym val dfg)
  866. (define (immediate-u8? val)
  867. (and (integer? val) (exact? val) (<= 0 val 255)))
  868. (define (find-exp term)
  869. (match term
  870. (($ $kargs names syms body) (find-exp body))
  871. (($ $letk conts body) (find-exp body))
  872. (else term)))
  873. (match dfg
  874. (($ $dfg conts blocks use-maps)
  875. (match (lookup-use-map sym use-maps)
  876. (($ $use-map _ _ def uses)
  877. (or-map
  878. (lambda (use)
  879. (match (find-expression (lookup-cont use conts))
  880. (($ $call) #f)
  881. (($ $values) #f)
  882. (($ $primcall 'free-ref (closure slot))
  883. (not (eq? sym slot)))
  884. (($ $primcall 'free-set! (closure slot value))
  885. (not (eq? sym slot)))
  886. (($ $primcall 'cache-current-module! (mod . _))
  887. (eq? sym mod))
  888. (($ $primcall 'cached-toplevel-box _)
  889. #f)
  890. (($ $primcall 'cached-module-box _)
  891. #f)
  892. (($ $primcall 'resolve (name bound?))
  893. (eq? sym name))
  894. (($ $primcall 'make-vector/immediate (len init))
  895. (not (eq? sym len)))
  896. (($ $primcall 'vector-ref/immediate (v i))
  897. (not (eq? sym i)))
  898. (($ $primcall 'vector-set!/immediate (v i x))
  899. (not (eq? sym i)))
  900. (($ $primcall 'allocate-struct/immediate (vtable nfields))
  901. (not (eq? sym nfields)))
  902. (($ $primcall 'struct-ref/immediate (s n))
  903. (not (eq? sym n)))
  904. (($ $primcall 'struct-set!/immediate (s n x))
  905. (not (eq? sym n)))
  906. (($ $primcall 'builtin-ref (idx))
  907. #f)
  908. (_ #t)))
  909. uses))))))
  910. (define (continuation-scope-contains? scope-k k blocks)
  911. (let ((scope-level (lookup-scope-level scope-k blocks)))
  912. (let lp ((k k))
  913. (or (eq? scope-k k)
  914. (match (lookup-block k blocks)
  915. (($ $block scope level)
  916. (and (< scope-level level)
  917. (lp scope))))))))
  918. (define (continuation-bound-in? k use-k dfg)
  919. (match dfg
  920. (($ $dfg conts blocks use-maps)
  921. (match (lookup-block k blocks)
  922. (($ $block def-k)
  923. (continuation-scope-contains? def-k use-k blocks))))))
  924. (define (variable-free-in? var k dfg)
  925. (match dfg
  926. (($ $dfg conts blocks use-maps)
  927. (or-map (lambda (use)
  928. (continuation-scope-contains? k use blocks))
  929. (match (lookup-use-map var use-maps)
  930. (($ $use-map name sym def uses)
  931. uses))))))
  932. ;; A continuation is a control point if it has multiple predecessors, or
  933. ;; if its single predecessor has multiple successors.
  934. (define (control-point? k dfg)
  935. (match (lookup-predecessors k dfg)
  936. ((pred)
  937. (match (lookup-successors pred dfg)
  938. ((_) #f)
  939. (_ #t)))
  940. (_ #t)))
  941. (define (lookup-bound-syms k dfg)
  942. (match dfg
  943. (($ $dfg conts blocks use-maps)
  944. (match (lookup-cont k conts)
  945. (($ $kargs names syms body)
  946. syms)))))