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))
87 (define (interference-graph cfg)
91 (define (interfere x y)
92 (if (not (memq x (byte-cell-interferes-with y)))
94 (byte-cell-interferes-with-set!
96 (cons y (byte-cell-interferes-with x)))
97 (byte-cell-interferes-with-set!
99 (cons x (byte-cell-interferes-with y))))))
101 (define (interfere-pairwise live)
102 (set! all-live (union all-live live))
103 (for-each (lambda (x)
104 (for-each (lambda (y)
110 (define (instr-interference-graph instr)
111 (let ((dst (instr-dst instr)))
113 (let ((src1 (instr-src1 instr))
114 (src2 (instr-src2 instr)))
115 (if (byte-cell? src1)
117 (byte-cell-coalesceable-with-set!
119 (union (byte-cell-coalesceable-with dst)
121 (byte-cell-coalesceable-with-set!
123 (union (byte-cell-coalesceable-with src1)
125 (if (byte-cell? src2)
127 (byte-cell-coalesceable-with-set!
129 (union (byte-cell-coalesceable-with dst)
131 (byte-cell-coalesceable-with-set!
133 (union (byte-cell-coalesceable-with src2)
135 (let ((live-before (instr-live-before instr)))
136 (interfere-pairwise live-before)))
138 (define (bb-interference-graph bb)
139 (for-each instr-interference-graph (bb-rev-instrs bb)))
141 (analyze-liveness cfg)
143 (for-each bb-interference-graph (cfg-bbs cfg))
147 (define (allocate-registers cfg)
148 (let ((all-live (interference-graph cfg)))
150 (define (color byte-cell)
151 (let ((coalesce-candidates
153 (diff (byte-cell-coalesceable-with byte-cell)
154 (byte-cell-interferes-with byte-cell)))))
156 (pp (list byte-cell: byte-cell;;;;;;;;;;;;;;;
158 ; interferes-with: (byte-cell-interferes-with byte-cell)
159 ; coalesceable-with: (byte-cell-coalesceable-with byte-cell)
162 (if #f #;(not (null? coalesce-candidates))
163 (let ((adr (byte-cell-adr (car coalesce-candidates))))
164 (byte-cell-adr-set! byte-cell adr))
165 (let ((neighbours (byte-cell-interferes-with byte-cell)))
167 (let loop2 ((lst neighbours))
169 (byte-cell-adr-set! byte-cell adr)
171 (if (= adr (byte-cell-adr x))
173 (loop2 (cdr lst)))))))))))
175 (define (delete byte-cell1 neighbours)
176 (for-each (lambda (byte-cell2)
177 (let ((lst (byte-cell-interferes-with byte-cell2)))
178 (byte-cell-interferes-with-set!
180 (remove byte-cell1 lst))))
183 (define (undelete byte-cell1 neighbours)
184 (for-each (lambda (byte-cell2)
185 (let ((lst (byte-cell-interferes-with byte-cell2)))
186 (byte-cell-interferes-with-set!
188 (cons byte-cell1 lst))))
191 (define (find-min-neighbours graph)
192 (let loop ((lst graph) (m #f) (byte-cell #f))
196 (n (length (byte-cell-interferes-with x))))
197 (if (or (not m) (< n m))
199 (loop (cdr lst) m byte-cell))))))
201 (define (alloc-reg graph)
202 (if (not (null? graph))
203 (let* ((byte-cell (find-min-neighbours graph))
204 (neighbours (byte-cell-interferes-with byte-cell)))
205 (let ((new-graph (remove byte-cell graph)))
206 (delete byte-cell neighbours)
207 (alloc-reg new-graph)
208 (undelete byte-cell neighbours))
209 (if (not (byte-cell-adr byte-cell))
210 (color byte-cell)))))
212 (alloc-reg all-live)))
214 ;------------------------------------------------------------------------------
216 (define (cfg->vector cfg)
217 (let ((vect (make-vector (cfg-next-label-num cfg) #f)))
218 (for-each (lambda (bb)
219 (vector-set! vect (bb-label-num bb) bb))
223 (define (remove-branch-cascades-and-dead-code cfg)
224 (let ((bbs-vector (cfg->vector cfg)))
226 (define (chase-branch-cascade bb seen)
229 (let* ((rev-instrs (bb-rev-instrs bb))
230 (last (car rev-instrs)))
231 (if (null? (cdr rev-instrs))
233 (cond ((eq? (instr-id last) 'goto)
235 (car (bb-succs bb))))
237 (chase-branch-cascade old-dest
239 ;; (if (not (eq? old-dest new-dest)) ;; TODO this seems to be a shortcut, and it broke a few things, so removed
241 ;; (pp (list "CASCADE" (bb-label-num bb)))
243 ;; (remove old-dest (bb-succs bb)))
244 ;; (bb-preds-set! old-dest
245 ;; (remove bb (bb-preds old-dest)))))
252 (define (bb-process bb)
258 (map (lambda (x) (chase-branch-cascade x seen)) old-succs)))
259 (for-each (lambda (old-dest new-dest)
260 (if (not (eq? old-dest new-dest))
262 (bb-succs-set! bb (replace old-dest new-dest (bb-succs bb)))
263 (bb-preds-set! old-dest
264 (remove bb (bb-preds old-dest)))
265 (bb-preds-set! new-dest
266 (cons bb (bb-preds old-dest))))))
270 (for-each bb-process (cfg-bbs cfg))))
272 ;------------------------------------------------------------------------------
274 ;; remove conditions whose 2 destination branches are the same, and replaces
275 ;; them with simple jumps
276 (define (remove-useless-conditions cfg)
278 (define (bb-process bb)
279 (let ((instrs (bb-rev-instrs bb))
280 (succs (bb-succs bb)))
281 (if (and (memq (instr-id (car instrs)) conditional-instrs) ; conditional
282 (>= (length succs) 2)
283 (eq? (car succs) (cadr succs))) ; both destinations are the same
284 (bb-rev-instrs-set! bb (cons (new-instr 'goto #f #f #f)
287 (for-each bb-process (cfg-bbs cfg)))