ssa.scm 6.2 KB

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