bogus type-error from array access optimization using negative index and positive offset

Bug #622958 reported by Nikodemus Siivola
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Fix Released
Medium
Unassigned

Bug Description

x86 and x86-64 only, I think.

Test case:

(defun oops ()
  #+nil
  (declare (optimize (safety 0)))
  (let ((table (make-array 7 :element-type 'fixnum :initial-contents '(0 1 2 3 4 5 6))))
    (loop for n from -3 upto 3
          do (print (aref table (+ 3 n))))))

signals an error unless SAFETY 0:

  The value -3 is not of type (MOD 1152921504606846973).

With SAFETY 0 prints out numbers 0-6, demonstrating that the computed offsets are correct.

The deftransform for data-vector-ref-with-offset calls FOLD-INDEX-ADDRESSING, which realizes that +3 means a constant offset, and the call is transformed into one using two offsets with the +3 as one.

However, somewhere we end up generating a type-check for the other offset, asserting that it is a regular array index -- whereas due to the +3 the lower end of the range has been extended to -3. I suspect that that typecheck is wholly pointless, actually.

Changed in sbcl:
status: New → Confirmed
importance: Undecided → High
importance: High → Medium
Revision history for this message
Nikodemus Siivola (nikodemus) wrote :

This is what the fix looks like:

diff --git a/src/compiler/fndb.lisp b/src/compiler/fndb.lisp
index dfb0dcd..5991492 100644
--- a/src/compiler/fndb.lisp
+++ b/src/compiler/fndb.lisp
@@ -1448,7 +1448,7 @@
 (defknown %check-bound (array index fixnum) index (movable foldable flushable))
 (defknown data-vector-ref (simple-array index) t
   (foldable explicit-check always-translatable))
-(defknown data-vector-ref-with-offset (simple-array index fixnum) t
+(defknown data-vector-ref-with-offset (simple-array fixnum fixnum) t
   (foldable explicit-check always-translatable))
 (defknown data-vector-set (array index t) t
   (unsafe explicit-check always-translatable))

Merging after freeze -- though I have good confidence in this fix, the problem has been there for a long time and no-one has yet to report it.

Revision history for this message
Nikodemus Siivola (nikodemus) wrote :

Actually, it is still fairly simple to construct cases that fail. Consider:

 (aref v (- x #.(1+ most-positive-fixnum)))

Revision history for this message
Nikodemus Siivola (nikodemus) wrote :

Ignore that last comment -- that doesn't end up on the DATA-VECTOR-REF-WITH-OFFSET path at all.

Revision history for this message
Nikodemus Siivola (nikodemus) wrote :

Fixed in SBCL 1.0.42.2.

Changed in sbcl:
status: Confirmed → Fix Committed
Revision history for this message
Nikodemus Siivola (nikodemus) wrote :

Feh, backed out from CVS as of 1.0.42.5:

* The VOPs need to accept negative indexes as well, of course -- which requires not only changing the type from positive-fixnum to tagged-num, but auditing them for sign handling.

* Same issue applies to DATA-VECTOR-SET-WITH-OFFSET too, of course.

Changed in sbcl:
status: Fix Committed → Confirmed
status: Confirmed → Triaged
summary: - bogus type error from array access optimization using negative offsets
+ bogus type-error from array access optimization using negative index and
+ positive offset
Revision history for this message
Paul Khuong (pvk) wrote :

Fixed in 1.1.9 (a3b10e4, Handle (aref v (+ i k)), with i negative).

Changed in sbcl:
status: Triaged → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.