open intervals and type derivation
[sbcl.git] / src / compiler / srctran.lisp
1 ;;;; This file contains macro-like source transformations which
2 ;;;; convert uses of certain functions into the canonical form desired
3 ;;;; within the compiler. FIXME: and other IR1 transforms and stuff.
4
5 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; more information.
7 ;;;;
8 ;;;; This software is derived from the CMU CL system, which was
9 ;;;; written at Carnegie Mellon University and released into the
10 ;;;; public domain. The software is in the public domain and is
11 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
12 ;;;; files for more information.
13
14 (in-package "SB!C")
15
16 ;;; Convert into an IF so that IF optimizations will eliminate redundant
17 ;;; negations.
18 (define-source-transform not (x) `(if ,x nil t))
19 (define-source-transform null (x) `(if ,x nil t))
20
21 ;;; ENDP is just NULL with a LIST assertion. The assertion will be
22 ;;; optimized away when SAFETY optimization is low; hopefully that
23 ;;; is consistent with ANSI's "should return an error".
24 (define-source-transform endp (x) `(null (the list ,x)))
25
26 ;;; We turn IDENTITY into PROG1 so that it is obvious that it just
27 ;;; returns the first value of its argument. Ditto for VALUES with one
28 ;;; arg.
29 (define-source-transform identity (x) `(prog1 ,x))
30 (define-source-transform values (x) `(prog1 ,x))
31
32
33 ;;; CONSTANTLY is pretty much never worth transforming, but it's good to get the type.
34 (defoptimizer (constantly derive-type) ((value))
35   (specifier-type
36    `(function (&rest t) (values ,(type-specifier (lvar-type value)) &optional))))
37
38 ;;; If the function has a known number of arguments, then return a
39 ;;; lambda with the appropriate fixed number of args. If the
40 ;;; destination is a FUNCALL, then do the &REST APPLY thing, and let
41 ;;; MV optimization figure things out.
42 (deftransform complement ((fun) * * :node node)
43   "open code"
44   (multiple-value-bind (min max)
45       (fun-type-nargs (lvar-type fun))
46     (cond
47      ((and min (eql min max))
48       (let ((dums (make-gensym-list min)))
49         `#'(lambda ,dums (not (funcall fun ,@dums)))))
50      ((awhen (node-lvar node)
51         (let ((dest (lvar-dest it)))
52           (and (combination-p dest)
53                (eq (combination-fun dest) it))))
54       '#'(lambda (&rest args)
55            (not (apply fun args))))
56      (t
57       (give-up-ir1-transform
58        "The function doesn't have a fixed argument count.")))))
59 \f
60 ;;;; SYMBOL-VALUE &co
61 (defun derive-symbol-value-type (lvar node)
62   (if (constant-lvar-p lvar)
63       (let* ((sym (lvar-value lvar))
64              (var (maybe-find-free-var sym))
65              (local-type (when var
66                            (let ((*lexenv* (node-lexenv node)))
67                              (lexenv-find var type-restrictions))))
68              (global-type (info :variable :type sym)))
69         (if local-type
70             (type-intersection local-type global-type)
71             global-type))
72       *universal-type*))
73
74 (defoptimizer (symbol-value derive-type) ((symbol) node)
75   (derive-symbol-value-type symbol node))
76
77 (defoptimizer (symbol-global-value derive-type) ((symbol) node)
78   (derive-symbol-value-type symbol node))
79 \f
80 ;;;; list hackery
81
82 ;;; Translate CxR into CAR/CDR combos.
83 (defun source-transform-cxr (form)
84   (if (/= (length form) 2)
85       (values nil t)
86       (let* ((name (car form))
87              (string (symbol-name
88                       (etypecase name
89                         (symbol name)
90                         (leaf (leaf-source-name name))))))
91         (do ((i (- (length string) 2) (1- i))
92              (res (cadr form)
93                   `(,(ecase (char string i)
94                        (#\A 'car)
95                        (#\D 'cdr))
96                     ,res)))
97             ((zerop i) res)))))
98
99 ;;; Make source transforms to turn CxR forms into combinations of CAR
100 ;;; and CDR. ANSI specifies that everything up to 4 A/D operations is
101 ;;; defined.
102 (/show0 "about to set CxR source transforms")
103 (loop for i of-type index from 2 upto 4 do
104       ;; Iterate over BUF = all names CxR where x = an I-element
105       ;; string of #\A or #\D characters.
106       (let ((buf (make-string (+ 2 i))))
107         (setf (aref buf 0) #\C
108               (aref buf (1+ i)) #\R)
109         (dotimes (j (ash 2 i))
110           (declare (type index j))
111           (dotimes (k i)
112             (declare (type index k))
113             (setf (aref buf (1+ k))
114                   (if (logbitp k j) #\A #\D)))
115           (setf (info :function :source-transform (intern buf))
116                 #'source-transform-cxr))))
117 (/show0 "done setting CxR source transforms")
118
119 ;;; Turn FIRST..FOURTH and REST into the obvious synonym, assuming
120 ;;; whatever is right for them is right for us. FIFTH..TENTH turn into
121 ;;; Nth, which can be expanded into a CAR/CDR later on if policy
122 ;;; favors it.
123 (define-source-transform first (x) `(car ,x))
124 (define-source-transform rest (x) `(cdr ,x))
125 (define-source-transform second (x) `(cadr ,x))
126 (define-source-transform third (x) `(caddr ,x))
127 (define-source-transform fourth (x) `(cadddr ,x))
128 (define-source-transform fifth (x) `(nth 4 ,x))
129 (define-source-transform sixth (x) `(nth 5 ,x))
130 (define-source-transform seventh (x) `(nth 6 ,x))
131 (define-source-transform eighth (x) `(nth 7 ,x))
132 (define-source-transform ninth (x) `(nth 8 ,x))
133 (define-source-transform tenth (x) `(nth 9 ,x))
134
135 ;;; LIST with one arg is an extremely common operation (at least inside
136 ;;; SBCL itself); translate it to CONS to take advantage of common
137 ;;; allocation routines.
138 (define-source-transform list (&rest args)
139   (case (length args)
140     (1 `(cons ,(first args) nil))
141     (t (values nil t))))
142
143 ;;; And similarly for LIST*.
144 (define-source-transform list* (arg &rest others)
145   (cond ((not others) arg)
146         ((not (cdr others)) `(cons ,arg ,(car others)))
147         (t (values nil t))))
148
149 (defoptimizer (list* derive-type) ((arg &rest args))
150   (if args
151       (specifier-type 'cons)
152       (lvar-type arg)))
153
154 ;;; Translate RPLACx to LET and SETF.
155 (define-source-transform rplaca (x y)
156   (once-only ((n-x x))
157     `(progn
158        (setf (car ,n-x) ,y)
159        ,n-x)))
160 (define-source-transform rplacd (x y)
161   (once-only ((n-x x))
162     `(progn
163        (setf (cdr ,n-x) ,y)
164        ,n-x)))
165
166 (define-source-transform nth (n l) `(car (nthcdr ,n ,l)))
167
168 (deftransform last ((list &optional n) (t &optional t))
169   (let ((c (constant-lvar-p n)))
170     (cond ((or (not n)
171                (and c (eql 1 (lvar-value n))))
172            '(%last1 list))
173           ((and c (eql 0 (lvar-value n)))
174            '(%last0 list))
175           (t
176            (let ((type (lvar-type n)))
177              (cond ((csubtypep type (specifier-type 'fixnum))
178                     '(%lastn/fixnum list n))
179                    ((csubtypep type (specifier-type 'bignum))
180                     '(%lastn/bignum list n))
181                    (t
182                     (give-up-ir1-transform "second argument type too vague"))))))))
183
184 (define-source-transform gethash (&rest args)
185   (case (length args)
186    (2 `(sb!impl::gethash3 ,@args nil))
187    (3 `(sb!impl::gethash3 ,@args))
188    (t (values nil t))))
189 (define-source-transform get (&rest args)
190   (case (length args)
191    (2 `(sb!impl::get2 ,@args))
192    (3 `(sb!impl::get3 ,@args))
193    (t (values nil t))))
194
195 (defvar *default-nthcdr-open-code-limit* 6)
196 (defvar *extreme-nthcdr-open-code-limit* 20)
197
198 (deftransform nthcdr ((n l) (unsigned-byte t) * :node node)
199   "convert NTHCDR to CAxxR"
200   (unless (constant-lvar-p n)
201     (give-up-ir1-transform))
202   (let ((n (lvar-value n)))
203     (when (> n
204              (if (policy node (and (= speed 3) (= space 0)))
205                  *extreme-nthcdr-open-code-limit*
206                  *default-nthcdr-open-code-limit*))
207       (give-up-ir1-transform))
208
209     (labels ((frob (n)
210                (if (zerop n)
211                    'l
212                    `(cdr ,(frob (1- n))))))
213       (frob n))))
214 \f
215 ;;;; arithmetic and numerology
216
217 (define-source-transform plusp (x) `(> ,x 0))
218 (define-source-transform minusp (x) `(< ,x 0))
219 (define-source-transform zerop (x) `(= ,x 0))
220
221 (define-source-transform 1+ (x) `(+ ,x 1))
222 (define-source-transform 1- (x) `(- ,x 1))
223
224 (define-source-transform oddp (x) `(logtest ,x 1))
225 (define-source-transform evenp (x) `(not (logtest ,x 1)))
226
227 ;;; Note that all the integer division functions are available for
228 ;;; inline expansion.
229
230 (macrolet ((deffrob (fun)
231              `(define-source-transform ,fun (x &optional (y nil y-p))
232                 (declare (ignore y))
233                 (if y-p
234                     (values nil t)
235                     `(,',fun ,x 1)))))
236   (deffrob truncate)
237   (deffrob round)
238   #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
239   (deffrob floor)
240   #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
241   (deffrob ceiling))
242
243 ;;; This used to be a source transform (hence the lack of restrictions
244 ;;; on the argument types), but we make it a regular transform so that
245 ;;; the VM has a chance to see the bare LOGTEST and potentiall choose
246 ;;; to implement it differently.  --njf, 06-02-2006
247 (deftransform logtest ((x y) * *)
248   `(not (zerop (logand x y))))
249
250 (deftransform logbitp
251     ((index integer) (unsigned-byte (or (signed-byte #.sb!vm:n-word-bits)
252                                         (unsigned-byte #.sb!vm:n-word-bits))))
253   `(if (>= index #.sb!vm:n-word-bits)
254        (minusp integer)
255        (not (zerop (logand integer (ash 1 index))))))
256
257 (define-source-transform byte (size position)
258   `(cons ,size ,position))
259 (define-source-transform byte-size (spec) `(car ,spec))
260 (define-source-transform byte-position (spec) `(cdr ,spec))
261 (define-source-transform ldb-test (bytespec integer)
262   `(not (zerop (mask-field ,bytespec ,integer))))
263
264 ;;; With the ratio and complex accessors, we pick off the "identity"
265 ;;; case, and use a primitive to handle the cell access case.
266 (define-source-transform numerator (num)
267   (once-only ((n-num `(the rational ,num)))
268     `(if (ratiop ,n-num)
269          (%numerator ,n-num)
270          ,n-num)))
271 (define-source-transform denominator (num)
272   (once-only ((n-num `(the rational ,num)))
273     `(if (ratiop ,n-num)
274          (%denominator ,n-num)
275          1)))
276 \f
277 ;;;; interval arithmetic for computing bounds
278 ;;;;
279 ;;;; This is a set of routines for operating on intervals. It
280 ;;;; implements a simple interval arithmetic package. Although SBCL
281 ;;;; has an interval type in NUMERIC-TYPE, we choose to use our own
282 ;;;; for two reasons:
283 ;;;;
284 ;;;;   1. This package is simpler than NUMERIC-TYPE.
285 ;;;;
286 ;;;;   2. It makes debugging much easier because you can just strip
287 ;;;;   out these routines and test them independently of SBCL. (This is a
288 ;;;;   big win!)
289 ;;;;
290 ;;;; One disadvantage is a probable increase in consing because we
291 ;;;; have to create these new interval structures even though
292 ;;;; numeric-type has everything we want to know. Reason 2 wins for
293 ;;;; now.
294
295 ;;; Support operations that mimic real arithmetic comparison
296 ;;; operators, but imposing a total order on the floating points such
297 ;;; that negative zeros are strictly less than positive zeros.
298 (macrolet ((def (name op)
299              `(defun ,name (x y)
300                 (declare (real x y))
301                 (if (and (floatp x) (floatp y) (zerop x) (zerop y))
302                     (,op (float-sign x) (float-sign y))
303                     (,op x y)))))
304   (def signed-zero->= >=)
305   (def signed-zero-> >)
306   (def signed-zero-= =)
307   (def signed-zero-< <)
308   (def signed-zero-<= <=))
309
310 ;;; The basic interval type. It can handle open and closed intervals.
311 ;;; A bound is open if it is a list containing a number, just like
312 ;;; Lisp says. NIL means unbounded.
313 (defstruct (interval (:constructor %make-interval)
314                      (:copier nil))
315   low high)
316
317 (defun make-interval (&key low high)
318   (labels ((normalize-bound (val)
319              (cond #-sb-xc-host
320                    ((and (floatp val)
321                          (float-infinity-p val))
322                     ;; Handle infinities.
323                     nil)
324                    ((or (numberp val)
325                         (eq val nil))
326                     ;; Handle any closed bounds.
327                     val)
328                    ((listp val)
329                     ;; We have an open bound. Normalize the numeric
330                     ;; bound. If the normalized bound is still a number
331                     ;; (not nil), keep the bound open. Otherwise, the
332                     ;; bound is really unbounded, so drop the openness.
333                     (let ((new-val (normalize-bound (first val))))
334                       (when new-val
335                         ;; The bound exists, so keep it open still.
336                         (list new-val))))
337                    (t
338                     (error "unknown bound type in MAKE-INTERVAL")))))
339     (%make-interval :low (normalize-bound low)
340                     :high (normalize-bound high))))
341
342 ;;; Given a number X, create a form suitable as a bound for an
343 ;;; interval. Make the bound open if OPEN-P is T. NIL remains NIL.
344 #!-sb-fluid (declaim (inline set-bound))
345 (defun set-bound (x open-p)
346   (if (and x open-p) (list x) x))
347
348 ;;; Apply the function F to a bound X. If X is an open bound and the
349 ;;; function is declared strictly monotonic, then the result will be
350 ;;; open. IF X is NIL, the result is NIL.
351 (defun bound-func (f x strict)
352   (declare (type function f))
353   (and x
354        (handler-case
355          (with-float-traps-masked (:underflow :overflow :inexact :divide-by-zero)
356            ;; With these traps masked, we might get things like infinity
357            ;; or negative infinity returned. Check for this and return
358            ;; NIL to indicate unbounded.
359            (let ((y (funcall f (type-bound-number x))))
360              (if (and (floatp y)
361                       (float-infinity-p y))
362                  nil
363                  (set-bound y (and strict (consp x))))))
364          ;; Some numerical operations will signal SIMPLE-TYPE-ERROR, e.g.
365          ;; in the course of converting a bignum to a float.  Default to
366          ;; NIL in that case.
367          (simple-type-error ()))))
368
369 (defun safe-double-coercion-p (x)
370   (or (typep x 'double-float)
371       (<= most-negative-double-float x most-positive-double-float)))
372
373 (defun safe-single-coercion-p (x)
374   (or (typep x 'single-float)
375       (and
376        ;; Fix for bug 420, and related issues: during type derivation we often
377        ;; end up deriving types for both
378        ;;
379        ;;   (some-op <int> <single>)
380        ;; and
381        ;;   (some-op (coerce <int> 'single-float) <single>)
382        ;;
383        ;; or other equivalent transformed forms. The problem with this
384        ;; is that on x86 (+ <int> <single>) is on the machine level
385        ;; equivalent of
386        ;;
387        ;;   (coerce (+ (coerce <int> 'double-float)
388        ;;              (coerce <single> 'double-float))
389        ;;           'single-float)
390        ;;
391        ;; so if the result of (coerce <int> 'single-float) is not exact, the
392        ;; derived types for the transformed forms will have an empty
393        ;; intersection -- which in turn means that the compiler will conclude
394        ;; that the call never returns, and all hell breaks lose when it *does*
395        ;; return at runtime. (This affects not just +, but other operators are
396        ;; well.)
397        ;;
398        ;; See also: SAFE-CTYPE-FOR-SINGLE-COERCION-P
399        ;;
400        ;; FIXME: If we ever add SSE-support for x86, this conditional needs to
401        ;; change.
402        #!+x86
403        (not (typep x `(or (integer * (,most-negative-exactly-single-float-fixnum))
404                           (integer (,most-positive-exactly-single-float-fixnum) *))))
405        (<= most-negative-single-float x most-positive-single-float))))
406
407 ;;; Apply a binary operator OP to two bounds X and Y. The result is
408 ;;; NIL if either is NIL. Otherwise bound is computed and the result
409 ;;; is open if either X or Y is open.
410 ;;;
411 ;;; FIXME: only used in this file, not needed in target runtime
412
413 ;;; ANSI contaigon specifies coercion to floating point if one of the
414 ;;; arguments is floating point. Here we should check to be sure that
415 ;;; the other argument is within the bounds of that floating point
416 ;;; type.
417
418 (defmacro safely-binop (op x y)
419   `(cond
420      ((typep ,x 'double-float)
421       (when (safe-double-coercion-p ,y)
422         (,op ,x ,y)))
423      ((typep ,y 'double-float)
424       (when (safe-double-coercion-p ,x)
425         (,op ,x ,y)))
426      ((typep ,x 'single-float)
427       (when (safe-single-coercion-p ,y)
428         (,op ,x ,y)))
429      ((typep ,y 'single-float)
430       (when (safe-single-coercion-p ,x)
431         (,op ,x ,y)))
432      (t (,op ,x ,y))))
433
434 (defmacro bound-binop (op x y)
435   (with-unique-names (xb yb res)
436     `(and ,x ,y
437           (with-float-traps-masked (:underflow :overflow :inexact :divide-by-zero)
438             (let* ((,xb (type-bound-number ,x))
439                    (,yb (type-bound-number ,y))
440                    (,res (safely-binop ,op ,xb ,yb)))
441               (set-bound ,res
442                          (and (or (consp ,x) (consp ,y))
443                               ;; Open bounds can very easily be messed up
444                               ;; by FP rounding, so take care here.
445                               ,(case op
446                                  (*
447                                   ;; Multiplying a greater-than-zero with
448                                   ;; less than one can round to zero.
449                                   `(or (not (fp-zero-p ,res))
450                                        (cond ((and (consp ,x) (fp-zero-p ,xb))
451                                               (>= (abs ,yb) 1))
452                                              ((and (consp ,y) (fp-zero-p ,yb))
453                                               (>= (abs ,xb) 1)))))
454                                  (/
455                                   ;; Dividing a greater-than-zero with
456                                   ;; greater than one can round to zero.
457                                   `(or (not (fp-zero-p ,res))
458                                        (cond ((and (consp ,x) (fp-zero-p ,xb))
459                                               (<= (abs ,yb) 1))
460                                              ((and (consp ,y) (fp-zero-p ,yb))
461                                               (<= (abs ,xb) 1)))))
462                                  ((+ -)
463                                   ;; Adding or subtracting greater-than-zero
464                                   ;; can end up with identity.
465                                   `(and (not (fp-zero-p ,xb))
466                                         (not (fp-zero-p ,yb))))))))))))
467
468 (defun coercion-loses-precision-p (val type)
469   (typecase val
470     (single-float)
471     (double-float (subtypep type 'single-float))
472     (rational (subtypep type 'float))
473     (t (bug "Unexpected arguments to bounds coercion: ~S ~S" val type))))
474
475 (defun coerce-for-bound (val type)
476   (if (consp val)
477       (let ((xbound (coerce-for-bound (car val) type)))
478         (if (coercion-loses-precision-p (car val) type)
479             xbound
480             (list xbound)))
481       (cond
482         ((subtypep type 'double-float)
483          (if (<= most-negative-double-float val most-positive-double-float)
484              (coerce val type)))
485         ((or (subtypep type 'single-float) (subtypep type 'float))
486          ;; coerce to float returns a single-float
487          (if (<= most-negative-single-float val most-positive-single-float)
488              (coerce val type)))
489         (t (coerce val type)))))
490
491 (defun coerce-and-truncate-floats (val type)
492   (when val
493     (if (consp val)
494         (let ((xbound (coerce-for-bound (car val) type)))
495           (if (coercion-loses-precision-p (car val) type)
496               xbound
497               (list xbound)))
498         (cond
499           ((subtypep type 'double-float)
500            (if (<= most-negative-double-float val most-positive-double-float)
501                (coerce val type)
502                (if (< val most-negative-double-float)
503                    most-negative-double-float most-positive-double-float)))
504           ((or (subtypep type 'single-float) (subtypep type 'float))
505            ;; coerce to float returns a single-float
506            (if (<= most-negative-single-float val most-positive-single-float)
507                (coerce val type)
508                (if (< val most-negative-single-float)
509                    most-negative-single-float most-positive-single-float)))
510           (t (coerce val type))))))
511
512 ;;; Convert a numeric-type object to an interval object.
513 (defun numeric-type->interval (x)
514   (declare (type numeric-type x))
515   (make-interval :low (numeric-type-low x)
516                  :high (numeric-type-high x)))
517
518 (defun type-approximate-interval (type)
519   (declare (type ctype type))
520   (let ((types (prepare-arg-for-derive-type type))
521         (result nil))
522     (dolist (type types)
523       (let ((type (if (member-type-p type)
524                       (convert-member-type type)
525                       type)))
526         (unless (numeric-type-p type)
527           (return-from type-approximate-interval nil))
528         (let ((interval (numeric-type->interval type)))
529           (setq result
530                 (if result
531                     (interval-approximate-union result interval)
532                     interval)))))
533     result))
534
535 (defun copy-interval-limit (limit)
536   (if (numberp limit)
537       limit
538       (copy-list limit)))
539
540 (defun copy-interval (x)
541   (declare (type interval x))
542   (make-interval :low (copy-interval-limit (interval-low x))
543                  :high (copy-interval-limit (interval-high x))))
544
545 ;;; Given a point P contained in the interval X, split X into two
546 ;;; intervals at the point P. If CLOSE-LOWER is T, then the left
547 ;;; interval contains P. If CLOSE-UPPER is T, the right interval
548 ;;; contains P. You can specify both to be T or NIL.
549 (defun interval-split (p x &optional close-lower close-upper)
550   (declare (type number p)
551            (type interval x))
552   (list (make-interval :low (copy-interval-limit (interval-low x))
553                        :high (if close-lower p (list p)))
554         (make-interval :low (if close-upper (list p) p)
555                        :high (copy-interval-limit (interval-high x)))))
556
557 ;;; Return the closure of the interval. That is, convert open bounds
558 ;;; to closed bounds.
559 (defun interval-closure (x)
560   (declare (type interval x))
561   (make-interval :low (type-bound-number (interval-low x))
562                  :high (type-bound-number (interval-high x))))
563
564 ;;; For an interval X, if X >= POINT, return '+. If X <= POINT, return
565 ;;; '-. Otherwise return NIL.
566 (defun interval-range-info (x &optional (point 0))
567   (declare (type interval x))
568   (let ((lo (interval-low x))
569         (hi (interval-high x)))
570     (cond ((and lo (signed-zero->= (type-bound-number lo) point))
571            '+)
572           ((and hi (signed-zero->= point (type-bound-number hi)))
573            '-)
574           (t
575            nil))))
576
577 ;;; Test to see whether the interval X is bounded. HOW determines the
578 ;;; test, and should be either ABOVE, BELOW, or BOTH.
579 (defun interval-bounded-p (x how)
580   (declare (type interval x))
581   (ecase how
582     (above
583      (interval-high x))
584     (below
585      (interval-low x))
586     (both
587      (and (interval-low x) (interval-high x)))))
588
589 ;;; See whether the interval X contains the number P, taking into
590 ;;; account that the interval might not be closed.
591 (defun interval-contains-p (p x)
592   (declare (type number p)
593            (type interval x))
594   ;; Does the interval X contain the number P?  This would be a lot
595   ;; easier if all intervals were closed!
596   (let ((lo (interval-low x))
597         (hi (interval-high x)))
598     (cond ((and lo hi)
599            ;; The interval is bounded
600            (if (and (signed-zero-<= (type-bound-number lo) p)
601                     (signed-zero-<= p (type-bound-number hi)))
602                ;; P is definitely in the closure of the interval.
603                ;; We just need to check the end points now.
604                (cond ((signed-zero-= p (type-bound-number lo))
605                       (numberp lo))
606                      ((signed-zero-= p (type-bound-number hi))
607                       (numberp hi))
608                      (t t))
609                nil))
610           (hi
611            ;; Interval with upper bound
612            (if (signed-zero-< p (type-bound-number hi))
613                t
614                (and (numberp hi) (signed-zero-= p hi))))
615           (lo
616            ;; Interval with lower bound
617            (if (signed-zero-> p (type-bound-number lo))
618                t
619                (and (numberp lo) (signed-zero-= p lo))))
620           (t
621            ;; Interval with no bounds
622            t))))
623
624 ;;; Determine whether two intervals X and Y intersect. Return T if so.
625 ;;; If CLOSED-INTERVALS-P is T, the treat the intervals as if they
626 ;;; were closed. Otherwise the intervals are treated as they are.
627 ;;;
628 ;;; Thus if X = [0, 1) and Y = (1, 2), then they do not intersect
629 ;;; because no element in X is in Y. However, if CLOSED-INTERVALS-P
630 ;;; is T, then they do intersect because we use the closure of X = [0,
631 ;;; 1] and Y = [1, 2] to determine intersection.
632 (defun interval-intersect-p (x y &optional closed-intervals-p)
633   (declare (type interval x y))
634   (and (interval-intersection/difference (if closed-intervals-p
635                                              (interval-closure x)
636                                              x)
637                                          (if closed-intervals-p
638                                              (interval-closure y)
639                                              y))
640        t))
641
642 ;;; Are the two intervals adjacent?  That is, is there a number
643 ;;; between the two intervals that is not an element of either
644 ;;; interval?  If so, they are not adjacent. For example [0, 1) and
645 ;;; [1, 2] are adjacent but [0, 1) and (1, 2] are not because 1 lies
646 ;;; between both intervals.
647 (defun interval-adjacent-p (x y)
648   (declare (type interval x y))
649   (flet ((adjacent (lo hi)
650            ;; Check to see whether lo and hi are adjacent. If either is
651            ;; nil, they can't be adjacent.
652            (when (and lo hi (= (type-bound-number lo) (type-bound-number hi)))
653              ;; The bounds are equal. They are adjacent if one of
654              ;; them is closed (a number). If both are open (consp),
655              ;; then there is a number that lies between them.
656              (or (numberp lo) (numberp hi)))))
657     (or (adjacent (interval-low y) (interval-high x))
658         (adjacent (interval-low x) (interval-high y)))))
659
660 ;;; Compute the intersection and difference between two intervals.
661 ;;; Two values are returned: the intersection and the difference.
662 ;;;
663 ;;; Let the two intervals be X and Y, and let I and D be the two
664 ;;; values returned by this function. Then I = X intersect Y. If I
665 ;;; is NIL (the empty set), then D is X union Y, represented as the
666 ;;; list of X and Y. If I is not the empty set, then D is (X union Y)
667 ;;; - I, which is a list of two intervals.
668 ;;;
669 ;;; For example, let X = [1,5] and Y = [-1,3). Then I = [1,3) and D =
670 ;;; [-1,1) union [3,5], which is returned as a list of two intervals.
671 (defun interval-intersection/difference (x y)
672   (declare (type interval x y))
673   (let ((x-lo (interval-low x))
674         (x-hi (interval-high x))
675         (y-lo (interval-low y))
676         (y-hi (interval-high y)))
677     (labels
678         ((opposite-bound (p)
679            ;; If p is an open bound, make it closed. If p is a closed
680            ;; bound, make it open.
681            (if (listp p)
682                (first p)
683                (list p)))
684          (test-number (p int bound)
685            ;; Test whether P is in the interval.
686            (let ((pn (type-bound-number p)))
687              (when (interval-contains-p pn (interval-closure int))
688                ;; Check for endpoints.
689                (let* ((lo (interval-low int))
690                       (hi (interval-high int))
691                       (lon (type-bound-number lo))
692                       (hin (type-bound-number hi)))
693                  (cond
694                    ;; Interval may be a point.
695                    ((and lon hin (= lon hin pn))
696                     (and (numberp p) (numberp lo) (numberp hi)))
697                    ;; Point matches the low end.
698                    ;; [P] [P,?} => TRUE     [P] (P,?} => FALSE
699                    ;; (P  [P,?} => TRUE      P) [P,?} => FALSE
700                    ;; (P  (P,?} => TRUE      P) (P,?} => FALSE
701                    ((and lon (= pn lon))
702                     (or (and (numberp p) (numberp lo))
703                         (and (consp p) (eq :low bound))))
704                    ;; [P] {?,P] => TRUE     [P] {?,P) => FALSE
705                    ;;  P) {?,P] => TRUE     (P  {?,P] => FALSE
706                    ;;  P) {?,P) => TRUE     (P  {?,P) => FALSE
707                    ((and hin (= pn hin))
708                     (or (and (numberp p) (numberp hi))
709                         (and (consp p) (eq :high bound))))
710                    ;; Not an endpoint, all is well.
711                    (t
712                     t))))))
713          (test-lower-bound (p int)
714            ;; P is a lower bound of an interval.
715            (if p
716                (test-number p int :low)
717                (not (interval-bounded-p int 'below))))
718          (test-upper-bound (p int)
719            ;; P is an upper bound of an interval.
720            (if p
721                (test-number p int :high)
722                (not (interval-bounded-p int 'above)))))
723       (let ((x-lo-in-y (test-lower-bound x-lo y))
724             (x-hi-in-y (test-upper-bound x-hi y))
725             (y-lo-in-x (test-lower-bound y-lo x))
726             (y-hi-in-x (test-upper-bound y-hi x)))
727         (cond ((or x-lo-in-y x-hi-in-y y-lo-in-x y-hi-in-x)
728                ;; Intervals intersect. Let's compute the intersection
729                ;; and the difference.
730                (multiple-value-bind (lo left-lo left-hi)
731                    (cond (x-lo-in-y (values x-lo y-lo (opposite-bound x-lo)))
732                          (y-lo-in-x (values y-lo x-lo (opposite-bound y-lo))))
733                  (multiple-value-bind (hi right-lo right-hi)
734                      (cond (x-hi-in-y
735                             (values x-hi (opposite-bound x-hi) y-hi))
736                            (y-hi-in-x
737                             (values y-hi (opposite-bound y-hi) x-hi)))
738                    (values (make-interval :low lo :high hi)
739                            (list (make-interval :low left-lo
740                                                 :high left-hi)
741                                  (make-interval :low right-lo
742                                                 :high right-hi))))))
743               (t
744                (values nil (list x y))))))))
745
746 ;;; If intervals X and Y intersect, return a new interval that is the
747 ;;; union of the two. If they do not intersect, return NIL.
748 (defun interval-merge-pair (x y)
749   (declare (type interval x y))
750   ;; If x and y intersect or are adjacent, create the union.
751   ;; Otherwise return nil
752   (when (or (interval-intersect-p x y)
753             (interval-adjacent-p x y))
754     (flet ((select-bound (x1 x2 min-op max-op)
755              (let ((x1-val (type-bound-number x1))
756                    (x2-val (type-bound-number x2)))
757                (cond ((and x1 x2)
758                       ;; Both bounds are finite. Select the right one.
759                       (cond ((funcall min-op x1-val x2-val)
760                              ;; x1 is definitely better.
761                              x1)
762                             ((funcall max-op x1-val x2-val)
763                              ;; x2 is definitely better.
764                              x2)
765                             (t
766                              ;; Bounds are equal. Select either
767                              ;; value and make it open only if
768                              ;; both were open.
769                              (set-bound x1-val (and (consp x1) (consp x2))))))
770                      (t
771                       ;; At least one bound is not finite. The
772                       ;; non-finite bound always wins.
773                       nil)))))
774       (let* ((x-lo (copy-interval-limit (interval-low x)))
775              (x-hi (copy-interval-limit (interval-high x)))
776              (y-lo (copy-interval-limit (interval-low y)))
777              (y-hi (copy-interval-limit (interval-high y))))
778         (make-interval :low (select-bound x-lo y-lo #'< #'>)
779                        :high (select-bound x-hi y-hi #'> #'<))))))
780
781 ;;; return the minimal interval, containing X and Y
782 (defun interval-approximate-union (x y)
783   (cond ((interval-merge-pair x y))
784         ((interval-< x y)
785          (make-interval :low (copy-interval-limit (interval-low x))
786                         :high (copy-interval-limit (interval-high y))))
787         (t
788          (make-interval :low (copy-interval-limit (interval-low y))
789                         :high (copy-interval-limit (interval-high x))))))
790
791 ;;; basic arithmetic operations on intervals. We probably should do
792 ;;; true interval arithmetic here, but it's complicated because we
793 ;;; have float and integer types and bounds can be open or closed.
794
795 ;;; the negative of an interval
796 (defun interval-neg (x)
797   (declare (type interval x))
798   (make-interval :low (bound-func #'- (interval-high x) t)
799                  :high (bound-func #'- (interval-low x) t)))
800
801 ;;; Add two intervals.
802 (defun interval-add (x y)
803   (declare (type interval x y))
804   (make-interval :low (bound-binop + (interval-low x) (interval-low y))
805                  :high (bound-binop + (interval-high x) (interval-high y))))
806
807 ;;; Subtract two intervals.
808 (defun interval-sub (x y)
809   (declare (type interval x y))
810   (make-interval :low (bound-binop - (interval-low x) (interval-high y))
811                  :high (bound-binop - (interval-high x) (interval-low y))))
812
813 ;;; Multiply two intervals.
814 (defun interval-mul (x y)
815   (declare (type interval x y))
816   (flet ((bound-mul (x y)
817            (cond ((or (null x) (null y))
818                   ;; Multiply by infinity is infinity
819                   nil)
820                  ((or (and (numberp x) (zerop x))
821                       (and (numberp y) (zerop y)))
822                   ;; Multiply by closed zero is special. The result
823                   ;; is always a closed bound. But don't replace this
824                   ;; with zero; we want the multiplication to produce
825                   ;; the correct signed zero, if needed. Use SIGNUM
826                   ;; to avoid trying to multiply huge bignums with 0.0.
827                   (* (signum (type-bound-number x)) (signum (type-bound-number y))))
828                  ((or (and (floatp x) (float-infinity-p x))
829                       (and (floatp y) (float-infinity-p y)))
830                   ;; Infinity times anything is infinity
831                   nil)
832                  (t
833                   ;; General multiply. The result is open if either is open.
834                   (bound-binop * x y)))))
835     (let ((x-range (interval-range-info x))
836           (y-range (interval-range-info y)))
837       (cond ((null x-range)
838              ;; Split x into two and multiply each separately
839              (destructuring-bind (x- x+) (interval-split 0 x t t)
840                (interval-merge-pair (interval-mul x- y)
841                                     (interval-mul x+ y))))
842             ((null y-range)
843              ;; Split y into two and multiply each separately
844              (destructuring-bind (y- y+) (interval-split 0 y t t)
845                (interval-merge-pair (interval-mul x y-)
846                                     (interval-mul x y+))))
847             ((eq x-range '-)
848              (interval-neg (interval-mul (interval-neg x) y)))
849             ((eq y-range '-)
850              (interval-neg (interval-mul x (interval-neg y))))
851             ((and (eq x-range '+) (eq y-range '+))
852              ;; If we are here, X and Y are both positive.
853              (make-interval
854               :low (bound-mul (interval-low x) (interval-low y))
855               :high (bound-mul (interval-high x) (interval-high y))))
856             (t
857              (bug "excluded case in INTERVAL-MUL"))))))
858
859 ;;; Divide two intervals.
860 (defun interval-div (top bot)
861   (declare (type interval top bot))
862   (flet ((bound-div (x y y-low-p)
863            ;; Compute x/y
864            (cond ((null y)
865                   ;; Divide by infinity means result is 0. However,
866                   ;; we need to watch out for the sign of the result,
867                   ;; to correctly handle signed zeros. We also need
868                   ;; to watch out for positive or negative infinity.
869                   (if (floatp (type-bound-number x))
870                       (if y-low-p
871                           (- (float-sign (type-bound-number x) 0.0))
872                           (float-sign (type-bound-number x) 0.0))
873                       0))
874                  ((zerop (type-bound-number y))
875                   ;; Divide by zero means result is infinity
876                   nil)
877                  (t
878                   (bound-binop / x y)))))
879     (let ((top-range (interval-range-info top))
880           (bot-range (interval-range-info bot)))
881       (cond ((null bot-range)
882              ;; The denominator contains zero, so anything goes!
883              (make-interval :low nil :high nil))
884             ((eq bot-range '-)
885              ;; Denominator is negative so flip the sign, compute the
886              ;; result, and flip it back.
887              (interval-neg (interval-div top (interval-neg bot))))
888             ((null top-range)
889              ;; Split top into two positive and negative parts, and
890              ;; divide each separately
891              (destructuring-bind (top- top+) (interval-split 0 top t t)
892                (interval-merge-pair (interval-div top- bot)
893                                     (interval-div top+ bot))))
894             ((eq top-range '-)
895              ;; Top is negative so flip the sign, divide, and flip the
896              ;; sign of the result.
897              (interval-neg (interval-div (interval-neg top) bot)))
898             ((and (eq top-range '+) (eq bot-range '+))
899              ;; the easy case
900              (make-interval
901               :low (bound-div (interval-low top) (interval-high bot) t)
902               :high (bound-div (interval-high top) (interval-low bot) nil)))
903             (t
904              (bug "excluded case in INTERVAL-DIV"))))))
905
906 ;;; Apply the function F to the interval X. If X = [a, b], then the
907 ;;; result is [f(a), f(b)]. It is up to the user to make sure the
908 ;;; result makes sense. It will if F is monotonic increasing (or, if
909 ;;; the interval is closed, non-decreasing).
910 ;;;
911 ;;; (Actually most uses of INTERVAL-FUNC are coercions to float types,
912 ;;; which are not monotonic increasing, so default to calling
913 ;;; BOUND-FUNC with a non-strict argument).
914 (defun interval-func (f x &optional increasing)
915   (declare (type function f)
916            (type interval x))
917   (let ((lo (bound-func f (interval-low x) increasing))
918         (hi (bound-func f (interval-high x) increasing)))
919     (make-interval :low lo :high hi)))
920
921 ;;; Return T if X < Y. That is every number in the interval X is
922 ;;; always less than any number in the interval Y.
923 (defun interval-< (x y)
924   (declare (type interval x y))
925   ;; X < Y only if X is bounded above, Y is bounded below, and they
926   ;; don't overlap.
927   (when (and (interval-bounded-p x 'above)
928              (interval-bounded-p y 'below))
929     ;; Intervals are bounded in the appropriate way. Make sure they
930     ;; don't overlap.
931     (let ((left (interval-high x))
932           (right (interval-low y)))
933       (cond ((> (type-bound-number left)
934                 (type-bound-number right))
935              ;; The intervals definitely overlap, so result is NIL.
936              nil)
937             ((< (type-bound-number left)
938                 (type-bound-number right))
939              ;; The intervals definitely don't touch, so result is T.
940              t)
941             (t
942              ;; Limits are equal. Check for open or closed bounds.
943              ;; Don't overlap if one or the other are open.
944              (or (consp left) (consp right)))))))
945
946 ;;; Return T if X >= Y. That is, every number in the interval X is
947 ;;; always greater than any number in the interval Y.
948 (defun interval->= (x y)
949   (declare (type interval x y))
950   ;; X >= Y if lower bound of X >= upper bound of Y
951   (when (and (interval-bounded-p x 'below)
952              (interval-bounded-p y 'above))
953     (>= (type-bound-number (interval-low x))
954         (type-bound-number (interval-high y)))))
955
956 ;;; Return T if X = Y.
957 (defun interval-= (x y)
958   (declare (type interval x y))
959   (and (interval-bounded-p x 'both)
960        (interval-bounded-p y 'both)
961        (flet ((bound (v)
962                 (if (numberp v)
963                     v
964                     ;; Open intervals cannot be =
965                     (return-from interval-= nil))))
966          ;; Both intervals refer to the same point
967          (= (bound (interval-high x)) (bound (interval-low x))
968             (bound (interval-high y)) (bound (interval-low y))))))
969
970 ;;; Return T if X /= Y
971 (defun interval-/= (x y)
972   (not (interval-intersect-p x y)))
973
974 ;;; Return an interval that is the absolute value of X. Thus, if
975 ;;; X = [-1 10], the result is [0, 10].
976 (defun interval-abs (x)
977   (declare (type interval x))
978   (case (interval-range-info x)
979     (+
980      (copy-interval x))
981     (-
982      (interval-neg x))
983     (t
984      (destructuring-bind (x- x+) (interval-split 0 x t t)
985        (interval-merge-pair (interval-neg x-) x+)))))
986
987 ;;; Compute the square of an interval.
988 (defun interval-sqr (x)
989   (declare (type interval x))
990   (interval-func (lambda (x) (* x x)) (interval-abs x)))
991 \f
992 ;;;; numeric DERIVE-TYPE methods
993
994 ;;; a utility for defining derive-type methods of integer operations. If
995 ;;; the types of both X and Y are integer types, then we compute a new
996 ;;; integer type with bounds determined by FUN when applied to X and Y.
997 ;;; Otherwise, we use NUMERIC-CONTAGION.
998 (defun derive-integer-type-aux (x y fun)
999   (declare (type function fun))
1000   (if (and (numeric-type-p x) (numeric-type-p y)
1001            (eq (numeric-type-class x) 'integer)
1002            (eq (numeric-type-class y) 'integer)
1003            (eq (numeric-type-complexp x) :real)
1004            (eq (numeric-type-complexp y) :real))
1005       (multiple-value-bind (low high) (funcall fun x y)
1006         (make-numeric-type :class 'integer
1007                            :complexp :real
1008                            :low low
1009                            :high high))
1010       (numeric-contagion x y)))
1011
1012 (defun derive-integer-type (x y fun)
1013   (declare (type lvar x y) (type function fun))
1014   (let ((x (lvar-type x))
1015         (y (lvar-type y)))
1016     (derive-integer-type-aux x y fun)))
1017
1018 ;;; simple utility to flatten a list
1019 (defun flatten-list (x)
1020   (labels ((flatten-and-append (tree list)
1021              (cond ((null tree) list)
1022                    ((atom tree) (cons tree list))
1023                    (t (flatten-and-append
1024                        (car tree) (flatten-and-append (cdr tree) list))))))
1025     (flatten-and-append x nil)))
1026
1027 ;;; Take some type of lvar and massage it so that we get a list of the
1028 ;;; constituent types. If ARG is *EMPTY-TYPE*, return NIL to indicate
1029 ;;; failure.
1030 (defun prepare-arg-for-derive-type (arg)
1031   (flet ((listify (arg)
1032            (typecase arg
1033              (numeric-type
1034               (list arg))
1035              (union-type
1036               (union-type-types arg))
1037              (t
1038               (list arg)))))
1039     (unless (eq arg *empty-type*)
1040       ;; Make sure all args are some type of numeric-type. For member
1041       ;; types, convert the list of members into a union of equivalent
1042       ;; single-element member-type's.
1043       (let ((new-args nil))
1044         (dolist (arg (listify arg))
1045           (if (member-type-p arg)
1046               ;; Run down the list of members and convert to a list of
1047               ;; member types.
1048               (mapc-member-type-members
1049                (lambda (member)
1050                  (push (if (numberp member)
1051                            (make-member-type :members (list member))
1052                            *empty-type*)
1053                        new-args))
1054                arg)
1055               (push arg new-args)))
1056         (unless (member *empty-type* new-args)
1057           new-args)))))
1058
1059 ;;; Convert from the standard type convention for which -0.0 and 0.0
1060 ;;; are equal to an intermediate convention for which they are
1061 ;;; considered different which is more natural for some of the
1062 ;;; optimisers.
1063 (defun convert-numeric-type (type)
1064   (declare (type numeric-type type))
1065   ;;; Only convert real float interval delimiters types.
1066   (if (eq (numeric-type-complexp type) :real)
1067       (let* ((lo (numeric-type-low type))
1068              (lo-val (type-bound-number lo))
1069              (lo-float-zero-p (and lo (floatp lo-val) (= lo-val 0.0)))
1070              (hi (numeric-type-high type))
1071              (hi-val (type-bound-number hi))
1072              (hi-float-zero-p (and hi (floatp hi-val) (= hi-val 0.0))))
1073         (if (or lo-float-zero-p hi-float-zero-p)
1074             (make-numeric-type
1075              :class (numeric-type-class type)
1076              :format (numeric-type-format type)
1077              :complexp :real
1078              :low (if lo-float-zero-p
1079                       (if (consp lo)
1080                           (list (float 0.0 lo-val))
1081                           (float (load-time-value (make-unportable-float :single-float-negative-zero)) lo-val))
1082                       lo)
1083              :high (if hi-float-zero-p
1084                        (if (consp hi)
1085                            (list (float (load-time-value (make-unportable-float :single-float-negative-zero)) hi-val))
1086                            (float 0.0 hi-val))
1087                        hi))
1088             type))
1089       ;; Not real float.
1090       type))
1091
1092 ;;; Convert back from the intermediate convention for which -0.0 and
1093 ;;; 0.0 are considered different to the standard type convention for
1094 ;;; which and equal.
1095 (defun convert-back-numeric-type (type)
1096   (declare (type numeric-type type))
1097   ;;; Only convert real float interval delimiters types.
1098   (if (eq (numeric-type-complexp type) :real)
1099       (let* ((lo (numeric-type-low type))
1100              (lo-val (type-bound-number lo))
1101              (lo-float-zero-p
1102               (and lo (floatp lo-val) (= lo-val 0.0)
1103                    (float-sign lo-val)))
1104              (hi (numeric-type-high type))
1105              (hi-val (type-bound-number hi))
1106              (hi-float-zero-p
1107               (and hi (floatp hi-val) (= hi-val 0.0)
1108                    (float-sign hi-val))))
1109         (cond
1110           ;; (float +0.0 +0.0) => (member 0.0)
1111           ;; (float -0.0 -0.0) => (member -0.0)
1112           ((and lo-float-zero-p hi-float-zero-p)
1113            ;; shouldn't have exclusive bounds here..
1114            (aver (and (not (consp lo)) (not (consp hi))))
1115            (if (= lo-float-zero-p hi-float-zero-p)
1116                ;; (float +0.0 +0.0) => (member 0.0)
1117                ;; (float -0.0 -0.0) => (member -0.0)
1118                (specifier-type `(member ,lo-val))
1119                ;; (float -0.0 +0.0) => (float 0.0 0.0)
1120                ;; (float +0.0 -0.0) => (float 0.0 0.0)
1121                (make-numeric-type :class (numeric-type-class type)
1122                                   :format (numeric-type-format type)
1123                                   :complexp :real
1124                                   :low hi-val
1125                                   :high hi-val)))
1126           (lo-float-zero-p
1127            (cond
1128              ;; (float -0.0 x) => (float 0.0 x)
1129              ((and (not (consp lo)) (minusp lo-float-zero-p))
1130               (make-numeric-type :class (numeric-type-class type)
1131                                  :format (numeric-type-format type)
1132                                  :complexp :real
1133                                  :low (float 0.0 lo-val)
1134                                  :high hi))
1135              ;; (float (+0.0) x) => (float (0.0) x)
1136              ((and (consp lo) (plusp lo-float-zero-p))
1137               (make-numeric-type :class (numeric-type-class type)
1138                                  :format (numeric-type-format type)
1139                                  :complexp :real
1140                                  :low (list (float 0.0 lo-val))
1141                                  :high hi))
1142              (t
1143               ;; (float +0.0 x) => (or (member 0.0) (float (0.0) x))
1144               ;; (float (-0.0) x) => (or (member 0.0) (float (0.0) x))
1145               (list (make-member-type :members (list (float 0.0 lo-val)))
1146                     (make-numeric-type :class (numeric-type-class type)
1147                                        :format (numeric-type-format type)
1148                                        :complexp :real
1149                                        :low (list (float 0.0 lo-val))
1150                                        :high hi)))))
1151           (hi-float-zero-p
1152            (cond
1153              ;; (float x +0.0) => (float x 0.0)
1154              ((and (not (consp hi)) (plusp hi-float-zero-p))
1155               (make-numeric-type :class (numeric-type-class type)
1156                                  :format (numeric-type-format type)
1157                                  :complexp :real
1158                                  :low lo
1159                                  :high (float 0.0 hi-val)))
1160              ;; (float x (-0.0)) => (float x (0.0))
1161              ((and (consp hi) (minusp hi-float-zero-p))
1162               (make-numeric-type :class (numeric-type-class type)
1163                                  :format (numeric-type-format type)
1164                                  :complexp :real
1165                                  :low lo
1166                                  :high (list (float 0.0 hi-val))))
1167              (t
1168               ;; (float x (+0.0)) => (or (member -0.0) (float x (0.0)))
1169               ;; (float x -0.0) => (or (member -0.0) (float x (0.0)))
1170               (list (make-member-type :members (list (float (load-time-value (make-unportable-float :single-float-negative-zero)) hi-val)))
1171                     (make-numeric-type :class (numeric-type-class type)
1172                                        :format (numeric-type-format type)
1173                                        :complexp :real
1174                                        :low lo
1175                                        :high (list (float 0.0 hi-val)))))))
1176           (t
1177            type)))
1178       ;; not real float
1179       type))
1180
1181 ;;; Convert back a possible list of numeric types.
1182 (defun convert-back-numeric-type-list (type-list)
1183   (typecase type-list
1184     (list
1185      (let ((results '()))
1186        (dolist (type type-list)
1187          (if (numeric-type-p type)
1188              (let ((result (convert-back-numeric-type type)))
1189                (if (listp result)
1190                    (setf results (append results result))
1191                    (push result results)))
1192              (push type results)))
1193        results))
1194     (numeric-type
1195      (convert-back-numeric-type type-list))
1196     (union-type
1197      (convert-back-numeric-type-list (union-type-types type-list)))
1198     (t
1199      type-list)))
1200
1201 ;;; Take a list of types and return a canonical type specifier,
1202 ;;; combining any MEMBER types together. If both positive and negative
1203 ;;; MEMBER types are present they are converted to a float type.
1204 ;;; XXX This would be far simpler if the type-union methods could handle
1205 ;;; member/number unions.
1206 ;;;
1207 ;;; If we're about to generate an overly complex union of numeric types, start
1208 ;;; collapse the ranges together.
1209 ;;;
1210 ;;; FIXME: The MEMBER canonicalization parts of MAKE-DERIVED-UNION-TYPE and
1211 ;;; entire CONVERT-MEMBER-TYPE probably belong in the kernel's type logic,
1212 ;;; invoked always, instead of in the compiler, invoked only during some type
1213 ;;; optimizations.
1214 (defvar *derived-numeric-union-complexity-limit* 6)
1215
1216 (defun make-derived-union-type (type-list)
1217   (let ((xset (alloc-xset))
1218         (fp-zeroes '())
1219         (misc-types '())
1220         (numeric-type *empty-type*))
1221     (dolist (type type-list)
1222       (cond ((member-type-p type)
1223              (mapc-member-type-members
1224               (lambda (member)
1225                 (if (fp-zero-p member)
1226                     (unless (member member fp-zeroes)
1227                       (pushnew member fp-zeroes))
1228                     (add-to-xset member xset)))
1229               type))
1230             ((numeric-type-p type)
1231              (let ((*approximate-numeric-unions*
1232                     (when (and (union-type-p numeric-type)
1233                                (nthcdr *derived-numeric-union-complexity-limit*
1234                                        (union-type-types numeric-type)))
1235                       t)))
1236                (setf numeric-type (type-union type numeric-type))))
1237             (t
1238              (push type misc-types))))
1239     (if (and (xset-empty-p xset) (not fp-zeroes))
1240         (apply #'type-union numeric-type misc-types)
1241         (apply #'type-union (make-member-type :xset xset :fp-zeroes fp-zeroes)
1242                numeric-type misc-types))))
1243
1244 ;;; Convert a member type with a single member to a numeric type.
1245 (defun convert-member-type (arg)
1246   (let* ((members (member-type-members arg))
1247          (member (first members))
1248          (member-type (type-of member)))
1249     (aver (not (rest members)))
1250     (specifier-type (cond ((typep member 'integer)
1251                            `(integer ,member ,member))
1252                           ((memq member-type '(short-float single-float
1253                                                double-float long-float))
1254                            `(,member-type ,member ,member))
1255                           (t
1256                            member-type)))))
1257
1258 ;;; This is used in defoptimizers for computing the resulting type of
1259 ;;; a function.
1260 ;;;
1261 ;;; Given the lvar ARG, derive the resulting type using the
1262 ;;; DERIVE-FUN. DERIVE-FUN takes exactly one argument which is some
1263 ;;; "atomic" lvar type like numeric-type or member-type (containing
1264 ;;; just one element). It should return the resulting type, which can
1265 ;;; be a list of types.
1266 ;;;
1267 ;;; For the case of member types, if a MEMBER-FUN is given it is
1268 ;;; called to compute the result otherwise the member type is first
1269 ;;; converted to a numeric type and the DERIVE-FUN is called.
1270 (defun one-arg-derive-type (arg derive-fun member-fun
1271                                 &optional (convert-type t))
1272   (declare (type function derive-fun)
1273            (type (or null function) member-fun))
1274   (let ((arg-list (prepare-arg-for-derive-type (lvar-type arg))))
1275     (when arg-list
1276       (flet ((deriver (x)
1277                (typecase x
1278                  (member-type
1279                   (if member-fun
1280                       (with-float-traps-masked
1281                           (:underflow :overflow :divide-by-zero)
1282                         (specifier-type
1283                          `(eql ,(funcall member-fun
1284                                          (first (member-type-members x))))))
1285                       ;; Otherwise convert to a numeric type.
1286                       (let ((result-type-list
1287                              (funcall derive-fun (convert-member-type x))))
1288                         (if convert-type
1289                             (convert-back-numeric-type-list result-type-list)
1290                             result-type-list))))
1291                  (numeric-type
1292                   (if convert-type
1293                       (convert-back-numeric-type-list
1294                        (funcall derive-fun (convert-numeric-type x)))
1295                       (funcall derive-fun x)))
1296                  (t
1297                   *universal-type*))))
1298         ;; Run down the list of args and derive the type of each one,
1299         ;; saving all of the results in a list.
1300         (let ((results nil))
1301           (dolist (arg arg-list)
1302             (let ((result (deriver arg)))
1303               (if (listp result)
1304                   (setf results (append results result))
1305                   (push result results))))
1306           (if (rest results)
1307               (make-derived-union-type results)
1308               (first results)))))))
1309
1310 ;;; Same as ONE-ARG-DERIVE-TYPE, except we assume the function takes
1311 ;;; two arguments. DERIVE-FUN takes 3 args in this case: the two
1312 ;;; original args and a third which is T to indicate if the two args
1313 ;;; really represent the same lvar. This is useful for deriving the
1314 ;;; type of things like (* x x), which should always be positive. If
1315 ;;; we didn't do this, we wouldn't be able to tell.
1316 (defun two-arg-derive-type (arg1 arg2 derive-fun fun
1317                                  &optional (convert-type t))
1318   (declare (type function derive-fun fun))
1319   (flet ((deriver (x y same-arg)
1320            (cond ((and (member-type-p x) (member-type-p y))
1321                   (let* ((x (first (member-type-members x)))
1322                          (y (first (member-type-members y)))
1323                          (result (ignore-errors
1324                                    (with-float-traps-masked
1325                                        (:underflow :overflow :divide-by-zero
1326                                                    :invalid)
1327                                      (funcall fun x y)))))
1328                     (cond ((null result) *empty-type*)
1329                           ((and (floatp result) (float-nan-p result))
1330                            (make-numeric-type :class 'float
1331                                               :format (type-of result)
1332                                               :complexp :real))
1333                           (t
1334                            (specifier-type `(eql ,result))))))
1335                  ((and (member-type-p x) (numeric-type-p y))
1336                   (let* ((x (convert-member-type x))
1337                          (y (if convert-type (convert-numeric-type y) y))
1338                          (result (funcall derive-fun x y same-arg)))
1339                     (if convert-type
1340                         (convert-back-numeric-type-list result)
1341                         result)))
1342                  ((and (numeric-type-p x) (member-type-p y))
1343                   (let* ((x (if convert-type (convert-numeric-type x) x))
1344                          (y (convert-member-type y))
1345                          (result (funcall derive-fun x y same-arg)))
1346                     (if convert-type
1347                         (convert-back-numeric-type-list result)
1348                         result)))
1349                  ((and (numeric-type-p x) (numeric-type-p y))
1350                   (let* ((x (if convert-type (convert-numeric-type x) x))
1351                          (y (if convert-type (convert-numeric-type y) y))
1352                          (result (funcall derive-fun x y same-arg)))
1353                     (if convert-type
1354                         (convert-back-numeric-type-list result)
1355                         result)))
1356                  (t
1357                   *universal-type*))))
1358     (let ((same-arg (same-leaf-ref-p arg1 arg2))
1359           (a1 (prepare-arg-for-derive-type (lvar-type arg1)))
1360           (a2 (prepare-arg-for-derive-type (lvar-type arg2))))
1361       (when (and a1 a2)
1362         (let ((results nil))
1363           (if same-arg
1364               ;; Since the args are the same LVARs, just run down the
1365               ;; lists.
1366               (dolist (x a1)
1367                 (let ((result (deriver x x same-arg)))
1368                   (if (listp result)
1369                       (setf results (append results result))
1370                       (push result results))))
1371               ;; Try all pairwise combinations.
1372               (dolist (x a1)
1373                 (dolist (y a2)
1374                   (let ((result (or (deriver x y same-arg)
1375                                     (numeric-contagion x y))))
1376                     (if (listp result)
1377                         (setf results (append results result))
1378                         (push result results))))))
1379           (if (rest results)
1380               (make-derived-union-type results)
1381               (first results)))))))
1382 \f
1383 #+sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1384 (progn
1385 (defoptimizer (+ derive-type) ((x y))
1386   (derive-integer-type
1387    x y
1388    #'(lambda (x y)
1389        (flet ((frob (x y)
1390                 (if (and x y)
1391                     (+ x y)
1392                     nil)))
1393          (values (frob (numeric-type-low x) (numeric-type-low y))
1394                  (frob (numeric-type-high x) (numeric-type-high y)))))))
1395
1396 (defoptimizer (- derive-type) ((x y))
1397   (derive-integer-type
1398    x y
1399    #'(lambda (x y)
1400        (flet ((frob (x y)
1401                 (if (and x y)
1402                     (- x y)
1403                     nil)))
1404          (values (frob (numeric-type-low x) (numeric-type-high y))
1405                  (frob (numeric-type-high x) (numeric-type-low y)))))))
1406
1407 (defoptimizer (* derive-type) ((x y))
1408   (derive-integer-type
1409    x y
1410    #'(lambda (x y)
1411        (let ((x-low (numeric-type-low x))
1412              (x-high (numeric-type-high x))
1413              (y-low (numeric-type-low y))
1414              (y-high (numeric-type-high y)))
1415          (cond ((not (and x-low y-low))
1416                 (values nil nil))
1417                ((or (minusp x-low) (minusp y-low))
1418                 (if (and x-high y-high)
1419                     (let ((max (* (max (abs x-low) (abs x-high))
1420                                   (max (abs y-low) (abs y-high)))))
1421                       (values (- max) max))
1422                     (values nil nil)))
1423                (t
1424                 (values (* x-low y-low)
1425                         (if (and x-high y-high)
1426                             (* x-high y-high)
1427                             nil))))))))
1428
1429 (defoptimizer (/ derive-type) ((x y))
1430   (numeric-contagion (lvar-type x) (lvar-type y)))
1431
1432 ) ; PROGN
1433
1434 #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1435 (progn
1436 (defun +-derive-type-aux (x y same-arg)
1437   (if (and (numeric-type-real-p x)
1438            (numeric-type-real-p y))
1439       (let ((result
1440              (if same-arg
1441                  (let ((x-int (numeric-type->interval x)))
1442                    (interval-add x-int x-int))
1443                  (interval-add (numeric-type->interval x)
1444                                (numeric-type->interval y))))
1445             (result-type (numeric-contagion x y)))
1446         ;; If the result type is a float, we need to be sure to coerce
1447         ;; the bounds into the correct type.
1448         (when (eq (numeric-type-class result-type) 'float)
1449           (setf result (interval-func
1450                         #'(lambda (x)
1451                             (coerce-for-bound x (or (numeric-type-format result-type)
1452                                                     'float)))
1453                         result)))
1454         (make-numeric-type
1455          :class (if (and (eq (numeric-type-class x) 'integer)
1456                          (eq (numeric-type-class y) 'integer))
1457                     ;; The sum of integers is always an integer.
1458                     'integer
1459                     (numeric-type-class result-type))
1460          :format (numeric-type-format result-type)
1461          :low (interval-low result)
1462          :high (interval-high result)))
1463       ;; general contagion
1464       (numeric-contagion x y)))
1465
1466 (defoptimizer (+ derive-type) ((x y))
1467   (two-arg-derive-type x y #'+-derive-type-aux #'+))
1468
1469 (defun --derive-type-aux (x y same-arg)
1470   (if (and (numeric-type-real-p x)
1471            (numeric-type-real-p y))
1472       (let ((result
1473              ;; (- X X) is always 0.
1474              (if same-arg
1475                  (make-interval :low 0 :high 0)
1476                  (interval-sub (numeric-type->interval x)
1477                                (numeric-type->interval y))))
1478             (result-type (numeric-contagion x y)))
1479         ;; If the result type is a float, we need to be sure to coerce
1480         ;; the bounds into the correct type.
1481         (when (eq (numeric-type-class result-type) 'float)
1482           (setf result (interval-func
1483                         #'(lambda (x)
1484                             (coerce-for-bound x (or (numeric-type-format result-type)
1485                                                     'float)))
1486                         result)))
1487         (make-numeric-type
1488          :class (if (and (eq (numeric-type-class x) 'integer)
1489                          (eq (numeric-type-class y) 'integer))
1490                     ;; The difference of integers is always an integer.
1491                     'integer
1492                     (numeric-type-class result-type))
1493          :format (numeric-type-format result-type)
1494          :low (interval-low result)
1495          :high (interval-high result)))
1496       ;; general contagion
1497       (numeric-contagion x y)))
1498
1499 (defoptimizer (- derive-type) ((x y))
1500   (two-arg-derive-type x y #'--derive-type-aux #'-))
1501
1502 (defun *-derive-type-aux (x y same-arg)
1503   (if (and (numeric-type-real-p x)
1504            (numeric-type-real-p y))
1505       (let ((result
1506              ;; (* X X) is always positive, so take care to do it right.
1507              (if same-arg
1508                  (interval-sqr (numeric-type->interval x))
1509                  (interval-mul (numeric-type->interval x)
1510                                (numeric-type->interval y))))
1511             (result-type (numeric-contagion x y)))
1512         ;; If the result type is a float, we need to be sure to coerce
1513         ;; the bounds into the correct type.
1514         (when (eq (numeric-type-class result-type) 'float)
1515           (setf result (interval-func
1516                         #'(lambda (x)
1517                             (coerce-for-bound x (or (numeric-type-format result-type)
1518                                                     'float)))
1519                         result)))
1520         (make-numeric-type
1521          :class (if (and (eq (numeric-type-class x) 'integer)
1522                          (eq (numeric-type-class y) 'integer))
1523                     ;; The product of integers is always an integer.
1524                     'integer
1525                     (numeric-type-class result-type))
1526          :format (numeric-type-format result-type)
1527          :low (interval-low result)
1528          :high (interval-high result)))
1529       (numeric-contagion x y)))
1530
1531 (defoptimizer (* derive-type) ((x y))
1532   (two-arg-derive-type x y #'*-derive-type-aux #'*))
1533
1534 (defun /-derive-type-aux (x y same-arg)
1535   (if (and (numeric-type-real-p x)
1536            (numeric-type-real-p y))
1537       (let ((result
1538              ;; (/ X X) is always 1, except if X can contain 0. In
1539              ;; that case, we shouldn't optimize the division away
1540              ;; because we want 0/0 to signal an error.
1541              (if (and same-arg
1542                       (not (interval-contains-p
1543                             0 (interval-closure (numeric-type->interval y)))))
1544                  (make-interval :low 1 :high 1)
1545                  (interval-div (numeric-type->interval x)
1546                                (numeric-type->interval y))))
1547             (result-type (numeric-contagion x y)))
1548         ;; If the result type is a float, we need to be sure to coerce
1549         ;; the bounds into the correct type.
1550         (when (eq (numeric-type-class result-type) 'float)
1551           (setf result (interval-func
1552                         #'(lambda (x)
1553                             (coerce-for-bound x (or (numeric-type-format result-type)
1554                                                     'float)))
1555                         result)))
1556         (make-numeric-type :class (numeric-type-class result-type)
1557                            :format (numeric-type-format result-type)
1558                            :low (interval-low result)
1559                            :high (interval-high result)))
1560       (numeric-contagion x y)))
1561
1562 (defoptimizer (/ derive-type) ((x y))
1563   (two-arg-derive-type x y #'/-derive-type-aux #'/))
1564
1565 ) ; PROGN
1566
1567 (defun ash-derive-type-aux (n-type shift same-arg)
1568   (declare (ignore same-arg))
1569   ;; KLUDGE: All this ASH optimization is suppressed under CMU CL for
1570   ;; some bignum cases because as of version 2.4.6 for Debian and 18d,
1571   ;; CMU CL blows up on (ASH 1000000000 -100000000000) (i.e. ASH of
1572   ;; two bignums yielding zero) and it's hard to avoid that
1573   ;; calculation in here.
1574   #+(and cmu sb-xc-host)
1575   (when (and (or (typep (numeric-type-low n-type) 'bignum)
1576                  (typep (numeric-type-high n-type) 'bignum))
1577              (or (typep (numeric-type-low shift) 'bignum)
1578                  (typep (numeric-type-high shift) 'bignum)))
1579     (return-from ash-derive-type-aux *universal-type*))
1580   (flet ((ash-outer (n s)
1581            (when (and (fixnump s)
1582                       (<= s 64)
1583                       (> s sb!xc:most-negative-fixnum))
1584              (ash n s)))
1585          ;; KLUDGE: The bare 64's here should be related to
1586          ;; symbolic machine word size values somehow.
1587
1588          (ash-inner (n s)
1589            (if (and (fixnump s)
1590                     (> s sb!xc:most-negative-fixnum))
1591              (ash n (min s 64))
1592              (if (minusp n) -1 0))))
1593     (or (and (csubtypep n-type (specifier-type 'integer))
1594              (csubtypep shift (specifier-type 'integer))
1595              (let ((n-low (numeric-type-low n-type))
1596                    (n-high (numeric-type-high n-type))
1597                    (s-low (numeric-type-low shift))
1598                    (s-high (numeric-type-high shift)))
1599                (make-numeric-type :class 'integer  :complexp :real
1600                                   :low (when n-low
1601                                          (if (minusp n-low)
1602                                            (ash-outer n-low s-high)
1603                                            (ash-inner n-low s-low)))
1604                                   :high (when n-high
1605                                           (if (minusp n-high)
1606                                             (ash-inner n-high s-low)
1607                                             (ash-outer n-high s-high))))))
1608         *universal-type*)))
1609
1610 (defoptimizer (ash derive-type) ((n shift))
1611   (two-arg-derive-type n shift #'ash-derive-type-aux #'ash))
1612
1613 #+sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1614 (macrolet ((frob (fun)
1615              `#'(lambda (type type2)
1616                   (declare (ignore type2))
1617                   (let ((lo (numeric-type-low type))
1618                         (hi (numeric-type-high type)))
1619                     (values (if hi (,fun hi) nil) (if lo (,fun lo) nil))))))
1620
1621   (defoptimizer (%negate derive-type) ((num))
1622     (derive-integer-type num num (frob -))))
1623
1624 (defun lognot-derive-type-aux (int)
1625   (derive-integer-type-aux int int
1626                            (lambda (type type2)
1627                              (declare (ignore type2))
1628                              (let ((lo (numeric-type-low type))
1629                                    (hi (numeric-type-high type)))
1630                                (values (if hi (lognot hi) nil)
1631                                        (if lo (lognot lo) nil)
1632                                        (numeric-type-class type)
1633                                        (numeric-type-format type))))))
1634
1635 (defoptimizer (lognot derive-type) ((int))
1636   (lognot-derive-type-aux (lvar-type int)))
1637
1638 #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1639 (defoptimizer (%negate derive-type) ((num))
1640   (flet ((negate-bound (b)
1641            (and b
1642                 (set-bound (- (type-bound-number b))
1643                            (consp b)))))
1644     (one-arg-derive-type num
1645                          (lambda (type)
1646                            (modified-numeric-type
1647                             type
1648                             :low (negate-bound (numeric-type-high type))
1649                             :high (negate-bound (numeric-type-low type))))
1650                          #'-)))
1651
1652 #+sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1653 (defoptimizer (abs derive-type) ((num))
1654   (let ((type (lvar-type num)))
1655     (if (and (numeric-type-p type)
1656              (eq (numeric-type-class type) 'integer)
1657              (eq (numeric-type-complexp type) :real))
1658         (let ((lo (numeric-type-low type))
1659               (hi (numeric-type-high type)))
1660           (make-numeric-type :class 'integer :complexp :real
1661                              :low (cond ((and hi (minusp hi))
1662                                          (abs hi))
1663                                         (lo
1664                                          (max 0 lo))
1665                                         (t
1666                                          0))
1667                              :high (if (and hi lo)
1668                                        (max (abs hi) (abs lo))
1669                                        nil)))
1670         (numeric-contagion type type))))
1671
1672 #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1673 (defun abs-derive-type-aux (type)
1674   (cond ((eq (numeric-type-complexp type) :complex)
1675          ;; The absolute value of a complex number is always a
1676          ;; non-negative float.
1677          (let* ((format (case (numeric-type-class type)
1678                           ((integer rational) 'single-float)
1679                           (t (numeric-type-format type))))
1680                 (bound-format (or format 'float)))
1681            (make-numeric-type :class 'float
1682                               :format format
1683                               :complexp :real
1684                               :low (coerce 0 bound-format)
1685                               :high nil)))
1686         (t
1687          ;; The absolute value of a real number is a non-negative real
1688          ;; of the same type.
1689          (let* ((abs-bnd (interval-abs (numeric-type->interval type)))
1690                 (class (numeric-type-class type))
1691                 (format (numeric-type-format type))
1692                 (bound-type (or format class 'real)))
1693            (make-numeric-type
1694             :class class
1695             :format format
1696             :complexp :real
1697             :low (coerce-and-truncate-floats (interval-low abs-bnd) bound-type)
1698             :high (coerce-and-truncate-floats
1699                    (interval-high abs-bnd) bound-type))))))
1700
1701 #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1702 (defoptimizer (abs derive-type) ((num))
1703   (one-arg-derive-type num #'abs-derive-type-aux #'abs))
1704
1705 #+sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1706 (defoptimizer (truncate derive-type) ((number divisor))
1707   (let ((number-type (lvar-type number))
1708         (divisor-type (lvar-type divisor))
1709         (integer-type (specifier-type 'integer)))
1710     (if (and (numeric-type-p number-type)
1711              (csubtypep number-type integer-type)
1712              (numeric-type-p divisor-type)
1713              (csubtypep divisor-type integer-type))
1714         (let ((number-low (numeric-type-low number-type))
1715               (number-high (numeric-type-high number-type))
1716               (divisor-low (numeric-type-low divisor-type))
1717               (divisor-high (numeric-type-high divisor-type)))
1718           (values-specifier-type
1719            `(values ,(integer-truncate-derive-type number-low number-high
1720                                                    divisor-low divisor-high)
1721                     ,(integer-rem-derive-type number-low number-high
1722                                               divisor-low divisor-high))))
1723         *universal-type*)))
1724
1725 #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1726 (progn
1727
1728 (defun rem-result-type (number-type divisor-type)
1729   ;; Figure out what the remainder type is. The remainder is an
1730   ;; integer if both args are integers; a rational if both args are
1731   ;; rational; and a float otherwise.
1732   (cond ((and (csubtypep number-type (specifier-type 'integer))
1733               (csubtypep divisor-type (specifier-type 'integer)))
1734          'integer)
1735         ((and (csubtypep number-type (specifier-type 'rational))
1736               (csubtypep divisor-type (specifier-type 'rational)))
1737          'rational)
1738         ((and (csubtypep number-type (specifier-type 'float))
1739               (csubtypep divisor-type (specifier-type 'float)))
1740          ;; Both are floats so the result is also a float, of
1741          ;; the largest type.
1742          (or (float-format-max (numeric-type-format number-type)
1743                                (numeric-type-format divisor-type))
1744              'float))
1745         ((and (csubtypep number-type (specifier-type 'float))
1746               (csubtypep divisor-type (specifier-type 'rational)))
1747          ;; One of the arguments is a float and the other is a
1748          ;; rational. The remainder is a float of the same
1749          ;; type.
1750          (or (numeric-type-format number-type) 'float))
1751         ((and (csubtypep divisor-type (specifier-type 'float))
1752               (csubtypep number-type (specifier-type 'rational)))
1753          ;; One of the arguments is a float and the other is a
1754          ;; rational. The remainder is a float of the same
1755          ;; type.
1756          (or (numeric-type-format divisor-type) 'float))
1757         (t
1758          ;; Some unhandled combination. This usually means both args
1759          ;; are REAL so the result is a REAL.
1760          'real)))
1761
1762 (defun truncate-derive-type-quot (number-type divisor-type)
1763   (let* ((rem-type (rem-result-type number-type divisor-type))
1764          (number-interval (numeric-type->interval number-type))
1765          (divisor-interval (numeric-type->interval divisor-type)))
1766     ;;(declare (type (member '(integer rational float)) rem-type))
1767     ;; We have real numbers now.
1768     (cond ((eq rem-type 'integer)
1769            ;; Since the remainder type is INTEGER, both args are
1770            ;; INTEGERs.
1771            (let* ((res (integer-truncate-derive-type
1772                         (interval-low number-interval)
1773                         (interval-high number-interval)
1774                         (interval-low divisor-interval)
1775                         (interval-high divisor-interval))))
1776              (specifier-type (if (listp res) res 'integer))))
1777           (t
1778            (let ((quot (truncate-quotient-bound
1779                         (interval-div number-interval
1780                                       divisor-interval))))
1781              (specifier-type `(integer ,(or (interval-low quot) '*)
1782                                        ,(or (interval-high quot) '*))))))))
1783
1784 (defun truncate-derive-type-rem (number-type divisor-type)
1785   (let* ((rem-type (rem-result-type number-type divisor-type))
1786          (number-interval (numeric-type->interval number-type))
1787          (divisor-interval (numeric-type->interval divisor-type))
1788          (rem (truncate-rem-bound number-interval divisor-interval)))
1789     ;;(declare (type (member '(integer rational float)) rem-type))
1790     ;; We have real numbers now.
1791     (cond ((eq rem-type 'integer)
1792            ;; Since the remainder type is INTEGER, both args are
1793            ;; INTEGERs.
1794            (specifier-type `(,rem-type ,(or (interval-low rem) '*)
1795                                        ,(or (interval-high rem) '*))))
1796           (t
1797            (multiple-value-bind (class format)
1798                (ecase rem-type
1799                  (integer
1800                   (values 'integer nil))
1801                  (rational
1802                   (values 'rational nil))
1803                  ((or single-float double-float #!+long-float long-float)
1804                   (values 'float rem-type))
1805                  (float
1806                   (values 'float nil))
1807                  (real
1808                   (values nil nil)))
1809              (when (member rem-type '(float single-float double-float
1810                                             #!+long-float long-float))
1811                (setf rem (interval-func #'(lambda (x)
1812                                             (coerce-for-bound x rem-type))
1813                                         rem)))
1814              (make-numeric-type :class class
1815                                 :format format
1816                                 :low (interval-low rem)
1817                                 :high (interval-high rem)))))))
1818
1819 (defun truncate-derive-type-quot-aux (num div same-arg)
1820   (declare (ignore same-arg))
1821   (if (and (numeric-type-real-p num)
1822            (numeric-type-real-p div))
1823       (truncate-derive-type-quot num div)
1824       *empty-type*))
1825
1826 (defun truncate-derive-type-rem-aux (num div same-arg)
1827   (declare (ignore same-arg))
1828   (if (and (numeric-type-real-p num)
1829            (numeric-type-real-p div))
1830       (truncate-derive-type-rem num div)
1831       *empty-type*))
1832
1833 (defoptimizer (truncate derive-type) ((number divisor))
1834   (let ((quot (two-arg-derive-type number divisor
1835                                    #'truncate-derive-type-quot-aux #'truncate))
1836         (rem (two-arg-derive-type number divisor
1837                                   #'truncate-derive-type-rem-aux #'rem)))
1838     (when (and quot rem)
1839       (make-values-type :required (list quot rem)))))
1840
1841 (defun ftruncate-derive-type-quot (number-type divisor-type)
1842   ;; The bounds are the same as for truncate. However, the first
1843   ;; result is a float of some type. We need to determine what that
1844   ;; type is. Basically it's the more contagious of the two types.
1845   (let ((q-type (truncate-derive-type-quot number-type divisor-type))
1846         (res-type (numeric-contagion number-type divisor-type)))
1847     (make-numeric-type :class 'float
1848                        :format (numeric-type-format res-type)
1849                        :low (numeric-type-low q-type)
1850                        :high (numeric-type-high q-type))))
1851
1852 (defun ftruncate-derive-type-quot-aux (n d same-arg)
1853   (declare (ignore same-arg))
1854   (if (and (numeric-type-real-p n)
1855            (numeric-type-real-p d))
1856       (ftruncate-derive-type-quot n d)
1857       *empty-type*))
1858
1859 (defoptimizer (ftruncate derive-type) ((number divisor))
1860   (let ((quot
1861          (two-arg-derive-type number divisor
1862                               #'ftruncate-derive-type-quot-aux #'ftruncate))
1863         (rem (two-arg-derive-type number divisor
1864                                   #'truncate-derive-type-rem-aux #'rem)))
1865     (when (and quot rem)
1866       (make-values-type :required (list quot rem)))))
1867
1868 (defun %unary-truncate-derive-type-aux (number)
1869   (truncate-derive-type-quot number (specifier-type '(integer 1 1))))
1870
1871 (defoptimizer (%unary-truncate derive-type) ((number))
1872   (one-arg-derive-type number
1873                        #'%unary-truncate-derive-type-aux
1874                        #'%unary-truncate))
1875
1876 (defoptimizer (%unary-truncate/single-float derive-type) ((number))
1877   (one-arg-derive-type number
1878                        #'%unary-truncate-derive-type-aux
1879                        #'%unary-truncate))
1880
1881 (defoptimizer (%unary-truncate/double-float derive-type) ((number))
1882   (one-arg-derive-type number
1883                        #'%unary-truncate-derive-type-aux
1884                        #'%unary-truncate))
1885
1886 (defoptimizer (%unary-ftruncate derive-type) ((number))
1887   (let ((divisor (specifier-type '(integer 1 1))))
1888     (one-arg-derive-type number
1889                          #'(lambda (n)
1890                              (ftruncate-derive-type-quot-aux n divisor nil))
1891                          #'%unary-ftruncate)))
1892
1893 (defoptimizer (%unary-round derive-type) ((number))
1894   (one-arg-derive-type number
1895                        (lambda (n)
1896                          (block nil
1897                            (unless (numeric-type-real-p n)
1898                              (return *empty-type*))
1899                            (let* ((interval (numeric-type->interval n))
1900                                   (low      (interval-low interval))
1901                                   (high     (interval-high interval)))
1902                              (when (consp low)
1903                                (setf low (car low)))
1904                              (when (consp high)
1905                                (setf high (car high)))
1906                              (specifier-type
1907                               `(integer ,(if low
1908                                              (round low)
1909                                              '*)
1910                                         ,(if high
1911                                              (round high)
1912                                              '*))))))
1913                        #'%unary-round))
1914
1915 ;;; Define optimizers for FLOOR and CEILING.
1916 (macrolet
1917     ((def (name q-name r-name)
1918        (let ((q-aux (symbolicate q-name "-AUX"))
1919              (r-aux (symbolicate r-name "-AUX")))
1920          `(progn
1921            ;; Compute type of quotient (first) result.
1922            (defun ,q-aux (number-type divisor-type)
1923              (let* ((number-interval
1924                      (numeric-type->interval number-type))
1925                     (divisor-interval
1926                      (numeric-type->interval divisor-type))
1927                     (quot (,q-name (interval-div number-interval
1928                                                  divisor-interval))))
1929                (specifier-type `(integer ,(or (interval-low quot) '*)
1930                                          ,(or (interval-high quot) '*)))))
1931            ;; Compute type of remainder.
1932            (defun ,r-aux (number-type divisor-type)
1933              (let* ((divisor-interval
1934                      (numeric-type->interval divisor-type))
1935                     (rem (,r-name divisor-interval))
1936                     (result-type (rem-result-type number-type divisor-type)))
1937                (multiple-value-bind (class format)
1938                    (ecase result-type
1939                      (integer
1940                       (values 'integer nil))
1941                      (rational
1942                       (values 'rational nil))
1943                      ((or single-float double-float #!+long-float long-float)
1944                       (values 'float result-type))
1945                      (float
1946                       (values 'float nil))
1947                      (real
1948                       (values nil nil)))
1949                  (when (member result-type '(float single-float double-float
1950                                              #!+long-float long-float))
1951                    ;; Make sure that the limits on the interval have
1952                    ;; the right type.
1953                    (setf rem (interval-func (lambda (x)
1954                                               (coerce-for-bound x result-type))
1955                                             rem)))
1956                  (make-numeric-type :class class
1957                                     :format format
1958                                     :low (interval-low rem)
1959                                     :high (interval-high rem)))))
1960            ;; the optimizer itself
1961            (defoptimizer (,name derive-type) ((number divisor))
1962              (flet ((derive-q (n d same-arg)
1963                       (declare (ignore same-arg))
1964                       (if (and (numeric-type-real-p n)
1965                                (numeric-type-real-p d))
1966                           (,q-aux n d)
1967                           *empty-type*))
1968                     (derive-r (n d same-arg)
1969                       (declare (ignore same-arg))
1970                       (if (and (numeric-type-real-p n)
1971                                (numeric-type-real-p d))
1972                           (,r-aux n d)
1973                           *empty-type*)))
1974                (let ((quot (two-arg-derive-type
1975                             number divisor #'derive-q #',name))
1976                      (rem (two-arg-derive-type
1977                            number divisor #'derive-r #'mod)))
1978                  (when (and quot rem)
1979                    (make-values-type :required (list quot rem))))))))))
1980
1981   (def floor floor-quotient-bound floor-rem-bound)
1982   (def ceiling ceiling-quotient-bound ceiling-rem-bound))
1983
1984 ;;; Define optimizers for FFLOOR and FCEILING
1985 (macrolet ((def (name q-name r-name)
1986              (let ((q-aux (symbolicate "F" q-name "-AUX"))
1987                    (r-aux (symbolicate r-name "-AUX")))
1988                `(progn
1989                   ;; Compute type of quotient (first) result.
1990                   (defun ,q-aux (number-type divisor-type)
1991                     (let* ((number-interval
1992                             (numeric-type->interval number-type))
1993                            (divisor-interval
1994                             (numeric-type->interval divisor-type))
1995                            (quot (,q-name (interval-div number-interval
1996                                                         divisor-interval)))
1997                            (res-type (numeric-contagion number-type
1998                                                         divisor-type)))
1999                       (make-numeric-type
2000                        :class (numeric-type-class res-type)
2001                        :format (numeric-type-format res-type)
2002                        :low  (interval-low quot)
2003                        :high (interval-high quot))))
2004
2005                   (defoptimizer (,name derive-type) ((number divisor))
2006                     (flet ((derive-q (n d same-arg)
2007                              (declare (ignore same-arg))
2008                              (if (and (numeric-type-real-p n)
2009                                       (numeric-type-real-p d))
2010                                  (,q-aux n d)
2011                                  *empty-type*))
2012                            (derive-r (n d same-arg)
2013                              (declare (ignore same-arg))
2014                              (if (and (numeric-type-real-p n)
2015                                       (numeric-type-real-p d))
2016                                  (,r-aux n d)
2017                                  *empty-type*)))
2018                       (let ((quot (two-arg-derive-type
2019                                    number divisor #'derive-q #',name))
2020                             (rem (two-arg-derive-type
2021                                   number divisor #'derive-r #'mod)))
2022                         (when (and quot rem)
2023                           (make-values-type :required (list quot rem))))))))))
2024
2025   (def ffloor floor-quotient-bound floor-rem-bound)
2026   (def fceiling ceiling-quotient-bound ceiling-rem-bound))
2027
2028 ;;; functions to compute the bounds on the quotient and remainder for
2029 ;;; the FLOOR function
2030 (defun floor-quotient-bound (quot)
2031   ;; Take the floor of the quotient and then massage it into what we
2032   ;; need.
2033   (let ((lo (interval-low quot))
2034         (hi (interval-high quot)))
2035     ;; Take the floor of the lower bound. The result is always a
2036     ;; closed lower bound.
2037     (setf lo (if lo
2038                  (floor (type-bound-number lo))
2039                  nil))
2040     ;; For the upper bound, we need to be careful.
2041     (setf hi
2042           (cond ((consp hi)
2043                  ;; An open bound. We need to be careful here because
2044                  ;; the floor of '(10.0) is 9, but the floor of
2045                  ;; 10.0 is 10.
2046                  (multiple-value-bind (q r) (floor (first hi))
2047                    (if (zerop r)
2048                        (1- q)
2049                        q)))
2050                 (hi
2051                  ;; A closed bound, so the answer is obvious.
2052                  (floor hi))
2053                 (t
2054                  hi)))
2055     (make-interval :low lo :high hi)))
2056 (defun floor-rem-bound (div)
2057   ;; The remainder depends only on the divisor. Try to get the
2058   ;; correct sign for the remainder if we can.
2059   (case (interval-range-info div)
2060     (+
2061      ;; The divisor is always positive.
2062      (let ((rem (interval-abs div)))
2063        (setf (interval-low rem) 0)
2064        (when (and (numberp (interval-high rem))
2065                   (not (zerop (interval-high rem))))
2066          ;; The remainder never contains the upper bound. However,
2067          ;; watch out for the case where the high limit is zero!
2068          (setf (interval-high rem) (list (interval-high rem))))
2069        rem))
2070     (-
2071      ;; The divisor is always negative.
2072      (let ((rem (interval-neg (interval-abs div))))
2073        (setf (interval-high rem) 0)
2074        (when (numberp (interval-low rem))
2075          ;; The remainder never contains the lower bound.
2076          (setf (interval-low rem) (list (interval-low rem))))
2077        rem))
2078     (otherwise
2079      ;; The divisor can be positive or negative. All bets off. The
2080      ;; magnitude of remainder is the maximum value of the divisor.
2081      (let ((limit (type-bound-number (interval-high (interval-abs div)))))
2082        ;; The bound never reaches the limit, so make the interval open.
2083        (make-interval :low (if limit
2084                                (list (- limit))
2085                                limit)
2086                       :high (list limit))))))
2087 #| Test cases
2088 (floor-quotient-bound (make-interval :low 0.3 :high 10.3))
2089 => #S(INTERVAL :LOW 0 :HIGH 10)
2090 (floor-quotient-bound (make-interval :low 0.3 :high '(10.3)))
2091 => #S(INTERVAL :LOW 0 :HIGH 10)
2092 (floor-quotient-bound (make-interval :low 0.3 :high 10))
2093 => #S(INTERVAL :LOW 0 :HIGH 10)
2094 (floor-quotient-bound (make-interval :low 0.3 :high '(10)))
2095 => #S(INTERVAL :LOW 0 :HIGH 9)
2096 (floor-quotient-bound (make-interval :low '(0.3) :high 10.3))
2097 => #S(INTERVAL :LOW 0 :HIGH 10)
2098 (floor-quotient-bound (make-interval :low '(0.0) :high 10.3))
2099 => #S(INTERVAL :LOW 0 :HIGH 10)
2100 (floor-quotient-bound (make-interval :low '(-1.3) :high 10.3))
2101 => #S(INTERVAL :LOW -2 :HIGH 10)
2102 (floor-quotient-bound (make-interval :low '(-1.0) :high 10.3))
2103 => #S(INTERVAL :LOW -1 :HIGH 10)
2104 (floor-quotient-bound (make-interval :low -1.0 :high 10.3))
2105 => #S(INTERVAL :LOW -1 :HIGH 10)
2106
2107 (floor-rem-bound (make-interval :low 0.3 :high 10.3))
2108 => #S(INTERVAL :LOW 0 :HIGH '(10.3))
2109 (floor-rem-bound (make-interval :low 0.3 :high '(10.3)))
2110 => #S(INTERVAL :LOW 0 :HIGH '(10.3))
2111 (floor-rem-bound (make-interval :low -10 :high -2.3))
2112 #S(INTERVAL :LOW (-10) :HIGH 0)
2113 (floor-rem-bound (make-interval :low 0.3 :high 10))
2114 => #S(INTERVAL :LOW 0 :HIGH '(10))
2115 (floor-rem-bound (make-interval :low '(-1.3) :high 10.3))
2116 => #S(INTERVAL :LOW '(-10.3) :HIGH '(10.3))
2117 (floor-rem-bound (make-interval :low '(-20.3) :high 10.3))
2118 => #S(INTERVAL :LOW (-20.3) :HIGH (20.3))
2119 |#
2120 \f
2121 ;;; same functions for CEILING
2122 (defun ceiling-quotient-bound (quot)
2123   ;; Take the ceiling of the quotient and then massage it into what we
2124   ;; need.
2125   (let ((lo (interval-low quot))
2126         (hi (interval-high quot)))
2127     ;; Take the ceiling of the upper bound. The result is always a
2128     ;; closed upper bound.
2129     (setf hi (if hi
2130                  (ceiling (type-bound-number hi))
2131                  nil))
2132     ;; For the lower bound, we need to be careful.
2133     (setf lo
2134           (cond ((consp lo)
2135                  ;; An open bound. We need to be careful here because
2136                  ;; the ceiling of '(10.0) is 11, but the ceiling of
2137                  ;; 10.0 is 10.
2138                  (multiple-value-bind (q r) (ceiling (first lo))
2139                    (if (zerop r)
2140                        (1+ q)
2141                        q)))
2142                 (lo
2143                  ;; A closed bound, so the answer is obvious.
2144                  (ceiling lo))
2145                 (t
2146                  lo)))
2147     (make-interval :low lo :high hi)))
2148 (defun ceiling-rem-bound (div)
2149   ;; The remainder depends only on the divisor. Try to get the
2150   ;; correct sign for the remainder if we can.
2151   (case (interval-range-info div)
2152     (+
2153      ;; Divisor is always positive. The remainder is negative.
2154      (let ((rem (interval-neg (interval-abs div))))
2155        (setf (interval-high rem) 0)
2156        (when (and (numberp (interval-low rem))
2157                   (not (zerop (interval-low rem))))
2158          ;; The remainder never contains the upper bound. However,
2159          ;; watch out for the case when the upper bound is zero!
2160          (setf (interval-low rem) (list (interval-low rem))))
2161        rem))
2162     (-
2163      ;; Divisor is always negative. The remainder is positive
2164      (let ((rem (interval-abs div)))
2165        (setf (interval-low rem) 0)
2166        (when (numberp (interval-high rem))
2167          ;; The remainder never contains the lower bound.
2168          (setf (interval-high rem) (list (interval-high rem))))
2169        rem))
2170     (otherwise
2171      ;; The divisor can be positive or negative. All bets off. The
2172      ;; magnitude of remainder is the maximum value of the divisor.
2173      (let ((limit (type-bound-number (interval-high (interval-abs div)))))
2174        ;; The bound never reaches the limit, so make the interval open.
2175        (make-interval :low (if limit
2176                                (list (- limit))
2177                                limit)
2178                       :high (list limit))))))
2179
2180 #| Test cases
2181 (ceiling-quotient-bound (make-interval :low 0.3 :high 10.3))
2182 => #S(INTERVAL :LOW 1 :HIGH 11)
2183 (ceiling-quotient-bound (make-interval :low 0.3 :high '(10.3)))
2184 => #S(INTERVAL :LOW 1 :HIGH 11)
2185 (ceiling-quotient-bound (make-interval :low 0.3 :high 10))
2186 => #S(INTERVAL :LOW 1 :HIGH 10)
2187 (ceiling-quotient-bound (make-interval :low 0.3 :high '(10)))
2188 => #S(INTERVAL :LOW 1 :HIGH 10)
2189 (ceiling-quotient-bound (make-interval :low '(0.3) :high 10.3))
2190 => #S(INTERVAL :LOW 1 :HIGH 11)
2191 (ceiling-quotient-bound (make-interval :low '(0.0) :high 10.3))
2192 => #S(INTERVAL :LOW 1 :HIGH 11)
2193 (ceiling-quotient-bound (make-interval :low '(-1.3) :high 10.3))
2194 => #S(INTERVAL :LOW -1 :HIGH 11)
2195 (ceiling-quotient-bound (make-interval :low '(-1.0) :high 10.3))
2196 => #S(INTERVAL :LOW 0 :HIGH 11)
2197 (ceiling-quotient-bound (make-interval :low -1.0 :high 10.3))
2198 => #S(INTERVAL :LOW -1 :HIGH 11)
2199
2200 (ceiling-rem-bound (make-interval :low 0.3 :high 10.3))
2201 => #S(INTERVAL :LOW (-10.3) :HIGH 0)
2202 (ceiling-rem-bound (make-interval :low 0.3 :high '(10.3)))
2203 => #S(INTERVAL :LOW 0 :HIGH '(10.3))
2204 (ceiling-rem-bound (make-interval :low -10 :high -2.3))
2205 => #S(INTERVAL :LOW 0 :HIGH (10))
2206 (ceiling-rem-bound (make-interval :low 0.3 :high 10))
2207 => #S(INTERVAL :LOW (-10) :HIGH 0)
2208 (ceiling-rem-bound (make-interval :low '(-1.3) :high 10.3))
2209 => #S(INTERVAL :LOW (-10.3) :HIGH (10.3))
2210 (ceiling-rem-bound (make-interval :low '(-20.3) :high 10.3))
2211 => #S(INTERVAL :LOW (-20.3) :HIGH (20.3))
2212 |#
2213 \f
2214 (defun truncate-quotient-bound (quot)
2215   ;; For positive quotients, truncate is exactly like floor. For
2216   ;; negative quotients, truncate is exactly like ceiling. Otherwise,
2217   ;; it's the union of the two pieces.
2218   (case (interval-range-info quot)
2219     (+
2220      ;; just like FLOOR
2221      (floor-quotient-bound quot))
2222     (-
2223      ;; just like CEILING
2224      (ceiling-quotient-bound quot))
2225     (otherwise
2226      ;; Split the interval into positive and negative pieces, compute
2227      ;; the result for each piece and put them back together.
2228      (destructuring-bind (neg pos) (interval-split 0 quot t t)
2229        (interval-merge-pair (ceiling-quotient-bound neg)
2230                             (floor-quotient-bound pos))))))
2231
2232 (defun truncate-rem-bound (num div)
2233   ;; This is significantly more complicated than FLOOR or CEILING. We
2234   ;; need both the number and the divisor to determine the range. The
2235   ;; basic idea is to split the ranges of NUM and DEN into positive
2236   ;; and negative pieces and deal with each of the four possibilities
2237   ;; in turn.
2238   (case (interval-range-info num)
2239     (+
2240      (case (interval-range-info div)
2241        (+
2242         (floor-rem-bound div))
2243        (-
2244         (ceiling-rem-bound div))
2245        (otherwise
2246         (destructuring-bind (neg pos) (interval-split 0 div t t)
2247           (interval-merge-pair (truncate-rem-bound num neg)
2248                                (truncate-rem-bound num pos))))))
2249     (-
2250      (case (interval-range-info div)
2251        (+
2252         (ceiling-rem-bound div))
2253        (-
2254         (floor-rem-bound div))
2255        (otherwise
2256         (destructuring-bind (neg pos) (interval-split 0 div t t)
2257           (interval-merge-pair (truncate-rem-bound num neg)
2258                                (truncate-rem-bound num pos))))))
2259     (otherwise
2260      (destructuring-bind (neg pos) (interval-split 0 num t t)
2261        (interval-merge-pair (truncate-rem-bound neg div)
2262                             (truncate-rem-bound pos div))))))
2263 ) ; PROGN
2264
2265 ;;; Derive useful information about the range. Returns three values:
2266 ;;; - '+ if its positive, '- negative, or nil if it overlaps 0.
2267 ;;; - The abs of the minimal value (i.e. closest to 0) in the range.
2268 ;;; - The abs of the maximal value if there is one, or nil if it is
2269 ;;;   unbounded.
2270 (defun numeric-range-info (low high)
2271   (cond ((and low (not (minusp low)))
2272          (values '+ low high))
2273         ((and high (not (plusp high)))
2274          (values '- (- high) (if low (- low) nil)))
2275         (t
2276          (values nil 0 (and low high (max (- low) high))))))
2277
2278 (defun integer-truncate-derive-type
2279        (number-low number-high divisor-low divisor-high)
2280   ;; The result cannot be larger in magnitude than the number, but the
2281   ;; sign might change. If we can determine the sign of either the
2282   ;; number or the divisor, we can eliminate some of the cases.
2283   (multiple-value-bind (number-sign number-min number-max)
2284       (numeric-range-info number-low number-high)
2285     (multiple-value-bind (divisor-sign divisor-min divisor-max)
2286         (numeric-range-info divisor-low divisor-high)
2287       (when (and divisor-max (zerop divisor-max))
2288         ;; We've got a problem: guaranteed division by zero.
2289         (return-from integer-truncate-derive-type t))
2290       (when (zerop divisor-min)
2291         ;; We'll assume that they aren't going to divide by zero.
2292         (incf divisor-min))
2293       (cond ((and number-sign divisor-sign)
2294              ;; We know the sign of both.
2295              (if (eq number-sign divisor-sign)
2296                  ;; Same sign, so the result will be positive.
2297                  `(integer ,(if divisor-max
2298                                 (truncate number-min divisor-max)
2299                                 0)
2300                            ,(if number-max
2301                                 (truncate number-max divisor-min)
2302                                 '*))
2303                  ;; Different signs, the result will be negative.
2304                  `(integer ,(if number-max
2305                                 (- (truncate number-max divisor-min))
2306                                 '*)
2307                            ,(if divisor-max
2308                                 (- (truncate number-min divisor-max))
2309                                 0))))
2310             ((eq divisor-sign '+)
2311              ;; The divisor is positive. Therefore, the number will just
2312              ;; become closer to zero.
2313              `(integer ,(if number-low
2314                             (truncate number-low divisor-min)
2315                             '*)
2316                        ,(if number-high
2317                             (truncate number-high divisor-min)
2318                             '*)))
2319             ((eq divisor-sign '-)
2320              ;; The divisor is negative. Therefore, the absolute value of
2321              ;; the number will become closer to zero, but the sign will also
2322              ;; change.
2323              `(integer ,(if number-high
2324                             (- (truncate number-high divisor-min))
2325                             '*)
2326                        ,(if number-low
2327                             (- (truncate number-low divisor-min))
2328                             '*)))
2329             ;; The divisor could be either positive or negative.
2330             (number-max
2331              ;; The number we are dividing has a bound. Divide that by the
2332              ;; smallest posible divisor.
2333              (let ((bound (truncate number-max divisor-min)))
2334                `(integer ,(- bound) ,bound)))
2335             (t
2336              ;; The number we are dividing is unbounded, so we can't tell
2337              ;; anything about the result.
2338              `integer)))))
2339
2340 #+sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
2341 (defun integer-rem-derive-type
2342        (number-low number-high divisor-low divisor-high)
2343   (if (and divisor-low divisor-high)
2344       ;; We know the range of the divisor, and the remainder must be
2345       ;; smaller than the divisor. We can tell the sign of the
2346       ;; remainder if we know the sign of the number.
2347       (let ((divisor-max (1- (max (abs divisor-low) (abs divisor-high)))))
2348         `(integer ,(if (or (null number-low)
2349                            (minusp number-low))
2350                        (- divisor-max)
2351                        0)
2352                   ,(if (or (null number-high)
2353                            (plusp number-high))
2354                        divisor-max
2355                        0)))
2356       ;; The divisor is potentially either very positive or very
2357       ;; negative. Therefore, the remainder is unbounded, but we might
2358       ;; be able to tell something about the sign from the number.
2359       `(integer ,(if (and number-low (not (minusp number-low)))
2360                      ;; The number we are dividing is positive.
2361                      ;; Therefore, the remainder must be positive.
2362                      0
2363                      '*)
2364                 ,(if (and number-high (not (plusp number-high)))
2365                      ;; The number we are dividing is negative.
2366                      ;; Therefore, the remainder must be negative.
2367                      0
2368                      '*))))
2369
2370 #+sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
2371 (defoptimizer (random derive-type) ((bound &optional state))
2372   (let ((type (lvar-type bound)))
2373     (when (numeric-type-p type)
2374       (let ((class (numeric-type-class type))
2375             (high (numeric-type-high type))
2376             (format (numeric-type-format type)))
2377         (make-numeric-type
2378          :class class
2379          :format format
2380          :low (coerce 0 (or format class 'real))
2381          :high (cond ((not high) nil)
2382                      ((eq class 'integer) (max (1- high) 0))
2383                      ((or (consp high) (zerop high)) high)
2384                      (t `(,high))))))))
2385
2386 #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
2387 (defun random-derive-type-aux (type)
2388   (let ((class (numeric-type-class type))
2389         (high (numeric-type-high type))
2390         (format (numeric-type-format type)))
2391     (make-numeric-type
2392          :class class
2393          :format format
2394          :low (coerce 0 (or format class 'real))
2395          :high (cond ((not high) nil)
2396                      ((eq class 'integer) (max (1- high) 0))
2397                      ((or (consp high) (zerop high)) high)
2398                      (t `(,high))))))
2399
2400 #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
2401 (defoptimizer (random derive-type) ((bound &optional state))
2402   (one-arg-derive-type bound #'random-derive-type-aux nil))
2403 \f
2404 ;;;; DERIVE-TYPE methods for LOGAND, LOGIOR, and friends
2405
2406 ;;; Return the maximum number of bits an integer of the supplied type
2407 ;;; can take up, or NIL if it is unbounded. The second (third) value
2408 ;;; is T if the integer can be positive (negative) and NIL if not.
2409 ;;; Zero counts as positive.
2410 (defun integer-type-length (type)
2411   (if (numeric-type-p type)
2412       (let ((min (numeric-type-low type))
2413             (max (numeric-type-high type)))
2414         (values (and min max (max (integer-length min) (integer-length max)))
2415                 (or (null max) (not (minusp max)))
2416                 (or (null min) (minusp min))))
2417       (values nil t t)))
2418
2419 ;;; See _Hacker's Delight_, Henry S. Warren, Jr. pp 58-63 for an
2420 ;;; explanation of LOG{AND,IOR,XOR}-DERIVE-UNSIGNED-{LOW,HIGH}-BOUND.
2421 ;;; Credit also goes to Raymond Toy for writing (and debugging!) similar
2422 ;;; versions in CMUCL, from which these functions copy liberally.
2423
2424 (defun logand-derive-unsigned-low-bound (x y)
2425   (let ((a (numeric-type-low x))
2426         (b (numeric-type-high x))
2427         (c (numeric-type-low y))
2428         (d (numeric-type-high y)))
2429     (loop for m = (ash 1 (integer-length (lognor a c))) then (ash m -1)
2430           until (zerop m) do
2431           (unless (zerop (logand m (lognot a) (lognot c)))
2432             (let ((temp (logandc2 (logior a m) (1- m))))
2433               (when (<= temp b)
2434                 (setf a temp)
2435                 (loop-finish))
2436               (setf temp (logandc2 (logior c m) (1- m)))
2437               (when (<= temp d)
2438                 (setf c temp)
2439                 (loop-finish))))
2440           finally (return (logand a c)))))
2441
2442 (defun logand-derive-unsigned-high-bound (x y)
2443   (let ((a (numeric-type-low x))
2444         (b (numeric-type-high x))
2445         (c (numeric-type-low y))
2446         (d (numeric-type-high y)))
2447     (loop for m = (ash 1 (integer-length (logxor b d))) then (ash m -1)
2448           until (zerop m) do
2449           (cond
2450             ((not (zerop (logand b (lognot d) m)))
2451              (let ((temp (logior (logandc2 b m) (1- m))))
2452                (when (>= temp a)
2453                  (setf b temp)
2454                  (loop-finish))))
2455             ((not (zerop (logand (lognot b) d m)))
2456              (let ((temp (logior (logandc2 d m) (1- m))))
2457                (when (>= temp c)
2458                  (setf d temp)
2459                  (loop-finish)))))
2460           finally (return (logand b d)))))
2461
2462 (defun logand-derive-type-aux (x y &optional same-leaf)
2463   (when same-leaf
2464     (return-from logand-derive-type-aux x))
2465   (multiple-value-bind (x-len x-pos x-neg) (integer-type-length x)
2466     (declare (ignore x-pos))
2467     (multiple-value-bind (y-len y-pos y-neg) (integer-type-length y)
2468       (declare (ignore y-pos))
2469       (if (not x-neg)
2470           ;; X must be positive.
2471           (if (not y-neg)
2472               ;; They must both be positive.
2473               (cond ((and (null x-len) (null y-len))
2474                      (specifier-type 'unsigned-byte))
2475                     ((null x-len)
2476                      (specifier-type `(unsigned-byte* ,y-len)))
2477                     ((null y-len)
2478                      (specifier-type `(unsigned-byte* ,x-len)))
2479                     (t
2480                      (let ((low (logand-derive-unsigned-low-bound x y))
2481                            (high (logand-derive-unsigned-high-bound x y)))
2482                        (specifier-type `(integer ,low ,high)))))
2483               ;; X is positive, but Y might be negative.
2484               (cond ((null x-len)
2485                      (specifier-type 'unsigned-byte))
2486                     (t
2487                      (specifier-type `(unsigned-byte* ,x-len)))))
2488           ;; X might be negative.
2489           (if (not y-neg)
2490               ;; Y must be positive.
2491               (cond ((null y-len)
2492                      (specifier-type 'unsigned-byte))
2493                     (t (specifier-type `(unsigned-byte* ,y-len))))
2494               ;; Either might be negative.
2495               (if (and x-len y-len)
2496                   ;; The result is bounded.
2497                   (specifier-type `(signed-byte ,(1+ (max x-len y-len))))
2498                   ;; We can't tell squat about the result.
2499                   (specifier-type 'integer)))))))
2500
2501 (defun logior-derive-unsigned-low-bound (x y)
2502   (let ((a (numeric-type-low x))
2503         (b (numeric-type-high x))
2504         (c (numeric-type-low y))
2505         (d (numeric-type-high y)))
2506     (loop for m = (ash 1 (integer-length (logxor a c))) then (ash m -1)
2507           until (zerop m) do
2508           (cond
2509             ((not (zerop (logandc2 (logand c m) a)))
2510              (let ((temp (logand (logior a m) (1+ (lognot m)))))
2511                (when (<= temp b)
2512                  (setf a temp)
2513                  (loop-finish))))
2514             ((not (zerop (logandc2 (logand a m) c)))
2515              (let ((temp (logand (logior c m) (1+ (lognot m)))))
2516                (when (<= temp d)
2517                  (setf c temp)
2518                  (loop-finish)))))
2519           finally (return (logior a c)))))
2520
2521 (defun logior-derive-unsigned-high-bound (x y)
2522   (let ((a (numeric-type-low x))
2523         (b (numeric-type-high x))
2524         (c (numeric-type-low y))
2525         (d (numeric-type-high y)))
2526     (loop for m = (ash 1 (integer-length (logand b d))) then (ash m -1)
2527           until (zerop m) do
2528           (unless (zerop (logand b d m))
2529             (let ((temp (logior (- b m) (1- m))))
2530               (when (>= temp a)
2531                 (setf b temp)
2532                 (loop-finish))
2533               (setf temp (logior (- d m) (1- m)))
2534               (when (>= temp c)
2535                 (setf d temp)
2536                 (loop-finish))))
2537           finally (return (logior b d)))))
2538
2539 (defun logior-derive-type-aux (x y &optional same-leaf)
2540   (when same-leaf
2541     (return-from logior-derive-type-aux x))
2542   (multiple-value-bind (x-len x-pos x-neg) (integer-type-length x)
2543     (multiple-value-bind (y-len y-pos y-neg) (integer-type-length y)
2544       (cond
2545        ((and (not x-neg) (not y-neg))
2546         ;; Both are positive.
2547         (if (and x-len y-len)
2548             (let ((low (logior-derive-unsigned-low-bound x y))
2549                   (high (logior-derive-unsigned-high-bound x y)))
2550               (specifier-type `(integer ,low ,high)))
2551             (specifier-type `(unsigned-byte* *))))
2552        ((not x-pos)
2553         ;; X must be negative.
2554         (if (not y-pos)
2555             ;; Both are negative. The result is going to be negative
2556             ;; and be the same length or shorter than the smaller.
2557             (if (and x-len y-len)
2558                 ;; It's bounded.
2559                 (specifier-type `(integer ,(ash -1 (min x-len y-len)) -1))
2560                 ;; It's unbounded.
2561                 (specifier-type '(integer * -1)))
2562             ;; X is negative, but we don't know about Y. The result
2563             ;; will be negative, but no more negative than X.
2564             (specifier-type
2565              `(integer ,(or (numeric-type-low x) '*)
2566                        -1))))
2567        (t
2568         ;; X might be either positive or negative.
2569         (if (not y-pos)
2570             ;; But Y is negative. The result will be negative.
2571             (specifier-type
2572              `(integer ,(or (numeric-type-low y) '*)
2573                        -1))
2574             ;; We don't know squat about either. It won't get any bigger.
2575             (if (and x-len y-len)
2576                 ;; Bounded.
2577                 (specifier-type `(signed-byte ,(1+ (max x-len y-len))))
2578                 ;; Unbounded.
2579                 (specifier-type 'integer))))))))
2580
2581 (defun logxor-derive-unsigned-low-bound (x y)
2582   (let ((a (numeric-type-low x))
2583         (b (numeric-type-high x))
2584         (c (numeric-type-low y))
2585         (d (numeric-type-high y)))
2586     (loop for m = (ash 1 (integer-length (logxor a c))) then (ash m -1)
2587           until (zerop m) do
2588           (cond
2589             ((not (zerop (logandc2 (logand c m) a)))
2590              (let ((temp (logand (logior a m)
2591                                  (1+ (lognot m)))))
2592                (when (<= temp b)
2593                  (setf a temp))))
2594             ((not (zerop (logandc2 (logand a m) c)))
2595              (let ((temp (logand (logior c m)
2596                                  (1+ (lognot m)))))
2597                (when (<= temp d)
2598                  (setf c temp)))))
2599           finally (return (logxor a c)))))
2600
2601 (defun logxor-derive-unsigned-high-bound (x y)
2602   (let ((a (numeric-type-low x))
2603         (b (numeric-type-high x))
2604         (c (numeric-type-low y))
2605         (d (numeric-type-high y)))
2606     (loop for m = (ash 1 (integer-length (logand b d))) then (ash m -1)
2607           until (zerop m) do
2608           (unless (zerop (logand b d m))
2609             (let ((temp (logior (- b m) (1- m))))
2610               (cond
2611                 ((>= temp a) (setf b temp))
2612                 (t (let ((temp (logior (- d m) (1- m))))
2613                      (when (>= temp c)
2614                        (setf d temp)))))))
2615           finally (return (logxor b d)))))
2616
2617 (defun logxor-derive-type-aux (x y &optional same-leaf)
2618   (when same-leaf
2619     (return-from logxor-derive-type-aux (specifier-type '(eql 0))))
2620   (multiple-value-bind (x-len x-pos x-neg) (integer-type-length x)
2621     (multiple-value-bind (y-len y-pos y-neg) (integer-type-length y)
2622       (cond
2623         ((and (not x-neg) (not y-neg))
2624          ;; Both are positive
2625          (if (and x-len y-len)
2626              (let ((low (logxor-derive-unsigned-low-bound x y))
2627                    (high (logxor-derive-unsigned-high-bound x y)))
2628                (specifier-type `(integer ,low ,high)))
2629              (specifier-type '(unsigned-byte* *))))
2630         ((and (not x-pos) (not y-pos))
2631          ;; Both are negative.  The result will be positive, and as long
2632          ;; as the longer.
2633          (specifier-type `(unsigned-byte* ,(if (and x-len y-len)
2634                                                (max x-len y-len)
2635                                                '*))))
2636         ((or (and (not x-pos) (not y-neg))
2637              (and (not y-pos) (not x-neg)))
2638          ;; Either X is negative and Y is positive or vice-versa. The
2639          ;; result will be negative.
2640          (specifier-type `(integer ,(if (and x-len y-len)
2641                                         (ash -1 (max x-len y-len))
2642                                         '*)
2643                            -1)))
2644         ;; We can't tell what the sign of the result is going to be.
2645         ;; All we know is that we don't create new bits.
2646         ((and x-len y-len)
2647          (specifier-type `(signed-byte ,(1+ (max x-len y-len)))))
2648         (t
2649          (specifier-type 'integer))))))
2650
2651 (macrolet ((deffrob (logfun)
2652              (let ((fun-aux (symbolicate logfun "-DERIVE-TYPE-AUX")))
2653              `(defoptimizer (,logfun derive-type) ((x y))
2654                 (two-arg-derive-type x y #',fun-aux #',logfun)))))
2655   (deffrob logand)
2656   (deffrob logior)
2657   (deffrob logxor))
2658
2659 (defoptimizer (logeqv derive-type) ((x y))
2660   (two-arg-derive-type x y (lambda (x y same-leaf)
2661                              (lognot-derive-type-aux
2662                               (logxor-derive-type-aux x y same-leaf)))
2663                        #'logeqv))
2664 (defoptimizer (lognand derive-type) ((x y))
2665   (two-arg-derive-type x y (lambda (x y same-leaf)
2666                              (lognot-derive-type-aux
2667                               (logand-derive-type-aux x y same-leaf)))
2668                        #'lognand))
2669 (defoptimizer (lognor derive-type) ((x y))
2670   (two-arg-derive-type x y (lambda (x y same-leaf)
2671                              (lognot-derive-type-aux
2672                               (logior-derive-type-aux x y same-leaf)))
2673                        #'lognor))
2674 (defoptimizer (logandc1 derive-type) ((x y))
2675   (two-arg-derive-type x y (lambda (x y same-leaf)
2676                              (if same-leaf
2677                                  (specifier-type '(eql 0))
2678                                  (logand-derive-type-aux
2679                                   (lognot-derive-type-aux x) y nil)))
2680                        #'logandc1))
2681 (defoptimizer (logandc2 derive-type) ((x y))
2682   (two-arg-derive-type x y (lambda (x y same-leaf)
2683                              (if same-leaf
2684                                  (specifier-type '(eql 0))
2685                                  (logand-derive-type-aux
2686                                   x (lognot-derive-type-aux y) nil)))
2687                        #'logandc2))
2688 (defoptimizer (logorc1 derive-type) ((x y))
2689   (two-arg-derive-type x y (lambda (x y same-leaf)
2690                              (if same-leaf
2691                                  (specifier-type '(eql -1))
2692                                  (logior-derive-type-aux
2693                                   (lognot-derive-type-aux x) y nil)))
2694                        #'logorc1))
2695 (defoptimizer (logorc2 derive-type) ((x y))
2696   (two-arg-derive-type x y (lambda (x y same-leaf)
2697                              (if same-leaf
2698                                  (specifier-type '(eql -1))
2699                                  (logior-derive-type-aux
2700                                   x (lognot-derive-type-aux y) nil)))
2701                        #'logorc2))
2702 \f
2703 ;;;; miscellaneous derive-type methods
2704
2705 (defoptimizer (integer-length derive-type) ((x))
2706   (let ((x-type (lvar-type x)))
2707     (when (numeric-type-p x-type)
2708       ;; If the X is of type (INTEGER LO HI), then the INTEGER-LENGTH
2709       ;; of X is (INTEGER (MIN lo hi) (MAX lo hi), basically.  Be
2710       ;; careful about LO or HI being NIL, though.  Also, if 0 is
2711       ;; contained in X, the lower bound is obviously 0.
2712       (flet ((null-or-min (a b)
2713                (and a b (min (integer-length a)
2714                              (integer-length b))))
2715              (null-or-max (a b)
2716                (and a b (max (integer-length a)
2717                              (integer-length b)))))
2718         (let* ((min (numeric-type-low x-type))
2719                (max (numeric-type-high x-type))
2720                (min-len (null-or-min min max))
2721                (max-len (null-or-max min max)))
2722           (when (ctypep 0 x-type)
2723             (setf min-len 0))
2724           (specifier-type `(integer ,(or min-len '*) ,(or max-len '*))))))))
2725
2726 (defoptimizer (isqrt derive-type) ((x))
2727   (let ((x-type (lvar-type x)))
2728     (when (numeric-type-p x-type)
2729       (let* ((lo (numeric-type-low x-type))
2730              (hi (numeric-type-high x-type))
2731              (lo-res (if lo (isqrt lo) '*))
2732              (hi-res (if hi (isqrt hi) '*)))
2733         (specifier-type `(integer ,lo-res ,hi-res))))))
2734
2735 (defoptimizer (char-code derive-type) ((char))
2736   (let ((type (type-intersection (lvar-type char) (specifier-type 'character))))
2737     (cond ((member-type-p type)
2738            (specifier-type
2739             `(member
2740               ,@(loop for member in (member-type-members type)
2741                       when (characterp member)
2742                       collect (char-code member)))))
2743           ((sb!kernel::character-set-type-p type)
2744            (specifier-type
2745             `(or
2746               ,@(loop for (low . high)
2747                       in (character-set-type-pairs type)
2748                       collect `(integer ,low ,high)))))
2749           ((csubtypep type (specifier-type 'base-char))
2750            (specifier-type
2751             `(mod ,base-char-code-limit)))
2752           (t
2753            (specifier-type
2754             `(mod ,char-code-limit))))))
2755
2756 (defoptimizer (code-char derive-type) ((code))
2757   (let ((type (lvar-type code)))
2758     ;; FIXME: unions of integral ranges?  It ought to be easier to do
2759     ;; this, given that CHARACTER-SET is basically an integral range
2760     ;; type.  -- CSR, 2004-10-04
2761     (when (numeric-type-p type)
2762       (let* ((lo (numeric-type-low type))
2763              (hi (numeric-type-high type))
2764              (type (specifier-type `(character-set ((,lo . ,hi))))))
2765         (cond
2766           ;; KLUDGE: when running on the host, we lose a slight amount
2767           ;; of precision so that we don't have to "unparse" types
2768           ;; that formally we can't, such as (CHARACTER-SET ((0
2769           ;; . 0))).  -- CSR, 2004-10-06
2770           #+sb-xc-host
2771           ((csubtypep type (specifier-type 'standard-char)) type)
2772           #+sb-xc-host
2773           ((csubtypep type (specifier-type 'base-char))
2774            (specifier-type 'base-char))
2775           #+sb-xc-host
2776           ((csubtypep type (specifier-type 'extended-char))
2777            (specifier-type 'extended-char))
2778           (t #+sb-xc-host (specifier-type 'character)
2779              #-sb-xc-host type))))))
2780
2781 (defoptimizer (values derive-type) ((&rest values))
2782   (make-values-type :required (mapcar #'lvar-type values)))
2783
2784 (defun signum-derive-type-aux (type)
2785   (if (eq (numeric-type-complexp type) :complex)
2786       (let* ((format (case (numeric-type-class type)
2787                           ((integer rational) 'single-float)
2788                           (t (numeric-type-format type))))
2789                 (bound-format (or format 'float)))
2790            (make-numeric-type :class 'float
2791                               :format format
2792                               :complexp :complex
2793                               :low (coerce -1 bound-format)
2794                               :high (coerce 1 bound-format)))
2795       (let* ((interval (numeric-type->interval type))
2796              (range-info (interval-range-info interval))
2797              (contains-0-p (interval-contains-p 0 interval))
2798              (class (numeric-type-class type))
2799              (format (numeric-type-format type))
2800              (one (coerce 1 (or format class 'real)))
2801              (zero (coerce 0 (or format class 'real)))
2802              (minus-one (coerce -1 (or format class 'real)))
2803              (plus (make-numeric-type :class class :format format
2804                                       :low one :high one))
2805              (minus (make-numeric-type :class class :format format
2806                                        :low minus-one :high minus-one))
2807              ;; KLUDGE: here we have a fairly horrible hack to deal
2808              ;; with the schizophrenia in the type derivation engine.
2809              ;; The problem is that the type derivers reinterpret
2810              ;; numeric types as being exact; so (DOUBLE-FLOAT 0d0
2811              ;; 0d0) within the derivation mechanism doesn't include
2812              ;; -0d0.  Ugh.  So force it in here, instead.
2813              (zero (make-numeric-type :class class :format format
2814                                       :low (- zero) :high zero)))
2815         (case range-info
2816           (+ (if contains-0-p (type-union plus zero) plus))
2817           (- (if contains-0-p (type-union minus zero) minus))
2818           (t (type-union minus zero plus))))))
2819
2820 (defoptimizer (signum derive-type) ((num))
2821   (one-arg-derive-type num #'signum-derive-type-aux nil))
2822 \f
2823 ;;;; byte operations
2824 ;;;;
2825 ;;;; We try to turn byte operations into simple logical operations.
2826 ;;;; First, we convert byte specifiers into separate size and position
2827 ;;;; arguments passed to internal %FOO functions. We then attempt to
2828 ;;;; transform the %FOO functions into boolean operations when the
2829 ;;;; size and position are constant and the operands are fixnums.
2830
2831 (macrolet (;; Evaluate body with SIZE-VAR and POS-VAR bound to
2832            ;; expressions that evaluate to the SIZE and POSITION of
2833            ;; the byte-specifier form SPEC. We may wrap a let around
2834            ;; the result of the body to bind some variables.
2835            ;;
2836            ;; If the spec is a BYTE form, then bind the vars to the
2837            ;; subforms. otherwise, evaluate SPEC and use the BYTE-SIZE
2838            ;; and BYTE-POSITION. The goal of this transformation is to
2839            ;; avoid consing up byte specifiers and then immediately
2840            ;; throwing them away.
2841            (with-byte-specifier ((size-var pos-var spec) &body body)
2842              (once-only ((spec `(macroexpand ,spec))
2843                          (temp '(gensym)))
2844                         `(if (and (consp ,spec)
2845                                   (eq (car ,spec) 'byte)
2846                                   (= (length ,spec) 3))
2847                         (let ((,size-var (second ,spec))
2848                               (,pos-var (third ,spec)))
2849                           ,@body)
2850                         (let ((,size-var `(byte-size ,,temp))
2851                               (,pos-var `(byte-position ,,temp)))
2852                           `(let ((,,temp ,,spec))
2853                              ,,@body))))))
2854
2855   (define-source-transform ldb (spec int)
2856     (with-byte-specifier (size pos spec)
2857       `(%ldb ,size ,pos ,int)))
2858
2859   (define-source-transform dpb (newbyte spec int)
2860     (with-byte-specifier (size pos spec)
2861       `(%dpb ,newbyte ,size ,pos ,int)))
2862
2863   (define-source-transform mask-field (spec int)
2864     (with-byte-specifier (size pos spec)
2865       `(%mask-field ,size ,pos ,int)))
2866
2867   (define-source-transform deposit-field (newbyte spec int)
2868     (with-byte-specifier (size pos spec)
2869       `(%deposit-field ,newbyte ,size ,pos ,int))))
2870
2871 (defoptimizer (%ldb derive-type) ((size posn num))
2872   (let ((size (lvar-type size)))
2873     (if (and (numeric-type-p size)
2874              (csubtypep size (specifier-type 'integer)))
2875         (let ((size-high (numeric-type-high size)))
2876           (if (and size-high (<= size-high sb!vm:n-word-bits))
2877               (specifier-type `(unsigned-byte* ,size-high))
2878               (specifier-type 'unsigned-byte)))
2879         *universal-type*)))
2880
2881 (defoptimizer (%mask-field derive-type) ((size posn num))
2882   (let ((size (lvar-type size))
2883         (posn (lvar-type posn)))
2884     (if (and (numeric-type-p size)
2885              (csubtypep size (specifier-type 'integer))
2886              (numeric-type-p posn)
2887              (csubtypep posn (specifier-type 'integer)))
2888         (let ((size-high (numeric-type-high size))
2889               (posn-high (numeric-type-high posn)))
2890           (if (and size-high posn-high
2891                    (<= (+ size-high posn-high) sb!vm:n-word-bits))
2892               (specifier-type `(unsigned-byte* ,(+ size-high posn-high)))
2893               (specifier-type 'unsigned-byte)))
2894         *universal-type*)))
2895
2896 (defun %deposit-field-derive-type-aux (size posn int)
2897   (let ((size (lvar-type size))
2898         (posn (lvar-type posn))
2899         (int (lvar-type int)))
2900     (when (and (numeric-type-p size)
2901                (numeric-type-p posn)
2902                (numeric-type-p int))
2903       (let ((size-high (numeric-type-high size))
2904             (posn-high (numeric-type-high posn))
2905             (high (numeric-type-high int))
2906             (low (numeric-type-low int)))
2907         (when (and size-high posn-high high low
2908                    ;; KLUDGE: we need this cutoff here, otherwise we
2909                    ;; will merrily derive the type of %DPB as
2910                    ;; (UNSIGNED-BYTE 1073741822), and then attempt to
2911                    ;; canonicalize this type to (INTEGER 0 (1- (ASH 1
2912                    ;; 1073741822))), with hilarious consequences.  We
2913                    ;; cutoff at 4*SB!VM:N-WORD-BITS to allow inference
2914                    ;; over a reasonable amount of shifting, even on
2915                    ;; the alpha/32 port, where N-WORD-BITS is 32 but
2916                    ;; machine integers are 64-bits.  -- CSR,
2917                    ;; 2003-09-12
2918                    (<= (+ size-high posn-high) (* 4 sb!vm:n-word-bits)))
2919           (let ((raw-bit-count (max (integer-length high)
2920                                     (integer-length low)
2921                                     (+ size-high posn-high))))
2922             (specifier-type
2923              (if (minusp low)
2924                  `(signed-byte ,(1+ raw-bit-count))
2925                  `(unsigned-byte* ,raw-bit-count)))))))))
2926
2927 (defoptimizer (%dpb derive-type) ((newbyte size posn int))
2928   (%deposit-field-derive-type-aux size posn int))
2929
2930 (defoptimizer (%deposit-field derive-type) ((newbyte size posn int))
2931   (%deposit-field-derive-type-aux size posn int))
2932
2933 (deftransform %ldb ((size posn int)
2934                     (fixnum fixnum integer)
2935                     (unsigned-byte #.sb!vm:n-word-bits))
2936   "convert to inline logical operations"
2937   `(logand (ash int (- posn))
2938            (ash ,(1- (ash 1 sb!vm:n-word-bits))
2939                 (- size ,sb!vm:n-word-bits))))
2940
2941 (deftransform %mask-field ((size posn int)
2942                            (fixnum fixnum integer)
2943                            (unsigned-byte #.sb!vm:n-word-bits))
2944   "convert to inline logical operations"
2945   `(logand int
2946            (ash (ash ,(1- (ash 1 sb!vm:n-word-bits))
2947                      (- size ,sb!vm:n-word-bits))
2948                 posn)))
2949
2950 ;;; Note: for %DPB and %DEPOSIT-FIELD, we can't use
2951 ;;;   (OR (SIGNED-BYTE N) (UNSIGNED-BYTE N))
2952 ;;; as the result type, as that would allow result types that cover
2953 ;;; the range -2^(n-1) .. 1-2^n, instead of allowing result types of
2954 ;;; (UNSIGNED-BYTE N) and result types of (SIGNED-BYTE N).
2955
2956 (deftransform %dpb ((new size posn int)
2957                     *
2958                     (unsigned-byte #.sb!vm:n-word-bits))
2959   "convert to inline logical operations"
2960   `(let ((mask (ldb (byte size 0) -1)))
2961      (logior (ash (logand new mask) posn)
2962              (logand int (lognot (ash mask posn))))))
2963
2964 (deftransform %dpb ((new size posn int)
2965                     *
2966                     (signed-byte #.sb!vm:n-word-bits))
2967   "convert to inline logical operations"
2968   `(let ((mask (ldb (byte size 0) -1)))
2969      (logior (ash (logand new mask) posn)
2970              (logand int (lognot (ash mask posn))))))
2971
2972 (deftransform %deposit-field ((new size posn int)
2973                               *
2974                               (unsigned-byte #.sb!vm:n-word-bits))
2975   "convert to inline logical operations"
2976   `(let ((mask (ash (ldb (byte size 0) -1) posn)))
2977      (logior (logand new mask)
2978              (logand int (lognot mask)))))
2979
2980 (deftransform %deposit-field ((new size posn int)
2981                               *
2982                               (signed-byte #.sb!vm:n-word-bits))
2983   "convert to inline logical operations"
2984   `(let ((mask (ash (ldb (byte size 0) -1) posn)))
2985      (logior (logand new mask)
2986              (logand int (lognot mask)))))
2987
2988 (defoptimizer (mask-signed-field derive-type) ((size x))
2989   (let ((size (lvar-type size)))
2990     (if (numeric-type-p size)
2991         (let ((size-high (numeric-type-high size)))
2992           (if (and size-high (<= 1 size-high sb!vm:n-word-bits))
2993               (specifier-type `(signed-byte ,size-high))
2994               *universal-type*))
2995         *universal-type*)))
2996
2997 \f
2998 ;;; Modular functions
2999
3000 ;;; (ldb (byte s 0) (foo                 x  y ...)) =
3001 ;;; (ldb (byte s 0) (foo (ldb (byte s 0) x) y ...))
3002 ;;;
3003 ;;; and similar for other arguments.
3004
3005 (defun make-modular-fun-type-deriver (prototype kind width signedp)
3006   (declare (ignore kind))
3007   #!-sb-fluid
3008   (binding* ((info (info :function :info prototype) :exit-if-null)
3009              (fun (fun-info-derive-type info) :exit-if-null)
3010              (mask-type (specifier-type
3011                          (ecase signedp
3012                              ((nil) (let ((mask (1- (ash 1 width))))
3013                                       `(integer ,mask ,mask)))
3014                              ((t) `(signed-byte ,width))))))
3015     (lambda (call)
3016       (let ((res (funcall fun call)))
3017         (when res
3018           (if (eq signedp nil)
3019               (logand-derive-type-aux res mask-type))))))
3020   #!+sb-fluid
3021   (lambda (call)
3022     (binding* ((info (info :function :info prototype) :exit-if-null)
3023                (fun (fun-info-derive-type info) :exit-if-null)
3024                (res (funcall fun call) :exit-if-null)
3025                (mask-type (specifier-type
3026                            (ecase signedp
3027                              ((nil) (let ((mask (1- (ash 1 width))))
3028                                       `(integer ,mask ,mask)))
3029                              ((t) `(signed-byte ,width))))))
3030       (if (eq signedp nil)
3031           (logand-derive-type-aux res mask-type)))))
3032
3033 ;;; Try to recursively cut all uses of LVAR to WIDTH bits.
3034 ;;;
3035 ;;; For good functions, we just recursively cut arguments; their
3036 ;;; "goodness" means that the result will not increase (in the
3037 ;;; (unsigned-byte +infinity) sense). An ordinary modular function is
3038 ;;; replaced with the version, cutting its result to WIDTH or more
3039 ;;; bits. For most functions (e.g. for +) we cut all arguments; for
3040 ;;; others (e.g. for ASH) we have "optimizers", cutting only necessary
3041 ;;; arguments (maybe to a different width) and returning the name of a
3042 ;;; modular version, if it exists, or NIL. If we have changed
3043 ;;; anything, we need to flush old derived types, because they have
3044 ;;; nothing in common with the new code.
3045 (defun cut-to-width (lvar kind width signedp)
3046   (declare (type lvar lvar) (type (integer 0) width))
3047   (let ((type (specifier-type (if (zerop width)
3048                                   '(eql 0)
3049                                   `(,(ecase signedp
3050                                        ((nil) 'unsigned-byte)
3051                                        ((t) 'signed-byte))
3052                                      ,width)))))
3053     (labels ((reoptimize-node (node name)
3054                (setf (node-derived-type node)
3055                      (fun-type-returns
3056                       (info :function :type name)))
3057                (setf (lvar-%derived-type (node-lvar node)) nil)
3058                (setf (node-reoptimize node) t)
3059                (setf (block-reoptimize (node-block node)) t)
3060                (reoptimize-component (node-component node) :maybe))
3061              (cut-node (node &aux did-something)
3062                (when (and (not (block-delete-p (node-block node)))
3063                           (ref-p node)
3064                           (constant-p (ref-leaf node)))
3065                  (let* ((constant-value (constant-value (ref-leaf node)))
3066                         (new-value (if signedp
3067                                        (mask-signed-field width constant-value)
3068                                        (ldb (byte width 0) constant-value))))
3069                    (unless (= constant-value new-value)
3070                      (change-ref-leaf node (make-constant new-value))
3071                      (setf (lvar-%derived-type (node-lvar node)) (make-values-type :required (list (ctype-of new-value))))
3072                      (setf (block-reoptimize (node-block node)) t)
3073                      (reoptimize-component (node-component node) :maybe)
3074                      (return-from cut-node t))))
3075                (when (and (not (block-delete-p (node-block node)))
3076                           (combination-p node)
3077                           (eq (basic-combination-kind node) :known))
3078                  (let* ((fun-ref (lvar-use (combination-fun node)))
3079                         (fun-name (leaf-source-name (ref-leaf fun-ref)))
3080                         (modular-fun (find-modular-version fun-name kind signedp width)))
3081                    (when (and modular-fun
3082                               (not (and (eq fun-name 'logand)
3083                                         (csubtypep
3084                                          (single-value-type (node-derived-type node))
3085                                          type))))
3086                      (binding* ((name (etypecase modular-fun
3087                                         ((eql :good) fun-name)
3088                                         (modular-fun-info
3089                                          (modular-fun-info-name modular-fun))
3090                                         (function
3091                                          (funcall modular-fun node width)))
3092                                       :exit-if-null))
3093                                (unless (eql modular-fun :good)
3094                                  (setq did-something t)
3095                                  (change-ref-leaf
3096                                   fun-ref
3097                                   (find-free-fun name "in a strange place"))
3098                                  (setf (combination-kind node) :full))
3099                                (unless (functionp modular-fun)
3100                                  (dolist (arg (basic-combination-args node))
3101                                    (when (cut-lvar arg)
3102                                      (setq did-something t))))
3103                                (when did-something
3104                                  (reoptimize-node node name))
3105                                did-something)))))
3106              (cut-lvar (lvar &aux did-something)
3107                (do-uses (node lvar)
3108                  (when (cut-node node)
3109                    (setq did-something t)))
3110                did-something))
3111       (cut-lvar lvar))))
3112
3113 (defun best-modular-version (width signedp)
3114   ;; 1. exact width-matched :untagged
3115   ;; 2. >/>= width-matched :tagged
3116   ;; 3. >/>= width-matched :untagged
3117   (let* ((uuwidths (modular-class-widths *untagged-unsigned-modular-class*))
3118          (uswidths (modular-class-widths *untagged-signed-modular-class*))
3119          (uwidths (merge 'list uuwidths uswidths #'< :key #'car))
3120          (twidths (modular-class-widths *tagged-modular-class*)))
3121     (let ((exact (find (cons width signedp) uwidths :test #'equal)))
3122       (when exact
3123         (return-from best-modular-version (values width :untagged signedp))))
3124     (flet ((inexact-match (w)
3125              (cond
3126                ((eq signedp (cdr w)) (<= width (car w)))
3127                ((eq signedp nil) (< width (car w))))))
3128       (let ((tgt (find-if #'inexact-match twidths)))
3129         (when tgt
3130           (return-from best-modular-version
3131             (values (car tgt) :tagged (cdr tgt)))))
3132       (let ((ugt (find-if #'inexact-match uwidths)))
3133         (when ugt
3134           (return-from best-modular-version
3135             (values (car ugt) :untagged (cdr ugt))))))))
3136
3137 (defoptimizer (logand optimizer) ((x y) node)
3138   (let ((result-type (single-value-type (node-derived-type node))))
3139     (when (numeric-type-p result-type)
3140       (let ((low (numeric-type-low result-type))
3141             (high (numeric-type-high result-type)))
3142         (when (and (numberp low)
3143                    (numberp high)
3144                    (>= low 0))
3145           (let ((width (integer-length high)))
3146             (multiple-value-bind (w kind signedp)
3147                 (best-modular-version width nil)
3148               (when w
3149                 ;; FIXME: This should be (CUT-TO-WIDTH NODE KIND WIDTH SIGNEDP).
3150                 ;;
3151                 ;; FIXME: I think the FIXME (which is from APD) above
3152                 ;; implies that CUT-TO-WIDTH should do /everything/
3153                 ;; that's required, including reoptimizing things
3154                 ;; itself that it knows are necessary.  At the moment,
3155                 ;; CUT-TO-WIDTH sets up some new calls with
3156                 ;; combination-type :FULL, which later get noticed as
3157                 ;; known functions and properly converted.
3158                 ;;
3159                 ;; We cut to W not WIDTH if SIGNEDP is true, because
3160                 ;; signed constant replacement needs to know which bit
3161                 ;; in the field is the signed bit.
3162                 (let ((xact (cut-to-width x kind (if signedp w width) signedp))
3163                       (yact (cut-to-width y kind (if signedp w width) signedp)))
3164                   (declare (ignore xact yact))
3165                   nil) ; After fixing above, replace with T, meaning
3166                        ; "don't reoptimize this (LOGAND) node any more".
3167                 ))))))))
3168
3169 (defoptimizer (mask-signed-field optimizer) ((width x) node)
3170   (let ((result-type (single-value-type (node-derived-type node))))
3171     (when (numeric-type-p result-type)
3172       (let ((low (numeric-type-low result-type))
3173             (high (numeric-type-high result-type)))
3174         (when (and (numberp low) (numberp high))
3175           (let ((width (max (integer-length high) (integer-length low))))
3176             (multiple-value-bind (w kind)
3177                 (best-modular-version width t)
3178               (when w
3179                 ;; FIXME: This should be (CUT-TO-WIDTH NODE KIND W T).
3180                 ;; [ see comment above in LOGAND optimizer ]
3181                 (cut-to-width x kind w t)
3182                 nil ; After fixing above, replace with T.
3183                 ))))))))
3184 \f
3185 ;;; miscellanous numeric transforms
3186
3187 ;;; If a constant appears as the first arg, swap the args.
3188 (deftransform commutative-arg-swap ((x y) * * :defun-only t :node node)
3189   (if (and (constant-lvar-p x)
3190            (not (constant-lvar-p y)))
3191       `(,(lvar-fun-name (basic-combination-fun node))
3192         y
3193         ,(lvar-value x))
3194       (give-up-ir1-transform)))
3195
3196 (dolist (x '(= char= + * logior logand logxor))
3197   (%deftransform x '(function * *) #'commutative-arg-swap
3198                  "place constant arg last"))
3199
3200 ;;; Handle the case of a constant BOOLE-CODE.
3201 (deftransform boole ((op x y) * *)
3202   "convert to inline logical operations"
3203   (unless (constant-lvar-p op)
3204     (give-up-ir1-transform "BOOLE code is not a constant."))
3205   (let ((control (lvar-value op)))
3206     (case control
3207       (#.sb!xc:boole-clr 0)
3208       (#.sb!xc:boole-set -1)
3209       (#.sb!xc:boole-1 'x)
3210       (#.sb!xc:boole-2 'y)
3211       (#.sb!xc:boole-c1 '(lognot x))
3212       (#.sb!xc:boole-c2 '(lognot y))
3213       (#.sb!xc:boole-and '(logand x y))
3214       (#.sb!xc:boole-ior '(logior x y))
3215       (#.sb!xc:boole-xor '(logxor x y))
3216       (#.sb!xc:boole-eqv '(logeqv x y))
3217       (#.sb!xc:boole-nand '(lognand x y))
3218       (#.sb!xc:boole-nor '(lognor x y))
3219       (#.sb!xc:boole-andc1 '(logandc1 x y))
3220       (#.sb!xc:boole-andc2 '(logandc2 x y))
3221       (#.sb!xc:boole-orc1 '(logorc1 x y))
3222       (#.sb!xc:boole-orc2 '(logorc2 x y))
3223       (t
3224        (abort-ir1-transform "~S is an illegal control arg to BOOLE."
3225                             control)))))
3226 \f
3227 ;;;; converting special case multiply/divide to shifts
3228
3229 ;;; If arg is a constant power of two, turn * into a shift.
3230 (deftransform * ((x y) (integer integer) *)
3231   "convert x*2^k to shift"
3232   (unless (constant-lvar-p y)
3233     (give-up-ir1-transform))
3234   (let* ((y (lvar-value y))
3235          (y-abs (abs y))
3236          (len (1- (integer-length y-abs))))
3237     (unless (and (> y-abs 0) (= y-abs (ash 1 len)))
3238       (give-up-ir1-transform))
3239     (if (minusp y)
3240         `(- (ash x ,len))
3241         `(ash x ,len))))
3242
3243 ;;; These must come before the ones below, so that they are tried
3244 ;;; first. Since %FLOOR and %CEILING are inlined, this allows
3245 ;;; the general case to be handled by TRUNCATE transforms.
3246 (deftransform floor ((x y))
3247   `(%floor x y))
3248
3249 (deftransform ceiling ((x y))
3250   `(%ceiling x y))
3251
3252 ;;; If arg is a constant power of two, turn FLOOR into a shift and
3253 ;;; mask. If CEILING, add in (1- (ABS Y)), do FLOOR and correct a
3254 ;;; remainder.
3255 (flet ((frob (y ceil-p)
3256          (unless (constant-lvar-p y)
3257            (give-up-ir1-transform))
3258          (let* ((y (lvar-value y))
3259                 (y-abs (abs y))
3260                 (len (1- (integer-length y-abs))))
3261            (unless (and (> y-abs 0) (= y-abs (ash 1 len)))
3262              (give-up-ir1-transform))
3263            (let ((shift (- len))
3264                  (mask (1- y-abs))
3265                  (delta (if ceil-p (* (signum y) (1- y-abs)) 0)))
3266              `(let ((x (+ x ,delta)))
3267                 ,(if (minusp y)
3268                      `(values (ash (- x) ,shift)
3269                               (- (- (logand (- x) ,mask)) ,delta))
3270                      `(values (ash x ,shift)
3271                               (- (logand x ,mask) ,delta))))))))
3272   (deftransform floor ((x y) (integer integer) *)
3273     "convert division by 2^k to shift"
3274     (frob y nil))
3275   (deftransform ceiling ((x y) (integer integer) *)
3276     "convert division by 2^k to shift"
3277     (frob y t)))
3278
3279 ;;; Do the same for MOD.
3280 (deftransform mod ((x y) (integer integer) *)
3281   "convert remainder mod 2^k to LOGAND"
3282   (unless (constant-lvar-p y)
3283     (give-up-ir1-transform))
3284   (let* ((y (lvar-value y))
3285          (y-abs (abs y))
3286          (len (1- (integer-length y-abs))))
3287     (unless (and (> y-abs 0) (= y-abs (ash 1 len)))
3288       (give-up-ir1-transform))
3289     (let ((mask (1- y-abs)))
3290       (if (minusp y)
3291           `(- (logand (- x) ,mask))
3292           `(logand x ,mask)))))
3293
3294 ;;; If arg is a constant power of two, turn TRUNCATE into a shift and mask.
3295 (deftransform truncate ((x y) (integer integer))
3296   "convert division by 2^k to shift"
3297   (unless (constant-lvar-p y)
3298     (give-up-ir1-transform))
3299   (let* ((y (lvar-value y))
3300          (y-abs (abs y))
3301          (len (1- (integer-length y-abs))))
3302     (unless (and (> y-abs 0) (= y-abs (ash 1 len)))
3303       (give-up-ir1-transform))
3304     (let* ((shift (- len))
3305            (mask (1- y-abs)))
3306       `(if (minusp x)
3307            (values ,(if (minusp y)
3308                         `(ash (- x) ,shift)
3309                         `(- (ash (- x) ,shift)))
3310                    (- (logand (- x) ,mask)))
3311            (values ,(if (minusp y)
3312                         `(ash (- ,mask x) ,shift)
3313                         `(ash x ,shift))
3314                    (logand x ,mask))))))
3315
3316 ;;; And the same for REM.
3317 (deftransform rem ((x y) (integer integer) *)
3318   "convert remainder mod 2^k to LOGAND"
3319   (unless (constant-lvar-p y)
3320     (give-up-ir1-transform))
3321   (let* ((y (lvar-value y))
3322          (y-abs (abs y))
3323          (len (1- (integer-length y-abs))))
3324     (unless (and (> y-abs 0) (= y-abs (ash 1 len)))
3325       (give-up-ir1-transform))
3326     (let ((mask (1- y-abs)))
3327       `(if (minusp x)
3328            (- (logand (- x) ,mask))
3329            (logand x ,mask)))))
3330
3331 ;;; Return an expression to calculate the integer quotient of X and
3332 ;;; constant Y, using multiplication, shift and add/sub instead of
3333 ;;; division. Both arguments must be unsigned, fit in a machine word and
3334 ;;; Y must neither be zero nor a power of two. The quotient is rounded
3335 ;;; towards zero.
3336 ;;; The algorithm is taken from the paper "Division by Invariant
3337 ;;; Integers using Multiplication", 1994 by Torbj\"{o}rn Granlund and
3338 ;;; Peter L. Montgomery, Figures 4.2 and 6.2, modified to exclude the
3339 ;;; case of division by powers of two.
3340 ;;; The algorithm includes an adaptive precision argument.  Use it, since
3341 ;;; we often have sub-word value ranges.  Careful, in this case, we need
3342 ;;; p s.t 2^p > n, not the ceiling of the binary log.
3343 ;;; Also, for some reason, the paper prefers shifting to masking.  Mask
3344 ;;; instead.  Masking is equivalent to shifting right, then left again;
3345 ;;; all the intermediate values are still words, so we just have to shift
3346 ;;; right a bit more to compensate, at the end.
3347 ;;;
3348 ;;; The following two examples show an average case and the worst case
3349 ;;; with respect to the complexity of the generated expression, under
3350 ;;; a word size of 64 bits:
3351 ;;;
3352 ;;; (UNSIGNED-DIV-TRANSFORMER 10 MOST-POSITIVE-WORD) ->
3353 ;;; (ASH (%MULTIPLY (LOGANDC2 X 0) 14757395258967641293) -3)
3354 ;;;
3355 ;;; (UNSIGNED-DIV-TRANSFORMER 7 MOST-POSITIVE-WORD) ->
3356 ;;; (LET* ((NUM X)
3357 ;;;        (T1 (%MULTIPLY NUM 2635249153387078803)))
3358 ;;;   (ASH (LDB (BYTE 64 0)
3359 ;;;             (+ T1 (ASH (LDB (BYTE 64 0)
3360 ;;;                             (- NUM T1))
3361 ;;;                        -1)))
3362 ;;;        -2))
3363 ;;;
3364 (defun gen-unsigned-div-by-constant-expr (y max-x)
3365   (declare (type (integer 3 #.most-positive-word) y)
3366            (type word max-x))
3367   (aver (not (zerop (logand y (1- y)))))
3368   (labels ((ld (x)
3369              ;; the floor of the binary logarithm of (positive) X
3370              (integer-length (1- x)))
3371            (choose-multiplier (y precision)
3372              (do* ((l (ld y))
3373                    (shift l (1- shift))
3374                    (expt-2-n+l (expt 2 (+ sb!vm:n-word-bits l)))
3375                    (m-low (truncate expt-2-n+l y) (ash m-low -1))
3376                    (m-high (truncate (+ expt-2-n+l
3377                                         (ash expt-2-n+l (- precision)))
3378                                      y)
3379                            (ash m-high -1)))
3380                   ((not (and (< (ash m-low -1) (ash m-high -1))
3381                              (> shift 0)))
3382                    (values m-high shift)))))
3383     (let ((n (expt 2 sb!vm:n-word-bits))
3384           (precision (integer-length max-x))
3385           (shift1 0))
3386       (multiple-value-bind (m shift2)
3387           (choose-multiplier y precision)
3388         (when (and (>= m n) (evenp y))
3389           (setq shift1 (ld (logand y (- y))))
3390           (multiple-value-setq (m shift2)
3391             (choose-multiplier (/ y (ash 1 shift1))
3392                                (- precision shift1))))
3393         (cond ((>= m n)
3394                (flet ((word (x)
3395                         `(truly-the word ,x)))
3396                  `(let* ((num x)
3397                          (t1 (%multiply-high num ,(- m n))))
3398                     (ash ,(word `(+ t1 (ash ,(word `(- num t1))
3399                                             -1)))
3400                          ,(- 1 shift2)))))
3401               ((and (zerop shift1) (zerop shift2))
3402                (let ((max (truncate max-x y)))
3403                  ;; Explicit TRULY-THE needed to get the FIXNUM=>FIXNUM
3404                  ;; VOP.
3405                  `(truly-the (integer 0 ,max)
3406                              (%multiply-high x ,m))))
3407               (t
3408                `(ash (%multiply-high (logandc2 x ,(1- (ash 1 shift1))) ,m)
3409                      ,(- (+ shift1 shift2)))))))))
3410
3411 ;;; If the divisor is constant and both args are positive and fit in a
3412 ;;; machine word, replace the division by a multiplication and possibly
3413 ;;; some shifts and an addition. Calculate the remainder by a second
3414 ;;; multiplication and a subtraction. Dead code elimination will
3415 ;;; suppress the latter part if only the quotient is needed. If the type
3416 ;;; of the dividend allows to derive that the quotient will always have
3417 ;;; the same value, emit much simpler code to handle that. (This case
3418 ;;; may be rare but it's easy to detect and the compiler doesn't find
3419 ;;; this optimization on its own.)
3420 (deftransform truncate ((x y) (word (constant-arg word))
3421                         *
3422                         :policy (and (> speed compilation-speed)
3423                                      (> speed space)))
3424   "convert integer division to multiplication"
3425   (let* ((y      (lvar-value y))
3426          (x-type (lvar-type x))
3427          (max-x  (or (and (numeric-type-p x-type)
3428                           (numeric-type-high x-type))
3429                      most-positive-word)))
3430     ;; Division by zero, one or powers of two is handled elsewhere.
3431     (when (zerop (logand y (1- y)))
3432       (give-up-ir1-transform))
3433     `(let* ((quot ,(gen-unsigned-div-by-constant-expr y max-x))
3434             (rem (ldb (byte #.sb!vm:n-word-bits 0)
3435                       (- x (* quot ,y)))))
3436        (values quot rem))))
3437 \f
3438 ;;;; arithmetic and logical identity operation elimination
3439
3440 ;;; Flush calls to various arith functions that convert to the
3441 ;;; identity function or a constant.
3442 (macrolet ((def (name identity result)
3443              `(deftransform ,name ((x y) (* (constant-arg (member ,identity))) *)
3444                 "fold identity operations"
3445                 ',result)))
3446   (def ash 0 x)
3447   (def logand -1 x)
3448   (def logand 0 0)
3449   (def logior 0 x)
3450   (def logior -1 -1)
3451   (def logxor -1 (lognot x))
3452   (def logxor 0 x))
3453
3454 (deftransform logand ((x y) (* (constant-arg t)) *)
3455   "fold identity operation"
3456   (let ((y (lvar-value y)))
3457     (unless (and (plusp y)
3458                  (= y (1- (ash 1 (integer-length y)))))
3459       (give-up-ir1-transform))
3460     (unless (csubtypep (lvar-type x)
3461                        (specifier-type `(integer 0 ,y)))
3462       (give-up-ir1-transform))
3463     'x))
3464
3465 (deftransform mask-signed-field ((size x) ((constant-arg t) *) *)
3466   "fold identity operation"
3467   (let ((size (lvar-value size)))
3468     (unless (csubtypep (lvar-type x) (specifier-type `(signed-byte ,size)))
3469       (give-up-ir1-transform))
3470     'x))
3471
3472 ;;; These are restricted to rationals, because (- 0 0.0) is 0.0, not -0.0, and
3473 ;;; (* 0 -4.0) is -0.0.
3474 (deftransform - ((x y) ((constant-arg (member 0)) rational) *)
3475   "convert (- 0 x) to negate"
3476   '(%negate y))
3477 (deftransform * ((x y) (rational (constant-arg (member 0))) *)
3478   "convert (* x 0) to 0"
3479   0)
3480
3481 ;;; Return T if in an arithmetic op including lvars X and Y, the
3482 ;;; result type is not affected by the type of X. That is, Y is at
3483 ;;; least as contagious as X.
3484 #+nil
3485 (defun not-more-contagious (x y)
3486   (declare (type continuation x y))
3487   (let ((x (lvar-type x))
3488         (y (lvar-type y)))
3489     (values (type= (numeric-contagion x y)
3490                    (numeric-contagion y y)))))
3491 ;;; Patched version by Raymond Toy. dtc: Should be safer although it
3492 ;;; XXX needs more work as valid transforms are missed; some cases are
3493 ;;; specific to particular transform functions so the use of this
3494 ;;; function may need a re-think.
3495 (defun not-more-contagious (x y)
3496   (declare (type lvar x y))
3497   (flet ((simple-numeric-type (num)
3498            (and (numeric-type-p num)
3499                 ;; Return non-NIL if NUM is integer, rational, or a float
3500                 ;; of some type (but not FLOAT)
3501                 (case (numeric-type-class num)
3502                   ((integer rational)
3503                    t)
3504                   (float
3505                    (numeric-type-format num))
3506                   (t
3507                    nil)))))
3508     (let ((x (lvar-type x))
3509           (y (lvar-type y)))
3510       (if (and (simple-numeric-type x)
3511                (simple-numeric-type y))
3512           (values (type= (numeric-contagion x y)
3513                          (numeric-contagion y y)))))))
3514
3515 (def!type exact-number ()
3516   '(or rational (complex rational)))
3517
3518 ;;; Fold (+ x 0).
3519 ;;;
3520 ;;; Only safely applicable for exact numbers. For floating-point
3521 ;;; x, one would have to first show that neither x or y are signed
3522 ;;; 0s, and that x isn't an SNaN.
3523 (deftransform + ((x y) (exact-number (constant-arg (eql 0))) *)
3524   "fold zero arg"
3525   'x)
3526
3527 ;;; Fold (- x 0).
3528 (deftransform - ((x y) (exact-number (constant-arg (eql 0))) *)
3529   "fold zero arg"
3530   'x)
3531
3532 ;;; Fold (OP x +/-1)
3533 ;;;
3534 ;;; %NEGATE might not always signal correctly.
3535 (macrolet
3536     ((def (name result minus-result)
3537          `(deftransform ,name ((x y)
3538                                (exact-number (constant-arg (member 1 -1))))
3539             "fold identity operations"
3540             (if (minusp (lvar-value y)) ',minus-result ',result))))
3541   (def * x (%negate x))
3542   (def / x (%negate x))
3543   (def expt x (/ 1 x)))
3544
3545 ;;; Fold (expt x n) into multiplications for small integral values of
3546 ;;; N; convert (expt x 1/2) to sqrt.
3547 (deftransform expt ((x y) (t (constant-arg real)) *)
3548   "recode as multiplication or sqrt"
3549   (let ((val (lvar-value y)))
3550     ;; If Y would cause the result to be promoted to the same type as
3551     ;; Y, we give up. If not, then the result will be the same type
3552     ;; as X, so we can replace the exponentiation with simple
3553     ;; multiplication and division for small integral powers.
3554     (unless (not-more-contagious y x)
3555       (give-up-ir1-transform))
3556     (cond ((zerop val)
3557            (let ((x-type (lvar-type x)))
3558              (cond ((csubtypep x-type (specifier-type '(or rational
3559                                                         (complex rational))))
3560                     '1)
3561                    ((csubtypep x-type (specifier-type 'real))
3562                     `(if (rationalp x)
3563                          1
3564                          (float 1 x)))
3565                    ((csubtypep x-type (specifier-type 'complex))
3566                     ;; both parts are float
3567                     `(1+ (* x ,val)))
3568                    (t (give-up-ir1-transform)))))
3569           ((= val 2) '(* x x))
3570           ((= val -2) '(/ (* x x)))
3571           ((= val 3) '(* x x x))
3572           ((= val -3) '(/ (* x x x)))
3573           ((= val 1/2) '(sqrt x))
3574           ((= val -1/2) '(/ (sqrt x)))
3575           (t (give-up-ir1-transform)))))
3576
3577 (deftransform expt ((x y) ((constant-arg (member -1 -1.0 -1.0d0)) integer) *)
3578   "recode as an ODDP check"
3579   (let ((val (lvar-value x)))
3580     (if (eql -1 val)
3581         '(- 1 (* 2 (logand 1 y)))
3582         `(if (oddp y)
3583              ,val
3584              ,(abs val)))))
3585
3586 ;;; KLUDGE: Shouldn't (/ 0.0 0.0), etc. cause exceptions in these
3587 ;;; transformations?
3588 ;;; Perhaps we should have to prove that the denominator is nonzero before
3589 ;;; doing them?  -- WHN 19990917
3590 (macrolet ((def (name)
3591              `(deftransform ,name ((x y) ((constant-arg (integer 0 0)) integer)
3592                                    *)
3593                 "fold zero arg"
3594                 0)))
3595   (def ash)
3596   (def /))
3597
3598 (macrolet ((def (name)
3599              `(deftransform ,name ((x y) ((constant-arg (integer 0 0)) integer)
3600                                    *)
3601                 "fold zero arg"
3602                 '(values 0 0))))
3603   (def truncate)
3604   (def round)
3605   (def floor)
3606   (def ceiling))
3607
3608 (macrolet ((def (name &optional float)
3609              (let ((x (if float '(float x) 'x)))
3610                `(deftransform ,name ((x y) (integer (constant-arg (member 1 -1)))
3611                                      *)
3612                   "fold division by 1"
3613                   `(values ,(if (minusp (lvar-value y))
3614                                 '(%negate ,x)
3615                                 ',x)  0)))))
3616   (def truncate)
3617   (def round)
3618   (def floor)
3619   (def ceiling)
3620   (def ftruncate t)
3621   (def fround t)
3622   (def ffloor t)
3623   (def fceiling t))
3624
3625 \f
3626 ;;;; character operations
3627
3628 (deftransform char-equal ((a b) (base-char base-char))
3629   "open code"
3630   '(let* ((ac (char-code a))
3631           (bc (char-code b))
3632           (sum (logxor ac bc)))
3633      (or (zerop sum)
3634          (when (eql sum #x20)
3635            (let ((sum (+ ac bc)))
3636              (or (and (> sum 161) (< sum 213))
3637                  (and (> sum 415) (< sum 461))
3638                  (and (> sum 463) (< sum 477))))))))
3639
3640 (deftransform char-upcase ((x) (base-char))
3641   "open code"
3642   '(let ((n-code (char-code x)))
3643      (if (or (and (> n-code #o140)      ; Octal 141 is #\a.
3644                   (< n-code #o173))     ; Octal 172 is #\z.
3645              (and (> n-code #o337)
3646                   (< n-code #o367))
3647              (and (> n-code #o367)
3648                   (< n-code #o377)))
3649          (code-char (logxor #x20 n-code))
3650          x)))
3651
3652 (deftransform char-downcase ((x) (base-char))
3653   "open code"
3654   '(let ((n-code (char-code x)))
3655      (if (or (and (> n-code 64)         ; 65 is #\A.
3656                   (< n-code 91))        ; 90 is #\Z.
3657              (and (> n-code 191)
3658                   (< n-code 215))
3659              (and (> n-code 215)
3660                   (< n-code 223)))
3661          (code-char (logxor #x20 n-code))
3662          x)))
3663 \f
3664 ;;;; equality predicate transforms
3665
3666 ;;; Return true if X and Y are lvars whose only use is a
3667 ;;; reference to the same leaf, and the value of the leaf cannot
3668 ;;; change.
3669 (defun same-leaf-ref-p (x y)
3670   (declare (type lvar x y))
3671   (let ((x-use (principal-lvar-use x))
3672         (y-use (principal-lvar-use y)))
3673     (and (ref-p x-use)
3674          (ref-p y-use)
3675          (eq (ref-leaf x-use) (ref-leaf y-use))
3676          (constant-reference-p x-use))))
3677
3678 ;;; If X and Y are the same leaf, then the result is true. Otherwise,
3679 ;;; if there is no intersection between the types of the arguments,
3680 ;;; then the result is definitely false.
3681 (deftransform simple-equality-transform ((x y) * *
3682                                          :defun-only t)
3683   (cond
3684     ((same-leaf-ref-p x y) t)
3685     ((not (types-equal-or-intersect (lvar-type x) (lvar-type y)))
3686          nil)
3687     (t (give-up-ir1-transform))))
3688
3689 (macrolet ((def (x)
3690              `(%deftransform ',x '(function * *) #'simple-equality-transform)))
3691   (def eq)
3692   (def char=))
3693
3694 ;;; This is similar to SIMPLE-EQUALITY-TRANSFORM, except that we also
3695 ;;; try to convert to a type-specific predicate or EQ:
3696 ;;; -- If both args are characters, convert to CHAR=. This is better than
3697 ;;;    just converting to EQ, since CHAR= may have special compilation
3698 ;;;    strategies for non-standard representations, etc.
3699 ;;; -- If either arg is definitely a fixnum, we check to see if X is
3700 ;;;    constant and if so, put X second. Doing this results in better
3701 ;;;    code from the backend, since the backend assumes that any constant
3702 ;;;    argument comes second.
3703 ;;; -- If either arg is definitely not a number or a fixnum, then we
3704 ;;;    can compare with EQ.
3705 ;;; -- Otherwise, we try to put the arg we know more about second. If X
3706 ;;;    is constant then we put it second. If X is a subtype of Y, we put
3707 ;;;    it second. These rules make it easier for the back end to match
3708 ;;;    these interesting cases.
3709 (deftransform eql ((x y) * * :node node)
3710   "convert to simpler equality predicate"
3711   (let ((x-type (lvar-type x))
3712         (y-type (lvar-type y))
3713         (char-type (specifier-type 'character)))
3714     (flet ((fixnum-type-p (type)
3715              (csubtypep type (specifier-type 'fixnum))))
3716       (cond
3717         ((same-leaf-ref-p x y) t)
3718         ((not (types-equal-or-intersect x-type y-type))
3719          nil)
3720         ((and (csubtypep x-type char-type)
3721               (csubtypep y-type char-type))
3722          '(char= x y))
3723         ((or (fixnum-type-p x-type) (fixnum-type-p y-type))
3724          (commutative-arg-swap node))
3725         ((or (eq-comparable-type-p x-type) (eq-comparable-type-p y-type))
3726          '(eq x y))
3727         ((and (not (constant-lvar-p y))
3728               (or (constant-lvar-p x)
3729                   (and (csubtypep x-type y-type)
3730                        (not (csubtypep y-type x-type)))))
3731          '(eql y x))
3732         (t
3733          (give-up-ir1-transform))))))
3734
3735 ;;; similarly to the EQL transform above, we attempt to constant-fold
3736 ;;; or convert to a simpler predicate: mostly we have to be careful
3737 ;;; with strings and bit-vectors.
3738 (deftransform equal ((x y) * *)
3739   "convert to simpler equality predicate"
3740   (let ((x-type (lvar-type x))
3741         (y-type (lvar-type y))
3742         (string-type (specifier-type 'string))
3743         (bit-vector-type (specifier-type 'bit-vector)))
3744     (cond
3745       ((same-leaf-ref-p x y) t)
3746       ((and (csubtypep x-type string-type)
3747             (csubtypep y-type string-type))
3748        '(string= x y))
3749       ((and (csubtypep x-type bit-vector-type)
3750             (csubtypep y-type bit-vector-type))
3751        '(bit-vector-= x y))
3752       ;; if at least one is not a string, and at least one is not a
3753       ;; bit-vector, then we can reason from types.
3754       ((and (not (and (types-equal-or-intersect x-type string-type)
3755                       (types-equal-or-intersect y-type string-type)))
3756             (not (and (types-equal-or-intersect x-type bit-vector-type)
3757                       (types-equal-or-intersect y-type bit-vector-type)))
3758             (not (types-equal-or-intersect x-type y-type)))
3759        nil)
3760       (t (give-up-ir1-transform)))))
3761
3762 ;;; Convert to EQL if both args are rational and complexp is specified
3763 ;;; and the same for both.
3764 (deftransform = ((x y) (number number) *)
3765   "open code"
3766   (let ((x-type (lvar-type x))
3767         (y-type (lvar-type y)))
3768     (cond ((or (and (csubtypep x-type (specifier-type 'float))
3769                     (csubtypep y-type (specifier-type 'float)))
3770                (and (csubtypep x-type (specifier-type '(complex float)))
3771                     (csubtypep y-type (specifier-type '(complex float))))
3772                #!+complex-float-vops
3773                (and (csubtypep x-type (specifier-type '(or single-float (complex single-float))))
3774                     (csubtypep y-type (specifier-type '(or single-float (complex single-float)))))
3775                #!+complex-float-vops
3776                (and (csubtypep x-type (specifier-type '(or double-float (complex double-float))))
3777                     (csubtypep y-type (specifier-type '(or double-float (complex double-float))))))
3778            ;; They are both floats. Leave as = so that -0.0 is
3779            ;; handled correctly.
3780            (give-up-ir1-transform))
3781           ((or (and (csubtypep x-type (specifier-type 'rational))
3782                     (csubtypep y-type (specifier-type 'rational)))
3783                (and (csubtypep x-type
3784                                (specifier-type '(complex rational)))
3785                     (csubtypep y-type
3786                                (specifier-type '(complex rational)))))
3787            ;; They are both rationals and complexp is the same.
3788            ;; Convert to EQL.
3789            '(eql x y))
3790           (t
3791            (give-up-ir1-transform
3792             "The operands might not be the same type.")))))
3793
3794 (defun maybe-float-lvar-p (lvar)
3795   (neq *empty-type* (type-intersection (specifier-type 'float)
3796                                        (lvar-type lvar))))
3797
3798 (flet ((maybe-invert (node op inverted x y)
3799          ;; Don't invert if either argument can be a float (NaNs)
3800          (cond
3801            ((or (maybe-float-lvar-p x) (maybe-float-lvar-p y))
3802             (delay-ir1-transform node :constraint)
3803             `(or (,op x y) (= x y)))
3804            (t
3805             `(if (,inverted x y) nil t)))))
3806   (deftransform >= ((x y) (number number) * :node node)
3807     "invert or open code"
3808     (maybe-invert node '> '< x y))
3809   (deftransform <= ((x y) (number number) * :node node)
3810     "invert or open code"
3811     (maybe-invert node '< '> x y)))
3812
3813 ;;; See whether we can statically determine (< X Y) using type
3814 ;;; information. If X's high bound is < Y's low, then X < Y.
3815 ;;; Similarly, if X's low is >= to Y's high, the X >= Y (so return
3816 ;;; NIL). If not, at least make sure any constant arg is second.
3817 (macrolet ((def (name inverse reflexive-p surely-true surely-false)
3818              `(deftransform ,name ((x y))
3819                 "optimize using intervals"
3820                 (if (and (same-leaf-ref-p x y)
3821                          ;; For non-reflexive functions we don't need
3822                          ;; to worry about NaNs: (non-ref-op NaN NaN) => false,
3823                          ;; but with reflexive ones we don't know...
3824                          ,@(when reflexive-p
3825                                  '((and (not (maybe-float-lvar-p x))
3826                                         (not (maybe-float-lvar-p y))))))
3827                     ,reflexive-p
3828                     (let ((ix (or (type-approximate-interval (lvar-type x))
3829                                   (give-up-ir1-transform)))
3830                           (iy (or (type-approximate-interval (lvar-type y))
3831                                   (give-up-ir1-transform))))
3832                       (cond (,surely-true
3833                              t)
3834                             (,surely-false
3835                              nil)
3836                             ((and (constant-lvar-p x)
3837                                   (not (constant-lvar-p y)))
3838                              `(,',inverse y x))
3839                             (t
3840                              (give-up-ir1-transform))))))))
3841   (def = = t (interval-= ix iy) (interval-/= ix iy))
3842   (def /= /= nil (interval-/= ix iy) (interval-= ix iy))
3843   (def < > nil (interval-< ix iy) (interval->= ix iy))
3844   (def > < nil (interval-< iy ix) (interval->= iy ix))
3845   (def <= >= t (interval->= iy ix) (interval-< iy ix))
3846   (def >= <= t (interval->= ix iy) (interval-< ix iy)))
3847
3848 (defun ir1-transform-char< (x y first second inverse)
3849   (cond
3850     ((same-leaf-ref-p x y) nil)
3851     ;; If we had interval representation of character types, as we
3852     ;; might eventually have to to support 2^21 characters, then here
3853     ;; we could do some compile-time computation as in transforms for
3854     ;; < above. -- CSR, 2003-07-01
3855     ((and (constant-lvar-p first)
3856           (not (constant-lvar-p second)))
3857      `(,inverse y x))
3858     (t (give-up-ir1-transform))))
3859
3860 (deftransform char< ((x y) (character character) *)
3861   (ir1-transform-char< x y x y 'char>))
3862
3863 (deftransform char> ((x y) (character character) *)
3864   (ir1-transform-char< y x x y 'char<))
3865 \f
3866 ;;;; converting N-arg comparisons
3867 ;;;;
3868 ;;;; We convert calls to N-arg comparison functions such as < into
3869 ;;;; two-arg calls. This transformation is enabled for all such
3870 ;;;; comparisons in this file. If any of these predicates are not
3871 ;;;; open-coded, then the transformation should be removed at some
3872 ;;;; point to avoid pessimization.
3873
3874 ;;; This function is used for source transformation of N-arg
3875 ;;; comparison functions other than inequality. We deal both with
3876 ;;; converting to two-arg calls and inverting the sense of the test,
3877 ;;; if necessary. If the call has two args, then we pass or return a
3878 ;;; negated test as appropriate. If it is a degenerate one-arg call,
3879 ;;; then we transform to code that returns true. Otherwise, we bind
3880 ;;; all the arguments and expand into a bunch of IFs.
3881 (defun multi-compare (predicate args not-p type &optional force-two-arg-p)
3882   (let ((nargs (length args)))
3883     (cond ((< nargs 1) (values nil t))
3884           ((= nargs 1) `(progn (the ,type ,@args) t))
3885           ((= nargs 2)
3886            (if not-p
3887                `(if (,predicate ,(first args) ,(second args)) nil t)
3888                (if force-two-arg-p
3889                    `(,predicate ,(first args) ,(second args))
3890                    (values nil t))))
3891           (t
3892            (do* ((i (1- nargs) (1- i))
3893                  (last nil current)
3894                  (current (gensym) (gensym))
3895                  (vars (list current) (cons current vars))
3896                  (result t (if not-p
3897                                `(if (,predicate ,current ,last)
3898                                     nil ,result)
3899                                `(if (,predicate ,current ,last)
3900                                     ,result nil))))
3901                ((zerop i)
3902                 `((lambda ,vars (declare (type ,type ,@vars)) ,result)
3903                   ,@args)))))))
3904
3905 (define-source-transform = (&rest args) (multi-compare '= args nil 'number))
3906 (define-source-transform < (&rest args) (multi-compare '< args nil 'real))
3907 (define-source-transform > (&rest args) (multi-compare '> args nil 'real))
3908 ;;; We cannot do the inversion for >= and <= here, since both
3909 ;;;   (< NaN X) and (> NaN X)
3910 ;;; are false, and we don't have type-information available yet. The
3911 ;;; deftransforms for two-argument versions of >= and <= takes care of
3912 ;;; the inversion to > and < when possible.
3913 (define-source-transform <= (&rest args) (multi-compare '<= args nil 'real))
3914 (define-source-transform >= (&rest args) (multi-compare '>= args nil 'real))
3915
3916 (define-source-transform char= (&rest args) (multi-compare 'char= args nil
3917                                                            'character))
3918 (define-source-transform char< (&rest args) (multi-compare 'char< args nil
3919                                                            'character))
3920 (define-source-transform char> (&rest args) (multi-compare 'char> args nil
3921                                                            'character))
3922 (define-source-transform char<= (&rest args) (multi-compare 'char> args t
3923                                                             'character))
3924 (define-source-transform char>= (&rest args) (multi-compare 'char< args t
3925                                                             'character))
3926
3927 (define-source-transform char-equal (&rest args)
3928   (multi-compare 'sb!impl::two-arg-char-equal args nil 'character t))
3929 (define-source-transform char-lessp (&rest args)
3930   (multi-compare 'sb!impl::two-arg-char-lessp args nil 'character t))
3931 (define-source-transform char-greaterp (&rest args)
3932   (multi-compare 'sb!impl::two-arg-char-greaterp args nil 'character t))
3933 (define-source-transform char-not-greaterp (&rest args)
3934   (multi-compare 'sb!impl::two-arg-char-greaterp args t 'character t))
3935 (define-source-transform char-not-lessp (&rest args)
3936   (multi-compare 'sb!impl::two-arg-char-lessp args t 'character t))
3937
3938 ;;; This function does source transformation of N-arg inequality
3939 ;;; functions such as /=. This is similar to MULTI-COMPARE in the <3
3940 ;;; arg cases. If there are more than two args, then we expand into
3941 ;;; the appropriate n^2 comparisons only when speed is important.
3942 (declaim (ftype (function (symbol list t) *) multi-not-equal))
3943 (defun multi-not-equal (predicate args type)
3944   (let ((nargs (length args)))
3945     (cond ((< nargs 1) (values nil t))
3946           ((= nargs 1) `(progn (the ,type ,@args) t))
3947           ((= nargs 2)
3948            `(if (,predicate ,(first args) ,(second args)) nil t))
3949           ((not (policy *lexenv*
3950                         (and (>= speed space)
3951                              (>= speed compilation-speed))))
3952            (values nil t))
3953           (t
3954            (let ((vars (make-gensym-list nargs)))
3955              (do ((var vars next)
3956                   (next (cdr vars) (cdr next))
3957                   (result t))
3958                  ((null next)
3959                   `((lambda ,vars (declare (type ,type ,@vars)) ,result)
3960                     ,@args))
3961                (let ((v1 (first var)))
3962                  (dolist (v2 next)
3963                    (setq result `(if (,predicate ,v1 ,v2) nil ,result))))))))))
3964
3965 (define-source-transform /= (&rest args)
3966   (multi-not-equal '= args 'number))
3967 (define-source-transform char/= (&rest args)
3968   (multi-not-equal 'char= args 'character))
3969 (define-source-transform char-not-equal (&rest args)
3970   (multi-not-equal 'char-equal args 'character))
3971
3972 ;;; Expand MAX and MIN into the obvious comparisons.
3973 (define-source-transform max (arg0 &rest rest)
3974   (once-only ((arg0 arg0))
3975     (if (null rest)
3976         `(values (the real ,arg0))
3977         `(let ((maxrest (max ,@rest)))
3978           (if (>= ,arg0 maxrest) ,arg0 maxrest)))))
3979 (define-source-transform min (arg0 &rest rest)
3980   (once-only ((arg0 arg0))
3981     (if (null rest)
3982         `(values (the real ,arg0))
3983         `(let ((minrest (min ,@rest)))
3984           (if (<= ,arg0 minrest) ,arg0 minrest)))))
3985 \f
3986 ;;;; converting N-arg arithmetic functions
3987 ;;;;
3988 ;;;; N-arg arithmetic and logic functions are associated into two-arg
3989 ;;;; versions, and degenerate cases are flushed.
3990
3991 ;;; Left-associate FIRST-ARG and MORE-ARGS using FUNCTION.
3992 (declaim (ftype (sfunction (symbol t list t) list) associate-args))
3993 (defun associate-args (fun first-arg more-args identity)
3994   (let ((next (rest more-args))
3995         (arg (first more-args)))
3996     (if (null next)
3997         `(,fun ,first-arg ,(if arg arg identity))
3998         (associate-args fun `(,fun ,first-arg ,arg) next identity))))
3999
4000 ;;; Reduce constants in ARGS list.
4001 (declaim (ftype (sfunction (symbol list t symbol) list) reduce-constants))
4002 (defun reduce-constants (fun args identity one-arg-result-type)
4003   (let ((one-arg-constant-p (ecase one-arg-result-type
4004                               (number #'numberp)
4005                               (integer #'integerp)))
4006         (reduced-value identity)
4007         (reduced-p nil))
4008     (collect ((not-constants))
4009       (dolist (arg args)
4010         (if (funcall one-arg-constant-p arg)
4011             (setf reduced-value (funcall fun reduced-value arg)
4012                   reduced-p t)
4013             (not-constants arg)))
4014       ;; It is tempting to drop constants reduced to identity here,
4015       ;; but if X is SNaN in (* X 1), we cannot drop the 1.
4016       (if (not-constants)
4017           (if reduced-p
4018               `(,reduced-value ,@(not-constants))
4019               (not-constants))
4020           `(,reduced-value)))))
4021
4022 ;;; Do source transformations for transitive functions such as +.
4023 ;;; One-arg cases are replaced with the arg and zero arg cases with
4024 ;;; the identity. ONE-ARG-RESULT-TYPE is the type to ensure (with THE)
4025 ;;; that the argument in one-argument calls is.
4026 (declaim (ftype (function (symbol list t &optional symbol list)
4027                           (values t &optional (member nil t)))
4028                 source-transform-transitive))
4029 (defun source-transform-transitive (fun args identity
4030                                     &optional (one-arg-result-type 'number)
4031                                               (one-arg-prefixes '(values)))
4032   (case (length args)
4033     (0 identity)
4034     (1 `(,@one-arg-prefixes (the ,one-arg-result-type ,(first args))))
4035     (2 (values nil t))
4036     (t (let ((reduced-args (reduce-constants fun args identity one-arg-result-type)))
4037          (associate-args fun (first reduced-args) (rest reduced-args) identity)))))
4038
4039 (define-source-transform + (&rest args)
4040   (source-transform-transitive '+ args 0))
4041 (define-source-transform * (&rest args)
4042   (source-transform-transitive '* args 1))
4043 (define-source-transform logior (&rest args)
4044   (source-transform-transitive 'logior args 0 'integer))
4045 (define-source-transform logxor (&rest args)
4046   (source-transform-transitive 'logxor args 0 'integer))
4047 (define-source-transform logand (&rest args)
4048   (source-transform-transitive 'logand args -1 'integer))
4049 (define-source-transform logeqv (&rest args)
4050   (source-transform-transitive 'logeqv args -1 'integer))
4051 (define-source-transform gcd (&rest args)
4052   (source-transform-transitive 'gcd args 0 'integer '(abs)))
4053 (define-source-transform lcm (&rest args)
4054   (source-transform-transitive 'lcm args 1 'integer '(abs)))
4055
4056 ;;; Do source transformations for intransitive n-arg functions such as
4057 ;;; /. With one arg, we form the inverse. With two args we pass.
4058 ;;; Otherwise we associate into two-arg calls.
4059 (declaim (ftype (function (symbol symbol list t list &optional symbol)
4060                           (values list &optional (member nil t)))
4061                 source-transform-intransitive))
4062 (defun source-transform-intransitive (fun fun* args identity one-arg-prefixes
4063                                       &optional (one-arg-result-type 'number))
4064   (case (length args)
4065     ((0 2) (values nil t))
4066     (1 `(,@one-arg-prefixes (the ,one-arg-result-type ,(first args))))
4067     (t (let ((reduced-args
4068               (reduce-constants fun* (rest args) identity one-arg-result-type)))
4069          (associate-args fun (first args) reduced-args identity)))))
4070
4071 (define-source-transform - (&rest args)
4072   (source-transform-intransitive '- '+ args 0 '(%negate)))
4073 (define-source-transform / (&rest args)
4074   (source-transform-intransitive '/ '* args 1 '(/ 1)))
4075 \f
4076 ;;;; transforming APPLY
4077
4078 ;;; We convert APPLY into MULTIPLE-VALUE-CALL so that the compiler
4079 ;;; only needs to understand one kind of variable-argument call. It is
4080 ;;; more efficient to convert APPLY to MV-CALL than MV-CALL to APPLY.
4081 (define-source-transform apply (fun arg &rest more-args)
4082   (let ((args (cons arg more-args)))
4083     `(multiple-value-call ,fun
4084        ,@(mapcar (lambda (x) `(values ,x)) (butlast args))
4085        (values-list ,(car (last args))))))
4086
4087 ;;; When &REST argument are at play, we also have extra context and count
4088 ;;; arguments -- convert to %VALUES-LIST-OR-CONTEXT when possible, so that the
4089 ;;; deftransform can decide what to do after everything has been converted.
4090 (define-source-transform values-list (list)
4091   (if (symbolp list)
4092       (let* ((var (lexenv-find list vars))
4093              (info (when (lambda-var-p var)
4094                      (lambda-var-arg-info var))))
4095         (if (and info
4096                  (eq :rest (arg-info-kind info))
4097                  (consp (arg-info-default info)))
4098             (destructuring-bind (context count &optional used) (arg-info-default info)
4099               (declare (ignore used))
4100               `(%values-list-or-context ,list ,context ,count))
4101             (values nil t)))
4102       (values nil t)))
4103
4104 (deftransform %values-list-or-context ((list context count) * * :node node)
4105   (let* ((use (lvar-use list))
4106          (var (when (ref-p use) (ref-leaf use)))
4107          (home (when (lambda-var-p var) (lambda-var-home var)))
4108          (info (when (lambda-var-p var) (lambda-var-arg-info var))))
4109     (flet ((ref-good-for-more-context-p (ref)
4110              (let ((dest (principal-lvar-end (node-lvar ref))))
4111                (and (combination-p dest)
4112                     ;; Uses outside VALUES-LIST will require a &REST list anyways,
4113                     ;; to it's no use saving effort here -- plus they might modify
4114                     ;; the list destructively.
4115                     (eq '%values-list-or-context (lvar-fun-name (combination-fun dest)))
4116                     ;; If the home lambda is different and isn't DX, it might
4117                     ;; escape -- in which case using the more context isn't safe.
4118                     (let ((clambda (node-home-lambda dest)))
4119                       (or (eq home clambda)
4120                           (leaf-dynamic-extent clambda)))))))
4121       (let ((context-ok
4122               (and info
4123                    (consp (arg-info-default info))
4124                    (not (lambda-var-specvar var))
4125                    (not (lambda-var-sets var))
4126                    (every #'ref-good-for-more-context-p (lambda-var-refs var))
4127                    (policy node (= 3 rest-conversion)))))
4128         (cond (context-ok
4129                (destructuring-bind (context count &optional used) (arg-info-default info)
4130                  (declare (ignore used))
4131                  (setf (arg-info-default info) (list context count t)))
4132                `(%more-arg-values context 0 count))
4133               (t
4134                (when info
4135                  (setf (arg-info-default info) t))
4136                `(values-list list)))))))
4137
4138 \f
4139 ;;;; transforming FORMAT
4140 ;;;;
4141 ;;;; If the control string is a compile-time constant, then replace it
4142 ;;;; with a use of the FORMATTER macro so that the control string is
4143 ;;;; ``compiled.'' Furthermore, if the destination is either a stream
4144 ;;;; or T and the control string is a function (i.e. FORMATTER), then
4145 ;;;; convert the call to FORMAT to just a FUNCALL of that function.
4146
4147 ;;; for compile-time argument count checking.
4148 ;;;
4149 ;;; FIXME II: In some cases, type information could be correlated; for
4150 ;;; instance, ~{ ... ~} requires a list argument, so if the lvar-type
4151 ;;; of a corresponding argument is known and does not intersect the
4152 ;;; list type, a warning could be signalled.
4153 (defun check-format-args (string args fun)
4154   (declare (type string string))
4155   (unless (typep string 'simple-string)
4156     (setq string (coerce string 'simple-string)))
4157   (multiple-value-bind (min max)
4158       (handler-case (sb!format:%compiler-walk-format-string string args)
4159         (sb!format:format-error (c)
4160           (compiler-warn "~A" c)))
4161     (when min
4162       (let ((nargs (length args)))
4163         (cond
4164           ((< nargs min)
4165            (warn 'format-too-few-args-warning
4166                  :format-control
4167                  "Too few arguments (~D) to ~S ~S: requires at least ~D."
4168                  :format-arguments (list nargs fun string min)))
4169           ((> nargs max)
4170            (warn 'format-too-many-args-warning
4171                  :format-control
4172                  "Too many arguments (~D) to ~S ~S: uses at most ~D."
4173                  :format-arguments (list nargs fun string max))))))))
4174
4175 (defoptimizer (format optimizer) ((dest control &rest args))
4176   (when (constant-lvar-p control)
4177     (let ((x (lvar-value control)))
4178       (when (stringp x)
4179         (check-format-args x args 'format)))))
4180
4181 ;;; We disable this transform in the cross-compiler to save memory in
4182 ;;; the target image; most of the uses of FORMAT in the compiler are for
4183 ;;; error messages, and those don't need to be particularly fast.
4184 #+sb-xc
4185 (deftransform format ((dest control &rest args) (t simple-string &rest t) *
4186                       :policy (>= speed space))
4187   (unless (constant-lvar-p control)
4188     (give-up-ir1-transform "The control string is not a constant."))
4189   (let ((arg-names (make-gensym-list (length args))))
4190     `(lambda (dest control ,@arg-names)
4191        (declare (ignore control))
4192        (format dest (formatter ,(lvar-value control)) ,@arg-names))))
4193
4194 (deftransform format ((stream control &rest args) (stream function &rest t))
4195   (let ((arg-names (make-gensym-list (length args))))
4196     `(lambda (stream control ,@arg-names)
4197        (funcall control stream ,@arg-names)
4198        nil)))
4199
4200 (deftransform format ((tee control &rest args) ((member t) function &rest t))
4201   (let ((arg-names (make-gensym-list (length args))))
4202     `(lambda (tee control ,@arg-names)
4203        (declare (ignore tee))
4204        (funcall control *standard-output* ,@arg-names)
4205        nil)))
4206
4207 (deftransform pathname ((pathspec) (pathname) *)
4208   'pathspec)
4209
4210 (deftransform pathname ((pathspec) (string) *)
4211   '(values (parse-namestring pathspec)))
4212
4213 (macrolet
4214     ((def (name)
4215          `(defoptimizer (,name optimizer) ((control &rest args))
4216             (when (constant-lvar-p control)
4217               (let ((x (lvar-value control)))
4218                 (when (stringp x)
4219                   (check-format-args x args ',name)))))))
4220   (def error)
4221   (def warn)
4222   #+sb-xc-host ; Only we should be using these
4223   (progn
4224     (def style-warn)
4225     (def compiler-error)
4226     (def compiler-warn)
4227     (def compiler-style-warn)
4228     (def compiler-notify)
4229     (def maybe-compiler-notify)
4230     (def bug)))
4231
4232 (defoptimizer (cerror optimizer) ((report control &rest args))
4233   (when (and (constant-lvar-p control)
4234              (constant-lvar-p report))
4235     (let ((x (lvar-value control))
4236           (y (lvar-value report)))
4237       (when (and (stringp x) (stringp y))
4238         (multiple-value-bind (min1 max1)
4239             (handler-case
4240                 (sb!format:%compiler-walk-format-string x args)
4241               (sb!format:format-error (c)
4242                 (compiler-warn "~A" c)))
4243           (when min1
4244             (multiple-value-bind (min2 max2)
4245                 (handler-case
4246                     (sb!format:%compiler-walk-format-string y args)
4247                   (sb!format:format-error (c)
4248                     (compiler-warn "~A" c)))
4249               (when min2
4250                 (let ((nargs (length args)))
4251                   (cond
4252                     ((< nargs (min min1 min2))
4253                      (warn 'format-too-few-args-warning
4254                            :format-control
4255                            "Too few arguments (~D) to ~S ~S ~S: ~
4256                             requires at least ~D."
4257                            :format-arguments
4258                            (list nargs 'cerror y x (min min1 min2))))
4259                     ((> nargs (max max1 max2))
4260                      (warn 'format-too-many-args-warning
4261                            :format-control
4262                            "Too many arguments (~D) to ~S ~S ~S: ~
4263                             uses at most ~D."
4264                            :format-arguments
4265                            (list nargs 'cerror y x (max max1 max2))))))))))))))
4266
4267 (defoptimizer (coerce derive-type) ((value type) node)
4268   (cond
4269     ((constant-lvar-p type)
4270      ;; This branch is essentially (RESULT-TYPE-SPECIFIER-NTH-ARG 2),
4271      ;; but dealing with the niggle that complex canonicalization gets
4272      ;; in the way: (COERCE 1 'COMPLEX) returns 1, which is not of
4273      ;; type COMPLEX.
4274      (let* ((specifier (lvar-value type))
4275             (result-typeoid (careful-specifier-type specifier)))
4276        (cond
4277          ((null result-typeoid) nil)
4278          ((csubtypep result-typeoid (specifier-type 'number))
4279           ;; the difficult case: we have to cope with ANSI 12.1.5.3
4280           ;; Rule of Canonical Representation for Complex Rationals,
4281           ;; which is a truly nasty delivery to field.
4282           (cond
4283             ((csubtypep result-typeoid (specifier-type 'real))
4284              ;; cleverness required here: it would be nice to deduce
4285              ;; that something of type (INTEGER 2 3) coerced to type
4286              ;; DOUBLE-FLOAT should return (DOUBLE-FLOAT 2.0d0 3.0d0).
4287              ;; FLOAT gets its own clause because it's implemented as
4288              ;; a UNION-TYPE, so we don't catch it in the NUMERIC-TYPE
4289              ;; logic below.
4290              result-typeoid)
4291             ((and (numeric-type-p result-typeoid)
4292                   (eq (numeric-type-complexp result-typeoid) :real))
4293              ;; FIXME: is this clause (a) necessary or (b) useful?
4294              result-typeoid)
4295             ((or (csubtypep result-typeoid
4296                             (specifier-type '(complex single-float)))
4297                  (csubtypep result-typeoid
4298                             (specifier-type '(complex double-float)))
4299                  #!+long-float
4300                  (csubtypep result-typeoid
4301                             (specifier-type '(complex long-float))))
4302              ;; float complex types are never canonicalized.
4303              result-typeoid)
4304             (t
4305              ;; if it's not a REAL, or a COMPLEX FLOAToid, it's
4306              ;; probably just a COMPLEX or equivalent.  So, in that
4307              ;; case, we will return a complex or an object of the
4308              ;; provided type if it's rational:
4309              (type-union result-typeoid
4310                          (type-intersection (lvar-type value)
4311                                             (specifier-type 'rational))))))
4312          ((and (policy node (zerop safety))
4313                (csubtypep result-typeoid (specifier-type '(array * (*)))))
4314           ;; At zero safety the deftransform for COERCE can elide dimension
4315           ;; checks for the things like (COERCE X '(SIMPLE-VECTOR 5)) -- so we
4316           ;; need to simplify the type to drop the dimension information.
4317           (let ((vtype (simplify-vector-type result-typeoid)))
4318             (if vtype
4319                 (specifier-type vtype)
4320                 result-typeoid)))
4321          (t
4322           result-typeoid))))
4323     (t
4324      ;; OK, the result-type argument isn't constant.  However, there
4325      ;; are common uses where we can still do better than just
4326      ;; *UNIVERSAL-TYPE*: e.g. (COERCE X (ARRAY-ELEMENT-TYPE Y)),
4327      ;; where Y is of a known type.  See messages on cmucl-imp
4328      ;; 2001-02-14 and sbcl-devel 2002-12-12.  We only worry here
4329      ;; about types that can be returned by (ARRAY-ELEMENT-TYPE Y), on
4330      ;; the basis that it's unlikely that other uses are both
4331      ;; time-critical and get to this branch of the COND (non-constant
4332      ;; second argument to COERCE).  -- CSR, 2002-12-16
4333      (let ((value-type (lvar-type value))
4334            (type-type (lvar-type type)))
4335        (labels
4336            ((good-cons-type-p (cons-type)
4337               ;; Make sure the cons-type we're looking at is something
4338               ;; we're prepared to handle which is basically something
4339               ;; that array-element-type can return.
4340               (or (and (member-type-p cons-type)
4341                        (eql 1 (member-type-size cons-type))
4342                        (null (first (member-type-members cons-type))))
4343                   (let ((car-type (cons-type-car-type cons-type)))
4344                     (and (member-type-p car-type)
4345                          (eql 1 (member-type-members car-type))
4346                          (let ((elt (first (member-type-members car-type))))
4347                            (or (symbolp elt)
4348                                (numberp elt)
4349                                (and (listp elt)
4350                                     (numberp (first elt)))))
4351                          (good-cons-type-p (cons-type-cdr-type cons-type))))))
4352             (unconsify-type (good-cons-type)
4353               ;; Convert the "printed" respresentation of a cons
4354               ;; specifier into a type specifier.  That is, the
4355               ;; specifier (CONS (EQL SIGNED-BYTE) (CONS (EQL 16)
4356               ;; NULL)) is converted to (SIGNED-BYTE 16).
4357               (cond ((or (null good-cons-type)
4358                          (eq good-cons-type 'null))
4359                      nil)
4360                     ((and (eq (first good-cons-type) 'cons)
4361                           (eq (first (second good-cons-type)) 'member))
4362                      `(,(second (second good-cons-type))
4363                        ,@(unconsify-type (caddr good-cons-type))))))
4364             (coerceable-p (part)
4365               ;; Can the value be coerced to the given type?  Coerce is
4366               ;; complicated, so we don't handle every possible case
4367               ;; here---just the most common and easiest cases:
4368               ;;
4369               ;; * Any REAL can be coerced to a FLOAT type.
4370               ;; * Any NUMBER can be coerced to a (COMPLEX
4371               ;;   SINGLE/DOUBLE-FLOAT).
4372               ;;
4373               ;; FIXME I: we should also be able to deal with characters
4374               ;; here.
4375               ;;
4376               ;; FIXME II: I'm not sure that anything is necessary
4377               ;; here, at least while COMPLEX is not a specialized
4378               ;; array element type in the system.  Reasoning: if
4379               ;; something cannot be coerced to the requested type, an
4380               ;; error will be raised (and so any downstream compiled
4381               ;; code on the assumption of the returned type is
4382               ;; unreachable).  If something can, then it will be of
4383               ;; the requested type, because (by assumption) COMPLEX
4384               ;; (and other difficult types like (COMPLEX INTEGER)
4385               ;; aren't specialized types.
4386               (let ((coerced-type (careful-specifier-type part)))
4387                 (when coerced-type
4388                   (or (and (csubtypep coerced-type (specifier-type 'float))
4389                            (csubtypep value-type (specifier-type 'real)))
4390                       (and (csubtypep coerced-type
4391                                       (specifier-type `(or (complex single-float)
4392                                                            (complex double-float))))
4393                           (csubtypep value-type (specifier-type 'number)))))))
4394             (process-types (type)
4395               ;; FIXME: This needs some work because we should be able
4396               ;; to derive the resulting type better than just the
4397               ;; type arg of coerce.  That is, if X is (INTEGER 10
4398               ;; 20), then (COERCE X 'DOUBLE-FLOAT) should say
4399               ;; (DOUBLE-FLOAT 10d0 20d0) instead of just
4400               ;; double-float.
4401               (cond ((member-type-p type)
4402                      (block punt
4403                        (let (members)
4404                          (mapc-member-type-members
4405                           (lambda (member)
4406                             (if (coerceable-p member)
4407                                 (push member members)
4408                                 (return-from punt *universal-type*)))
4409                           type)
4410                          (specifier-type `(or ,@members)))))
4411                     ((and (cons-type-p type)
4412                           (good-cons-type-p type))
4413                      (let ((c-type (unconsify-type (type-specifier type))))
4414                        (if (coerceable-p c-type)
4415                            (specifier-type c-type)
4416                            *universal-type*)))
4417                     (t
4418                      *universal-type*))))
4419          (cond ((union-type-p type-type)
4420                 (apply #'type-union (mapcar #'process-types
4421                                             (union-type-types type-type))))
4422                ((or (member-type-p type-type)
4423                     (cons-type-p type-type))
4424                 (process-types type-type))
4425                (t
4426                 *universal-type*)))))))
4427
4428 (defoptimizer (compile derive-type) ((nameoid function))
4429   (when (csubtypep (lvar-type nameoid)
4430                    (specifier-type 'null))
4431     (values-specifier-type '(values function boolean boolean))))
4432
4433 ;;; FIXME: Maybe also STREAM-ELEMENT-TYPE should be given some loving
4434 ;;; treatment along these lines? (See discussion in COERCE DERIVE-TYPE
4435 ;;; optimizer, above).
4436 (defoptimizer (array-element-type derive-type) ((array))
4437   (let ((array-type (lvar-type array)))
4438     (labels ((consify (list)
4439               (if (endp list)
4440                   '(eql nil)
4441                   `(cons (eql ,(car list)) ,(consify (rest list)))))
4442             (get-element-type (a)
4443               (let ((element-type
4444                      (type-specifier (array-type-specialized-element-type a))))
4445                 (cond ((eq element-type '*)
4446                        (specifier-type 'type-specifier))
4447                       ((symbolp element-type)
4448                        (make-member-type :members (list element-type)))
4449                       ((consp element-type)
4450                        (specifier-type (consify element-type)))
4451                       (t
4452                        (error "can't understand type ~S~%" element-type))))))
4453       (labels ((recurse (type)
4454                   (cond ((array-type-p type)
4455                          (get-element-type type))
4456                         ((union-type-p type)
4457                          (apply #'type-union
4458                                 (mapcar #'recurse (union-type-types type))))
4459                         (t
4460                          *universal-type*))))
4461         (recurse array-type)))))
4462
4463 (define-source-transform sb!impl::sort-vector (vector start end predicate key)
4464   ;; Like CMU CL, we use HEAPSORT. However, other than that, this code
4465   ;; isn't really related to the CMU CL code, since instead of trying
4466   ;; to generalize the CMU CL code to allow START and END values, this
4467   ;; code has been written from scratch following Chapter 7 of
4468   ;; _Introduction to Algorithms_ by Corman, Rivest, and Shamir.
4469   `(macrolet ((%index (x) `(truly-the index ,x))
4470               (%parent (i) `(ash ,i -1))
4471               (%left (i) `(%index (ash ,i 1)))
4472               (%right (i) `(%index (1+ (ash ,i 1))))
4473               (%heapify (i)
4474                `(do* ((i ,i)
4475                       (left (%left i) (%left i)))
4476                  ((> left current-heap-size))
4477                  (declare (type index i left))
4478                  (let* ((i-elt (%elt i))
4479                         (i-key (funcall keyfun i-elt))
4480                         (left-elt (%elt left))
4481                         (left-key (funcall keyfun left-elt)))
4482                    (multiple-value-bind (large large-elt large-key)
4483                        (if (funcall ,',predicate i-key left-key)
4484                            (values left left-elt left-key)
4485                            (values i i-elt i-key))
4486                      (let ((right (%right i)))
4487                        (multiple-value-bind (largest largest-elt)
4488                            (if (> right current-heap-size)
4489                                (values large large-elt)
4490                                (let* ((right-elt (%elt right))
4491                                       (right-key (funcall keyfun right-elt)))
4492                                  (if (funcall ,',predicate large-key right-key)
4493                                      (values right right-elt)
4494                                      (values large large-elt))))
4495                          (cond ((= largest i)
4496                                 (return))
4497                                (t
4498                                 (setf (%elt i) largest-elt
4499                                       (%elt largest) i-elt
4500                                       i largest)))))))))
4501               (%sort-vector (keyfun &optional (vtype 'vector))
4502                `(macrolet (;; KLUDGE: In SBCL ca. 0.6.10, I had
4503                            ;; trouble getting type inference to
4504                            ;; propagate all the way through this
4505                            ;; tangled mess of inlining. The TRULY-THE
4506                            ;; here works around that. -- WHN
4507                            (%elt (i)
4508                             `(aref (truly-the ,',vtype ,',',vector)
4509                               (%index (+ (%index ,i) start-1)))))
4510                  (let (;; Heaps prefer 1-based addressing.
4511                        (start-1 (1- ,',start))
4512                        (current-heap-size (- ,',end ,',start))
4513                        (keyfun ,keyfun))
4514                    (declare (type (integer -1 #.(1- sb!xc:most-positive-fixnum))
4515                                   start-1))
4516                    (declare (type index current-heap-size))
4517                    (declare (type function keyfun))
4518                    (loop for i of-type index
4519                          from (ash current-heap-size -1) downto 1 do
4520                          (%heapify i))
4521                    (loop
4522                     (when (< current-heap-size 2)
4523                       (return))
4524                     (rotatef (%elt 1) (%elt current-heap-size))
4525                     (decf current-heap-size)
4526                     (%heapify 1))))))
4527     (if (typep ,vector 'simple-vector)
4528         ;; (VECTOR T) is worth optimizing for, and SIMPLE-VECTOR is
4529         ;; what we get from (VECTOR T) inside WITH-ARRAY-DATA.
4530         (if (null ,key)
4531             ;; Special-casing the KEY=NIL case lets us avoid some
4532             ;; function calls.
4533             (%sort-vector #'identity simple-vector)
4534             (%sort-vector ,key simple-vector))
4535         ;; It's hard to anticipate many speed-critical applications for
4536         ;; sorting vector types other than (VECTOR T), so we just lump
4537         ;; them all together in one slow dynamically typed mess.
4538         (locally
4539           (declare (optimize (speed 2) (space 2) (inhibit-warnings 3)))
4540           (%sort-vector (or ,key #'identity))))))
4541 \f
4542 ;;;; debuggers' little helpers
4543
4544 ;;; for debugging when transforms are behaving mysteriously,
4545 ;;; e.g. when debugging a problem with an ASH transform
4546 ;;;   (defun foo (&optional s)
4547 ;;;     (sb-c::/report-lvar s "S outside WHEN")
4548 ;;;     (when (and (integerp s) (> s 3))
4549 ;;;       (sb-c::/report-lvar s "S inside WHEN")
4550 ;;;       (let ((bound (ash 1 (1- s))))
4551 ;;;         (sb-c::/report-lvar bound "BOUND")
4552 ;;;         (let ((x (- bound))
4553 ;;;               (y (1- bound)))
4554 ;;;           (sb-c::/report-lvar x "X")
4555 ;;;           (sb-c::/report-lvar x "Y"))
4556 ;;;         `(integer ,(- bound) ,(1- bound)))))
4557 ;;; (The DEFTRANSFORM doesn't do anything but report at compile time,
4558 ;;; and the function doesn't do anything at all.)
4559 #!+sb-show
4560 (progn
4561   (defknown /report-lvar (t t) null)
4562   (deftransform /report-lvar ((x message) (t t))
4563     (format t "~%/in /REPORT-LVAR~%")
4564     (format t "/(LVAR-TYPE X)=~S~%" (lvar-type x))
4565     (when (constant-lvar-p x)
4566       (format t "/(LVAR-VALUE X)=~S~%" (lvar-value x)))
4567     (format t "/MESSAGE=~S~%" (lvar-value message))
4568     (give-up-ir1-transform "not a real transform"))
4569   (defun /report-lvar (x message)
4570     (declare (ignore x message))))
4571
4572 \f
4573 ;;;; Transforms for internal compiler utilities
4574
4575 ;;; If QUALITY-NAME is constant and a valid name, don't bother
4576 ;;; checking that it's still valid at run-time.
4577 (deftransform policy-quality ((policy quality-name)
4578                               (t symbol))
4579   (unless (and (constant-lvar-p quality-name)
4580                (policy-quality-name-p (lvar-value quality-name)))
4581     (give-up-ir1-transform))
4582   '(%policy-quality policy quality-name))