Chez Scheme: move cp machine-register indirection

Register allocation needs fresh machine-register state for each
compilation, and that was previously implemented by allocating a new
register record and indirecting references through a parameter. Move
the indirection to the places where conflict-set, index, and precolor
state is manipulated, and pass a state vector though to keep access
efficient. This change makes compilation slightly faster, and it makes
registers easier to work with by not having to introduce
indirections/delays in various places for register references.
This commit is contained in:
Matthew Flatt 2021-03-14 09:56:26 -06:00
parent 467ca64a7f
commit c0cfd32bcb
6 changed files with 256 additions and 188 deletions

View File

@ -2408,10 +2408,10 @@
(or (andmap double-member? members)
(andmap float-member? members)))))]
[else #f]))
(define int-argument-regs (lambda () (list %Carg1 %Carg2 %Carg3 %Carg4
%Carg5 %Carg6 %Carg7 %Carg8)))
(define fp-argument-regs (lambda () (list %Cfparg1 %Cfparg2 %Cfparg3 %Cfparg4
%Cfparg5 %Cfparg6 %Cfparg7 %Cfparg8)))
(define int-argument-regs (list %Carg1 %Carg2 %Carg3 %Carg4
%Carg5 %Carg6 %Carg7 %Carg8))
(define fp-argument-regs (list %Cfparg1 %Cfparg2 %Cfparg3 %Cfparg4
%Cfparg5 %Cfparg6 %Cfparg7 %Cfparg8))
(define save-and-restore
(lambda (regs e)
(safe-assert (andmap reg? regs))
@ -2499,7 +2499,7 @@
(define categorize-arguments
(lambda (types varargs-after)
(let loop ([types types] [int* (int-argument-regs)] [fp* (fp-argument-regs)]
(let loop ([types types] [int* int-argument-regs] [fp* fp-argument-regs]
[varargs-after varargs-after]
;; accumulate alignment from previous args so we can compute any
;; needed padding and alignment after this next argument

View File

@ -8473,6 +8473,7 @@
(define-threaded max-fv)
(define-threaded max-fs@call)
(define-threaded poison-cset)
(define-threaded current-reg-spillinfo)
(define no-live* empty-tree)
@ -8486,18 +8487,18 @@
(tree-same? live1 live2)))
(define live?
(lambda (live* live-size x)
(tree-bit-set? live* live-size (var-index x))))
(lambda (live* live-size x reg-spillinfo)
(tree-bit-set? live* live-size (var-index x reg-spillinfo))))
(define get-live-vars
(lambda (live* live-size v)
(tree-extract live* live-size v)))
(define make-add-var
(lambda (live-size)
(lambda (live-size reg-spillinfo)
; add x to live*. result is eq? to live* if x is already in live*.
(lambda (live* x)
(let ([index (var-index x)])
(let ([index (var-index x reg-spillinfo)])
(if index
(let ([new (tree-bit-set live* live-size index)])
(safe-assert (or (eq? new live*) (not (tree-same? new live*))))
@ -8506,11 +8507,11 @@
(define make-remove-var
; remove x from live*. result is eq? to live* if x is not in live*.
(lambda (live-size)
(lambda (live-size reg-spillinfo)
(lambda (live* x)
(let ([index (var-index x)])
(let ([index (var-index x reg-spillinfo)])
(if index
(let ([new (tree-bit-unset live* live-size (var-index x))])
(let ([new (tree-bit-unset live* live-size (var-index x reg-spillinfo))])
(safe-assert (or (eq? new live*) (not (tree-same? new live*))))
new)
live*)))))
@ -8580,9 +8581,9 @@
[(1) #t])))
(define do-live-analysis!
(lambda (live-size entry-block*)
(define add-var (make-add-var live-size))
(define remove-var (make-remove-var live-size))
(lambda (live-size entry-block* reg-spillinfo)
(define add-var (make-add-var live-size reg-spillinfo))
(define remove-var (make-remove-var live-size reg-spillinfo))
(define-who scan-block
; if we maintain a list of kills and a list of useless variables for
; each block, and we discover on entry to scan-block that the useless
@ -8638,7 +8639,7 @@
(lambda (out instr)
(nanopass-case (L15a Effect) instr
[(set! ,live-info ,x ,rhs)
(if (var-index x)
(if (var-index x reg-spillinfo)
(let ([new-out (remove-var out x)])
(if (and (eq? new-out out)
(nanopass-case (L15a Rhs) rhs
@ -8888,11 +8889,11 @@
(refine (fxsrl skip 1) skip)))))))
(define-who do-spillable-conflict!
(lambda (kspillable kfv varvec live-size block*)
(define remove-var (make-remove-var live-size))
(lambda (kspillable reg-spillinfo kfv varvec live-size block*)
(define remove-var (make-remove-var live-size reg-spillinfo))
(define add-move!
(lambda (x1 x2)
(when (var-index x2)
(when (var-index x2 reg-spillinfo)
($add-move! x1 x2 2)
($add-move! x2 x1 2))))
(define add-conflict!
@ -8900,14 +8901,14 @@
; invariants:
; all poison spillables explicitly point to all spillables
; all non-poison spillables implicitly point to all poison spillables via poison-cset
(let ([x-offset (var-index x)])
(let ([x-offset (var-index x reg-spillinfo)])
(when x-offset
(if (and (fx< x-offset kspillable) (uvar-poison? x))
(tree-for-each out live-size kspillable (fx+ kspillable kfv)
(lambda (y-offset)
; frame y -> poison spillable x
(conflict-bit-set! (var-spillable-conflict* (vector-ref varvec y-offset)) x-offset)))
(let ([cset (var-spillable-conflict* x)])
(conflict-bit-set! (var-spillable-conflict* (vector-ref varvec y-offset) reg-spillinfo) x-offset)))
(let ([cset (var-spillable-conflict* x reg-spillinfo)])
(if (fx< x-offset kspillable)
(begin
(tree-for-each out live-size 0 kspillable
@ -8917,12 +8918,12 @@
; non-poison spillable x -> non-poison spillable y
(conflict-bit-set! cset y-offset)
; and vice versa
(conflict-bit-set! (var-spillable-conflict* y) x-offset)))))
(conflict-bit-set! (var-spillable-conflict* y reg-spillinfo) x-offset)))))
(tree-for-each out live-size kspillable live-size
(lambda (y-offset)
(let ([y (vector-ref varvec y-offset)])
; frame or register y -> non-poison spillable x
(conflict-bit-set! (var-spillable-conflict* y) x-offset)))))
(conflict-bit-set! (var-spillable-conflict* y reg-spillinfo) x-offset)))))
(if (fx< x-offset (fx+ kspillable kfv))
(tree-for-each out live-size 0 kspillable
(lambda (y-offset)
@ -8947,8 +8948,8 @@
(if (live-info-useless live-info)
new-effect*
(let ([live (live-info-live live-info)])
(when (var-index x)
(if (and (var? rhs) (var-index rhs))
(when (var-index x reg-spillinfo)
(if (and (var? rhs) (var-index rhs reg-spillinfo))
(begin
(add-conflict! x (remove-var live rhs))
(add-move! x rhs))
@ -8970,11 +8971,11 @@
(conflict-bit-set! poison-cset i)
; leaving each poison spillable in conflict with itself, but this shouldn't matter
; since we never ask for the degree of a poison spillable
(var-spillable-conflict*-set! x (make-full-cset kspillable)))
(var-spillable-conflict*-set! x (make-empty-cset kspillable)))))
(var-spillable-conflict*-set! x reg-spillinfo (make-full-cset kspillable)))
(var-spillable-conflict*-set! x reg-spillinfo (make-empty-cset kspillable)))))
(do ([i kspillable (fx+ i 1)])
((fx= i live-size))
(var-spillable-conflict*-set! (vector-ref varvec i) (make-empty-cset kspillable)))
(var-spillable-conflict*-set! (vector-ref varvec i) reg-spillinfo (make-empty-cset kspillable)))
(for-each
(lambda (block)
(block-effect*-set! block
@ -8982,15 +8983,15 @@
block*)))
(define-who show-conflicts
(lambda (name varvec unvarvec)
(lambda (name varvec unvarvec reg-spillinfo)
(define any? #f)
(printf "\n~s conflicts:" name)
(for-each
(lambda (x)
(let ([ls (append
(let ([cset (var-spillable-conflict* x)])
(let ([cset (var-spillable-conflict* x reg-spillinfo)])
(if cset (extract-conflicts cset varvec) '()))
(let ([cset (var-unspillable-conflict* x)])
(let ([cset (var-unspillable-conflict* x reg-spillinfo)])
(if cset (extract-conflicts cset unvarvec) '())))])
(unless (null? ls) (set! any? #t) (printf "\n~s:~{ ~s~}" x ls))))
(append spillable* unspillable* (vector->list regvec) (map get-fv (iota (fx+ max-fv 1)))))
@ -8999,19 +9000,19 @@
(module (assign-frame! assign-new-frame!)
(define update-conflict!
(lambda (fv spill)
(let ([cset1 (var-spillable-conflict* fv)]
[cset2 (var-spillable-conflict* spill)])
(lambda (fv spill reg-spillinfo)
(let ([cset1 (var-spillable-conflict* fv reg-spillinfo)]
[cset2 (var-spillable-conflict* spill reg-spillinfo)])
(if cset1
(cset-merge! cset1 cset2)
; tempting to set to cset2 rather than (cset-copy cset2), but this would not be
; correct for local saves, which need their unaltered sets for later, and copying
; is cheap anyway.
(var-spillable-conflict*-set! fv (cset-copy cset2))))
(unless (uvar-poison? spill) (cset-merge! (var-spillable-conflict* fv) poison-cset))))
(var-spillable-conflict*-set! fv reg-spillinfo (cset-copy cset2))))
(unless (uvar-poison? spill) (cset-merge! (var-spillable-conflict* fv reg-spillinfo) poison-cset))))
(define assign-frame!
(lambda (spill*)
(lambda (spill* reg-spillinfo)
(define sort-spill*
; NB: sorts based on likelihood of successfully assigning move-related vars to the same location
; NB: probably should sort based on value of assigning move-related vars to the same location,
@ -9035,8 +9036,8 @@
(lambda (x0 succ fail)
(define conflict-fv?
(lambda (x fv)
(let ([cset (var-spillable-conflict* fv)])
(and cset (conflict-bit-set? cset (var-index x))))))
(let ([cset (var-spillable-conflict* fv reg-spillinfo)])
(and cset (conflict-bit-set? cset (var-index x reg-spillinfo))))))
(let f ([x x0] [work* '()] [clear-seen! void])
(if (uvar-seen? x)
(if (null? work*) (begin (clear-seen!) (fail)) (f (car work*) (cdr work*) clear-seen!))
@ -9067,7 +9068,7 @@
(lambda (home max-fv first-open)
(safe-assert (compatible-fv? home (uvar-type spill)))
(uvar-location-set! spill home)
(update-conflict! home spill)
(update-conflict! home spill reg-spillinfo)
(let ([max-fv
(constant-case ptr-bits
[(32)
@ -9084,14 +9085,14 @@
(lambda (home) (return home max-fv first-open))
(lambda ()
(let f ([first-open first-open])
(let* ([fv (get-fv first-open (uvar-type spill))] [cset (var-spillable-conflict* fv)])
(let* ([fv (get-fv first-open (uvar-type spill))] [cset (var-spillable-conflict* fv reg-spillinfo)])
(if (and cset (cset-full? cset))
(f (fx+ first-open 1))
(let ([spill-offset (var-index spill)])
(let ([spill-offset (var-index spill reg-spillinfo)])
(let f ([fv-offset first-open] [fv fv] [cset cset])
(if (or (and cset (conflict-bit-set? cset spill-offset))
(not (compatible-fv? fv (uvar-type spill))))
(let* ([fv-offset (fx+ fv-offset 1)] [fv (get-fv fv-offset (uvar-type spill))] [cset (var-spillable-conflict* fv)])
(let* ([fv-offset (fx+ fv-offset 1)] [fv (get-fv fv-offset (uvar-type spill))] [cset (var-spillable-conflict* fv reg-spillinfo)])
(f fv-offset fv cset))
(return fv (fxmax fv-offset max-fv) first-open)))))))))))
(define find-homes!
@ -9106,9 +9107,9 @@
; live across only a few (only when setup-nfv?)
(set! max-fv (find-homes! (sort-spill* spill*) max-fv 1))))
(define-pass assign-new-frame! : (L15a Dummy) (ir lambda-info live-size varvec block*) -> (L15b Dummy) ()
(define-pass assign-new-frame! : (L15a Dummy) (ir lambda-info live-size varvec reg-spillinfo block*) -> (L15b Dummy) ()
(definitions
(define remove-var (make-remove-var live-size))
(define remove-var (make-remove-var live-size reg-spillinfo))
(define find-max-fv
(lambda (call-live*)
(fold-left
@ -9122,8 +9123,8 @@
(and (or (not (car nfv*))
(let ([fv (get-fv offset)])
(and (compatible-fv? fv 'ptr)
(let ([cset (var-spillable-conflict* fv)])
(not (and cset (conflict-bit-set? cset (var-index (car nfv*)))))))))
(let ([cset (var-spillable-conflict* fv reg-spillinfo)])
(not (and cset (conflict-bit-set? cset (var-index (car nfv*) reg-spillinfo))))))))
(loop (cdr nfv*) (fx+ offset 1)))))))
(define assign-new-frame!
(lambda (cnfv* nfv** call-live*)
@ -9134,7 +9135,7 @@
(let* ([nfv (car nfv*)] [home (get-fv offset (uvar-type nfv))])
(safe-assert (compatible-fv? home (uvar-type nfv)))
(uvar-location-set! nfv home)
(update-conflict! home nfv)
(update-conflict! home nfv reg-spillinfo)
(set-offsets! (cdr nfv*) (fx+ offset 1))))))
(let ([arg-offset (fx+ (length cnfv*) 1)]) ; +1 for return address slot
(let loop ([base (fx+ (find-max-fv call-live*) 1)])
@ -9246,7 +9247,7 @@
[(restore-local-saves ,live-info ,info)
(with-output-language (L15b Effect)
(let ([live (live-info-live live-info)])
(let loop ([x* (filter (lambda (x) (live? live live-size x)) (info-newframe-local-save* info))]
(let loop ([x* (filter (lambda (x) (live? live live-size x reg-spillinfo)) (info-newframe-local-save* info))]
[live live]
[new-effect* new-effect*])
(if (null? x*)
@ -9292,7 +9293,8 @@
[(newframe-block? block)
(let ([info (newframe-block-info block)])
(process-info-newframe! info)
(safe-assert (andmap (lambda (x) (live? (newframe-block-live-call block) live-size x)) (info-newframe-local-save* info)))
(safe-assert (andmap (lambda (x) (live? (newframe-block-live-call block) live-size x reg-spillinfo))
(info-newframe-local-save* info)))
(with-output-language (L15b Effect)
(let ([live (newframe-block-live-out block)])
(fold-left
@ -9415,7 +9417,8 @@
(define make-restricted-unspillable
(lambda (x reg*)
(import (only np-languages make-restricted-unspillable))
(safe-assert (andmap reg? reg*) (andmap var-index reg*))
(safe-assert (andmap reg? reg*)
(andmap (lambda (r) (var-index r current-reg-spillinfo)) reg*))
(let ([tmp (make-restricted-unspillable x reg*)])
(set! unspillable* (cons tmp unspillable*))
tmp)))
@ -9425,11 +9428,12 @@
; for correct code but causes a spilled unspillable error if we try to use the same
; machine register for two conflicting variables
(lambda (name reg)
(or (reg-precolored reg)
(let ([tmp (make-restricted-unspillable name (remq reg (vector->list regvec)))])
(safe-assert (memq reg (vector->list regvec)))
(reg-precolored-set! reg tmp)
tmp))))
(let ([reg-spillinfo current-reg-spillinfo])
(or (reg-precolored reg reg-spillinfo)
(let ([tmp (make-restricted-unspillable name (remq reg (vector->list regvec)))])
(safe-assert (memq reg (vector->list regvec)))
(reg-precolored-set! reg reg-spillinfo tmp)
tmp)))))
(define-syntax build-set!
(lambda (x)
@ -9737,10 +9741,10 @@
[(k context (sym ...) cl ...) #'(k context (sym ...) (definitions) cl ...)]
[(k context sym cl ...) (identifier? #'sym) #'(k context (sym) (definitions) cl ...)])))
(define-pass select-instructions! : (L15c Dummy) (ir block* live-size force-overflow?) -> (L15d Dummy) ()
(define-pass select-instructions! : (L15c Dummy) (ir block* live-size reg-spillinfo force-overflow?) -> (L15d Dummy) ()
(definitions
(module (handle-jump handle-effect-inline handle-pred-inline handle-value-inline)
(define add-var (make-add-var live-size))
(define add-var (make-add-var live-size reg-spillinfo))
(define Triv
(lambda (out t)
(nanopass-case (L15d Triv) t
@ -9927,8 +9931,8 @@
)
(define-who do-unspillable-conflict!
(lambda (kfv kspillable varvec live-size kunspillable unvarvec block*)
(define remove-var (make-remove-var live-size))
(lambda (kfv kspillable reg-spillinfo varvec live-size kunspillable unvarvec block*)
(define remove-var (make-remove-var live-size reg-spillinfo))
(define unspillable?
(lambda (x)
(and (uvar? x) (uvar-unspillable? x))))
@ -9941,26 +9945,26 @@
unspillable*)))
(define add-move!
(lambda (x1 x2)
(when (var-index x2)
(when (var-index x2 reg-spillinfo)
($add-move! x1 x2 2)
($add-move! x2 x1 2))))
(define add-move-hint!
(lambda (x1 x2)
(when (var-index x2)
(when (var-index x2 reg-spillinfo)
($add-move! x1 x2 1)
($add-move! x2 x1 1))))
(define add-static-conflict!
(lambda (u reg*)
(let ([u-offset (var-index u)])
(let ([u-offset (var-index u reg-spillinfo)])
(for-each
(lambda (reg) (conflict-bit-set! (var-unspillable-conflict* reg) u-offset))
(lambda (reg) (conflict-bit-set! (var-unspillable-conflict* reg reg-spillinfo) u-offset))
reg*))))
(define add-us->s-conflicts!
(lambda (x out) ; x is an unspillable
(let ([x-offset (var-index x)] [cset (var-spillable-conflict* x)])
(let ([x-offset (var-index x reg-spillinfo)] [cset (var-spillable-conflict* x reg-spillinfo)])
(tree-for-each out live-size 0 live-size
(lambda (y-offset)
(let* ([y (vector-ref varvec y-offset)] [y-cset (var-unspillable-conflict* y)])
(let* ([y (vector-ref varvec y-offset)] [y-cset (var-unspillable-conflict* y reg-spillinfo)])
(when y-cset
; if y is a spillable, point the unspillable x at y
(when (fx< y-offset kspillable) (conflict-bit-set! cset y-offset))
@ -9968,23 +9972,23 @@
(conflict-bit-set! y-cset x-offset))))))))
(define add-us->us-conflicts!
(lambda (x unspillable*) ; x is a unspillable
(let ([x-offset (var-index x)] [cset (var-unspillable-conflict* x)])
(let ([x-offset (var-index x reg-spillinfo)] [cset (var-unspillable-conflict* x reg-spillinfo)])
(for-each
(lambda (y)
(let ([y-offset (var-index y)])
(let ([y-offset (var-index y reg-spillinfo)])
(conflict-bit-set! cset y-offset)
(conflict-bit-set! (var-unspillable-conflict* y) x-offset)))
(conflict-bit-set! (var-unspillable-conflict* y reg-spillinfo) x-offset)))
unspillable*))))
(define add-s->us-conflicts!
(lambda (x unspillable*) ; x is a spillable or register
(let ([x-offset (var-index x)] [cset (var-unspillable-conflict* x)])
(let ([x-offset (var-index x reg-spillinfo)] [cset (var-unspillable-conflict* x reg-spillinfo)])
(for-each
(lambda (y)
(let ([y-offset (var-index y)])
(let ([y-offset (var-index y reg-spillinfo)])
; point x at unspillable y
(conflict-bit-set! cset y-offset)
; if x is a spillable, point unspillable y at x
(when (fx< x-offset kspillable) (conflict-bit-set! (var-spillable-conflict* y) x-offset))))
(when (fx< x-offset kspillable) (conflict-bit-set! (var-spillable-conflict* y reg-spillinfo) x-offset))))
unspillable*))))
(define Triv
(lambda (unspillable* t)
@ -10021,7 +10025,7 @@
(let ([unspillable* (remq x unspillable*)])
(safe-assert (uvar-seen? x))
(uvar-seen! x #f)
(if (and (var? rhs) (var-index rhs))
(if (and (var? rhs) (var-index rhs reg-spillinfo))
(begin
(if (unspillable? rhs)
(begin
@ -10036,7 +10040,7 @@
(add-us->s-conflicts! x spillable-live)))
(Rhs unspillable* rhs))
(begin
(when (var-unspillable-conflict* x)
(when (var-unspillable-conflict* x reg-spillinfo)
(if (unspillable? rhs)
(begin
(add-s->us-conflicts! x (remq rhs unspillable*))
@ -10048,8 +10052,8 @@
[(move-related ,x1 ,x2) (add-move-hint! x1 x2) unspillable*]
[(overflow-check ,p ,e* ...) (Effect* (reverse e*) '()) (Pred p)]
[else unspillable*])))))
(for-each (lambda (x) (var-spillable-conflict*-set! x (make-empty-cset kspillable))) unspillable*)
(let ([f (lambda (x) (var-unspillable-conflict*-set! x (make-empty-cset kunspillable)))])
(for-each (lambda (x) (var-spillable-conflict*-set! x reg-spillinfo (make-empty-cset kspillable))) unspillable*)
(let ([f (lambda (x) (var-unspillable-conflict*-set! x reg-spillinfo (make-empty-cset kunspillable)))])
(vector-for-each f regvec)
(for-each f spillable*)
(vector-for-each f unvarvec))
@ -10065,7 +10069,7 @@
block*)))
(define-who assign-registers!
(lambda (lambda-info varvec unvarvec)
(lambda (lambda-info varvec unvarvec reg-spillinfo)
(define total-k (vector-length regvec))
(define fp-k (length extra-fpregisters))
(define ptr-k (- total-k fp-k))
@ -10089,18 +10093,18 @@
(uvar-degree-set! x
(fx+
; spills have been trimmed from the var-spillable-conflict* sets
(conflict-bit-count (var-spillable-conflict* x))
(conflict-bit-count (var-unspillable-conflict* x)))))
(conflict-bit-count (var-spillable-conflict* x reg-spillinfo))
(conflict-bit-count (var-unspillable-conflict* x reg-spillinfo)))))
x*)
; account for reg -> uvar conflicts
(vector-for-each
(lambda (reg)
(cset-for-each (var-spillable-conflict* reg)
(cset-for-each (var-spillable-conflict* reg reg-spillinfo)
(lambda (x-offset)
(let ([x (vector-ref varvec x-offset)])
(unless (uvar-location x)
(uvar-degree-set! x (fx+ (uvar-degree x) 1))))))
(cset-for-each (var-unspillable-conflict* reg)
(cset-for-each (var-unspillable-conflict* reg reg-spillinfo)
(lambda (x-offset)
(let ([x (vector-ref unvarvec x-offset)])
(uvar-degree-set! x (fx+ (uvar-degree x) 1))))))
@ -10110,8 +10114,8 @@
(define conflict?
(lambda (reg x)
(or (not (compatible-var-types? (reg-type reg) (uvar-type x)))
(let ([cset (if (uvar-unspillable? x) (var-unspillable-conflict* reg) (var-spillable-conflict* reg))])
(conflict-bit-set? cset (var-index x))))))
(let ([cset (if (uvar-unspillable? x) (var-unspillable-conflict* reg reg-spillinfo) (var-spillable-conflict* reg reg-spillinfo))])
(conflict-bit-set? cset (var-index x reg-spillinfo))))))
(define find-move-related-home
(lambda (x0 succ fail)
(let f ([x x0] [work* '()] [clear-seen! void])
@ -10140,8 +10144,8 @@
(lambda (home)
(define update-conflict!
(lambda (reg x)
(cset-merge! (var-spillable-conflict* reg) (var-spillable-conflict* x))
(cset-merge! (var-unspillable-conflict* reg) (var-unspillable-conflict* x))))
(cset-merge! (var-spillable-conflict* reg reg-spillinfo) (var-spillable-conflict* x reg-spillinfo))
(cset-merge! (var-unspillable-conflict* reg reg-spillinfo) (var-unspillable-conflict* x reg-spillinfo))))
(uvar-location-set! x home)
(update-conflict! home x)))
(find-move-related-home x
@ -10177,11 +10181,11 @@
(values x (remq x x*)))))
(define remove-victim!
(lambda (victim)
(cset-for-each (var-spillable-conflict* victim)
(cset-for-each (var-spillable-conflict* victim reg-spillinfo)
(lambda (offset)
(let ([x (vector-ref varvec offset)])
(uvar-degree-set! x (fx- (uvar-degree x) 1)))))
(cset-for-each (var-unspillable-conflict* victim)
(cset-for-each (var-unspillable-conflict* victim reg-spillinfo)
(lambda (offset)
(let ([x (vector-ref unvarvec offset)])
(uvar-degree-set! x (fx- (uvar-degree x) 1)))))))
@ -10438,16 +10442,17 @@
[(_ ?unparser pass-name ?arg ...)
#'(xpass pass-name (RAprinter ?unparser) (list ?arg ...))]))))
(safe-assert (andmap (lambda (x) (eq? (uvar-location x) #f)) local*))
(let ([kspillable (length local*)] [kfv (fx+ max-fv0 1)] [kreg (vector-length regvec)])
(fluid-let ([spillable* local*] [unspillable* '()] [max-fv max-fv0] [max-fs@call 0] [poison-cset (make-empty-cset kspillable)])
(let ([kspillable (length local*)] [kfv (fx+ max-fv0 1)] [kreg (vector-length regvec)] [reg-spillinfo (make-reg-spillinfo)])
(fluid-let ([spillable* local*] [unspillable* '()] [max-fv max-fv0] [max-fs@call 0]
[poison-cset (make-empty-cset kspillable)] [current-reg-spillinfo reg-spillinfo])
(let* ([live-size (fx+ kfv kreg kspillable)] [varvec (make-vector live-size)])
; set up var indices & varvec mapping from indices to vars
(fold-left (lambda (i x) (var-index-set! x i) (vector-set! varvec i x) (fx+ i 1)) 0 spillable*)
(do ([i 0 (fx+ i 1)]) ((fx= i kfv)) (let ([fv (get-fv i)] [i (fx+ i kspillable)]) (var-index-set! fv i) (vector-set! varvec i fv)))
(do ([i 0 (fx+ i 1)]) ((fx= i kreg)) (let ([reg (vector-ref regvec i)] [i (fx+ i kspillable kfv)]) (var-index-set! reg i) (vector-set! varvec i reg)))
(do ([i 0 (fx+ i 1)]) ((fx= i kreg)) (let ([reg (vector-ref regvec i)] [i (fx+ i kspillable kfv)]) (var-index-set! reg reg-spillinfo i) (vector-set! varvec i reg)))
(with-live-info-record-writer live-size varvec
; run intra/inter-block live analysis
(RApass unparse-L15a do-live-analysis! live-size entry-block*)
(RApass unparse-L15a do-live-analysis! live-size entry-block* reg-spillinfo)
; this is worth enabling from time to time...
#;(check-entry-live! (info-lambda-name info) live-size varvec entry-block*)
; rerun intra-block live analysis and record (fv v reg v spillable) x spillable conflicts
@ -10455,64 +10460,64 @@
;; NB: we could just use (vector-length varvec) to get live-size
(when (fx> kspillable 1000) ; NB: parameter?
(RApass unparse-L15a identify-poison! kspillable varvec live-size block*))
(RApass unparse-L15a do-spillable-conflict! kspillable kfv varvec live-size block*)
#;(show-conflicts (info-lambda-name info) varvec '#())
(RApass unparse-L15a do-spillable-conflict! kspillable reg-spillinfo kfv varvec live-size block*)
#;(show-conflicts (info-lambda-name info) varvec '#() reg-spillinfo)
; find frame homes for call-live variables; adds new fv x spillable conflicts
(RApass unparse-L15a assign-frame! (filter uvar-spilled? spillable*))
(RApass unparse-L15a assign-frame! (filter uvar-spilled? spillable*) reg-spillinfo)
#;(show-homes)
(RApass unparse-L15a record-inspector-information! info)
; determine frame sizes at nontail-call sites and assign homes to new-frame variables
; adds new fv x spillable conflicts
(let ([dummy (RApass unparse-L15b assign-new-frame! (with-output-language (L15a Dummy) `(dummy)) info live-size varvec block*)])
(let ([dummy (RApass unparse-L15b assign-new-frame! (with-output-language (L15a Dummy) `(dummy)) info live-size varvec reg-spillinfo block*)])
; record fp offset on entry to each block
(RApass unparse-L15b record-fp-offsets! entry-block*)
; assign frame homes to poison variables
(let ([spill* (filter (lambda (x) (and (not (uvar-location x)) (uvar-poison? x))) spillable*)])
(unless (null? spill*)
(for-each (lambda (x) (uvar-spilled! x #t)) spill*)
(RApass unparse-L15b assign-frame! spill*)))
(RApass unparse-L15b assign-frame! spill* reg-spillinfo)))
; on entry to loop, have assigned call-live and new-frame variables to frame homes, determined frame sizes, and computed block-entry fp offsets
(let ([saved-reg-csets (vector-map (lambda (reg) (cset-copy (var-spillable-conflict* reg))) regvec)]
(let ([saved-reg-csets (vector-map (lambda (reg) (cset-copy (var-spillable-conflict* reg reg-spillinfo))) regvec)]
[bcache* (map cache-block-info block*)])
(let loop ()
(for-each
(lambda (spill)
; remove each spill from each other spillable's spillable conflict set
(unless (uvar-poison? spill)
(let ([spill-index (var-index spill)])
(cset-for-each (var-spillable-conflict* spill)
(let ([spill-index (var-index spill reg-spillinfo)])
(cset-for-each (var-spillable-conflict* spill reg-spillinfo)
(lambda (i)
(let ([x (vector-ref varvec i)])
(unless (uvar-location x)
(conflict-bit-unset! (var-spillable-conflict* x) spill-index)))))))
(conflict-bit-unset! (var-spillable-conflict* x reg-spillinfo) spill-index)))))))
; release the spill's conflict* set
(var-spillable-conflict*-set! spill #f))
(var-spillable-conflict*-set! spill reg-spillinfo #f))
(filter uvar-location spillable*))
(set! spillable* (remp uvar-location spillable*))
(let ([saved-move* (map uvar-move* spillable*)])
#;(show-homes)
(let ([dummy (RApass unparse-L15c finalize-frame-locations! dummy block*)])
(let ([dummy (RApass unparse-L15d select-instructions! dummy block* live-size
(let ([dummy (RApass unparse-L15d select-instructions! dummy block* live-size reg-spillinfo
(let ([libspec (info-lambda-libspec info)])
(and libspec (libspec-does-not-expect-headroom? libspec))))])
(vector-for-each (lambda (reg) (reg-precolored-set! reg #f)) regvec)
(vector-for-each (lambda (reg) (reg-precolored-set! reg reg-spillinfo #f)) regvec)
(let* ([kunspillable (length unspillable*)] [unvarvec (make-vector kunspillable)])
; set up var indices & unvarvec mapping from indices to unspillables
(fold-left (lambda (i x) (var-index-set! x i) (vector-set! unvarvec i x) (fx+ i 1)) 0 unspillable*)
(fold-left (lambda (i x) (var-index-set! x reg-spillinfo i) (vector-set! unvarvec i x) (fx+ i 1)) 0 unspillable*)
; select-instrcutions! kept intra-block live analysis up-to-date, so now
; record (reg v spillable v unspillable) x unspillable conflicts
(RApass unparse-L15d do-unspillable-conflict! kfv kspillable varvec live-size kunspillable unvarvec block*)
#;(show-conflicts (info-lambda-name info) varvec unvarvec)
(RApass unparse-L15d assign-registers! info varvec unvarvec)
(RApass unparse-L15d do-unspillable-conflict! kfv kspillable reg-spillinfo varvec live-size kunspillable unvarvec block*)
#;(show-conflicts (info-lambda-name info) varvec unvarvec reg-spillinfo)
(RApass unparse-L15d assign-registers! info varvec unvarvec reg-spillinfo)
; release the unspillable conflict sets
(for-each (lambda (x) (var-unspillable-conflict*-set! x #f)) spillable*)
(vector-for-each (lambda (x) (var-unspillable-conflict*-set! x #f)) regvec)
(for-each (lambda (x) (var-unspillable-conflict*-set! x reg-spillinfo #f)) spillable*)
(vector-for-each (lambda (x) (var-unspillable-conflict*-set! x reg-spillinfo #f)) regvec)
#;(show-homes unspillable*)
(if (everybody-home?)
(let ([dummy (RApass unparse-L15e finalize-register-locations! dummy block*)])
; release the spillable conflict sets
(vector-for-each (lambda (reg) (var-spillable-conflict*-set! reg #f)) regvec)
(do ([i max-fv (fx- i 1)]) ((fx< i 0)) (var-spillable-conflict*-set! (get-fv i) #f))
(vector-for-each (lambda (reg) (var-spillable-conflict*-set! reg reg-spillinfo #f)) regvec)
(do ([i max-fv (fx- i 1)]) ((fx< i 0)) (var-spillable-conflict*-set! (get-fv i) reg-spillinfo #f))
(let-values ([(dummy entry-block* block*)
(xpass expose-overflow-check-blocks!
(lambda (val*)
@ -10525,11 +10530,12 @@
`(lambda ,info (,entry-block* ...) (,block* ...))))
(begin
(for-each restore-block-info! block* bcache*)
(vector-for-each var-spillable-conflict*-set! regvec saved-reg-csets)
(vector-for-each (lambda (r c*) (var-spillable-conflict*-set! r reg-spillinfo c*))
regvec saved-reg-csets)
(for-each (lambda (x) (uvar-location-set! x #f)) spillable*)
(for-each uvar-move*-set! spillable* saved-move*)
(set! unspillable* '())
(RApass unparse-L15b assign-frame! (filter uvar-spilled? spillable*))
(RApass unparse-L15b assign-frame! (filter uvar-spilled? spillable*) reg-spillinfo)
(loop)))))))))))))))])))
; NB: commonize with earlier
@ -10679,7 +10685,6 @@
(set! $np-compile
(lambda (original-input-expression pt?)
(with-initialized-registers
(fluid-let ([frame-vars (make-vector 8 #f)]
[next-lambda-seqno 0]
[pass-time? pass-time?])
@ -10722,11 +10727,10 @@
(pass np-flatten-case-lambda unparse-L12)
(pass np-insert-trap-check unparse-L12.5)
(pass np-impose-calling-conventions unparse-L13)
np-after-calling-conventions)))))
np-after-calling-conventions))))
(set! $np-boot-code
(lambda (which)
(with-initialized-registers
($c-func-code-record
(fluid-let ([frame-vars (make-vector 8 #f)]
[next-lambda-seqno 0]
@ -10735,7 +10739,7 @@
(np-after-calling-conventions
(with-output-language (L13 Program)
(let ([l (make-local-label 'Linvoke)])
`(labels ([,l (hand-coded ,which)]) ,l))))))))))
`(labels ([,l (hand-coded ,which)]) ,l)))))))))
)
(set! $np-tracer tracer)

View File

@ -95,38 +95,33 @@
((new kill*) libspec save-ra?)]))))
(module (intrinsic-info-asmlib intrinsic-return-live* intrinsic-entry-live* intrinsic-modify-reg* dorest-intrinsics)
; standing on our heads here to avoid referencing registers at
; load time...would be cleaner if registers were immutable,
; i.e., mutable fields (direct and inherited from var) were kept
; in separate tables...but that might add more cost to register
; allocation, which is already expensive.
(define-record-type intrinsic
(nongenerative #{intrinsic bcpkdd2y9yyv643zicd4jbe3y-8})
(nongenerative #{intrinsic bcpkdd2y9yyv643zicd4jbe3y-A})
(sealed #t)
(fields libspec get-kill* get-live* get-rv*))
(fields libspec kill* live* rv*))
(define intrinsic-info-asmlib
(lambda (intrinsic save-ra?)
(make-info-asmlib ((intrinsic-get-kill* intrinsic))
(make-info-asmlib (intrinsic-kill* intrinsic)
(intrinsic-libspec intrinsic)
save-ra?
((intrinsic-get-live* intrinsic)))))
(intrinsic-live* intrinsic))))
(define intrinsic-return-live*
; used a handful of times, just while compiling library.ss...don't bother optimizing
(lambda (intrinsic)
(fold-left (lambda (live* kill) (remq kill live*))
(vector->list regvec) ((intrinsic-get-kill* intrinsic)))))
(vector->list regvec) (intrinsic-kill* intrinsic))))
(define intrinsic-entry-live*
; used a handful of times, just while compiling library.ss...don't bother optimizing
(lambda (intrinsic) ; return-live* - rv + live*
(fold-left (lambda (live* live) (if (memq live live*) live* (cons live live*)))
(fold-left (lambda (live* rv) (remq rv live*))
(intrinsic-return-live* intrinsic)
((intrinsic-get-rv* intrinsic)))
((intrinsic-get-live* intrinsic)))))
(intrinsic-rv* intrinsic))
(intrinsic-live* intrinsic))))
(define intrinsic-modify-reg*
(lambda (intrinsic)
(append ((intrinsic-get-rv* intrinsic))
((intrinsic-get-kill* intrinsic)))))
(append (intrinsic-rv* intrinsic)
(intrinsic-kill* intrinsic))))
(define-syntax declare-intrinsic
(syntax-rules (unquote)
[(_ name entry-name (kill ...) (live ...) (rv ...))
@ -134,9 +129,9 @@
(define name
(make-intrinsic
(lookup-libspec entry-name)
(lambda () (reg-list kill ...))
(lambda () (reg-list live ...))
(lambda () (reg-list rv ...))))
(reg-list kill ...)
(reg-list live ...)
(reg-list rv ...)))
(export name))]))
; must include in kill ... any register explicitly assigned by the intrinsic
; plus additional registers as needed to avoid spilled unspillables. the
@ -183,9 +178,9 @@
'()
(cons #`(make-intrinsic
(lookup-libspec #,(construct-name #'k "dorest" i))
(lambda () (reg-list %ac0 %xp %ts %td))
(lambda () (reg-cons* %ac0 (list-xtail arg-registers #,i)))
(lambda () (let ([ls (list-xtail arg-registers #,i)]) (if (null? ls) '() (list (car ls))))))
(reg-list %ac0 %xp %ts %td)
(reg-cons* %ac0 (list-xtail arg-registers #,i))
(let ([ls (list-xtail arg-registers #,i)]) (if (null? ls) '() (list (car ls)))))
(f (fx+ i 1))))))))
dorests)))

View File

@ -32,6 +32,7 @@
fv-offset fv-type
var-spillable-conflict* var-spillable-conflict*-set!
var-unspillable-conflict* var-unspillable-conflict*-set!
var-spillinfo-redirect! make-redirect-var
uvar-degree uvar-degree-set!
uvar-info-lambda uvar-info-lambda-set!
uvar-iii uvar-iii-set!
@ -86,14 +87,89 @@
(define datum? (lambda (x) #t))
(define-record-type var
(fields (mutable index) (mutable spillable-conflict*) (mutable unspillable-conflict*))
(nongenerative #{var n93q6qho9id46fha8itaytldd-1})
(fields (mutable index-or-redirect) (mutable spillable-conflict*-or-redirect) (mutable unspillable-conflict*-or-redirect))
(nongenerative #{var fjh3mleeyv82pb1x1uhd4vsbv-1})
(protocol (lambda (new) (lambda () (new #f #f #f)))))
;; relies on pairs being distinct from conflict sets and indices:
(define (make-spillinfo-redirect index) (cons index '()))
(define (spillinfo-redirect? v) (pair? v))
(define (spillinfo-redirect-index r) (car r))
(define-record-type precolor-var
(parent var)
(fields (mutable precolored))
(nongenerative #{precolor-var fjh3mleeyv82pb1x1uhd4vsbv-5})
(protocol (lambda (pargs->new) (lambda () ((pargs->new) #f)))))
(define (make-redirect-var name)
(make-precolor-var))
(define (var-spillinfo-redirect! v index)
(let ([r (make-spillinfo-redirect index)])
(var-index-or-redirect-set! v r)
(var-spillable-conflict*-or-redirect-set! v r)
(var-unspillable-conflict*-or-redirect-set! v r)))
(define var-index
(case-lambda
[(v) ; when index is not used for spill information
(safe-assert (not (spillinfo-redirect? (var-index-or-redirect v))))
(var-index-or-redirect v)]
[(v reg-spillinfo) ; when index is used for spill information
(let ([i (var-index-or-redirect v)])
(if (spillinfo-redirect? i)
(var-index-or-redirect
(vector-ref reg-spillinfo (spillinfo-redirect-index i)))
i))]))
(define var-index-set!
(case-lambda
[(v i) ; when index is not used for spill information
(safe-assert (not (spillinfo-redirect? (var-index-or-redirect v))))
(var-index-or-redirect-set! v i)]
[(v reg-spillinfo i) ; when index is used for spill information
(let ([old-i (var-index-or-redirect v)])
(if (spillinfo-redirect? old-i)
(var-index-or-redirect-set!
(vector-ref reg-spillinfo (spillinfo-redirect-index old-i))
i)
(var-index-or-redirect-set! v i)))]))
(define (var-spillable-conflict* v reg-spillinfo)
(let ([c* (var-spillable-conflict*-or-redirect v)])
(if (spillinfo-redirect? c*)
(var-spillable-conflict*-or-redirect
(vector-ref reg-spillinfo (spillinfo-redirect-index c*)))
c*)))
(define (var-unspillable-conflict* v reg-spillinfo)
(let ([c* (var-unspillable-conflict*-or-redirect v)])
(if (spillinfo-redirect? c*)
(var-unspillable-conflict*-or-redirect
(vector-ref reg-spillinfo (spillinfo-redirect-index c*)))
c*)))
(define (var-spillable-conflict*-set! v reg-spillinfo c*)
(let ([old-c* (var-spillable-conflict*-or-redirect v)])
(if (spillinfo-redirect? old-c*)
(var-spillable-conflict*-or-redirect-set!
(vector-ref reg-spillinfo (spillinfo-redirect-index old-c*))
c*)
(var-spillable-conflict*-or-redirect-set! v c*))))
(define (var-unspillable-conflict*-set! v reg-spillinfo c*)
(let ([old-c* (var-unspillable-conflict*-or-redirect v)])
(if (spillinfo-redirect? old-c*)
(var-unspillable-conflict*-or-redirect-set!
(vector-ref reg-spillinfo (spillinfo-redirect-index old-c*))
c*)
(var-unspillable-conflict*-or-redirect-set! v c*))))
(define-record-type (fv $make-fv fv?)
(parent var)
(fields offset type)
(nongenerative #{var n93q6qho9id46fha8itaytldd-2})
(nongenerative #{fv fjh3mleeyv82pb1x1uhd4vsbv-2})
(sealed #t)
(protocol
(lambda (pargs->new)
@ -107,13 +183,20 @@
(define-record-type reg
(parent var)
(fields name mdinfo tc-disp callee-save? type (mutable precolored))
(nongenerative #{var n93q6qho9id46fha8itaytldd-3})
(fields name mdinfo tc-disp callee-save? type)
(nongenerative #{reg fjh3mleeyv82pb1x1uhd4vsbv-6})
(sealed #t)
(protocol
(lambda (pargs->new)
(lambda (name mdinfo tc-disp callee-save? type)
((pargs->new) name mdinfo tc-disp callee-save? type #f)))))
((pargs->new) name mdinfo tc-disp callee-save? type)))))
(define (reg-precolored reg reg-spillinfo)
(let ([i (var-index-or-redirect reg)])
(precolor-var-precolored (vector-ref reg-spillinfo (spillinfo-redirect-index i)))))
(define (reg-precolored-set! reg reg-spillinfo v)
(let ([i (var-index-or-redirect reg)])
(precolor-var-precolored-set! (vector-ref reg-spillinfo (spillinfo-redirect-index i)) v)))
(module ()
(record-writer (record-type-descriptor reg)
@ -181,7 +264,7 @@
(mutable save-weight) ; must be a fixnum!
(mutable live-count) ; must be a fixnum!
)
(nongenerative #{var n93q6qho9id46fha8itaytldd-4})
(nongenerative #{uvar fjh3mleeyv82pb1x1uhd4vsbv-4})
(sealed #t)
(protocol
(lambda (pargs->new)

View File

@ -27,11 +27,15 @@
(module (alias ...) (define x regid) (define alias x) ...))
...)])))
(define-syntax define-register-aliases
(syntax-rules ()
[(_ regid reg-alias ...) (begin (define reg-alias regid) ...)]))
(define-syntax define-allocable-registers
(lambda (x)
(assert (fx<= (constant asm-arg-reg-cnt) (constant asm-arg-reg-max)))
(syntax-case x ()
[(_ regvec arg-registers extra-registers extra-fpregisters with-initialized-registers
[(_ regvec arg-registers extra-registers extra-fpregisters make-reg-spillinfo
[regid reg-alias ... callee-save? mdinfo type] ...)
(with-syntax ([((tc-disp ...) (arg-regid ...) (extra-regid ...) (extra-fpregid ...))
(syntax-case #'([regid type] ...) (%ac0 %xp %ts %td uptr)
@ -72,36 +76,20 @@
(f (cdr other*) (cdr other-type*) (cons arg-offset rtc-disp*)
(fx+ arg-offset (constant ptr-bytes)) fp-offset (cons other rextra*) rfpextra*))))))]
[_ (syntax-error x "missing or out-of-order required registers")])]
[(regid-loc ...) (generate-temporaries #'(regid ...))])
[(reg-spillinfo-index ...) (iota (length #'(regid ...)))])
#'(begin
(define-syntax define-squawking-parameter
(syntax-rules ()
[(_ (id (... ...)) loc)
(begin
(define-once loc (id (... ...)) ($make-thread-parameter #f))
(define-syntax id
(lambda (q)
(unless (identifier? q) (syntax-error q))
#`(let ([x (loc)])
(unless x (syntax-error #'#,q "uninitialized"))
x)))
(... ...))]
[(_ id loc) (define-squawking-parameter (id) loc)]))
(define-squawking-parameter (regid reg-alias ...) regid-loc)
(define-once regid (let ([r (make-reg 'regid 'mdinfo tc-disp callee-save? 'type)])
(var-spillinfo-redirect! r reg-spillinfo-index)
r))
...
(define-squawking-parameter regvec regvec-loc)
(define-squawking-parameter arg-registers arg-registers-loc)
(define-squawking-parameter extra-registers extra-registers-loc)
(define-squawking-parameter extra-fpregisters extra-fpregisters-loc)
(define-syntax with-initialized-registers
(syntax-rules ()
[(_ b1 b2 (... ...))
(parameterize ([regid-loc (make-reg 'regid 'mdinfo tc-disp callee-save? 'type)] ...)
(parameterize ([regvec-loc (vector regid ...)]
[arg-registers-loc (list arg-regid ...)]
[extra-registers-loc (list extra-regid ...)]
[extra-fpregisters-loc (list extra-fpregid ...)])
(let () b1 b2 (... ...))))]))))])))
(define-register-aliases regid reg-alias ...) ...
(define regvec (vector regid ...))
(define arg-registers (list arg-regid ...))
(define extra-registers (list extra-regid ...))
(define extra-fpregisters (list extra-fpregid ...))
(define (make-reg-spillinfo)
(vector (make-redirect-var 'regid)
...))))])))
(define-syntax define-machine-dependent-registers
(lambda (x)
@ -119,10 +107,10 @@
[(k (reserved [rreg rreg-alias ... rreg-callee-save? rreg-mdinfo rreg-type] ...)
(allocable [areg areg-alias ... areg-callee-save? areg-mdinfo areg-type] ...)
(machine-depdendent [mdreg mdreg-alias ... mdreg-callee-save? mdreg-mdinfo mdreg-type] ...))
(with-implicit (k regvec arg-registers extra-registers extra-fpregisters real-register? with-initialized-registers)
(with-implicit (k regvec arg-registers extra-registers extra-fpregisters real-register? make-reg-spillinfo)
#`(begin
(define-reserved-registers [rreg rreg-alias ... rreg-callee-save? rreg-mdinfo rreg-type] ...)
(define-allocable-registers regvec arg-registers extra-registers extra-fpregisters with-initialized-registers
(define-allocable-registers regvec arg-registers extra-registers extra-fpregisters make-reg-spillinfo
[areg areg-alias ... areg-callee-save? areg-mdinfo areg-type] ...)
(define-machine-dependent-registers [mdreg mdreg-alias ... mdreg-callee-save? mdreg-mdinfo mdreg-type] ...)
(define-syntax real-register?

View File

@ -2431,11 +2431,11 @@
(module (asm-foreign-call asm-foreign-callable)
(if-feature windows
(begin
(define make-vint (lambda () (vector %Carg1 %Carg2 %Carg3 %Carg4)))
(define make-vfp (lambda () (vector %Cfparg1 %Cfparg2 %Cfparg3 %Cfparg4))))
(define vint (vector %Carg1 %Carg2 %Carg3 %Carg4))
(define vfp (vector %Cfparg1 %Cfparg2 %Cfparg3 %Cfparg4)))
(begin
(define make-vint (lambda () (vector %Carg1 %Carg2 %Carg3 %Carg4 %Carg5 %Carg6)))
(define make-vfp (lambda () (vector %Cfparg1 %Cfparg2 %Cfparg3 %Cfparg4 %Cfparg5 %Cfparg6 %Cfparg7 %Cfparg8)))))
(define vint (vector %Carg1 %Carg2 %Carg3 %Carg4 %Carg5 %Carg6))
(define vfp (vector %Cfparg1 %Cfparg2 %Cfparg3 %Cfparg4 %Cfparg5 %Cfparg6 %Cfparg7 %Cfparg8))))
(define (align n size)
(fxlogand (fx+ n (fx- size 1)) (fx- size)))
@ -2629,7 +2629,7 @@
`(set! ,(%mref ,%sp ,offset) (inline ,(make-info-load 'integer-8 #f)
,%load ,x ,%zero (immediate ,x-offset)))]))))]
[load-content-regs
(lambda (classes size iint ifp vint vfp)
(lambda (classes size iint ifp)
(lambda (x) ; requires var
(let loop ([size size] [iint iint] [ifp ifp] [classes classes] [x-offset 0])
(cond
@ -2686,7 +2686,7 @@
(add-regs (fx- ints 1) (fx+ ir 1) vr
(cons (vector-ref vr ir) regs))]))]
[do-args
(lambda (types vint vfp)
(lambda (types)
(if-feature windows
(let loop ([types types] [locs '()] [regs '()] [fp-regs '()] [i 0] [isp 0])
(if (null? types)
@ -2721,12 +2721,12 @@
(eq? 'float (caar ($ftd->members ftd))))
;; float or double
(loop (cdr types)
(cons (load-content-regs '(sse) ($ftd-size ftd) i i vint vfp) locs)
(cons (load-content-regs '(sse) ($ftd-size ftd) i i) locs)
(add-regs 1 i vint regs) (add-regs 1 i vfp fp-regs) (fx+ i 1) isp)]
[else
;; integer
(loop (cdr types)
(cons (load-content-regs '(integer) ($ftd-size ftd) i i vint vfp) locs)
(cons (load-content-regs '(integer) ($ftd-size ftd) i i) locs)
(add-regs 1 i vint regs) fp-regs(fx+ i 1) isp)])]
[else
;; pass as value on the stack
@ -2790,7 +2790,7 @@
[else
;; pass in registers
(loop (cdr types)
(cons (load-content-regs classes ($ftd-size ftd) iint ifp vint vfp) locs)
(cons (load-content-regs classes ($ftd-size ftd) iint ifp) locs)
(add-regs ints iint vint regs) (add-regs fps ifp vfp fp-regs)
(fx+ iint ints) (fx+ ifp fps) isp)]))]
[else
@ -2921,7 +2921,7 @@
[fill-result-here? (result-fits-in-registers? result-classes)]
[result-reg* (get-result-regs fill-result-here? result-type result-classes)]
[adjust-active? (if-feature pthreads (memq 'adjust-active conv*) #f)])
(with-values (do-args (if fill-result-here? (cdr arg-type*) arg-type*) (make-vint) (make-vfp))
(with-values (do-args (if fill-result-here? (cdr arg-type*) arg-type*))
(lambda (frame-size nfp locs live* fp-live*)
(with-values (add-save-fill-target fill-result-here? frame-size locs)
(lambda (frame-size locs)
@ -3065,8 +3065,6 @@
`(set! ,lvalue ,(%inline + ,%sp (immediate ,offset))))))
(define save-arg-regs
(lambda (types)
(define vint (make-vint))
(define vfp (make-vfp))
(if-feature windows
(let f ([types types] [i 0] [isp 8])
(if (or (null? types) (fx= i 4))