123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- (define-module (ps-compiler util dominators)
- #:use-module (srfi srfi-9)
- #:use-module (prescheme scheme48)
- #:use-module (ps-compiler util util)
- #:export (find-dominators!))
- (define-record-type :vertex
- (really-make-vertex node semi bucket ancestor debug)
- vertex?
- (node vertex-node)
- (semi vertex-semi
- set-vertex-semi!)
-
-
-
- (parent vertex-parent
- set-vertex-parent!)
- (pred vertex-pred
- set-vertex-pred!)
- (label vertex-label
- set-vertex-label!)
- (bucket vertex-bucket
- set-vertex-bucket!)
- (dom vertex-dom
- set-vertex-dom!)
-
-
-
-
-
-
-
- (ancestor vertex-ancestor
- set-vertex-ancestor!)
- (debug vertex-debug
- set-vertex-debug!))
- (define (make-vertex node semi)
- (really-make-vertex node
- semi
- '()
- #f
- #f))
- (define (push-vertex-bucket! inf elt)
- (set-vertex-bucket! inf (cons elt (vertex-bucket inf))))
- (define (find-dominators-quickly! root
- succ
- pred
- slot
- set-slot!)
-
-
-
- (define (dfs root)
- (let ((n 0) (vertices '()))
- (let go ((node root) (parent #f))
- (let ((v (make-vertex node n)))
- (set-slot! node v)
- (set! n (+ n 1))
- (set-vertex-parent! v parent)
- (set-vertex-label! v v)
- (set! vertices (cons v vertices))
- (for-each (lambda (node)
- (if (not (slot node))
- (go node v)))
- (succ node))))
-
- (let ((vertex-map (list->vector (reverse! vertices))))
- (do ((i 0 (+ i 1)))
- ((= i (vector-length vertex-map)))
- (let ((v (vector-ref vertex-map i)))
- (set-vertex-pred! v (map slot (pred (vertex-node v))))))
- (values n vertex-map))))
- (define (compress! v)
- (let ((a (vertex-ancestor v)))
- (if (vertex-ancestor a)
- (begin
- (compress! a)
- (if (< (vertex-semi (vertex-label a))
- (vertex-semi (vertex-label v)))
- (set-vertex-label! v (vertex-label a)))
- (set-vertex-ancestor! v (vertex-ancestor (vertex-ancestor v)))))))
-
- (define (eval! v)
- (cond ((not (vertex-ancestor v))
- v)
- (else
- (compress! v)
- (vertex-label v))))
-
- (define (link! v w)
- (set-vertex-ancestor! w v))
-
- (receive (n vertex-map) (dfs root)
- (do ((i (- n 1) (- i 1)))
- ((= i 0))
- (let ((w (vector-ref vertex-map i)))
- (for-each (lambda (v)
- (let ((u (eval! v)))
- (if (< (vertex-semi u)
- (vertex-semi w))
- (set-vertex-semi! w
- (vertex-semi u)))))
- (vertex-pred w))
- (push-vertex-bucket! (vector-ref vertex-map (vertex-semi w)) w)
- (link! (vertex-parent w) w)
- (for-each (lambda (v)
-
-
- (let ((u (eval! v)))
- (set-vertex-dom! v
- (if (< (vertex-semi u)
- (vertex-semi v))
- u
- (vertex-parent w)))))
- (vertex-bucket (vertex-parent w)))))
-
- (do ((i 1 (+ i 1)))
- ((= i n))
- (let ((w (vector-ref vertex-map i)))
- (if (not (eq? (vertex-dom w)
- (vector-ref vertex-map (vertex-semi w))))
- (set-vertex-dom! w
- (vertex-dom (vertex-dom w))))))
- (set-vertex-dom! (slot root) #f)
-
-
-
- (do ((i 0 (+ i 1)))
- ((= i n))
- (let ((w (vector-ref vertex-map i)))
- (let ((d (vertex-dom w)))
- (set-slot! (vertex-node w) (if d (vertex-node d) #f)))))))
- (define (find-dominators-slowly! root succ pred slot set-slot!)
- (define vertex-succ vertex-pred)
- (define set-vertex-succ! set-vertex-pred!)
- (define vertex-mark vertex-ancestor)
- (define set-vertex-mark! set-vertex-ancestor!)
- (define (dfs root)
- (let ((n 0) (vertices '()))
- (let go ((node root) (parent #f))
- (let ((v (make-vertex node n)))
- (set-slot! node v)
- (set! n (+ n 1))
- (set! vertices (cons v vertices))
- (set-vertex-parent! v #f)
- (set-vertex-label! v #f)
- (for-each (lambda (node)
- (if (not (slot node))
- (go node v)))
- (succ node))))
- (for-each (lambda (v)
- (set-vertex-succ! v (map slot (succ (vertex-node v)))))
- vertices)
- (values n (reverse! vertices))))
- (receive (n vertices) (dfs root)
- (define (inaccessible v)
-
- (set-vertex-mark! v #t)
- (let go ((w (car vertices)))
- (set-vertex-mark! w #t)
- (for-each (lambda (u)
- (if (not (vertex-mark u))
- (go u)))
- (vertex-succ w)))
- (filter (lambda (w)
- (cond
- ((vertex-mark w)
- (set-vertex-mark! w #f)
- #f)
- (else #t)))
- vertices))
- (for-each (lambda (v) (set-vertex-dom! v (car vertices)))
- (cdr vertices))
- (for-each (lambda (v)
- (let ((dominated-by-v (inaccessible v)))
- (for-each (lambda (w)
- (if (eq? (vertex-dom w) (vertex-dom v))
- (set-vertex-dom! w v)))
- dominated-by-v)))
- (cdr vertices))
- (set-vertex-dom! (car vertices) #f)
-
- (for-each (lambda (v)
- (set-slot! (vertex-node v)
- (let ((d (vertex-dom v)))
- (if d (vertex-node d) #f))))
- vertices)))
- (define (time-thunk thunk) (thunk))
- (define (find-and-check-dominators! root succ pred slot set-slot!)
- (let ((set-fast-slot! (lambda (x v) (set-car! (slot x) v)))
- (fast-slot (lambda (x) (car (slot x))))
- (set-slow-slot! (lambda (x v) (set-cdr! (slot x) v)))
- (slow-slot (lambda (x) (cdr (slot x)))))
- (let go ((node root))
- (set-slot! node (cons #f #f))
- (for-each (lambda (node)
- (if (not (slot node))
- (go node)))
- (succ node)))
- (let ((fast (time-thunk
- (lambda ()
- (find-dominators-quickly!
- root succ pred fast-slot set-fast-slot!))))
- (slow (time-thunk (lambda ()
- (find-dominators-slowly!
- root succ pred slow-slot set-slow-slot!)))))
-
- (let go ((node root))
- (if (not (eq? (fast-slot node) (slow-slot node)))
- (bug "Dominator algorithm error"))
- (set-slot! node (fast-slot node))
- (for-each (lambda (node)
- (if (pair? (slot node))
- (go node)))
- (succ node))))))
- (define *check?* #t)
- (define (find-dominators! . args)
- (apply (if *check?*
- find-and-check-dominators!
- find-dominators-quickly!)
- args))
|