[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 02/02: Fix effects analysis: field writes clobber object
From: |
Andy Wingo |
Subject: |
[Guile-commits] 02/02: Fix effects analysis: field writes clobber object reads |
Date: |
Wed, 20 Mar 2024 06:51:37 -0400 (EDT) |
wingo pushed a commit to branch main
in repository guile.
commit 48548df91e9eb5d4a46391da0ad0a8cdd3387857
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Wed Mar 20 11:32:51 2024 +0100
Fix effects analysis: field writes clobber object reads
* module/language/cps/effects-analysis.scm (compute-clobber-map):
Previously a whole-object read would not be clobbered by a specific
field write. This crops up for the &read introduced at the site of
`cons` for the synthetic car and cdr definitions. This error was there
before but didn't cause bugs before 3.0.10 because cons got eagerly
lowered to separate allocation and initialization instructions.
---
module/language/cps/effects-analysis.scm | 100 +++++++++++++++++++++----------
1 file changed, 69 insertions(+), 31 deletions(-)
diff --git a/module/language/cps/effects-analysis.scm
b/module/language/cps/effects-analysis.scm
index 50c7007e4..c768f2eaa 100644
--- a/module/language/cps/effects-analysis.scm
+++ b/module/language/cps/effects-analysis.scm
@@ -311,37 +311,75 @@ the LABELS that are clobbered by the effects of LABEL."
clobbered-labels
(intset-remove clobbered-labels clobbered-label)))))
clobbered-labels clobbered-labels))))
- (let ((clobbered-by-write (make-hash-table)))
- (intmap-fold
- (lambda (label fx)
- ;; Unless an expression causes a read, it isn't clobbered by
- ;; anything.
- (when (causes-effect? fx &read)
- (let ((me (intset label)))
- (define (add! kind field)
- (let* ((k (logior (ash field &memory-kind-bits) kind))
- (clobber (hashv-ref clobbered-by-write k empty-intset)))
- (hashv-set! clobbered-by-write k (intset-union me clobber))))
- ;; Clobbered by write to specific field of this memory
- ;; kind, write to any field of this memory kind, or
- ;; write to any field of unknown memory kinds.
- (let* ((loc (ash fx (- &effect-kind-bits)))
- (kind (logand loc &memory-kind-mask))
- (field (ash loc (- &memory-kind-bits))))
- (add! kind field)
- (add! kind -1)
- (add! &unknown-memory-kinds -1))))
- (values))
- effects)
- (intmap-map (lambda (label fx)
- (if (causes-effect? fx &write)
- (filter-may-alias
- label
- (hashv-ref clobbered-by-write
- (ash fx (- &effect-kind-bits))
- empty-intset))
- empty-intset))
- effects)))
+
+ (define (make-clobber-vector) (make-vector &memory-kind-mask empty-intset))
+
+ (define clobbered-by-write-to-unknown empty-intset)
+ (define clobbered-by-write-to-any-field (make-clobber-vector))
+ (define clobbered-by-write-to-all-fields (make-clobber-vector))
+ (define clobbered-by-write-to-specific-field (make-hash-table))
+
+ (define (adjoin-to-clobber-vector! v k id)
+ (vector-set! v k (intset-union (vector-ref v k) (intset id))))
+ (define (add-clobbered-by-write-to-any-field! kind label)
+ (adjoin-to-clobber-vector! clobbered-by-write-to-any-field kind label))
+ (define (add-clobbered-by-write-to-all-fields! kind label)
+ (adjoin-to-clobber-vector! clobbered-by-write-to-all-fields kind label))
+ (define (adjoin-to-clobber-hash! h k id)
+ (hashv-set! h k (intset-union (hashv-ref h k empty-intset) (intset id))))
+ (define (add-clobbered-by-write-to-specific-field! kind+field label)
+ (adjoin-to-clobber-hash! clobbered-by-write-to-specific-field
+ kind+field label))
+
+ (intmap-fold
+ (lambda (label fx)
+ ;; Unless an expression causes a read, it isn't clobbered by
+ ;; anything.
+ (when (causes-effect? fx &read)
+ (define kind+field (ash fx (- &effect-kind-bits)))
+ (define kind (logand &memory-kind-mask kind+field))
+ (define field (ash kind+field (- &memory-kind-bits)))
+ (cond
+ ((eqv? field -1)
+ ;; A read of the whole object is clobbered by a write to any
+ ;; field.
+ (add-clobbered-by-write-to-all-fields! kind label)
+ (add-clobbered-by-write-to-any-field! kind label))
+ ((negative? field) (error "unexpected field"))
+ (else
+ ;; A read of a specific field is clobbered by a write to that
+ ;; specific field, or a write to all fields.
+ (add-clobbered-by-write-to-all-fields! kind label)
+ (add-clobbered-by-write-to-specific-field! kind+field label)))
+
+ ;; Also clobbered by write to any field of unknown memory kinds.
+ (add-clobbered-by-write-to-any-field! &unknown-memory-kinds label))
+ (values))
+ effects)
+ (define (lookup-clobbers fx)
+ (define kind+field (ash fx (- &effect-kind-bits)))
+ (define kind (logand &memory-kind-mask kind+field))
+ (define field (ash kind+field (- &memory-kind-bits)))
+ (cond
+ ((eqv? field -1)
+ ;; A write to the whole object.
+ (intset-union
+ (vector-ref clobbered-by-write-to-any-field kind)
+ (vector-ref clobbered-by-write-to-all-fields kind)))
+ ((negative? field) (error "unexpected field"))
+ (else
+ ;; A write to a specific field. In addition to clobbering reads
+ ;; of this specific field, we clobber reads of the whole object,
+ ;; for example the ones that correspond to the synthesized "car"
+ ;; and "cdr" definitions that are associated with a "cons" expr.
+ (intset-union
+ (vector-ref clobbered-by-write-to-any-field kind)
+ (hashv-ref clobbered-by-write-to-specific-field kind+field)))))
+ (intmap-map (lambda (label fx)
+ (if (causes-effect? fx &write)
+ (filter-may-alias label (lookup-clobbers fx))
+ empty-intset))
+ effects))
(define *primitive-effects* (make-hash-table))