123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- ;;; Ported from Scheme 48 1.9. See file COPYING for notices and license.
- ;;;
- ;;; Port Author: Andrew Whatson
- ;;;
- ;;; Original Authors: Richard Kelsey
- ;;;
- ;;; scheme48-1.9.2/ps-compiler/util/ssa.scm
- ;;;
- ;;; 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-module (ps-compiler util ssa)
- #:use-module (srfi srfi-9)
- #:use-module (prescheme scheme48)
- #:use-module (ps-compiler util dominators)
- #:export (graph->ssa-graph! find-joins))
- (define-record-type :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)
|