Fix cut-to-width in the presence of bad constants in dead code.
authorStas Boukarev <stassats@gmail.com>
Sat, 7 Dec 2013 09:04:14 +0000 (13:04 +0400)
committerStas Boukarev <stassats@gmail.com>
Sat, 7 Dec 2013 09:04:14 +0000 (13:04 +0400)
Unreachable branches may have mismatching types and constant values,
and when cut-to-width is run before such nodes are deleted, it gets
confused.

Reported by Douglas Katzman.

NEWS
src/compiler/srctran.lisp
tests/compiler.impure.lisp

diff --git a/NEWS b/NEWS
index 303ebc0..364d1e9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,8 @@ changes relative to sbcl-1.1.14:
     having GUI applications without an automatically appearing console window.
   * bug fix: Windows applications without the console window no longer misbehave.
     (patch by Wilfredo Velazquez, lp#1256034).
+  * bug fix: modular arithmetic optimizations do not stumble on dead branches
+    with bad constants. (reported by Douglas Katzman)
 
 changes in sbcl-1.1.14 relative to sbcl-1.1.13:
   * optimization: complicated TYPEP tests are less opaque to the type
index c808988..fa780c9 100644 (file)
                  (setf (block-reoptimize (node-block node)) t)
                  (reoptimize-component (node-component node) :maybe))
                t)
-             (cut-node (node &aux did-something over-wide)
+             (cut-node (node)
                "Try to cut a node to width. The primary return value is
                 whether we managed to cut (cleverly), and the second whether
                 anything was changed.  The third return value tells whether
                   (typecase (ref-leaf node)
                     (constant
                      (let* ((constant-value (constant-value (ref-leaf node)))
-                            (new-value (if signedp
-                                           (mask-signed-field width constant-value)
-                                           (ldb (byte width 0) constant-value))))
+                            (new-value
+                              (cond ((not (integerp constant-value))
+                                     (return-from cut-node (values t nil)))
+                                    (signedp
+                                     (mask-signed-field width constant-value))
+                                    (t
+                                     (ldb (byte width 0) constant-value)))))
                        (cond ((= constant-value new-value)
                               (values t nil)) ; we knew what to do and did nothing
                              (t
                                                  (modular-fun-info-name modular-fun))
                                                 (function
                                                  (funcall modular-fun node width)))
-                                              :exit-if-null))
+                                              :exit-if-null)
+                                        (did-something nil)
+                                        (over-wide nil))
                                (unless (eql modular-fun :good)
                                  (setq did-something t
                                        over-wide t)
index 2fe23b1..e63e2d6 100644 (file)
   (assert (equal (compile '(setf compile-setf))
                  '(setf compile-setf))))
 
+(declaim (inline cut-test))
+(defun cut-test (b)
+  (cond ((integerp b) b)
+        (b 469)
+        (t 2)))
+
+(with-test (:name :cut-to-width-bad-constant)
+  (assert (= (funcall (compile nil
+                               `(lambda ()
+                                  (multiple-value-bind (a b) (values t t)
+                                    (declare (ignore b))
+                                    (mask-field (byte 10 0) (cut-test a))))))
+             469)))
+
 \f
 ;;;; tests not in the problem domain, but of the consistency of the
 ;;;; compiler machinery itself