ssa.scm 6.1 KB

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