uses
(list uses))))
+(declaim (ftype (sfunction (lvar) lvar) principal-lvar))
+(defun principal-lvar (lvar)
+ (labels ((pl (lvar)
+ (let ((use (lvar-uses lvar)))
+ (if (cast-p use)
+ (pl (cast-value use))
+ lvar))))
+ (pl lvar)))
+
(defun principal-lvar-use (lvar)
(labels ((plu (lvar)
(declare (type lvar lvar))
(awhen (node-lvar node)
(lvar-dynamic-extent it)))
+(declaim (ftype (sfunction (node (member nil t :truly) &optional (or null component))
+ boolean) use-good-for-dx-p))
+(declaim (ftype (sfunction (lvar (member nil t :truly) &optional (or null component))
+ boolean) lvar-good-for-dx-p))
+(defun use-good-for-dx-p (use dx &optional component)
+ ;; FIXME: Can casts point to LVARs in other components?
+ ;; RECHECK-DYNAMIC-EXTENT-LVARS assumes that they can't -- that is, that the
+ ;; PRINCIPAL-LVAR is always in the same component as the original one. It
+ ;; would be either good to have an explanation of why casts don't point
+ ;; across components, or an explanation of when they do it. ...in the
+ ;; meanwhile AVER that our assumption holds true.
+ (aver (or (not component) (eq component (node-component use))))
+ (or (and (combination-p use)
+ (eq (combination-kind use) :known)
+ (awhen (fun-info-stack-allocate-result (combination-fun-info use))
+ (funcall it use dx))
+ t)
+ (and (cast-p use)
+ (not (cast-type-check use))
+ (lvar-good-for-dx-p (cast-value use) dx component)
+ t)))
+
+(defun lvar-good-for-dx-p (lvar dx &optional component)
+ (let ((uses (lvar-uses lvar)))
+ (if (listp uses)
+ (every (lambda (use)
+ (use-good-for-dx-p use dx component))
+ uses)
+ (use-good-for-dx-p uses dx component))))
+
(declaim (inline block-to-be-deleted-p))
(defun block-to-be-deleted-p (block)
(or (block-delete-p block)
(let* ((block (node-block node))
(start (node-next node))
(last (block-last block)))
+ (check-type last node)
(unless (eq last node)
(aver (and (eq (ctran-kind start) :inside-block)
(not (block-delete-p block))))
;;; of arguments changes, the transform must be prepared to return a
;;; lambda with a new lambda-list with the correct number of
;;; arguments.
-(defun extract-fun-args (lvar fun num-args)
+(defun splice-fun-args (lvar fun num-args)
#!+sb-doc
"If LVAR is a call to FUN with NUM-ARGS args, change those arguments
to feed directly to the LVAR-DEST of LVAR, which must be a
(flush-dest lvar)
(values))))))
+(defun extract-fun-args (lvar fun num-args)
+ (declare (type lvar lvar)
+ (type (or symbol list) fun)
+ (type index num-args))
+ (let ((fun (if (listp fun) fun (list fun))))
+ (let ((inside (lvar-uses lvar)))
+ (unless (combination-p inside)
+ (give-up-ir1-transform))
+ (let ((inside-fun (combination-fun inside)))
+ (unless (member (lvar-fun-name inside-fun) fun)
+ (give-up-ir1-transform))
+ (let ((inside-args (combination-args inside)))
+ (unless (= (length inside-args) num-args)
+ (give-up-ir1-transform))
+ (values (lvar-fun-name inside-fun) inside-args))))))
+
(defun flush-combination (combination)
(declare (type combination combination))
(flush-dest (combination-fun combination))
;;; Return a LEAF which represents the specified constant object. If
;;; the object is not in *CONSTANTS*, then we create a new constant
-;;; LEAF and enter it.
-(defun find-constant (object)
- (if (typep object
- ;; FIXME: What is the significance of this test? ("things
- ;; that are worth uniquifying"?)
- '(or symbol number character instance))
- (or (gethash object *constants*)
- (setf (gethash object *constants*)
- (make-constant :value object
- :%source-name '.anonymous.
- :type (ctype-of object)
- :where-from :defined)))
- (make-constant :value object
- :%source-name '.anonymous.
- :type (ctype-of object)
- :where-from :defined)))
+;;; LEAF and enter it. If we are producing a fasl file, make sure that
+;;; MAKE-LOAD-FORM gets used on any parts of the constant that it
+;;; needs to be.
+;;;
+;;; We are allowed to coalesce things like EQUAL strings and bit-vectors
+;;; when file-compiling, but not when using COMPILE.
+(defun find-constant (object &optional (name nil namep))
+ (let ((faslp (producing-fasl-file)))
+ (labels ((make-it ()
+ (when faslp
+ (if namep
+ (maybe-emit-make-load-forms object name)
+ (maybe-emit-make-load-forms object)))
+ (make-constant object))
+ (core-coalesce-p (x)
+ ;; True for things which retain their identity under EQUAL,
+ ;; so we can safely share the same CONSTANT leaf between
+ ;; multiple references.
+ (or (typep x '(or symbol number character))
+ ;; Amusingly enough, we see CLAMBDAs --among other things--
+ ;; here, from compiling things like %ALLOCATE-CLOSUREs forms.
+ ;; No point in stuffing them in the hash-table.
+ (and (typep x 'instance)
+ (not (or (leaf-p x) (node-p x))))))
+ (file-coalesce-p (x)
+ ;; CLHS 3.2.4.2.2: We are also allowed to coalesce various
+ ;; other things when file-compiling.
+ (or (core-coalesce-p x)
+ (if (consp x)
+ (if (eq +code-coverage-unmarked+ (cdr x))
+ ;; These are already coalesced, and the CAR should
+ ;; always be OK, so no need to check.
+ t
+ (unless (maybe-cyclic-p x) ; safe for EQUAL?
+ (do ((y x (cdr y)))
+ ((atom y) (file-coalesce-p y))
+ (unless (file-coalesce-p (car y))
+ (return nil)))))
+ ;; We *could* coalesce base-strings as well, but we'd need
+ ;; a separate hash-table for that, since we are not allowed to
+ ;; coalesce base-strings with non-base-strings.
+ (typep x '(or (vector character) bit-vector)))))
+ (coalescep (x)
+ (if faslp (file-coalesce-p x) (core-coalesce-p x))))
+ (if (and (boundp '*constants*) (coalescep object))
+ (or (gethash object *constants*)
+ (setf (gethash object *constants*)
+ (make-it)))
+ (make-it)))))
\f
;;; Return true if VAR would have to be closed over if environment
;;; analysis ran now (i.e. if there are any uses that have a different
nil))
nil)))
+(defun lvar-fun-debug-name (lvar)
+ (declare (type lvar lvar))
+ (let ((uses (lvar-uses lvar)))
+ (flet ((name1 (use)
+ (leaf-debug-name (ref-leaf use))))
+ (if (ref-p uses)
+ (name1 uses)
+ (mapcar #'name1 uses)))))
+
;;; Return the source name of a combination. (This is an idiom
;;; which was used in CMU CL. I gather it always works. -- WHN)
(defun combination-fun-source-name (combination)
(setf (node-reoptimize node) t)
(setf (block-reoptimize (node-block node)) t)
(reoptimize-component (node-component node) :maybe)))))))
+
+;;; Return true if LVAR's only use is a non-NOTINLINE reference to a
+;;; global function with one of the specified NAMES.
+(defun lvar-fun-is (lvar names)
+ (declare (type lvar lvar) (list names))
+ (let ((use (lvar-uses lvar)))
+ (and (ref-p use)
+ (let ((leaf (ref-leaf use)))
+ (and (global-var-p leaf)
+ (eq (global-var-kind leaf) :global-function)
+ (not (null (member (leaf-source-name leaf) names
+ :test #'equal))))))))