File: ssa.scm

package info (click to toggle)
scheme48 1.8%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 14,980 kB
  • ctags: 14,127
  • sloc: lisp: 76,272; ansic: 71,514; sh: 3,026; makefile: 637
file content (187 lines) | stat: -rw-r--r-- 6,279 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
; Copyright (c) 1993-2008 by Richard Kelsey.  See file COPYING.


; Finding where to put phi-functions.
;
; First call:
; (GRAPH->SSA-GRAPH! <root-node> <node-successors> <node-temp> <set-node-temp!>)
;
; Then:
; (FIND-JOINS <nodes> <node-temp>)
;  will return the list of nodes N for which there are (at least) two paths
;  ... N_0 M_0 ... M_i N and ... N_1 P_0 ... P_j N such that N_0 and N_1
;  are distinct members of <nodes> and the M's and P's are disjoint sets.
;
; Algorithm from:
;   Efficiently computing static single assignment form and the control
;     dependence graph,
;   Ron Cytron, Jeanne Ferrante, Barry K. Rosen, Mark N. Wegman, and
;     F. Kenneth Zadeck,
;   ACM Transactions on Programming Languages and Systems 1991 13(4)
;   pages 451-490

(define-record-type ssa-node :node
  (really-make-node data use-uid predecessors dominator dominated
		    seen-mark join-mark)
  node?
  (data node-data)                ; user's stuff
  (use-uid node-use-uid)          ; distinguishes between different invocations
  (successors node-successors     ; parents
	      set-node-successors!)
  (predecessors node-predecessors ;  and children in the graph
		set-node-predecessors!)
  (dominator node-dominator       ; parent ;; initialize for goofy dominator code
	     set-node-dominator!)
  (dominated node-dominated       ;   and children in the dominator tree
	     set-node-dominated!)
  (frontier node-frontier         ; dominator frontier
	    set-node-frontier!)
  (seen-mark node-seen-mark       ; two markers used in
	     set-node-seen-mark!)
  (join-mark node-join-mark       ;  the ssa algorithm
	     set-node-join-mark!))

(define (make-node data use-uid)
  (really-make-node data
		    use-uid
		    '()       ; predecessors
		    #f        ; dominator
		    '()       ; dominated
		    -1        ; see-mark
		    -1))      ; join-mark

(define (graph->ssa-graph! root successors temp set-temp!)
  (let ((graph (real-graph->ssa-graph root successors temp set-temp!)))
    (find-dominators! (car graph)
		      node-successors node-predecessors
		      node-dominator set-node-dominator!)
    (for-each (lambda (node)
		(let ((dom (node-dominator node)))
		  (set-node-dominated! dom (cons node (node-dominated dom)))))
	      (cdr graph))   ; root has no dominator
    (find-frontiers! (car graph))
    (values)))

; Turn the user's graph into a NODE graph.

(define (real-graph->ssa-graph root successors temp set-temp!)
  (let ((uid (next-uid))
	(nodes '()))
    (let recur ((data root))
      (let ((node (temp data)))
	(if (and (node? node)
		 (= uid (node-use-uid node)))
	    node
	    (let ((node (make-node data uid)))
	      (set! nodes (cons node nodes))
	      (set-temp! data node)
	      (let ((succs (map recur (successors data))))
		(for-each (lambda (succ)
			    (set-node-predecessors! succ
						    (cons node (node-predecessors succ))))
			  succs)
		(set-node-successors! node succs))
	      node))))
    (if (any (lambda (node)
	       (not (eq? node (temp (node-data node)))))
	     nodes)
	(breakpoint "graph made incorrectly"))
    (reverse! nodes)))  ; root ends up at front

; Find the dominance frontiers of the nodes in a graph.

(define (find-frontiers! node)
  (let ((frontier (let loop ((succs (node-successors node)) (frontier '()))
               (if (null? succs)
                   frontier
                        (loop (cdr succs)
                             (if (eq? node (node-dominator (car succs)))
                                 frontier
                                (cons (car succs) frontier)))))))
    (let loop ((kids (node-dominated node)) (frontier frontier))
      (cond ((null? kids)
         (set-node-frontier! node frontier)
      frontier)
      (else
            (let kid-loop ((kid-frontier (find-frontiers! (car kids)))
                      (frontier frontier))
               (if (null? kid-frontier)
            (loop (cdr kids) frontier)
              (kid-loop (cdr kid-frontier)
                      (if (eq? node (node-dominator (car kid-frontier)))
                          frontier
                                (cons (car kid-frontier) frontier))))))))))

(define (find-joins nodes temp)
  (for-each (lambda (n)
	      (if (not (node? (temp n)))
		  (begin
		    (breakpoint "node not seen before ~s" n)
		    n)))
	    nodes)
  (map node-data (really-find-joins (map temp nodes))))

(define (really-find-joins nodes)
  (let ((marker (next-uid)))
    (for-each (lambda (n)
		(set-node-seen-mark! n marker))
	      nodes)
    (let loop ((to-do nodes) (joins '()))
      (if (null? to-do)
	  joins
	  (let frontier-loop ((frontier (node-frontier (car to-do)))
			      (to-do (cdr to-do))
			      (joins joins))
	    (cond ((null? frontier)
		   (loop to-do joins))
		  ((eq? marker (node-join-mark (car frontier)))
		   (frontier-loop (cdr frontier) to-do joins))
		  (else
		   (let ((node (car frontier)))
		     (set-node-join-mark! node marker)
		     (frontier-loop (cdr frontier)
				    (if (eq? marker (node-seen-mark node))
					to-do
					(begin
					  (set-node-seen-mark! node marker)
					  (cons node to-do)))
				    (cons node joins))))))))))

; Integers as UID's

(define *next-uid* 0)

(define (next-uid)
  (let ((uid *next-uid*))
    (set! *next-uid* (+ uid 1))
    uid))

;----------------------------------------------------------------
; Testing

;(define-record-type data
;  (name)
;  (kids
;   temp))
;
;(define-record-discloser type/data
;  (lambda (data)
;    (list 'data (data-name data))))
;
;(define (make-test-graph spec)
;  (let ((vertices (map (lambda (d)
;                         (data-maker (car d)))
;                       spec)))
;    (for-each (lambda (data vertex)
;                (set-data-kids! vertex (map (lambda (s)
;                                              (first (lambda (v)
;                                                       (eq? s (data-name v)))
;                                                     vertices))
;                                            (cdr data))))
;              spec
;              vertices)
;    vertices))

;(define g1 (make-test-graph '((a b) (b c d) (c b e) (d d e) (e))))
;(graph->ssa-graph (car g1) data-kids data-temp set-data-temp!)
;(find-joins (list (list-ref g1 0)) data-temp)