(print (incf start 22))
(print (incf start 26))))))
+ [ Update: 1.0.14.36 improved this quite a bit (20-25%) by
+ eliminating useless work from PROPAGATE-FROM-SETS -- but as alluded
+ below, maybe we should be smarter about when to decide a derived
+ type is "good enough". ]
+
This example could be solved with clever enough constraint
propagation or with SSA, but consider
when SB-DEBUG:*SHOW-ENTRY-POINT-DETAILS* is NIL.
* unreadably printed representation of hash-tables now includes
weakness if any.
+ * bug fix: partially fixed #188: type propagation from assignments
+ is now more efficient.
+ * bug fix: fixed #407: (COERCE X 'SINGLE-FLOAT) and (COERCE X
+ 'DOUBLE-FLOAT) are not flushable.
* bug fix: on x86 and x86-64 pointer based EQ-hashing now uses the
full address of the object, and none of the tag bits.
* bug fix: readably printing hash-tables now respects other printer
(when value
(derive-node-type node (lvar-derived-type value)))))
(cset
+ ;; PROPAGATE-FROM-SETS can do a better job if NODE-REOPTIMIZE
+ ;; is accurate till the node actually has been reoptimized.
+ (setf (node-reoptimize node) t)
(ir1-optimize-set node))
(cast
(ir1-optimize-cast node)))))
;;; the union of the INITIAL-TYPE and the types of all the set
;;; values and to a PROPAGATE-TO-REFS with this type.
(defun propagate-from-sets (var initial-type)
- (collect ((res initial-type type-union))
- (dolist (set (basic-var-sets var))
+ (let ((changes (not (csubtypep (lambda-var-last-initial-type var) initial-type)))
+ (types nil))
+ (dolist (set (lambda-var-sets var))
(let ((type (lvar-type (set-value set))))
- (res type)
+ (push type types)
(when (node-reoptimize set)
- (derive-node-type set (make-single-value-type type))
+ (let ((old-type (node-derived-type set)))
+ (unless (values-subtypep old-type type)
+ (derive-node-type set (make-single-value-type type))
+ (setf changes t)))
(setf (node-reoptimize set) nil))))
- (let ((res (res)))
- (awhen (maybe-infer-iteration-var-type var initial-type)
- (setq res it))
- (propagate-to-refs var res)))
+ (when changes
+ (setf (lambda-var-last-initial-type var) initial-type)
+ (let ((res-type (or (maybe-infer-iteration-var-type var initial-type)
+ (apply #'type-union initial-type types))))
+ (propagate-to-refs var res-type))))
(values))
;;; If a LET variable, find the initial value's type and do
(initial-type (lvar-type initial-value)))
(setf (lvar-reoptimize initial-value) nil)
(propagate-from-sets var initial-type))))))
-
(derive-node-type node (make-single-value-type
(lvar-type (set-value node))))
+ (setf (node-reoptimize node) nil)
(values))
;;; Return true if the value of REF will always be the same (and is
;; determine that this is a set closure variable, and is thus not a
;; good subject for flow analysis.
(constraints nil :type (or sset null))
+ ;; Initial type of a LET variable as last seen by PROPAGATE-FROM-SETS.
+ (last-initial-type *universal-type* :type ctype)
;; The FOP handle of the lexical variable represented by LAMBDA-VAR
;; in the fopcompiler.
(fop-value nil))