mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-22 20:40:29 +02:00
Rewrite effects analysis to be precise for fields.
* module/language/cps/effects-analysis.scm: Rewrite so that instead of the depends/causes effects, there is just &type-check, &allocation, &read, and &write. The object kind is a separate part of the bitfield, and the field in the object (if appropriate) is another field. Effects are still a fixnum. This enables precise effects for vectors and structs on all architectures. This kind of effects analysis was not possible in Tree-IL because Tree-IL relied on logior-ing effects of subexpressions, whereas with CPS we have no sub-expressions and we do flow analysis instead. (effect-clobbers?): Replace effects-commute? with this inherently directional and precise predicate. * module/language/cps/cse.scm (compute-always-available-expressions): (compute-equivalent-subexpressions): Adapt to effects analysis change. * module/language/cps/dce.scm (compute-live-code): Likewise.
This commit is contained in:
parent
466bdf7ee3
commit
5d25fdae37
3 changed files with 314 additions and 390 deletions
|
@ -33,13 +33,14 @@
|
||||||
|
|
||||||
(define (compute-always-available-expressions effects)
|
(define (compute-always-available-expressions effects)
|
||||||
"Return the set of continuations whose values are always available
|
"Return the set of continuations whose values are always available
|
||||||
within their dominance frontier. This is the case for effects that have
|
within their dominance frontier. This is the case for effects that do
|
||||||
no dependencies and which cause no effects besides &type-check."
|
not allocate, read, or write mutable memory."
|
||||||
(let ((out (make-bitvector (vector-length effects) #f)))
|
(let ((out (make-bitvector (vector-length effects) #f)))
|
||||||
(let lp ((n 0))
|
(let lp ((n 0))
|
||||||
(cond
|
(cond
|
||||||
((< n (vector-length effects))
|
((< n (vector-length effects))
|
||||||
(when (constant? (exclude-effects (vector-ref effects n) &type-check))
|
(unless (causes-effect? (vector-ref effects n)
|
||||||
|
(logior &allocation &read &write))
|
||||||
(bitvector-set! out n #t))
|
(bitvector-set! out n #t))
|
||||||
(lp (1+ n)))
|
(lp (1+ n)))
|
||||||
(else out)))))
|
(else out)))))
|
||||||
|
@ -104,10 +105,10 @@ index corresponds to MIN-LABEL, and so on."
|
||||||
(bitvector-copy! out in)
|
(bitvector-copy! out in)
|
||||||
;; Kill expressions that don't commute.
|
;; Kill expressions that don't commute.
|
||||||
(cond
|
(cond
|
||||||
((causes-all-effects? fx &all-effects)
|
((causes-all-effects? fx)
|
||||||
;; Fast-path if this expression clobbers the world.
|
;; Fast-path if this expression clobbers the world.
|
||||||
(intersect! out always-avail))
|
(intersect! out always-avail))
|
||||||
((effect-free? (exclude-effects fx &type-check))
|
((not (causes-effect? fx &write))
|
||||||
;; Fast-path if this expression clobbers nothing.
|
;; Fast-path if this expression clobbers nothing.
|
||||||
#t)
|
#t)
|
||||||
(else
|
(else
|
||||||
|
@ -117,7 +118,7 @@ index corresponds to MIN-LABEL, and so on."
|
||||||
(let lp ((i 0))
|
(let lp ((i 0))
|
||||||
(let ((i (bit-position #t tmp i)))
|
(let ((i (bit-position #t tmp i)))
|
||||||
(when i
|
(when i
|
||||||
(unless (effects-commute? (vector-ref effects i) fx)
|
(when (effect-clobbers? fx (vector-ref effects i))
|
||||||
(bitvector-set! out i #f))
|
(bitvector-set! out i #f))
|
||||||
(lp (1+ i))))))))
|
(lp (1+ i))))))))
|
||||||
(bitvector-set! out n #t)
|
(bitvector-set! out n #t)
|
||||||
|
@ -412,6 +413,7 @@ be that both true and false proofs are available."
|
||||||
(let* ((exp-key (compute-exp-key exp))
|
(let* ((exp-key (compute-exp-key exp))
|
||||||
(equiv (hash-ref equiv-set exp-key '()))
|
(equiv (hash-ref equiv-set exp-key '()))
|
||||||
(lidx (label->idx label))
|
(lidx (label->idx label))
|
||||||
|
(fx (vector-ref effects lidx))
|
||||||
(avail (vector-ref avail lidx)))
|
(avail (vector-ref avail lidx)))
|
||||||
(let lp ((candidates equiv))
|
(let lp ((candidates equiv))
|
||||||
(match candidates
|
(match candidates
|
||||||
|
@ -424,10 +426,10 @@ be that both true and false proofs are available."
|
||||||
;; if the value proves to be unused, in the
|
;; if the value proves to be unused, in the
|
||||||
;; allocation case).
|
;; allocation case).
|
||||||
(when (and exp-key
|
(when (and exp-key
|
||||||
(not (causes-effects?
|
(not (causes-effect? fx &allocation))
|
||||||
(vector-ref effects lidx)
|
(not (effect-clobbers?
|
||||||
(logior &fluid-environment
|
fx
|
||||||
&allocation))))
|
(&read-object &fluid))))
|
||||||
(hash-set! equiv-set exp-key
|
(hash-set! equiv-set exp-key
|
||||||
(acons label (vector-ref defs lidx)
|
(acons label (vector-ref defs lidx)
|
||||||
equiv))))
|
equiv))))
|
||||||
|
|
|
@ -210,26 +210,17 @@
|
||||||
(not defs)
|
(not defs)
|
||||||
;; Do we have a live def?
|
;; Do we have a live def?
|
||||||
(or-map value-live? defs)
|
(or-map value-live? defs)
|
||||||
;; Does this expression cause any effects we don't know
|
;; Does this expression cause all effects? If so, it's
|
||||||
;; how to elide?
|
;; definitely live.
|
||||||
(not (effect-free?
|
(causes-all-effects? fx)
|
||||||
(exclude-effects fx
|
|
||||||
(logior &allocation &type-check
|
|
||||||
&car &cdr &vector &struct &box))))
|
|
||||||
;; Does it cause a type check, but we can't prove that the
|
;; Does it cause a type check, but we can't prove that the
|
||||||
;; types check?
|
;; types check?
|
||||||
(and (causes-effects? fx &type-check)
|
(and (causes-effect? fx &type-check)
|
||||||
(not (types-check? exp)))
|
(not (types-check? exp)))
|
||||||
(cond
|
|
||||||
((effect-free?
|
|
||||||
(exclude-effects fx (logior &type-check &allocation)))
|
|
||||||
;; We've already handled type checks. If allocation is
|
|
||||||
;; the only remaining effect, this expression is still
|
|
||||||
;; dead.
|
|
||||||
#f)
|
|
||||||
(else
|
|
||||||
;; We might have a setter. If the object being assigned
|
;; We might have a setter. If the object being assigned
|
||||||
;; to is live, then this expression is live.
|
;; to is live, then this expression is live. Otherwise
|
||||||
|
;; the value is still dead.
|
||||||
|
(and (causes-effect? fx &write)
|
||||||
(match exp
|
(match exp
|
||||||
(($ $primcall 'vector-set!/immediate (vec idx val))
|
(($ $primcall 'vector-set!/immediate (vec idx val))
|
||||||
(value-live? vec))
|
(value-live? vec))
|
||||||
|
@ -239,7 +230,7 @@
|
||||||
(value-live? pair))
|
(value-live? pair))
|
||||||
(($ $primcall 'box-set! (box val))
|
(($ $primcall 'box-set! (box val))
|
||||||
(value-live? box))
|
(value-live? box))
|
||||||
(_ #t)))))))
|
(_ #t))))))
|
||||||
(define (idx->label idx) (+ idx min-label))
|
(define (idx->label idx) (+ idx min-label))
|
||||||
(let lp ((n (1- (vector-length effects))))
|
(let lp ((n (1- (vector-length effects))))
|
||||||
(unless (< n 0)
|
(unless (< n 0)
|
||||||
|
|
|
@ -47,10 +47,13 @@
|
||||||
compute-effects
|
compute-effects
|
||||||
synthesize-definition-effects!
|
synthesize-definition-effects!
|
||||||
|
|
||||||
&fluid
|
|
||||||
&fluid-environment
|
|
||||||
&prompt
|
|
||||||
&allocation
|
&allocation
|
||||||
|
&type-check
|
||||||
|
&read
|
||||||
|
&write
|
||||||
|
|
||||||
|
&fluid
|
||||||
|
&prompt
|
||||||
&car
|
&car
|
||||||
&cdr
|
&cdr
|
||||||
&vector
|
&vector
|
||||||
|
@ -59,100 +62,40 @@
|
||||||
&struct
|
&struct
|
||||||
&string
|
&string
|
||||||
&bytevector
|
&bytevector
|
||||||
&type-check
|
|
||||||
|
&object
|
||||||
|
&field
|
||||||
|
|
||||||
|
&allocate
|
||||||
|
&read-object
|
||||||
|
&read-field
|
||||||
|
&write-object
|
||||||
|
&write-field
|
||||||
|
|
||||||
&no-effects
|
&no-effects
|
||||||
&all-effects
|
&all-effects
|
||||||
|
|
||||||
effects-commute?
|
|
||||||
exclude-effects
|
exclude-effects
|
||||||
effect-free?
|
effect-free?
|
||||||
constant?
|
constant?
|
||||||
depends-on-effects?
|
causes-effect?
|
||||||
causes-effects?
|
causes-all-effects?
|
||||||
causes-all-effects?))
|
effect-clobbers?))
|
||||||
|
|
||||||
(define-syntax define-effects
|
(define-syntax define-flags
|
||||||
(lambda (x)
|
(lambda (x)
|
||||||
(syntax-case x ()
|
(syntax-case x ()
|
||||||
((_ all name ...)
|
((_ all shift name ...)
|
||||||
(with-syntax (((n ...) (iota (length #'(name ...)))))
|
(let ((count (length #'(name ...))))
|
||||||
|
(with-syntax (((n ...) (iota count))
|
||||||
|
(count count))
|
||||||
#'(begin
|
#'(begin
|
||||||
(define-syntax name (identifier-syntax (ash 1 (* n 2))))
|
(define-syntax name (identifier-syntax (ash 1 n)))
|
||||||
...
|
...
|
||||||
(define-syntax all (identifier-syntax (logior name ...)))))))))
|
(define-syntax all (identifier-syntax (1- (ash 1 count))))
|
||||||
|
(define-syntax shift (identifier-syntax count)))))))))
|
||||||
(define-syntax compile-time-cond
|
|
||||||
(lambda (x)
|
|
||||||
(syntax-case x (else)
|
|
||||||
((_ (else body ...))
|
|
||||||
#'(begin body ...))
|
|
||||||
((_ (exp body ...) clause ...)
|
|
||||||
(if (eval (syntax->datum #'exp) (current-module))
|
|
||||||
#'(begin body ...)
|
|
||||||
#'(compile-time-cond clause ...))))))
|
|
||||||
|
|
||||||
;; Here we define the effects, indicating the meaning of the effect.
|
|
||||||
;;
|
|
||||||
;; Effects that are described in a "depends on" sense can also be used
|
|
||||||
;; in the "causes" sense.
|
|
||||||
;;
|
|
||||||
;; Effects that are described as causing an effect are not usually used
|
|
||||||
;; in a "depends-on" sense. Although the "depends-on" sense is used
|
|
||||||
;; when checking for the existence of the "causes" effect, the effects
|
|
||||||
;; analyzer will not associate the "depends-on" sense of these effects
|
|
||||||
;; with any expression.
|
|
||||||
;;
|
|
||||||
(compile-time-cond
|
|
||||||
((>= (logcount most-positive-fixnum) 60)
|
|
||||||
(define-effects &all-effects
|
|
||||||
;; Indicates that an expression depends on the value of a fluid
|
|
||||||
;; variable.
|
|
||||||
&fluid
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the current fluid environment.
|
|
||||||
&fluid-environment
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the current prompt
|
|
||||||
;; stack.
|
|
||||||
&prompt
|
|
||||||
|
|
||||||
;; Indicates that an expression may return a fresh object -- a
|
|
||||||
;; "causes" effect.
|
|
||||||
&allocation
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the value of the car of a
|
|
||||||
;; pair.
|
|
||||||
&car
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the value of the cdr of a
|
|
||||||
;; pair.
|
|
||||||
&cdr
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the value of a vector
|
|
||||||
;; field. We cannot be more precise, as vectors may alias other
|
|
||||||
;; vectors.
|
|
||||||
&vector
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the value of a variable
|
|
||||||
;; cell.
|
|
||||||
&box
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the current module.
|
|
||||||
&module
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the value of a particular
|
|
||||||
;; struct field.
|
|
||||||
&struct-0 &struct-1 &struct-2 &struct-3 &struct-4 &struct-5 &struct-6+
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the contents of a string.
|
|
||||||
&string
|
|
||||||
|
|
||||||
;; Indicates that an expression depends on the contents of a
|
|
||||||
;; bytevector. We cannot be more precise, as bytevectors may alias
|
|
||||||
;; other bytevectors.
|
|
||||||
&bytevector
|
|
||||||
|
|
||||||
|
(define-flags &all-effect-kinds &effect-kind-bits
|
||||||
;; Indicates that an expression may cause a type check. A type check,
|
;; Indicates that an expression may cause a type check. A type check,
|
||||||
;; for the purposes of this analysis, is the possibility of throwing
|
;; for the purposes of this analysis, is the possibility of throwing
|
||||||
;; an exception the first time an expression is evaluated. If the
|
;; an exception the first time an expression is evaluated. If the
|
||||||
|
@ -163,313 +106,321 @@
|
||||||
;; For example, (+ x y) might throw if X or Y are not numbers. But if
|
;; For example, (+ x y) might throw if X or Y are not numbers. But if
|
||||||
;; it doesn't throw, it should be safe to elide a dominated, common
|
;; it doesn't throw, it should be safe to elide a dominated, common
|
||||||
;; subexpression (+ x y).
|
;; subexpression (+ x y).
|
||||||
&type-check)
|
&type-check
|
||||||
|
|
||||||
;; Indicates that an expression depends on the contents of an unknown
|
;; Indicates that an expression may return a fresh object. The kind
|
||||||
;; struct field.
|
;; of object is indicated in the object kind field.
|
||||||
(define-syntax &struct
|
|
||||||
(identifier-syntax
|
|
||||||
(logior &struct-1 &struct-2 &struct-3 &struct-4 &struct-5 &struct-6+))))
|
|
||||||
|
|
||||||
(else
|
|
||||||
;; For systems with smaller fixnums, be less precise regarding struct
|
|
||||||
;; fields.
|
|
||||||
(define-effects &all-effects
|
|
||||||
&fluid
|
|
||||||
&prompt
|
|
||||||
&allocation
|
&allocation
|
||||||
&car
|
|
||||||
&cdr
|
;; Indicates that an expression may cause a read from memory. The
|
||||||
|
;; kind of memory is given in the object kind field. Some object
|
||||||
|
;; kinds have finer-grained fields; those are expressed in the "field"
|
||||||
|
;; part of the effects value. -1 indicates "the whole object".
|
||||||
|
&read
|
||||||
|
|
||||||
|
;; Indicates that an expression may cause a write to memory.
|
||||||
|
&write)
|
||||||
|
|
||||||
|
(define-flags &all-memory-kinds &memory-kind-bits
|
||||||
|
;; Indicates that an expression depends on the value of a fluid
|
||||||
|
;; variable, or on the current fluid environment.
|
||||||
|
&fluid
|
||||||
|
|
||||||
|
;; Indicates that an expression depends on the current prompt
|
||||||
|
;; stack.
|
||||||
|
&prompt
|
||||||
|
|
||||||
|
;; Indicates that an expression depends on the value of the car or cdr
|
||||||
|
;; of a pair.
|
||||||
|
&pair
|
||||||
|
|
||||||
|
;; Indicates that an expression depends on the value of a vector
|
||||||
|
;; field. The effect field indicates the specific field, or zero for
|
||||||
|
;; an unknown field.
|
||||||
&vector
|
&vector
|
||||||
|
|
||||||
|
;; Indicates that an expression depends on the value of a variable
|
||||||
|
;; cell.
|
||||||
&box
|
&box
|
||||||
|
|
||||||
|
;; Indicates that an expression depends on the current module.
|
||||||
&module
|
&module
|
||||||
|
|
||||||
|
;; Indicates that an expression depends on the value of a struct
|
||||||
|
;; field. The effect field indicates the specific field, or zero for
|
||||||
|
;; an unknown field.
|
||||||
&struct
|
&struct
|
||||||
|
|
||||||
|
;; Indicates that an expression depends on the contents of a string.
|
||||||
&string
|
&string
|
||||||
&bytevector
|
|
||||||
&type-check)
|
;; Indicates that an expression depends on the contents of a
|
||||||
(define-syntax &fluid-environment (identifier-syntax &fluid))
|
;; bytevector. We cannot be more precise, as bytevectors may alias
|
||||||
(define-syntax &struct-0 (identifier-syntax &struct))
|
;; other bytevectors.
|
||||||
(define-syntax &struct-1 (identifier-syntax &struct))
|
&bytevector)
|
||||||
(define-syntax &struct-2 (identifier-syntax &struct))
|
|
||||||
(define-syntax &struct-3 (identifier-syntax &struct))
|
(define-inlinable (&field kind field)
|
||||||
(define-syntax &struct-4 (identifier-syntax &struct))
|
(ash (logior (ash field &memory-kind-bits) kind) &effect-kind-bits))
|
||||||
(define-syntax &struct-5 (identifier-syntax &struct))
|
(define-inlinable (&object kind)
|
||||||
(define-syntax &struct-6+ (identifier-syntax &struct))))
|
(&field kind -1))
|
||||||
|
|
||||||
|
(define-inlinable (&allocate kind)
|
||||||
|
(logior &allocation (&object kind)))
|
||||||
|
(define-inlinable (&read-field kind field)
|
||||||
|
(logior &read (&field kind field)))
|
||||||
|
(define-inlinable (&read-object kind)
|
||||||
|
(logior &read (&object kind)))
|
||||||
|
(define-inlinable (&write-field kind field)
|
||||||
|
(logior &write (&field kind field)))
|
||||||
|
(define-inlinable (&write-object kind)
|
||||||
|
(logior &write (&object kind)))
|
||||||
|
|
||||||
(define-syntax &no-effects (identifier-syntax 0))
|
(define-syntax &no-effects (identifier-syntax 0))
|
||||||
|
(define-syntax &all-effects
|
||||||
|
(identifier-syntax
|
||||||
|
(logior &all-effect-kinds (&field &all-memory-kinds -1))))
|
||||||
|
|
||||||
(define-inlinable (cause effect)
|
|
||||||
(ash effect 1))
|
|
||||||
|
|
||||||
(define-inlinable (&depends-on a)
|
|
||||||
(logand a &all-effects))
|
|
||||||
(define-inlinable (&causes a)
|
|
||||||
(logand a (cause &all-effects)))
|
|
||||||
|
|
||||||
(define-inlinable (exclude-effects effects exclude)
|
|
||||||
(logand effects (lognot (cause exclude))))
|
|
||||||
(define-inlinable (effect-free? effects)
|
|
||||||
(zero? (&causes effects)))
|
|
||||||
(define-inlinable (constant? effects)
|
(define-inlinable (constant? effects)
|
||||||
(zero? effects))
|
(zero? effects))
|
||||||
(define-inlinable (effects-clobber effects)
|
|
||||||
(ash (&causes effects) -1))
|
|
||||||
|
|
||||||
(define-inlinable (depends-on-effects? x effects)
|
(define-inlinable (causes-effect? x effects)
|
||||||
(not (zero? (logand (&depends-on x) effects))))
|
(not (zero? (logand x effects))))
|
||||||
(define-inlinable (causes-effects? x effects)
|
|
||||||
(not (zero? (logand (&causes x) (cause effects)))))
|
|
||||||
(define-inlinable (causes-all-effects? x effects)
|
|
||||||
(= (logand (&causes x) (cause effects)) (cause effects)))
|
|
||||||
|
|
||||||
(define-inlinable (effects-commute? a b)
|
(define-inlinable (causes-all-effects? x)
|
||||||
(and (not (causes-effects? a (&depends-on b)))
|
(eqv? x &all-effects))
|
||||||
(not (causes-effects? b (&depends-on a)))))
|
|
||||||
|
(define (effect-clobbers? a b)
|
||||||
|
"Return true if A clobbers B. This is the case if A is a write, and B
|
||||||
|
is or might be a read or a write to the same location as A."
|
||||||
|
(define (locations-same?)
|
||||||
|
(and (not (zero? (logand a b (ash &all-memory-kinds &effect-kind-bits))))
|
||||||
|
;; A negative field indicates "the whole object". Non-negative
|
||||||
|
;; fields indicate only part of the object.
|
||||||
|
(or (< a 0) (< b 0)
|
||||||
|
(= (ash a (- (+ &effect-kind-bits &memory-kind-bits)))
|
||||||
|
(ash b (- (+ &effect-kind-bits &memory-kind-bits)))))))
|
||||||
|
(and (not (zero? (logand a &write)))
|
||||||
|
(not (zero? (logand b (logior &read &write))))
|
||||||
|
(locations-same?)))
|
||||||
|
|
||||||
(define (lookup-constant-index sym dfg)
|
(define (lookup-constant-index sym dfg)
|
||||||
(call-with-values (lambda () (find-constant-value sym dfg))
|
(call-with-values (lambda () (find-constant-value sym dfg))
|
||||||
(lambda (has-const? val)
|
(lambda (has-const? val)
|
||||||
(and has-const? (integer? val) (exact? val) (<= 0 val) val))))
|
(and has-const? (integer? val) (exact? val) (<= 0 val) val))))
|
||||||
|
|
||||||
|
(define-inlinable (indexed-field kind n dfg)
|
||||||
|
(cond
|
||||||
|
((lookup-constant-index n dfg)
|
||||||
|
=> (lambda (idx)
|
||||||
|
(&field kind idx)))
|
||||||
|
(else (&object kind))))
|
||||||
|
|
||||||
(define *primitive-effects* (make-hash-table))
|
(define *primitive-effects* (make-hash-table))
|
||||||
|
|
||||||
(define-syntax-rule (define-primitive-effects* dfg ((name . args) effects) ...)
|
(define-syntax-rule (define-primitive-effects* dfg
|
||||||
|
((name . args) effects ...)
|
||||||
|
...)
|
||||||
(begin
|
(begin
|
||||||
(hashq-set! *primitive-effects* 'name
|
(hashq-set! *primitive-effects* 'name
|
||||||
(case-lambda* ((dfg . args) effects)
|
(case-lambda*
|
||||||
(_ (logior &all-effects (cause &all-effects)))))
|
((dfg . args) (logior effects ...))
|
||||||
|
(_ &all-effects)))
|
||||||
...))
|
...))
|
||||||
|
|
||||||
(define-syntax-rule (define-primitive-effects ((name . args) effects) ...)
|
(define-syntax-rule (define-primitive-effects ((name . args) effects ...) ...)
|
||||||
(define-primitive-effects* dfg ((name . args) effects) ...))
|
(define-primitive-effects* dfg ((name . args) effects ...) ...))
|
||||||
|
|
||||||
;; Miscellaneous.
|
;; Miscellaneous.
|
||||||
(define-primitive-effects
|
(define-primitive-effects
|
||||||
((values . _) &no-effects)
|
((values . _))
|
||||||
((not arg) &no-effects))
|
((not arg)))
|
||||||
|
|
||||||
;; Generic predicates.
|
;; Generic effect-free predicates.
|
||||||
(define-primitive-effects
|
(define-primitive-effects
|
||||||
((eq? . _) &no-effects)
|
((eq? . _))
|
||||||
((eqv? . _) &no-effects)
|
((eqv? . _))
|
||||||
((equal? . _) &no-effects)
|
((equal? . _))
|
||||||
((pair? arg) &no-effects)
|
((pair? arg))
|
||||||
((null? arg) &no-effects)
|
((null? arg))
|
||||||
((nil? arg ) &no-effects)
|
((nil? arg ))
|
||||||
((symbol? arg) &no-effects)
|
((symbol? arg))
|
||||||
((variable? arg) &no-effects)
|
((variable? arg))
|
||||||
((vector? arg) &no-effects)
|
((vector? arg))
|
||||||
((struct? arg) &no-effects)
|
((struct? arg))
|
||||||
((string? arg) &no-effects)
|
((string? arg))
|
||||||
((number? arg) &no-effects)
|
((number? arg))
|
||||||
((char? arg) &no-effects)
|
((char? arg))
|
||||||
((procedure? arg) &no-effects)
|
((procedure? arg))
|
||||||
((thunk? arg) &no-effects))
|
((thunk? arg)))
|
||||||
|
|
||||||
;; Fluids.
|
;; Fluids.
|
||||||
(define-primitive-effects
|
(define-primitive-effects
|
||||||
((fluid-ref f)
|
((fluid-ref f) (&read-object &fluid) &type-check)
|
||||||
(logior (cause &type-check) &fluid &fluid-environment))
|
((fluid-set! f v) (&write-object &fluid) &type-check)
|
||||||
((fluid-set! f v)
|
((push-fluid f v) (&write-object &fluid) &type-check)
|
||||||
(logior (cause &type-check) (cause &fluid) &fluid-environment))
|
((pop-fluid) (&write-object &fluid) &type-check))
|
||||||
((push-fluid f v)
|
|
||||||
(logior (cause &type-check) (cause &fluid-environment)))
|
|
||||||
((pop-fluid)
|
|
||||||
(logior (cause &fluid-environment))))
|
|
||||||
|
|
||||||
;; Prompts.
|
;; Prompts.
|
||||||
(define-primitive-effects
|
(define-primitive-effects
|
||||||
((make-prompt-tag #:optional arg) (cause &allocation)))
|
((make-prompt-tag #:optional arg) (&allocate &all-memory-kinds)))
|
||||||
|
|
||||||
;; Pairs.
|
;; Pairs.
|
||||||
(define-primitive-effects
|
(define-primitive-effects
|
||||||
((cons a b) (cause &allocation))
|
((cons a b) (&allocate &pair))
|
||||||
((list . _) (cause &allocation))
|
((list . _) (&allocate &pair))
|
||||||
((car x) (logior (cause &type-check) &car))
|
((car x) (&read-field &pair 0) &type-check)
|
||||||
((set-car! x y) (logior (cause &type-check) (cause &car)))
|
((set-car! x y) (&write-field &pair 0) &type-check)
|
||||||
((cdr x) (logior (cause &type-check) &cdr))
|
((cdr x) (&read-field &pair 1) &type-check)
|
||||||
((set-cdr! x y) (logior (cause &type-check) (cause &cdr)))
|
((set-cdr! x y) (&write-field &pair 1) &type-check)
|
||||||
((memq x y) (logior (cause &type-check) &car &cdr))
|
((memq x y) (&read-object &pair) &type-check)
|
||||||
((memv x y) (logior (cause &type-check) &car &cdr))
|
((memv x y) (&read-object &pair) &type-check)
|
||||||
((list? arg) &cdr)
|
((list? arg) (&read-field &pair 1))
|
||||||
((length l) (logior (cause &type-check) &cdr)))
|
((length l) (&read-field &pair 1) &type-check))
|
||||||
|
|
||||||
;; Vectors.
|
|
||||||
(define-primitive-effects
|
|
||||||
((vector . _) (cause &allocation))
|
|
||||||
((make-vector n init) (logior (cause &type-check) (cause &allocation)))
|
|
||||||
((make-vector/immediate n init) (cause &allocation))
|
|
||||||
((vector-ref v n) (logior (cause &type-check) &vector))
|
|
||||||
((vector-ref/immediate v n) (logior (cause &type-check) &vector))
|
|
||||||
((vector-set! v n x) (logior (cause &type-check) (cause &vector)))
|
|
||||||
((vector-set!/immediate v n x) (logior (cause &type-check) (cause &vector)))
|
|
||||||
((vector-length v) (cause &type-check)))
|
|
||||||
|
|
||||||
;; Variables.
|
;; Variables.
|
||||||
(define-primitive-effects
|
(define-primitive-effects
|
||||||
((box v) (cause &allocation))
|
((box v) (&allocate &box))
|
||||||
((box-ref v) (logior (cause &type-check) &box))
|
((box-ref v) (&read-object &box) &type-check)
|
||||||
((box-set! v x) (logior (cause &type-check) (cause &box))))
|
((box-set! v x) (&write-object &box) &type-check))
|
||||||
|
|
||||||
|
;; Vectors.
|
||||||
|
(define (vector-field n dfg)
|
||||||
|
(indexed-field &vector n dfg))
|
||||||
|
(define (read-vector-field n dfg)
|
||||||
|
(logior &read (vector-field n dfg)))
|
||||||
|
(define (write-vector-field n dfg)
|
||||||
|
(logior &write (vector-field n dfg)))
|
||||||
|
(define-primitive-effects* dfg
|
||||||
|
((vector . _) (&allocate &vector))
|
||||||
|
((make-vector n init) (&allocate &vector) &type-check)
|
||||||
|
((make-vector/immediate n init) (&allocate &vector))
|
||||||
|
((vector-ref v n) (read-vector-field n dfg) &type-check)
|
||||||
|
((vector-ref/immediate v n) (read-vector-field n dfg) &type-check)
|
||||||
|
((vector-set! v n x) (write-vector-field n dfg) &type-check)
|
||||||
|
((vector-set!/immediate v n x) (write-vector-field n dfg) &type-check)
|
||||||
|
((vector-length v) &type-check))
|
||||||
|
|
||||||
;; Structs.
|
;; Structs.
|
||||||
|
(define (struct-field n dfg)
|
||||||
|
(indexed-field &struct n dfg))
|
||||||
|
(define (read-struct-field n dfg)
|
||||||
|
(logior &read (struct-field n dfg)))
|
||||||
|
(define (write-struct-field n dfg)
|
||||||
|
(logior &write (struct-field n dfg)))
|
||||||
(define-primitive-effects* dfg
|
(define-primitive-effects* dfg
|
||||||
((allocate-struct vtable nfields)
|
((allocate-struct vt n) (&allocate &struct) &type-check)
|
||||||
(logior (cause &type-check) (cause &allocation)))
|
((allocate-struct/immediate v n) (&allocate &struct) &type-check)
|
||||||
((allocate-struct/immediate vtable nfields)
|
((make-struct vt ntail . _) (&allocate &struct) &type-check)
|
||||||
(logior (cause &type-check) (cause &allocation)))
|
((make-struct/no-tail vt . _) (&allocate &struct) &type-check)
|
||||||
((make-struct vtable ntail . args)
|
((struct-ref s n) (read-struct-field n dfg) &type-check)
|
||||||
(logior (cause &type-check) (cause &allocation)))
|
((struct-ref/immediate s n) (read-struct-field n dfg) &type-check)
|
||||||
((make-struct/no-tail vtable . args)
|
((struct-set! s n x) (write-struct-field n dfg) &type-check)
|
||||||
(logior (cause &type-check) (cause &allocation)))
|
((struct-set!/immediate s n x) (write-struct-field n dfg) &type-check)
|
||||||
((struct-ref s n)
|
((struct-vtable s) &type-check))
|
||||||
(logior (cause &type-check)
|
|
||||||
(match (lookup-constant-index n dfg)
|
|
||||||
(#f &struct)
|
|
||||||
(0 &struct-0)
|
|
||||||
(1 &struct-1)
|
|
||||||
(2 &struct-2)
|
|
||||||
(3 &struct-3)
|
|
||||||
(4 &struct-4)
|
|
||||||
(5 &struct-5)
|
|
||||||
(_ &struct-6+))))
|
|
||||||
((struct-ref/immediate s n)
|
|
||||||
(logior (cause &type-check)
|
|
||||||
(match (lookup-constant-index n dfg)
|
|
||||||
(#f &struct)
|
|
||||||
(0 &struct-0)
|
|
||||||
(1 &struct-1)
|
|
||||||
(2 &struct-2)
|
|
||||||
(3 &struct-3)
|
|
||||||
(4 &struct-4)
|
|
||||||
(5 &struct-5)
|
|
||||||
(_ &struct-6+))))
|
|
||||||
((struct-set! s n x)
|
|
||||||
(logior (cause &type-check)
|
|
||||||
(match (lookup-constant-index n dfg)
|
|
||||||
(#f (cause &struct))
|
|
||||||
(0 (cause &struct-0))
|
|
||||||
(1 (cause &struct-1))
|
|
||||||
(2 (cause &struct-2))
|
|
||||||
(3 (cause &struct-3))
|
|
||||||
(4 (cause &struct-4))
|
|
||||||
(5 (cause &struct-5))
|
|
||||||
(_ (cause &struct-6+)))))
|
|
||||||
((struct-set!/immediate s n x)
|
|
||||||
(logior (cause &type-check)
|
|
||||||
(match (lookup-constant-index n dfg)
|
|
||||||
(#f (cause &struct))
|
|
||||||
(0 (cause &struct-0))
|
|
||||||
(1 (cause &struct-1))
|
|
||||||
(2 (cause &struct-2))
|
|
||||||
(3 (cause &struct-3))
|
|
||||||
(4 (cause &struct-4))
|
|
||||||
(5 (cause &struct-5))
|
|
||||||
(_ (cause &struct-6+)))))
|
|
||||||
((struct-vtable s) (cause &type-check)))
|
|
||||||
|
|
||||||
;; Strings.
|
;; Strings.
|
||||||
(define-primitive-effects
|
(define-primitive-effects
|
||||||
((string-ref s n) (logior (cause &type-check) &string))
|
((string-ref s n) (&read-object &string) &type-check)
|
||||||
((string-set! s n c) (logior (cause &type-check) (cause &string)))
|
((string-set! s n c) (&write-object &string) &type-check)
|
||||||
((number->string _) (cause &type-check))
|
((number->string _) (&allocate &string) &type-check)
|
||||||
((string->number _) (logior (cause &type-check) &string))
|
((string->number _) (&read-object &string) &type-check)
|
||||||
((string-length s) (cause &type-check)))
|
((string-length s) &type-check))
|
||||||
|
|
||||||
;; Bytevectors.
|
;; Bytevectors.
|
||||||
(define-primitive-effects
|
(define-primitive-effects
|
||||||
((bytevector-length _) (cause &type-check))
|
((bytevector-length _) &type-check)
|
||||||
|
|
||||||
((bv-u8-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-u8-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
((bv-s8-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-s8-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
((bv-u16-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-u16-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
((bv-s16-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-s16-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
((bv-u32-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-u32-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
((bv-s32-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-s32-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
((bv-u64-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-u64-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
((bv-s64-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-s64-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
((bv-f32-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-f32-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
((bv-f64-ref bv n) (logior (cause &type-check) &bytevector))
|
((bv-f64-ref bv n) (&read-object &bytevector) &type-check)
|
||||||
|
|
||||||
((bv-u8-set! bv n x) (logior (cause &type-check) (cause &bytevector)))
|
((bv-u8-set! bv n x) (&write-object &bytevector) &type-check)
|
||||||
((bv-s8-set! bv n x) (logior (cause &type-check) (cause &bytevector)))
|
((bv-s8-set! bv n x) (&write-object &bytevector) &type-check)
|
||||||
((bv-u16-set! bv n x) (logior (cause &type-check) (cause &bytevector)))
|
((bv-u16-set! bv n x) (&write-object &bytevector) &type-check)
|
||||||
((bv-s16-set! bv n x) (logior (cause &type-check) (cause &bytevector)))
|
((bv-s16-set! bv n x) (&write-object &bytevector) &type-check)
|
||||||
((bv-u32-set! bv n x) (logior (cause &type-check) (cause &bytevector)))
|
((bv-u32-set! bv n x) (&write-object &bytevector) &type-check)
|
||||||
((bv-s32-set! bv n x) (logior (cause &type-check) (cause &bytevector)))
|
((bv-s32-set! bv n x) (&write-object &bytevector) &type-check)
|
||||||
((bv-u64-set! bv n x) (logior (cause &type-check) (cause &bytevector)))
|
((bv-u64-set! bv n x) (&write-object &bytevector) &type-check)
|
||||||
((bv-s64-set! bv n x) (logior (cause &type-check) (cause &bytevector)))
|
((bv-s64-set! bv n x) (&write-object &bytevector) &type-check)
|
||||||
((bv-f32-set! bv n x) (logior (cause &type-check) (cause &bytevector)))
|
((bv-f32-set! bv n x) (&write-object &bytevector) &type-check)
|
||||||
((bv-f64-set! bv n x) (logior (cause &type-check) (cause &bytevector))))
|
((bv-f64-set! bv n x) (&write-object &bytevector) &type-check))
|
||||||
|
|
||||||
;; Numbers.
|
|
||||||
(define-primitive-effects
|
|
||||||
((= . _) (cause &type-check))
|
|
||||||
((< . _) (cause &type-check))
|
|
||||||
((> . _) (cause &type-check))
|
|
||||||
((<= . _) (cause &type-check))
|
|
||||||
((>= . _) (cause &type-check))
|
|
||||||
((zero? . _) (cause &type-check))
|
|
||||||
((add . _) (cause &type-check))
|
|
||||||
((mul . _) (cause &type-check))
|
|
||||||
((sub . _) (cause &type-check))
|
|
||||||
((div . _) (cause &type-check))
|
|
||||||
((sub1 . _) (cause &type-check))
|
|
||||||
((add1 . _) (cause &type-check))
|
|
||||||
((quo . _) (cause &type-check))
|
|
||||||
((rem . _) (cause &type-check))
|
|
||||||
((mod . _) (cause &type-check))
|
|
||||||
((complex? _) (cause &type-check))
|
|
||||||
((real? _) (cause &type-check))
|
|
||||||
((rational? _) (cause &type-check))
|
|
||||||
((inf? _) (cause &type-check))
|
|
||||||
((nan? _) (cause &type-check))
|
|
||||||
((integer? _) (cause &type-check))
|
|
||||||
((exact? _) (cause &type-check))
|
|
||||||
((inexact? _) (cause &type-check))
|
|
||||||
((even? _) (cause &type-check))
|
|
||||||
((odd? _) (cause &type-check))
|
|
||||||
((ash n m) (cause &type-check))
|
|
||||||
((logand . _) (cause &type-check))
|
|
||||||
((logior . _) (cause &type-check))
|
|
||||||
((logior . _) (cause &type-check))
|
|
||||||
((lognot . _) (cause &type-check))
|
|
||||||
((sqrt _) (cause &type-check))
|
|
||||||
((abs _) (cause &type-check)))
|
|
||||||
|
|
||||||
;; Characters.
|
|
||||||
(define-primitive-effects
|
|
||||||
((char<? . _) (cause &type-check))
|
|
||||||
((char<=? . _) (cause &type-check))
|
|
||||||
((char>=? . _) (cause &type-check))
|
|
||||||
((char>? . _) (cause &type-check))
|
|
||||||
((integer->char _) (cause &type-check))
|
|
||||||
((char->integer _) (cause &type-check)))
|
|
||||||
|
|
||||||
;; Modules.
|
;; Modules.
|
||||||
(define-primitive-effects
|
(define-primitive-effects
|
||||||
((current-module) &module)
|
((current-module) (&read-object &module))
|
||||||
((cache-current-module! mod scope) (cause &box))
|
((cache-current-module! m scope) (&write-object &box))
|
||||||
((resolve name bound?) (logior &module (cause &type-check)))
|
((resolve name bound?) (&read-object &module) &type-check)
|
||||||
((cached-toplevel-box scope name bound?) (cause &type-check))
|
((cached-toplevel-box scope name bound?) &type-check)
|
||||||
((cached-module-box mod name public? bound?) (cause &type-check))
|
((cached-module-box mod name public? bound?) &type-check)
|
||||||
((define! name val) (logior &module (cause &box))))
|
((define! name val) (&read-object &module) (&write-object &box)))
|
||||||
|
|
||||||
|
;; Numbers.
|
||||||
|
(define-primitive-effects
|
||||||
|
((= . _) &type-check)
|
||||||
|
((< . _) &type-check)
|
||||||
|
((> . _) &type-check)
|
||||||
|
((<= . _) &type-check)
|
||||||
|
((>= . _) &type-check)
|
||||||
|
((zero? . _) &type-check)
|
||||||
|
((add . _) &type-check)
|
||||||
|
((mul . _) &type-check)
|
||||||
|
((sub . _) &type-check)
|
||||||
|
((div . _) &type-check)
|
||||||
|
((sub1 . _) &type-check)
|
||||||
|
((add1 . _) &type-check)
|
||||||
|
((quo . _) &type-check)
|
||||||
|
((rem . _) &type-check)
|
||||||
|
((mod . _) &type-check)
|
||||||
|
((complex? _) &type-check)
|
||||||
|
((real? _) &type-check)
|
||||||
|
((rational? _) &type-check)
|
||||||
|
((inf? _) &type-check)
|
||||||
|
((nan? _) &type-check)
|
||||||
|
((integer? _) &type-check)
|
||||||
|
((exact? _) &type-check)
|
||||||
|
((inexact? _) &type-check)
|
||||||
|
((even? _) &type-check)
|
||||||
|
((odd? _) &type-check)
|
||||||
|
((ash n m) &type-check)
|
||||||
|
((logand . _) &type-check)
|
||||||
|
((logior . _) &type-check)
|
||||||
|
((logxor . _) &type-check)
|
||||||
|
((lognot . _) &type-check)
|
||||||
|
((sqrt _) &type-check)
|
||||||
|
((abs _) &type-check))
|
||||||
|
|
||||||
|
;; Characters.
|
||||||
|
(define-primitive-effects
|
||||||
|
((char<? . _) &type-check)
|
||||||
|
((char<=? . _) &type-check)
|
||||||
|
((char>=? . _) &type-check)
|
||||||
|
((char>? . _) &type-check)
|
||||||
|
((integer->char _) &type-check)
|
||||||
|
((char->integer _) &type-check))
|
||||||
|
|
||||||
(define (primitive-effects dfg name args)
|
(define (primitive-effects dfg name args)
|
||||||
(let ((proc (hashq-ref *primitive-effects* name)))
|
(let ((proc (hashq-ref *primitive-effects* name)))
|
||||||
(if proc
|
(if proc
|
||||||
(apply proc dfg args)
|
(apply proc dfg args)
|
||||||
(logior &all-effects (cause &all-effects)))))
|
&all-effects)))
|
||||||
|
|
||||||
(define (expression-effects exp dfg)
|
(define (expression-effects exp dfg)
|
||||||
(match exp
|
(match exp
|
||||||
((or ($ $void) ($ $const) ($ $prim) ($ $values))
|
((or ($ $void) ($ $const) ($ $prim) ($ $values))
|
||||||
&no-effects)
|
&no-effects)
|
||||||
(($ $fun)
|
(($ $fun)
|
||||||
(cause &allocation))
|
(&allocate &all-memory-kinds))
|
||||||
(($ $prompt)
|
(($ $prompt)
|
||||||
(cause &prompt))
|
(logior (&write-object &prompt)))
|
||||||
((or ($ $call) ($ $callk))
|
((or ($ $call) ($ $callk))
|
||||||
(logior &all-effects (cause &all-effects)))
|
&all-effects)
|
||||||
(($ $primcall name args)
|
(($ $primcall name args)
|
||||||
(primitive-effects dfg name args))))
|
(primitive-effects dfg name args))))
|
||||||
|
|
||||||
|
@ -487,13 +438,12 @@
|
||||||
(expression-effects (find-expression body) dfg))
|
(expression-effects (find-expression body) dfg))
|
||||||
(($ $kreceive arity kargs)
|
(($ $kreceive arity kargs)
|
||||||
(match arity
|
(match arity
|
||||||
(($ $arity _ () #f () #f) (cause &type-check))
|
(($ $arity _ () #f () #f) &type-check)
|
||||||
(($ $arity () () _ () #f) (cause &allocation))
|
(($ $arity () () _ () #f) (&allocate &pair))
|
||||||
(($ $arity _ () _ () #f) (logior (cause &allocation)
|
(($ $arity _ () _ () #f) (logior (&allocate &pair) &type-check))))
|
||||||
(cause &type-check)))))
|
|
||||||
(($ $kif) &no-effects)
|
(($ $kif) &no-effects)
|
||||||
(($ $kfun) (cause &type-check))
|
(($ $kfun) &type-check)
|
||||||
(($ $kclause) (cause &type-check))
|
(($ $kclause) &type-check)
|
||||||
(($ $ktail) &no-effects)))
|
(($ $ktail) &no-effects)))
|
||||||
(lp (1+ n))))
|
(lp (1+ n))))
|
||||||
effects))
|
effects))
|
||||||
|
@ -515,25 +465,6 @@
|
||||||
(when (< label (+ min-label label-count))
|
(when (< label (+ min-label label-count))
|
||||||
(let* ((lidx (label->idx label))
|
(let* ((lidx (label->idx label))
|
||||||
(fx (vector-ref effects lidx)))
|
(fx (vector-ref effects lidx)))
|
||||||
(define (add-deps! deps)
|
(unless (zero? (logand (logior &write &allocation) fx))
|
||||||
(vector-set! effects lidx (logior fx deps)))
|
(vector-set! effects lidx (logior (vector-ref effects lidx) &read)))
|
||||||
(match (lookup-cont label dfg)
|
|
||||||
(($ $kargs _ _ term)
|
|
||||||
(match (find-expression term)
|
|
||||||
(($ $primcall 'cons)
|
|
||||||
(add-deps! (logior &car &cdr)))
|
|
||||||
(($ $primcall (or 'make-vector 'make-vector/immediate))
|
|
||||||
(add-deps! &vector))
|
|
||||||
(($ $primcall (or 'allocate-struct 'allocate-struct/immediate
|
|
||||||
'make-struct/no-tail 'make-struct))
|
|
||||||
(add-deps! &struct))
|
|
||||||
(($ $primcall 'box)
|
|
||||||
(add-deps! &box))
|
|
||||||
(_
|
|
||||||
(add-deps! (effects-clobber
|
|
||||||
(logand
|
|
||||||
fx
|
|
||||||
(cause (logior &car &cdr &vector &struct &box)))))
|
|
||||||
#t)))
|
|
||||||
(_ #t))
|
|
||||||
(lp (1+ label))))))
|
(lp (1+ label))))))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue