-;;; the lambda Fun might be converted into a let. This is done after
-;;; local call analysis, and also when a reference is deleted. We only
-;;; convert to a let when the function is a normal local function, has
-;;; no XEP, and is referenced in exactly one local call. Conversion is
-;;; also inhibited if the only reference is in a block about to be
-;;; deleted. We return true if we converted.
-;;;
-;;; These rules may seem unnecessarily restrictive, since there are
-;;; some cases where we could do the return with a jump that don't
-;;; satisfy these requirements. The reason for doing things this way
-;;; is that it makes the concept of a LET much more useful at the
-;;; level of IR1 semantics. The :ASSIGNMENT function kind provides
-;;; another way to optimize calls to single-return/multiple call
-;;; functions.
-;;;
-;;; We don't attempt to convert calls to functions that have an XEP,
-;;; since we might be embarrassed later when we want to convert a
-;;; newly discovered local call. Also, see OK-INITIAL-CONVERT-P.
-(defun maybe-let-convert (fun)
- (declare (type clambda fun))
- (let ((refs (leaf-refs fun)))
- (when (and refs
- (null (rest refs))
- (member (functional-kind fun) '(nil :assignment))
- (not (functional-entry-function fun)))
- (let* ((ref-cont (node-cont (first refs)))
- (dest (continuation-dest ref-cont)))
- (when (and dest
- (basic-combination-p dest)
- (eq (basic-combination-fun dest) ref-cont)
- (eq (basic-combination-kind dest) :local)
- (not (block-delete-p (node-block dest)))
- (cond ((ok-initial-convert-p fun) t)
- (t
- (reoptimize-continuation ref-cont)
- nil)))
- (unless (eq (functional-kind fun) :assignment)
- (let-convert fun dest))
- (reoptimize-call dest)
- (setf (functional-kind fun)
- (if (mv-combination-p dest) :mv-let :let))))
- t)))
+;;; CLAMBDA might be converted into a LET. This is done after local
+;;; call analysis, and also when a reference is deleted. We return
+;;; true if we converted.
+(defun maybe-let-convert (clambda)
+ (declare (type clambda clambda))
+ (unless (or (declarations-suppress-let-conversion-p clambda)
+ (functional-has-external-references-p clambda))
+ ;; We only convert to a LET when the function is a normal local
+ ;; function, has no XEP, and is referenced in exactly one local
+ ;; call. Conversion is also inhibited if the only reference is in
+ ;; a block about to be deleted.
+ ;;
+ ;; These rules limiting LET conversion may seem unnecessarily
+ ;; restrictive, since there are some cases where we could do the
+ ;; return with a jump that don't satisfy these requirements. The
+ ;; reason for doing things this way is that it makes the concept
+ ;; of a LET much more useful at the level of IR1 semantics. The
+ ;; :ASSIGNMENT function kind provides another way to optimize
+ ;; calls to single-return/multiple call functions.
+ ;;
+ ;; We don't attempt to convert calls to functions that have an
+ ;; XEP, since we might be embarrassed later when we want to
+ ;; convert a newly discovered local call. Also, see
+ ;; OK-INITIAL-CONVERT-P.
+ (let ((refs (leaf-refs clambda)))
+ (when (and refs
+ (null (rest refs))
+ (memq (functional-kind clambda) '(nil :assignment))
+ (not (functional-entry-fun clambda)))
+ (binding* ((ref (first refs))
+ (ref-lvar (node-lvar ref) :exit-if-null)
+ (dest (lvar-dest ref-lvar)))
+ (when (and (basic-combination-p dest)
+ (eq (basic-combination-fun dest) ref-lvar)
+ (eq (basic-combination-kind dest) :local)
+ (not (node-to-be-deleted-p dest))
+ (not (block-delete-p (lambda-block clambda)))
+ (cond ((ok-initial-convert-p clambda) t)
+ (t
+ (reoptimize-lvar ref-lvar)
+ nil)))
+ (when (eq clambda (node-home-lambda dest))
+ (delete-lambda clambda)
+ (return-from maybe-let-convert nil))
+ (unless (eq (functional-kind clambda) :assignment)
+ (let-convert clambda dest))
+ (reoptimize-call dest)
+ (setf (functional-kind clambda)
+ (if (mv-combination-p dest) :mv-let :let))))
+ t))))