0.8.1.33:
[sbcl.git] / src / compiler / generic / vm-tran.lisp
1 ;;;; implementation-dependent transforms
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
11
12 (in-package "SB!C")
13
14 ;;; We need to define these predicates, since the TYPEP source
15 ;;; transform picks whichever predicate was defined last when there
16 ;;; are multiple predicates for equivalent types.
17 (define-source-transform short-float-p (x) `(single-float-p ,x))
18 #!-long-float
19 (define-source-transform long-float-p (x) `(double-float-p ,x))
20
21 (define-source-transform compiled-function-p (x)
22   `(functionp ,x))
23
24 (define-source-transform char-int (x)
25   `(char-code ,x))
26
27 (deftransform abs ((x) (rational))
28   '(if (< x 0) (- x) x))
29
30 ;;; The layout is stored in slot 0.
31 (define-source-transform %instance-layout (x)
32   `(truly-the layout (%instance-ref ,x 0)))
33 (define-source-transform %set-instance-layout (x val)
34   `(%instance-set ,x 0 (the layout ,val)))
35 \f
36 ;;;; character support
37
38 ;;; In our implementation there are really only BASE-CHARs.
39 (define-source-transform characterp (obj)
40   `(base-char-p ,obj))
41 \f
42 ;;;; simplifying HAIRY-DATA-VECTOR-REF and HAIRY-DATA-VECTOR-SET
43
44 (deftransform hairy-data-vector-ref ((array index) (array t) * :important t)
45   "avoid runtime dispatch on array element type"
46   (let ((element-ctype (extract-upgraded-element-type array))
47         (declared-element-ctype (extract-declared-element-type array)))
48     (declare (type ctype element-ctype))
49     (when (eq *wild-type* element-ctype)
50       (give-up-ir1-transform
51        "Upgraded element type of array is not known at compile time."))
52     ;; (The expansion here is basically a degenerate case of
53     ;; WITH-ARRAY-DATA. Since WITH-ARRAY-DATA is implemented as a
54     ;; macro, and macros aren't expanded in transform output, we have
55     ;; to hand-expand it ourselves.)
56     (let ((element-type-specifier (type-specifier element-ctype)))
57       `(multiple-value-bind (array index)
58            (%data-vector-and-index array index)
59          (declare (type (simple-array ,element-type-specifier 1) array))
60          ,(let ((bare-form '(data-vector-ref array index)))
61             (if (type= element-ctype declared-element-ctype)
62                 bare-form
63                 `(the ,(type-specifier declared-element-ctype)
64                       ,bare-form)))))))
65
66 (deftransform data-vector-ref ((array index)
67                                (simple-array t))
68   (let ((array-type (continuation-type array)))
69     (unless (array-type-p array-type)
70       (give-up-ir1-transform))
71     (let ((dims (array-type-dimensions array-type)))
72       (when (or (atom dims) (= (length dims) 1))
73         (give-up-ir1-transform))
74       (let ((el-type (array-type-specialized-element-type array-type))
75             (total-size (if (member '* dims)
76                             '*
77                             (reduce #'* dims))))
78         `(data-vector-ref (truly-the (simple-array ,(type-specifier el-type)
79                                                    (,total-size))
80                                      (%array-data-vector array))
81                           index)))))
82
83 (deftransform hairy-data-vector-set ((array index new-value)
84                                      (array t t)
85                                      *
86                                      :important t)
87   "avoid runtime dispatch on array element type"
88   (let ((element-ctype (extract-upgraded-element-type array))
89         (declared-element-ctype (extract-declared-element-type array)))
90     (declare (type ctype element-ctype))
91     (when (eq *wild-type* element-ctype)
92       (give-up-ir1-transform
93        "Upgraded element type of array is not known at compile time."))
94     (let ((element-type-specifier (type-specifier element-ctype)))
95       `(multiple-value-bind (array index)
96            (%data-vector-and-index array index)
97          (declare (type (simple-array ,element-type-specifier 1) array)
98                   (type ,element-type-specifier new-value))
99          ,(if (type= element-ctype declared-element-ctype)
100               '(data-vector-set array index new-value)
101               `(truly-the ,(type-specifier declared-element-ctype)
102                  (data-vector-set array index
103                   (the ,(type-specifier declared-element-ctype)
104                        new-value))))))))
105
106 (deftransform data-vector-set ((array index new-value)
107                                (simple-array t t))
108   (let ((array-type (continuation-type array)))
109     (unless (array-type-p array-type)
110       (give-up-ir1-transform))
111     (let ((dims (array-type-dimensions array-type)))
112       (when (or (atom dims) (= (length dims) 1))
113         (give-up-ir1-transform))
114       (let ((el-type (array-type-specialized-element-type array-type))
115             (total-size (if (member '* dims)
116                             '*
117                             (reduce #'* dims))))
118         `(data-vector-set (truly-the (simple-array ,(type-specifier el-type)
119                                                    (,total-size))
120                                      (%array-data-vector array))
121                           index
122                           new-value)))))
123
124 (defoptimizer (%data-vector-and-index derive-type) ((array index))
125   (let ((atype (continuation-type array)))
126     (when (array-type-p atype)
127       (values-specifier-type
128        `(values (simple-array ,(type-specifier
129                                 (array-type-specialized-element-type atype))
130                               (*))
131                 index)))))
132
133 (deftransform %data-vector-and-index ((%array %index)
134                                       (simple-array t)
135                                       *
136                                       :important t)
137   ;; KLUDGE: why the percent signs?  Well, ARRAY and INDEX are
138   ;; respectively exported from the CL and SB!INT packages, which
139   ;; means that they're visible to all sorts of things.  If the
140   ;; compiler can prove that the call to ARRAY-HEADER-P, below, either
141   ;; returns T or NIL, it will delete the irrelevant branch.  However,
142   ;; user code might have got here with a variable named CL:ARRAY, and
143   ;; quite often compiler code with a variable named SB!INT:INDEX, so
144   ;; this can generate code deletion notes for innocuous user code:
145   ;; (DEFUN F (ARRAY I) (DECLARE (SIMPLE-VECTOR ARRAY)) (AREF ARRAY I))
146   ;; -- CSR, 2003-04-01
147
148   ;; We do this solely for the -OR-GIVE-UP side effect, since we want
149   ;; to know that the type can be figured out in the end before we
150   ;; proceed, but we don't care yet what the type will turn out to be.
151   (upgraded-element-type-specifier-or-give-up %array)
152
153   '(if (array-header-p %array)
154        (values (%array-data-vector %array) %index)
155        (values %array %index)))
156
157 ;;; transforms for getting at simple arrays of (UNSIGNED-BYTE N) when (< N 8)
158 ;;;
159 ;;; FIXME: In CMU CL, these were commented out with #+NIL. Why? Should
160 ;;; we fix them or should we delete them? (Perhaps these definitions
161 ;;; predate the various DATA-VECTOR-REF-FOO VOPs which have
162 ;;; (:TRANSLATE DATA-VECTOR-REF), and are redundant now?)
163 #+nil
164 (macrolet
165     ((frob (type bits)
166        (let ((elements-per-word (truncate sb!vm:n-word-bits bits)))
167          `(progn
168             (deftransform data-vector-ref ((vector index)
169                                            (,type *))
170               `(multiple-value-bind (word bit)
171                    (floor index ,',elements-per-word)
172                  (ldb ,(ecase sb!vm:target-byte-order
173                          (:little-endian '(byte ,bits (* bit ,bits)))
174                          (:big-endian '(byte ,bits (- sb!vm:n-word-bits
175                                                       (* (1+ bit) ,bits)))))
176                       (%raw-bits vector (+ word sb!vm:vector-data-offset)))))
177             (deftransform data-vector-set ((vector index new-value)
178                                            (,type * *))
179               `(multiple-value-bind (word bit)
180                    (floor index ,',elements-per-word)
181                  (setf (ldb ,(ecase sb!vm:target-byte-order
182                                (:little-endian '(byte ,bits (* bit ,bits)))
183                                (:big-endian
184                                 '(byte ,bits (- sb!vm:n-word-bits
185                                                 (* (1+ bit) ,bits)))))
186                             (%raw-bits vector (+ word sb!vm:vector-data-offset)))
187                        new-value)))))))
188   (frob simple-bit-vector 1)
189   (frob (simple-array (unsigned-byte 2) (*)) 2)
190   (frob (simple-array (unsigned-byte 4) (*)) 4))
191 \f
192 ;;;; BIT-VECTOR hackery
193
194 ;;; SIMPLE-BIT-VECTOR bit-array operations are transformed to a word
195 ;;; loop that does 32 bits at a time.
196 ;;;
197 ;;; FIXME: This is a lot of repeatedly macroexpanded code. It should
198 ;;; be a function call instead.
199 (macrolet ((def (bitfun wordfun)
200              `(deftransform ,bitfun ((bit-array-1 bit-array-2 result-bit-array)
201                                      (simple-bit-vector
202                                       simple-bit-vector
203                                       simple-bit-vector)
204                                      *
205                                      :node node :policy (>= speed space))
206                 `(progn
207                    ,@(unless (policy node (zerop safety))
208                              '((unless (= (length bit-array-1)
209                                           (length bit-array-2)
210                                           (length result-bit-array))
211                                  (error "Argument and/or result bit arrays are not the same length:~
212                          ~%  ~S~%  ~S  ~%  ~S"
213                                         bit-array-1
214                                         bit-array-2
215                                         result-bit-array))))
216                   (let ((length (length result-bit-array)))
217                     (if (= length 0)
218                         ;; We avoid doing anything to 0-length
219                         ;; bit-vectors, or rather, the memory that
220                         ;; follows them. Other divisible-by-32 cases
221                         ;; are handled by the (1- length), below.
222                         ;; CSR, 2002-04-24
223                         result-bit-array
224                         (do ((index sb!vm:vector-data-offset (1+ index))
225                              (end-1 (+ sb!vm:vector-data-offset
226                                        ;; bit-vectors of length 1-32
227                                        ;; need precisely one (SETF
228                                        ;; %RAW-BITS), done here in the
229                                        ;; epilogue. - CSR, 2002-04-24
230                                        (truncate (truly-the index (1- length))
231                                                  sb!vm:n-word-bits))))
232                             ((= index end-1)
233                              (setf (%raw-bits result-bit-array index)
234                                    (,',wordfun (%raw-bits bit-array-1 index)
235                                                (%raw-bits bit-array-2 index)))
236                              result-bit-array)
237                           (declare (optimize (speed 3) (safety 0))
238                                    (type index index end-1))
239                           (setf (%raw-bits result-bit-array index)
240                                 (,',wordfun (%raw-bits bit-array-1 index)
241                                             (%raw-bits bit-array-2 index))))))))))
242  (def bit-and 32bit-logical-and)
243  (def bit-ior 32bit-logical-or)
244  (def bit-xor 32bit-logical-xor)
245  (def bit-eqv 32bit-logical-eqv)
246  (def bit-nand 32bit-logical-nand)
247  (def bit-nor 32bit-logical-nor)
248  (def bit-andc1 32bit-logical-andc1)
249  (def bit-andc2 32bit-logical-andc2)
250  (def bit-orc1 32bit-logical-orc1)
251  (def bit-orc2 32bit-logical-orc2))
252
253 (deftransform bit-not
254               ((bit-array result-bit-array)
255                (simple-bit-vector simple-bit-vector) *
256                :node node :policy (>= speed space))
257   `(progn
258      ,@(unless (policy node (zerop safety))
259          '((unless (= (length bit-array)
260                       (length result-bit-array))
261              (error "Argument and result bit arrays are not the same length:~
262                      ~%  ~S~%  ~S"
263                     bit-array result-bit-array))))
264     (let ((length (length result-bit-array)))
265       (if (= length 0)
266           ;; We avoid doing anything to 0-length bit-vectors, or
267           ;; rather, the memory that follows them. Other
268           ;; divisible-by-32 cases are handled by the (1- length),
269           ;; below.  CSR, 2002-04-24
270           result-bit-array
271           (do ((index sb!vm:vector-data-offset (1+ index))
272                (end-1 (+ sb!vm:vector-data-offset
273                          ;; bit-vectors of length 1-32 need precisely
274                          ;; one (SETF %RAW-BITS), done here in the
275                          ;; epilogue. - CSR, 2002-04-24
276                          (truncate (truly-the index (1- length))
277                                    sb!vm:n-word-bits))))
278               ((= index end-1)
279                (setf (%raw-bits result-bit-array index)
280                      (32bit-logical-not (%raw-bits bit-array index)))
281                result-bit-array)
282             (declare (optimize (speed 3) (safety 0))
283                      (type index index end-1))
284             (setf (%raw-bits result-bit-array index)
285                   (32bit-logical-not (%raw-bits bit-array index))))))))
286
287 (deftransform bit-vector-= ((x y) (simple-bit-vector simple-bit-vector))
288   `(and (= (length x) (length y))
289         (let ((length (length x)))
290           (or (= length 0)
291               (do* ((i sb!vm:vector-data-offset (+ i 1))
292                     (end-1 (+ sb!vm:vector-data-offset
293                               (floor (1- length) sb!vm:n-word-bits))))
294                    ((= i end-1)
295                     (let* ((extra (mod length sb!vm:n-word-bits))
296                            (mask (1- (ash 1 extra)))
297                            (numx
298                             (logand
299                              (ash mask
300                                   ,(ecase sb!c:*backend-byte-order*
301                                      (:little-endian 0)
302                                      (:big-endian
303                                       '(- sb!vm:n-word-bits extra))))
304                              (%raw-bits x i)))
305                            (numy
306                             (logand
307                              (ash mask
308                                   ,(ecase sb!c:*backend-byte-order*
309                                      (:little-endian 0)
310                                      (:big-endian
311                                       '(- sb!vm:n-word-bits extra))))
312                              (%raw-bits y i))))
313                       (declare (type (integer 0 31) extra)
314                                (type (unsigned-byte 32) mask numx numy))
315                       (= numx numy)))
316                 (declare (type index i end-1))
317                 (let ((numx (%raw-bits x i))
318                       (numy (%raw-bits y i)))
319                   (declare (type (unsigned-byte 32) numx numy))
320                   (unless (= numx numy)
321                     (return nil))))))))
322 \f
323 ;;;; %BYTE-BLT
324
325 ;;; FIXME: The old CMU CL code used various COPY-TO/FROM-SYSTEM-AREA
326 ;;; stuff (with all the associated bit-index cruft and overflow
327 ;;; issues) even for byte moves. In SBCL, we're converting to byte
328 ;;; moves as problems are discovered with the old code, and this is
329 ;;; currently (ca. sbcl-0.6.12.30) the main interface for code in
330 ;;; SB!KERNEL and SB!SYS (e.g. i/o code). It's not clear that it's the
331 ;;; ideal interface, though, and it probably deserves some thought.
332 (deftransform %byte-blt ((src src-start dst dst-start dst-end)
333                          ((or (simple-unboxed-array (*)) system-area-pointer)
334                           index
335                           (or (simple-unboxed-array (*)) system-area-pointer)
336                           index
337                           index))
338   ;; FIXME: CMU CL had a hairier implementation of this (back when it
339   ;; was still called (%PRIMITIVE BYTE-BLT). It had the small problem
340   ;; that it didn't work for large (>16M) values of SRC-START or
341   ;; DST-START. However, it might have been more efficient. In
342   ;; particular, I don't really know how much the foreign function
343   ;; call costs us here. My guess is that if the overhead is
344   ;; acceptable for SQRT and COS, it's acceptable here, but this
345   ;; should probably be checked. -- WHN
346   '(flet ((sapify (thing)
347             (etypecase thing
348               (system-area-pointer thing)
349               ;; FIXME: The code here rather relies on the simple
350               ;; unboxed array here having byte-sized entries. That
351               ;; should be asserted explicitly, I just haven't found
352               ;; a concise way of doing it. (It would be nice to
353               ;; declare it in the DEFKNOWN too.)
354               ((simple-unboxed-array (*)) (vector-sap thing)))))
355      (declare (inline sapify))
356      (without-gcing
357       (memmove (sap+ (sapify dst) dst-start)
358                (sap+ (sapify src) src-start)
359                (- dst-end dst-start)))
360      (values)))
361 \f
362 ;;;; transforms for EQL of floating point values
363
364 (deftransform eql ((x y) (single-float single-float))
365   '(= (single-float-bits x) (single-float-bits y)))
366
367 (deftransform eql ((x y) (double-float double-float))
368   '(and (= (double-float-low-bits x) (double-float-low-bits y))
369         (= (double-float-high-bits x) (double-float-high-bits y))))
370