ssa.scm 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. ;;; Ported from Scheme 48 1.9. See file COPYING for notices and license.
  2. ;;;
  3. ;;; Port Author: Andrew Whatson
  4. ;;;
  5. ;;; Original Authors: Richard Kelsey
  6. ;;;
  7. ;;; scheme48-1.9.2/ps-compiler/util/ssa.scm
  8. ;;;
  9. ;;; Finding where to put phi-functions.
  10. ;;;
  11. ;;; First call:
  12. ;;; (GRAPH->SSA-GRAPH! <root-node> <node-successors> <node-temp> <set-node-temp!>)
  13. ;;;
  14. ;;; Then:
  15. ;;; (FIND-JOINS <nodes> <node-temp>)
  16. ;;; will return the list of nodes N for which there are (at least) two paths
  17. ;;; ... N_0 M_0 ... M_i N and ... N_1 P_0 ... P_j N such that N_0 and N_1
  18. ;;; are distinct members of <nodes> and the M's and P's are disjoint sets.
  19. ;;;
  20. ;;; Algorithm from:
  21. ;;; Efficiently computing static single assignment form and the control
  22. ;;; dependence graph,
  23. ;;; Ron Cytron, Jeanne Ferrante, Barry K. Rosen, Mark N. Wegman, and
  24. ;;; F. Kenneth Zadeck,
  25. ;;; ACM Transactions on Programming Languages and Systems 1991 13(4)
  26. ;;; pages 451-490
  27. (define-module (ps-compiler util ssa)
  28. #:use-module (srfi srfi-9)
  29. #:use-module (prescheme scheme48)
  30. #:use-module (ps-compiler util dominators)
  31. #:export (graph->ssa-graph! find-joins))
  32. (define-record-type :node
  33. (really-make-node data use-uid predecessors dominator dominated
  34. seen-mark join-mark)
  35. node?
  36. (data node-data) ;; user's stuff
  37. (use-uid node-use-uid) ;; distinguishes between different invocations
  38. (successors node-successors ;; parents
  39. set-node-successors!)
  40. (predecessors node-predecessors ;; and children in the graph
  41. set-node-predecessors!)
  42. (dominator node-dominator ;; parent ;; initialize for goofy dominator code
  43. set-node-dominator!)
  44. (dominated node-dominated ;; and children in the dominator tree
  45. set-node-dominated!)
  46. (frontier node-frontier ;; dominator frontier
  47. set-node-frontier!)
  48. (seen-mark node-seen-mark ;; two markers used in
  49. set-node-seen-mark!)
  50. (join-mark node-join-mark ;; the ssa algorithm
  51. set-node-join-mark!))
  52. (define (make-node data use-uid)
  53. (really-make-node data
  54. use-uid
  55. '() ;; predecessors
  56. #f ;; dominator
  57. '() ;; dominated
  58. -1 ;; see-mark
  59. -1)) ;; join-mark
  60. (define (graph->ssa-graph! root successors temp set-temp!)
  61. (let ((graph (real-graph->ssa-graph root successors temp set-temp!)))
  62. (find-dominators! (car graph)
  63. node-successors node-predecessors
  64. node-dominator set-node-dominator!)
  65. (for-each (lambda (node)
  66. (let ((dom (node-dominator node)))
  67. (set-node-dominated! dom (cons node (node-dominated dom)))))
  68. (cdr graph)) ;; root has no dominator
  69. (find-frontiers! (car graph))
  70. (values)))
  71. ;; Turn the user's graph into a NODE graph.
  72. (define (real-graph->ssa-graph root successors temp set-temp!)
  73. (let ((uid (next-uid))
  74. (nodes '()))
  75. (let recur ((data root))
  76. (let ((node (temp data)))
  77. (if (and (node? node)
  78. (= uid (node-use-uid node)))
  79. node
  80. (let ((node (make-node data uid)))
  81. (set! nodes (cons node nodes))
  82. (set-temp! data node)
  83. (let ((succs (map recur (successors data))))
  84. (for-each (lambda (succ)
  85. (set-node-predecessors! succ
  86. (cons node (node-predecessors succ))))
  87. succs)
  88. (set-node-successors! node succs))
  89. node))))
  90. (if (any (lambda (node)
  91. (not (eq? node (temp (node-data node)))))
  92. nodes)
  93. (breakpoint "graph made incorrectly"))
  94. (reverse! nodes))) ;; root ends up at front
  95. ;; Find the dominance frontiers of the nodes in a graph.
  96. (define (find-frontiers! node)
  97. (let ((frontier (let loop ((succs (node-successors node)) (frontier '()))
  98. (if (null? succs)
  99. frontier
  100. (loop (cdr succs)
  101. (if (eq? node (node-dominator (car succs)))
  102. frontier
  103. (cons (car succs) frontier)))))))
  104. (let loop ((kids (node-dominated node)) (frontier frontier))
  105. (cond ((null? kids)
  106. (set-node-frontier! node frontier)
  107. frontier)
  108. (else
  109. (let kid-loop ((kid-frontier (find-frontiers! (car kids)))
  110. (frontier frontier))
  111. (if (null? kid-frontier)
  112. (loop (cdr kids) frontier)
  113. (kid-loop (cdr kid-frontier)
  114. (if (eq? node (node-dominator (car kid-frontier)))
  115. frontier
  116. (cons (car kid-frontier) frontier))))))))))
  117. (define (find-joins nodes temp)
  118. (for-each (lambda (n)
  119. (if (not (node? (temp n)))
  120. (begin
  121. (breakpoint "node not seen before ~s" n)
  122. n)))
  123. nodes)
  124. (map node-data (really-find-joins (map temp nodes))))
  125. (define (really-find-joins nodes)
  126. (let ((marker (next-uid)))
  127. (for-each (lambda (n)
  128. (set-node-seen-mark! n marker))
  129. nodes)
  130. (let loop ((to-do nodes) (joins '()))
  131. (if (null? to-do)
  132. joins
  133. (let frontier-loop ((frontier (node-frontier (car to-do)))
  134. (to-do (cdr to-do))
  135. (joins joins))
  136. (cond ((null? frontier)
  137. (loop to-do joins))
  138. ((eq? marker (node-join-mark (car frontier)))
  139. (frontier-loop (cdr frontier) to-do joins))
  140. (else
  141. (let ((node (car frontier)))
  142. (set-node-join-mark! node marker)
  143. (frontier-loop (cdr frontier)
  144. (if (eq? marker (node-seen-mark node))
  145. to-do
  146. (begin
  147. (set-node-seen-mark! node marker)
  148. (cons node to-do)))
  149. (cons node joins))))))))))
  150. ;; Integers as UID's
  151. (define *next-uid* 0)
  152. (define (next-uid)
  153. (let ((uid *next-uid*))
  154. (set! *next-uid* (+ uid 1))
  155. uid))
  156. ;;----------------------------------------------------------------
  157. ;; Testing
  158. ;;(define-record-type data
  159. ;; (name)
  160. ;; (kids
  161. ;; temp))
  162. ;;
  163. ;;(define-record-discloser type/data
  164. ;; (lambda (data)
  165. ;; (list 'data (data-name data))))
  166. ;;
  167. ;;(define (make-test-graph spec)
  168. ;; (let ((vertices (map (lambda (d)
  169. ;; (data-maker (car d)))
  170. ;; spec)))
  171. ;; (for-each (lambda (data vertex)
  172. ;; (set-data-kids! vertex (map (lambda (s)
  173. ;; (first (lambda (v)
  174. ;; (eq? s (data-name v)))
  175. ;; vertices))
  176. ;; (cdr data))))
  177. ;; spec
  178. ;; vertices)
  179. ;; vertices))
  180. ;;(define g1 (make-test-graph '((a b) (b c d) (c b e) (d d e) (e))))
  181. ;;(graph->ssa-graph (car g1) data-kids data-temp set-data-temp!)
  182. ;;(find-joins (list (list-ref g1 0)) data-temp)