master: lvar-constants: combine functions and refs from multiple uses

stassats via Sbcl-commits <[email protected]> Fri, 05 Jun 2026 00:02:25 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  a3cfdde6a335d9b1f0028006f19ce0a71694a32c (commit)
      from  898313d8e7d3d953e8153d74da078975c2957bf4 (commit)

- Log -----------------------------------------------------------------
commit a3cfdde6a335d9b1f0028006f19ce0a71694a32c
Author: Stas Boukarev <[email protected]>
Date:   Fri Jun 5 02:56:28 2026 +0300

    lvar-constants: combine functions and refs from multiple uses
---
 src/compiler/ir1util.lisp | 110 +++++++++++++++++++++++++++++++---------------
 tests/bad-code.pure.lisp  |   5 +++
 2 files changed, 79 insertions(+), 36 deletions(-)

diff --git a/src/compiler/ir1util.lisp b/src/compiler/ir1util.lisp
index bf1a3c846..d1e03dd84 100644
--- a/src/compiler/ir1util.lisp
+++ b/src/compiler/ir1util.lisp
@@ -96,6 +96,21 @@
                           use))))))
       (recurse lvar))))
 
+(defun principal-ref (ref &optional casts)
+  (labels ((recurse-lvar (lvar ref)
+             (if lvar
+                 (recurse (lvar-uses lvar) ref)
+                 ref))
+           (recurse (node original-ref)
+             (cond ((ref-p node)
+                    (recurse-lvar (lambda-var-ref-lvar node) node))
+                   ((and casts
+                         (cast-p node))
+                    (recurse-lvar (cast-value node) node))
+                   (t
+                    original-ref))))
+    (recurse ref ref)))
+
 (defun principal-lvar-ref (lvar &optional casts)
   (labels ((recurse (lvar ref)
              (if lvar
@@ -3769,42 +3784,65 @@ is :ANY, the function name is not checked."
                                   (node-lvar ref)))))
                      lvar))
            (uses (lvar-uses lvar)))
-      (cond ((constant-lvar-p lvar)
-             (values :values (list (lvar-value lvar))))
-            ((constant-lvar-uses-p lvar)
-             (values :values (lvar-uses-values lvar)))
-            ((ref-p uses)
-             (let* ((ref (principal-lvar-ref lvar))
-                    (leaf (and ref
-                               (ref-leaf ref))))
-               (when (lambda-var-p leaf)
-                 (let ((seen (or seen (alloc-xset)))
-                       constants)
-                   (add-to-xset lvar seen)
-                   (map-lambda-var-refs-from-calls
-                    (lambda (call lvar)
-                      (unless (xset-member-p lvar seen)
-                        (add-to-xset lvar seen)
-                        (multiple-value-bind (type values) (recurse lvar seen)
-                          (case type
-                            (:values
-                             (push (cons call values) constants))
-                            (:calls
-                             (setf constants (nconc values constants)))))))
-                    leaf)
-                   (when constants
-                     (values :calls constants))))))
-            ((and walk-functions
-                  (combination-p uses)
-                  (eq (combination-kind uses) :known))
-             (let ((fun-info (fun-info-constants (combination-fun-info uses))))
-               (when fun-info
-                 (let ((constants (funcall fun-info uses)))
-                   (when constants
-                     (multiple-value-bind (kind constants)
-                         (recurse constants seen)
-                       (when constants
-                         (values kind constants))))))))))))
+      (flet ((handle-ref (ref)
+               (let* ((ref (principal-ref ref))
+                      (leaf (and ref
+                                 (ref-leaf ref))))
+                 (cond ((lambda-var-p leaf)
+                        (let ((seen (or seen (alloc-xset)))
+                              constants)
+                          (add-to-xset lvar seen)
+                          (map-lambda-var-refs-from-calls
+                           (lambda (call lvar)
+                             (unless (xset-member-p lvar seen)
+                               (add-to-xset lvar seen)
+                               (multiple-value-bind (type values) (recurse lvar seen)
+                                 (case type
+                                   (:values
+                                    (push (cons call values) constants))
+                                   (:calls
+                                    (setf constants (nconc values constants)))))))
+                           leaf)
+                          (when constants
+                            (values :calls constants))))
+                       ((constant-p leaf)
+                        (values :values (list (constant-value leaf)))))))
+             (handle-combination (node)
+               (and (combination-p node)
+                    (eq (combination-kind node) :known)
+                    (let ((fun-info (fun-info-constants (combination-fun-info node))))
+                      (when fun-info
+                        (let ((constants (funcall fun-info node)))
+                          (when constants
+                            (multiple-value-bind (kind constants)
+                                (recurse constants seen)
+                              (when constants
+                                (values kind constants))))))))))
+        (cond ((constant-lvar-p lvar)
+               (values :values (list (lvar-value lvar))))
+              ((constant-lvar-uses-p lvar)
+               (values :values (lvar-uses-values lvar)))
+              ((ref-p uses)
+               (handle-ref uses))
+              (walk-functions
+               (if (consp uses)
+                   (let (constants)
+                     (loop for use in uses
+                           do (multiple-value-bind (kind values)
+                                  (typecase use
+                                    (ref
+                                     (handle-ref use))
+                                    (t
+                                     (handle-combination use)))
+                                (case kind
+                                  (:values
+                                   (setf constants (nconc values constants)))
+                                  (:valls
+                                   (setf constants (nconc values (cdr constants))))
+                                  (t
+                                   (return))))
+                           finally (return (values :values constants))))
+                   (handle-combination uses))))))))
 
 (defun lambda-var-original-name (leaf)
   (let ((home (lambda-var-home leaf)))
diff --git a/tests/bad-code.pure.lisp b/tests/bad-code.pure.lisp
index 93b34c766..3db776fc5 100644
--- a/tests/bad-code.pure.lisp
+++ b/tests/bad-code.pure.lisp
@@ -882,6 +882,11 @@
                      (checked-compile
                       '(lambda (n)
                         (setf (car (aref #((1) (2)) n)) 10))
+                      :allow-warnings t)))
+  (assert (nth-value 2
+                     (checked-compile
+                      '(lambda (x)
+                        (sort (if x (aref #((1) (4)) x)) #'>))
                       :allow-warnings t))))
 
 (with-test (:name :constant-modification-nil)

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL