Stricter precondition when strength reducing variable right shifts
authorPaul Khuong <pvk@pvk.ca>
Fri, 31 May 2013 01:49:55 +0000 (21:49 -0400)
committerPaul Khuong <pvk@pvk.ca>
Fri, 31 May 2013 01:57:02 +0000 (21:57 -0400)
 Looking at the node's derived type is safer than a result type
 constraint, which seems to consider the LVAR's derived or
 truly-declared type.

 Remove a redundant AVER too. If people call %ash/right directly and
 incorrectly, they're looking for trouble. Moreover, the call's
 type will be derived only if the argument types are correct.

 Reported by Eric Marsden on sbcl-devel; further reduced test cases
 by Christophe Rhodes.

src/compiler/srctran.lisp
tests/compiler.pure.lisp

index 4fc7754..ef9de86 100644 (file)
     "Convert %ASH/RIGHT by constant back to ASH"
     `(ash integer ,(- (lvar-value amount))))
 
-  (deftransform %ash/right ((integer amount) * (member -1 0) :node node)
-    ;; constant-fold large shifts
+  (deftransform %ash/right ((integer amount) * * :node node)
+    "strength reduce large variable right shift"
     (let ((return-type (single-value-type (node-derived-type node))))
       (cond ((type= return-type (specifier-type '(eql 0)))
              0)
             ((type= return-type (specifier-type '(eql -1)))
              -1)
+            ((csubtypep return-type (specifier-type '(member -1 0)))
+             `(ash integer ,(- sb!vm:n-word-bits)))
             (t
-             (aver (csubtypep (lvar-type integer) (specifier-type 'sb!vm:signed-word)))
-             `(ash integer ,(- 1 sb!vm:n-word-bits))))))
+             (give-up-ir1-transform)))))
 
   (defun %ash/right-derive-type-aux (n-type shift same-arg)
     (declare (ignore same-arg))
index bccf8ef..3e949b3 100644 (file)
                            ((simple-array character (*)) vector)
                            ((unsigned-byte 24) index))
                   (aref vector (1+ (mod index (1- (length vector))))))))
+
+(test-util:with-test (:name :constant-fold-ash/right-fixnum)
+  (compile nil `(lambda (a b)
+                  (declare (type fixnum a)
+                           (type (integer * -84) b))
+                  (ash a b))))
+
+(test-util:with-test (:name :constant-fold-ash/right-word)
+  (compile nil `(lambda (a b)
+                  (declare (type word a)
+                           (type (integer * -84) b))
+                  (ash a b))))