1 (define (analyze-liveness cfg)
5 (define (instr-analyze-liveness instr live-after)
7 (cond ((call-instr? instr)
8 (let ((def-proc (call-instr-def-proc instr)))
10 (def-procedure-live-after-calls def-proc))
14 (if (not (set-equal? old new))
17 (def-procedure-live-after-calls-set! def-proc new))))
21 (map (lambda (def-var)
22 (value-bytes (def-variable-value def-var)))
23 (def-procedure-params def-proc)))
25 (value-bytes (def-procedure-value def-proc))))))
26 (if (bb? (def-procedure-entry def-proc))
28 (bb-live-before (def-procedure-entry def-proc))
31 ((return-instr? instr)
32 ;;(pp (list instr: instr))
33 (let ((def-proc (return-instr-def-proc instr)))
35 (if (def-procedure? def-proc)
36 (def-procedure-live-after-calls def-proc)
37 (value-bytes def-proc))))
38 (let ((live (keep byte-cell? live)))
39 ;;(pp (list live: live))
40 (set! live-after live)
44 ;;(pp (list instr: instr))
45 (let* ((src1 (instr-src1 instr))
46 (src2 (instr-src2 instr))
47 (dst (instr-dst instr))
48 (use (if (byte-cell? src1)
50 (union (list src1) (list src2))
55 (def (if (byte-cell? dst)
58 (if #f #;(and (byte-cell? dst) ; dead instruction?
59 (not (memq dst live-after))
60 (not (and (byte-cell? dst) (byte-cell-adr dst))))
62 (union use (diff live-after def))))))))
63 (instr-live-before-set! instr live-before)
64 (instr-live-after-set! instr live-after)
67 (define (bb-analyze-liveness bb)
68 (let loop ((rev-instrs (bb-rev-instrs bb))
69 (live-after (union-multi (map bb-live-before (bb-succs bb)))))
70 (if (null? rev-instrs)
71 (if (not (set-equal? live-after (bb-live-before bb)))
74 (bb-live-before-set! bb live-after)))
75 (let* ((instr (car rev-instrs))
76 (live-before (instr-analyze-liveness instr live-after)))
77 (loop (cdr rev-instrs)
84 (for-each bb-analyze-liveness (cfg-bbs cfg))
88 ;------------------------------------------------------------------------------
90 (define (cfg->vector cfg)
91 (let ((vect (make-vector (cfg-next-label-num cfg) #f)))
92 (for-each (lambda (bb)
93 (vector-set! vect (bb-label-num bb) bb))
97 (define (remove-branch-cascades-and-dead-code cfg)
98 (let ((bbs-vector (cfg->vector cfg)))
100 (define (chase-branch-cascade bb seen)
103 (let* ((rev-instrs (bb-rev-instrs bb))
104 (last (car rev-instrs)))
105 (if (null? (cdr rev-instrs))
107 (cond ((eq? (instr-id last) 'goto)
109 (car (bb-succs bb))))
111 (chase-branch-cascade old-dest
113 ;; (if (not (eq? old-dest new-dest)) ;; TODO this seems to be a shortcut, and it broke a few things, so removed
115 ;; (pp (list "CASCADE" (bb-label-num bb)))
117 ;; (remove old-dest (bb-succs bb)))
118 ;; (bb-preds-set! old-dest
119 ;; (remove bb (bb-preds old-dest)))))
126 (define (bb-process bb)
132 (map (lambda (x) (chase-branch-cascade x seen)) old-succs)))
133 (for-each (lambda (old-dest new-dest)
134 (if (not (eq? old-dest new-dest))
136 (bb-succs-set! bb (replace old-dest new-dest (bb-succs bb)))
137 (bb-preds-set! old-dest
138 (remove bb (bb-preds old-dest)))
139 (bb-preds-set! new-dest
140 (cons bb (bb-preds old-dest))))))
144 (for-each bb-process (cfg-bbs cfg))))
146 ;------------------------------------------------------------------------------
148 ;; remove conditions whose 2 destination branches are the same, and replaces
149 ;; them with simple jumps
150 (define (remove-converging-branches cfg)
152 (define (bb-process bb)
153 (let ((instrs (bb-rev-instrs bb))
154 (succs (bb-succs bb)))
155 (if (and (memq (instr-id (car instrs)) conditional-instrs) ; conditional
156 (>= (length succs) 2)
157 (eq? (car succs) (cadr succs))) ; both destinations are the same
158 (bb-rev-instrs-set! bb (cons (new-instr 'goto #f #f #f)
161 (for-each bb-process (cfg-bbs cfg)))
163 ;------------------------------------------------------------------------------
165 ;; removes dead instructions (instructions after a return or after all jumps)
166 (define (remove-dead-instructions cfg)
168 (define (bb-process bb)
169 ;; since instructions are in erverse order, loop until we find a jump,
170 ;; and keep everything after
171 (let loop ((instrs (reverse (bb-rev-instrs bb)))
173 (let* ((head (car instrs))
174 (op (instr-id head)))
175 (if (or (eq? op 'return)
177 (memq op conditional-instrs))
178 (bb-rev-instrs-set! bb (cons head new-instrs))
180 (cons head new-instrs))))))
182 (for-each bb-process (cfg-bbs cfg)))