Eliminate style-warning about undefined type GLOBAL-VAR
[sbcl.git] / src / compiler / pack-iterative.lisp
blob11b2c16aa346df5a35e0b79b5f8b29fb59ccf77a
1 ;;;; This file contains code for the iterative spilling/coloring
2 ;;;; register allocator
4 ;;;; This software is part of the SBCL system. See the README file for
5 ;;;; more information.
6 ;;;;
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
13 (in-package "SB!REGALLOC")
14 ;;;; Useful references to understand the algorithms and decisions made
15 ;;;; in this allocator.
16 ;;;;
17 ;;;; For more background:
18 ;;;;
19 ;;;; Chaitin, Gregory J. "Register allocation & spilling via graph
20 ;;;; coloring." ACM Sigplan Notices. Vol. 17. No. 6. ACM, 1982.
21 ;;;; (http://web.eecs.umich.edu/~mahlke/courses/583f12/reading/chaitin82.pdf)
22 ;;;;
23 ;;;; Briggs, Preston. "Register allocation via graph coloring."
24 ;;;; Diss. Rice University, 1992.
25 ;;;; (http://www.cs.utexas.edu/~mckinley/380C/lecs/briggs-thesis-1992.pdf)
26 ;;;;
27 ;;;; Shorter or more directly applied articles:
28 ;;;;
29 ;;;; Briggs, Preston, Keith D. Cooper, and Linda Torczon.
30 ;;;; "Improvements to graph coloring register allocation." ACM
31 ;;;; Transactions on Programming Languages and Systems (TOPLAS) 16.3
32 ;;;; (1994): 428-455.
33 ;;;; (http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.30.2616)
34 ;;;;
35 ;;;; Smith, Michael D., Norman Ramsey, and Glenn Holloway. "A
36 ;;;; generalized algorithm for graph-coloring register allocation."
37 ;;;; ACM SIGPLAN Notices. Vol. 39. No. 6. ACM, 2004.
38 ;;;; (http://www.cs.tufts.edu/~nr/pubs/gcra-abstract.html)
39 ;;;;
40 ;;;; Cooper, Keith D., Anshuman Dasgupta, and Jason Eckhardt.
41 ;;;; "Revisiting graph coloring register allocation: A study of the
42 ;;;; Chaitin-Briggs and Callahan-Koblenz algorithms." Languages and
43 ;;;; Compilers for Parallel Computing. Springer Berlin Heidelberg,
44 ;;;; 2006. 1-16.
45 ;;;; (http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.107.9598)
47 ;;; Interference graph data structure
48 (defstruct (ordered-set
49 (:include sset)
50 (:conc-name #:oset-))
51 (members nil :type list))
53 (defun oset-adjoin (oset element)
54 (when (sset-adjoin element oset)
55 (push element (oset-members oset))
56 t))
58 (defun oset-delete (oset element)
59 (when (sset-delete element oset)
60 (setf (oset-members oset)
61 (delete element (oset-members oset)))
62 t))
64 (defun oset-member (oset element)
65 (sset-member element oset))
67 (defmacro do-oset-elements ((variable oset &optional return) &body body)
68 `(dolist (,variable (oset-members ,oset) ,return)
69 ,@body))
71 ;; vertex in an interference graph
72 (def!struct (vertex
73 (:include sset-element)
74 (:constructor make-vertex (tn pack-type)))
75 ;; incidence set, as an ordered list (for reproducibility)
76 (incidence (make-ordered-set) :type ordered-set)
77 ;; list of potential locations in the TN's preferred SB for the
78 ;; vertex, taking into account reserve locations and preallocated
79 ;; TNs.
80 (initial-domain nil :type list)
81 (initial-domain-size 0 :type index)
82 ;; TN this is a vertex for.
83 (tn nil :type tn)
84 ;; type of packing necessary. We should only have to determine
85 ;; colors for :normal TNs/vertices
86 (pack-type nil :type (member :normal :wired :restricted))
87 ;; color offset
88 (color nil :type (or fixnum null))
89 ;; current status, removed from the interference graph or not (on
90 ;; stack or not)
91 (invisible nil :type t)
92 ;; (tn-spill-cost (vertex-tn vertex))
93 (spill-cost 0 :type fixnum))
95 (declaim (inline vertex-sc))
96 (defun vertex-sc (vertex)
97 (tn-sc (vertex-tn vertex)))
99 ;; interference graph
100 (def!struct (interference-graph
101 (:constructor %make-interference-graph)
102 (:conc-name #:ig-))
103 ;; sorted set of yet-uncolored (and not necessarily spilled)
104 ;; vertices: vertices with lower spill cost come first.
105 (vertices nil :type list)
106 ;; unsorted set of precolored vertices.
107 (precolored-vertices nil :type list)
108 (tn-vertex (bug "missing arg") :type hash-table)
109 ;; A function that maps TNs to vertices, and then to the vertex's
110 ;; assigned offset, if any. The offset (or NIL) is returned first,
111 ;; then the vertex as a second value.
112 (tn-vertex-mapping (bug "missing arg") :type function))
114 ;;; Interference graph construction
116 ;;; First, compute conflict edges between vertices that aren't
117 ;;; precolored: precolored vertices have already been handled via
118 ;;; domain initialisation.
120 ;;; This area is ripe for hard-to-explain bugs. If PACK-COLORED starts
121 ;;; AVERing out, it may be useful to comment out most of
122 ;;; INSERT-CONFLICT-EDGES and test for TNS-CONFLICT in a double loop
123 ;;; over the concatenation of all three vertex lists.
125 ;; Adjoin symmetric edge (A,B) to both A and B. Unless
126 ;; PERHAPS-REDUNDANT, aver that these edges are new.
127 (defun insert-one-edge (a b &optional perhaps-redundant)
128 (declare (type vertex a b))
129 (aver (neq a b))
130 ;; not even in the same storage base => no conflict;
131 ;; or one is pre-allocated => handled via domain.
132 (unless (or (neq (sc-sb (vertex-sc a)) (sc-sb (vertex-sc b)))
133 (tn-offset (vertex-tn a))
134 (tn-offset (vertex-tn b)))
135 (aver (or (oset-adjoin (vertex-incidence a) b)
136 perhaps-redundant))
137 (aver (or (oset-adjoin (vertex-incidence b) a)
138 perhaps-redundant))))
140 ;; Partition the global TNs that appear in that IR2 block, between
141 ;; those that are LIVE throughout the block and the rest.
142 (defun block-gtns (block tn-vertex)
143 (declare (type ir2-block block)
144 (type hash-table tn-vertex))
145 (collect ((live-gtns)
146 (gtns))
147 (do ((conflict (ir2-block-global-tns block)
148 (global-conflicts-next-blockwise
149 conflict)))
150 ((null conflict)
151 (values (live-gtns) (gtns)))
152 (let ((tn (global-conflicts-tn conflict)))
153 (awhen (and (not (tn-offset tn))
154 (not (eql :component (tn-kind tn)))
155 (gethash tn tn-vertex))
156 (if (eql (global-conflicts-kind conflict) :live)
157 (live-gtns it)
158 (gtns (cons it conflict))))))))
160 ;; Scan CONFLICTS for conflicts with TNs that come after VERTEX in the
161 ;; local TN order. Also, add edges with all LIVE-GTNs: they conflict
162 ;; with everything but are absent from conflict bitvectors.
163 (defun insert-block-local-conflicts-for (vertex number conflicts
164 local-tns ltn-count
165 gtn-p live-gtns tn-vertex)
166 (declare (type vertex vertex) (type local-tn-number number)
167 (type local-tn-bit-vector conflicts)
168 (type local-tn-vector local-tns) (type local-tn-count ltn-count)
169 (type list live-gtns) (type hash-table tn-vertex))
170 ;; conflict with all live gtns
171 (dolist (b live-gtns)
172 (insert-one-edge vertex b gtn-p))
173 ;; and add conflicts if LTN number > number
174 (loop
175 with local = (tn-local (vertex-tn vertex))
176 for j from (1+ number) below ltn-count
177 when (plusp (sbit conflicts j))
178 do (let ((b (aref local-tns j)))
179 (when (tn-p b)
180 (aver (or gtn-p
181 (tn-global-conflicts b)
182 (eq local (tn-local b))))
183 (awhen (gethash b tn-vertex)
184 (insert-one-edge vertex it (and gtn-p
185 (tn-global-conflicts b))))))))
187 ;; Compute all conflicts in a single IR2 block
188 (defun insert-block-local-conflicts (block tn-vertex)
189 (declare (type ir2-block block)
190 (type hash-table tn-vertex))
191 (let* ((local-tns (ir2-block-local-tns block))
192 (n (ir2-block-local-tn-count block)))
193 (multiple-value-bind (live-gtns gtns)
194 (block-gtns block tn-vertex)
195 ;; all live gtns conflict with one another
196 (loop for (a . rest) on live-gtns do
197 (dolist (b rest)
198 (insert-one-edge a b t)))
199 ;; normal gtn-* edges
200 (loop for (a . conflict) in gtns do
201 (let ((number (global-conflicts-number conflict))
202 (conflicts (global-conflicts-conflicts conflict)))
203 (insert-block-local-conflicts-for a number conflicts
204 local-tns n
205 t live-gtns tn-vertex)))
206 ;; local-* interference
207 (dotimes (i n)
208 (binding* ((a (aref local-tns i))
209 (vertex (gethash a tn-vertex) :exit-if-null)
210 (conflicts (tn-local-conflicts a)))
211 (unless (or (tn-offset a)
212 (tn-global-conflicts a))
213 (insert-block-local-conflicts-for vertex i conflicts
214 local-tns n
215 nil live-gtns tn-vertex)))))))
217 ;; Compute all conflict edges for component
218 ;; COMPONENT-VERTICES is a list of vertices for :component TNs,
219 ;; GLOBAL-VERTICES a list of vertices for TNs with global conflicts,
220 ;; and LOCAL-VERTICES a list of vertices for local TNs.
222 ;; TN-VERTEX is a hash table from TN -> VERTEX, for all vertices that
223 ;; must be colored.
224 (defun insert-conflict-edges (component
225 component-vertices global-vertices
226 local-vertices tn-vertex)
227 (declare (type list component-vertices global-vertices local-vertices)
228 (type hash-table tn-vertex))
229 ;; COMPONENT vertices conflict with everything
230 (loop for (a . rest) on component-vertices
231 do (dolist (b rest)
232 (insert-one-edge a b))
233 (dolist (b global-vertices)
234 (insert-one-edge a b))
235 (dolist (b local-vertices)
236 (insert-one-edge a b)))
237 ;; Find the other edges by enumerating IR2 blocks
238 (do-ir2-blocks (block component)
239 (insert-block-local-conflicts block tn-vertex)))
241 ;;; Interference graph construction, the rest: annotating vertex
242 ;;; structures, and bundling up the conflict graph.
244 ;;; Also, permanently removing a vertex from a graph, without
245 ;;; reconstructing it from scratch.
247 ;; Supposing that TN is restricted to its preferred SC, what locations
248 ;; are available?
249 (defun restricted-tn-locations (tn)
250 (declare (type tn tn))
251 (let* ((sc (tn-sc tn))
252 (reserve (sc-reserve-locations sc)))
253 (loop
254 for loc in (sc-locations sc)
255 unless (or (and reserve (memq loc reserve)) ; common case: no reserve
256 (conflicts-in-sc tn sc loc))
257 collect loc)))
259 ;; walk over vertices, precomputing as much information as possible,
260 ;; and partitioning according to their kind.
261 ;; Return the partition, and a hash table to map tns to vertices.
262 (defun prepare-vertices (vertices)
263 (let (component-vertices
264 global-vertices
265 local-vertices
266 (tn-vertex (make-hash-table)))
267 (loop for i upfrom 0
268 for vertex in vertices
269 do (let* ((tn (vertex-tn vertex))
270 (offset (tn-offset tn))
271 (locs (if offset
272 (list offset)
273 (restricted-tn-locations tn))))
274 (aver (not (unbounded-tn-p tn)))
275 (setf (vertex-number vertex) i
276 (vertex-incidence vertex) (make-ordered-set)
277 (vertex-initial-domain vertex) locs
278 (vertex-initial-domain-size vertex) (length locs)
279 (vertex-color vertex) offset
280 (vertex-invisible vertex) nil
281 (vertex-spill-cost vertex) (tn-cost tn)
282 (gethash tn tn-vertex) vertex)
283 (cond (offset) ; precolored -> no need to track conflict
284 ((eql :component (tn-kind tn))
285 (push vertex component-vertices))
286 ((tn-global-conflicts tn)
287 (push vertex global-vertices))
289 (aver (tn-local tn))
290 (push vertex local-vertices)))))
291 (values component-vertices global-vertices local-vertices
292 tn-vertex)))
294 ;; Construct the interference graph for these vertices in the component.
295 ;; All TNs types are included in the graph, both with offset and without,
296 ;; but only those requiring coloring appear in the VERTICES slot.
297 (defun make-interference-graph (vertices component)
298 (multiple-value-bind (component-vertices global-vertices local-vertices
299 tn-vertex)
300 (prepare-vertices vertices)
301 (insert-conflict-edges component
302 component-vertices global-vertices local-vertices
303 tn-vertex)
304 ;; Normalize adjacency list ordering, and collect all uncolored
305 ;; vertices in the graph.
306 (collect ((colored)
307 (uncolored))
308 (dolist (v vertices)
309 (let ((incidence (vertex-incidence v)))
310 (setf (oset-members incidence)
311 ;; this really doesn't matter, but minimises variability
312 (sort (oset-members incidence) #'< :key #'vertex-number)))
313 (cond ((vertex-color v)
314 (aver (tn-offset (vertex-tn v)))
315 (colored v))
317 (aver (not (tn-offset (vertex-tn v))))
318 (uncolored v))))
319 ;; Later passes like having this list sorted; do it in advance.
320 (%make-interference-graph
321 :vertices (stable-sort (uncolored) #'< :key #'vertex-spill-cost)
322 :precolored-vertices (colored)
323 :tn-vertex tn-vertex
324 :tn-vertex-mapping (lambda (tn)
325 (awhen (gethash tn tn-vertex)
326 (values (vertex-color it) it)))))))
328 ;; &key reset: whether coloring/invisibility information should be
329 ;; removed from all the remaining vertices
330 (defun remove-vertex-from-interference-graph (vertex graph &key reset)
331 (declare (type vertex vertex) (type interference-graph graph))
332 (let ((vertices (if reset
333 (loop for v in (ig-vertices graph)
334 unless (eql v vertex)
335 do (aver (not (tn-offset (vertex-tn v))))
336 (setf (vertex-invisible v) nil
337 (vertex-color v) nil)
338 and collect v)
339 (remove vertex (ig-vertices graph)))))
340 (setf (ig-vertices graph) vertices)
341 (do-oset-elements (neighbor (vertex-incidence vertex) graph)
342 (oset-delete (vertex-incidence neighbor) vertex))))
344 ;;; Support code
346 ;; Return nil if COLOR conflicts with any of NEIGHBOR-COLORS.
347 ;; Take into account element sizes of the respective SCs.
348 (defun color-no-conflicts-p (color vertex)
349 (declare (type fixnum color)
350 (type vertex vertex)
351 (optimize speed (safety 0)))
352 (let ((color+size (+ color (sc-element-size (vertex-sc vertex)))))
353 (flet ((intervals-intersect-p (color2 vertex2)
354 (declare (fixnum color2))
355 (if (< color2 color)
356 (< color (+ color2 (sc-element-size (vertex-sc vertex2))))
357 (< color2 color+size))))
358 (do-oset-elements (neighbor (vertex-incidence vertex) t)
359 (cond ((vertex-invisible neighbor))
360 ((intervals-intersect-p (vertex-color neighbor) neighbor)
361 (return nil)))))))
363 ;; Assumes that VERTEX pack-type is :WIRED.
364 (defun vertex-color-possible-p (vertex color)
365 (declare (type fixnum color) (type vertex vertex))
366 (and (or (and (neq (vertex-pack-type vertex) :wired)
367 (not (tn-offset (vertex-tn vertex))))
368 (= color (the fixnum (vertex-color vertex))))
369 (member color (vertex-initial-domain vertex))
370 (color-no-conflicts-p color vertex)))
372 ;; Sorted list of all possible locations for vertex in its preferred
373 ;; SC: more heavily loaded (i.e that should be tried first) locations
374 ;; first. vertex-initial-domain is already sorted, only have to
375 ;; remove offsets that aren't currently available.
376 (defun vertex-domain (vertex)
377 (declare (type vertex vertex))
378 (remove-if-not (lambda (color)
379 (vertex-color-possible-p vertex color))
380 (vertex-initial-domain vertex)))
382 ;; Return a list of vertices that we might want VERTEX to share its
383 ;; location with.
384 (defun vertex-target-vertices (vertex tn-offset)
385 (declare (type vertex vertex) (type function tn-offset))
386 (let ((sb (sc-sb (vertex-sc vertex)))
387 (neighbors (vertex-incidence vertex))
388 vertices)
389 (do-target-tns (current (vertex-tn vertex) :limit 20)
390 (multiple-value-bind (offset target)
391 (funcall tn-offset current)
392 (when (and offset
393 (eq sb (sc-sb (tn-sc current)))
394 (not (oset-member neighbors target)))
395 (pushnew target vertices))))
396 (nreverse vertices)))
398 ;; Choose the "best" color for these vertices: a color is good if as
399 ;; many of these vertices simultaneously take that color, and those
400 ;; that can't have a low spill cost.
401 (defun vertices-best-color (vertices colors)
402 (let ((best-color nil)
403 (best-compatible '())
404 (best-cost nil))
405 ;; TODO: sort vertices by spill cost, so that high-spill cost ones
406 ;; are more likely to be compatible? We're trying to find a
407 ;; maximal 1-colorable subgraph here, ie. a maximum independent
408 ;; set :\ Still, a heuristic like first attempting to pack in
409 ;; max-cost vertices may be useful
410 (dolist (color colors)
411 (let ((compatible '())
412 (cost 0))
413 (dolist (vertex vertices)
414 (when (and (notany (lambda (existing)
415 (oset-member (vertex-incidence existing)
416 vertex))
417 compatible)
418 (vertex-color-possible-p vertex color))
419 (incf cost (max 1 (vertex-spill-cost vertex)))
420 (push vertex compatible)))
421 (when (or (null best-cost)
422 (> cost best-cost))
423 (setf best-color color
424 best-compatible compatible
425 best-cost cost))))
426 (values best-color best-compatible)))
428 ;;; Coloring inner loop
430 ;; Greedily choose the color for this vertex, also moving around any
431 ;; :target vertex to the same color if possible.
432 (defun find-vertex-color (vertex tn-vertex-mapping)
433 (awhen (vertex-domain vertex)
434 (let* ((targets (vertex-target-vertices vertex tn-vertex-mapping))
435 (sc (vertex-sc vertex))
436 (sb (sc-sb sc)))
437 (multiple-value-bind (color recolor-vertices)
438 (if targets
439 (vertices-best-color targets it)
440 (values (first it) nil))
441 (aver color)
442 (dolist (target recolor-vertices)
443 (aver (vertex-color target))
444 (unless (eql color (vertex-color target))
445 (aver (eq sb (sc-sb (vertex-sc target))))
446 (aver (not (tn-offset (vertex-tn target))))
447 #+nil ; this check is slow
448 (aver (vertex-color-possible-p target color))
449 (setf (vertex-color target) color)))
450 color))))
452 ;; Partition vertices into those that are likely to be colored and
453 ;; those that are likely to be spilled. Assumes that the interference
454 ;; graph's vertices are sorted with the least spill cost first, so
455 ;; that the stacks end up with the greatest spill cost vertices first.
456 (defun partition-and-order-vertices (interference-graph)
457 (flet ((domain-size (vertex)
458 (vertex-initial-domain-size vertex))
459 (degree (vertex)
460 (count-if-not #'vertex-invisible
461 (oset-members (vertex-incidence vertex))))
462 (eliminate-vertex (vertex)
463 (setf (vertex-invisible vertex) t)))
464 (let* ((precoloring-stack '())
465 (prespilling-stack '())
466 (vertices (ig-vertices interference-graph)))
467 ;; walk the vertices from least important to most important TN wrt
468 ;; spill cost. That way the TNs we really don't want to spill are
469 ;; at the head of the colouring lists.
470 (loop for vertex in vertices do
471 (aver (not (vertex-color vertex))) ; we already took those out above
472 (eliminate-vertex vertex)
473 ;; FIXME: some interference will be with vertices that don't
474 ;; take the same number of slots. Find a smarter heuristic.
475 (cond ((< (degree vertex) (domain-size vertex))
476 (push vertex precoloring-stack))
478 (push vertex prespilling-stack))))
479 (values precoloring-stack prespilling-stack))))
481 ;; Try and color the interference graph once.
482 (defun color-interference-graph (interference-graph)
483 (let ((tn-vertex (ig-tn-vertex-mapping interference-graph)))
484 (flet ((color-vertices (vertices)
485 (dolist (vertex vertices)
486 (awhen (find-vertex-color vertex tn-vertex)
487 (setf (vertex-color vertex) it
488 (vertex-invisible vertex) nil)))))
489 (multiple-value-bind (probably-colored probably-spilled)
490 (partition-and-order-vertices interference-graph)
491 (color-vertices probably-colored)
492 ;; These might benefit from further ordering... LexBFS?
493 (color-vertices probably-spilled))))
494 interference-graph)
496 ;;; Iterative spilling logic.
498 ;; maximum number of spill iterations
499 (defvar *pack-iterations* 500)
501 ;; Find the least-spill-cost neighbor in each color.
502 ;; FIXME: this is too slow and isn't the right interface anymore.
503 ;; The code might be fast enough if there were a simple way to detect
504 ;; whether a given vertex is a min-candidate for another uncolored
505 ;; vertex.
506 ;; I'm leaving this around as an idea of what a smart spill choice
507 ;; might be like. -- PK
508 #+nil
509 (defun collect-min-spill-candidates (vertex)
510 (let ((colors '()))
511 (do-oset-elements (neighbor (vertex-incidence vertex))
512 (when (eql :normal (vertex-pack-type neighbor))
513 (let* ((color (vertex-color neighbor))
514 (cell (assoc color colors))
515 (cost-neighbor (tn-spill-cost (vertex-tn neighbor))))
516 (cond (cell
517 (when (< cost-neighbor (tn-spill-cost
518 (vertex-tn (cdr cell))))
519 (setf (cdr cell) neighbor)))
520 (t (push (cons color neighbor) colors))))))
521 (remove nil (mapcar #'cdr colors))))
523 ;; Try to color the graph. If some TNs are left uncolored, find a
524 ;; spill candidate, force it on the stack, and try again.
525 (defun iterate-color (vertices component
526 &optional (iterations *pack-iterations*))
527 (let* ((spill-list '())
528 ;; presorting edges helps; later sorts are stable, so this
529 ;; ends up sorting by (sum of) loop depth for TNs with equal
530 ;; costs.
531 (vertices (stable-sort (copy-list vertices) #'>
532 :key (lambda (vertex)
533 (tn-loop-depth
534 (vertex-tn vertex)))))
535 (nvertices (length vertices))
536 (graph (make-interference-graph vertices component))
537 to-spill)
538 (labels ((spill-candidates-p (vertex)
539 (unless (vertex-color vertex)
540 (aver (eql :normal (vertex-pack-type vertex)))
542 (iter (to-spill)
543 (when to-spill
544 (setf (vertex-invisible to-spill) t
545 (vertex-color to-spill) nil)
546 (push to-spill spill-list)
547 (setf graph (remove-vertex-from-interference-graph
548 to-spill graph :reset t)))
549 (color-interference-graph graph)
550 (find-if #'spill-candidates-p (ig-vertices graph))))
551 (loop repeat iterations
552 while (setf to-spill (iter to-spill))))
553 (let ((colored (ig-vertices graph)))
554 (aver (= nvertices (+ (length spill-list) (length colored)
555 (length (ig-precolored-vertices graph)))))
556 colored)))
558 ;;; Nice interface
560 ;; Just pack vertices that have been assigned a color.
561 (defun pack-colored (colored-vertices optimize)
562 (dolist (vertex colored-vertices)
563 (let* ((color (vertex-color vertex))
564 (tn (vertex-tn vertex)))
565 (cond ((tn-offset tn))
566 (color
567 (aver (not (conflicts-in-sc tn (tn-sc tn) color)))
568 (setf (tn-offset tn) color)
569 (pack-wired-tn (vertex-tn vertex) optimize))
571 ;; we better not have a :restricted TN not packed in its
572 ;; finite SC
573 (aver (neq (vertex-pack-type vertex) :restricted)))))))
575 ;; Pack pre-allocated TNs, collect vertices, and color.
576 (defun pack-iterative (component 2comp optimize)
577 (declare (type component component) (type ir2-component 2comp))
578 (collect ((vertices))
579 ;; Pack TNs that *must* be in a certain location, but still
580 ;; register them in the interference graph: it's useful to have
581 ;; them in the graph for targeting purposes.
582 (do ((tn (ir2-component-wired-tns 2comp) (tn-next tn)))
583 ((null tn))
584 (pack-wired-tn tn optimize)
585 (unless (unbounded-tn-p tn)
586 (vertices (make-vertex tn :wired))))
588 ;; Preallocate vertices that *must* be in this finite SC. If
589 ;; targeting is improved, giving them a high priority in regular
590 ;; regalloc may be a better idea.
591 (collect ((component)
592 (normal))
593 (do ((tn (ir2-component-restricted-tns 2comp) (tn-next tn)))
594 ((null tn))
595 (unless (or (tn-offset tn) (unbounded-tn-p tn))
596 (vertices (make-vertex tn :restricted))
597 (if (eq :component (tn-kind tn))
598 (component tn)
599 (normal tn))))
600 ;; First, pack TNs that span the whole component to minimise
601 ;; fragmentation. Also, pack high cost TNs first, so they get
602 ;; nice targeting.
603 (flet ((pack-tns (tns)
604 (dolist (tn (stable-sort tns #'> :key #'tn-cost))
605 (pack-tn tn t optimize))))
606 (pack-tns (component))
607 (pack-tns (normal))))
609 ;; Now that all pre-packed TNs are registered as vertices, work on
610 ;; the rest. Walk through all normal TNs, and determine whether
611 ;; we should try to put them in registers or stick them straight
612 ;; to the stack.
613 (do ((tn (ir2-component-normal-tns 2comp) (tn-next tn)))
614 ((null tn))
615 ;; Only consider TNs that aren't forced on the stack and for
616 ;; which the spill cost is non-negative (i.e. not live across so
617 ;; many calls that it's simpler to just leave them on the stack)
618 (when (and (not (tn-offset tn))
619 (neq (tn-kind tn) :more)
620 (not (unbounded-tn-p tn))
621 (not (and (sc-save-p (tn-sc tn)) ; SC is caller-save, and
622 (minusp (tn-cost tn))))) ; TN lives in many calls
623 ;; otherwise, we'll let the final pass handle them.
624 (vertices (make-vertex tn :normal))))
625 ;; Sum loop depths to guide the spilling logic
626 (assign-tn-depths component :reducer #'+)
627 ;; Iteratively find a coloring/spill partition, and allocate those
628 ;; for which we have a location
629 (pack-colored (iterate-color (vertices) component)
630 optimize))
631 nil)