Initial revision
[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. ### 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 (file-comment
17   "$Header$")
18
19 ;;; Convert into an IF so that IF optimizations will eliminate redundant
20 ;;; negations.
21 (def-source-transform not (x) `(if ,x nil t))
22 (def-source-transform null (x) `(if ,x nil t))
23
24 ;;; ENDP is just NULL with a LIST assertion.
25 (def-source-transform endp (x) `(null (the list ,x)))
26 ;;; FIXME: Is THE LIST a strong enough assertion for ANSI's "should
27 ;;; return an error"? (THE LIST is optimized away when safety is low;
28 ;;; does that satisfy the spec?)
29
30 ;;; We turn IDENTITY into PROG1 so that it is obvious that it just
31 ;;; returns the first value of its argument. Ditto for VALUES with one
32 ;;; arg.
33 (def-source-transform identity (x) `(prog1 ,x))
34 (def-source-transform values (x) `(prog1 ,x))
35
36 ;;; Bind the values and make a closure that returns them.
37 (def-source-transform constantly (value &rest values)
38   (let ((temps (loop repeat (1+ (length values))
39                      collect (gensym)))
40         (dum (gensym)))
41     `(let ,(loop for temp in temps and
42                  value in (list* value values)
43                  collect `(,temp ,value))
44        #'(lambda (&rest ,dum)
45            (declare (ignore ,dum))
46            (values ,@temps)))))
47
48 ;;; If the function has a known number of arguments, then return a
49 ;;; lambda with the appropriate fixed number of args. If the
50 ;;; destination is a FUNCALL, then do the &REST APPLY thing, and let
51 ;;; MV optimization figure things out.
52 (deftransform complement ((fun) * * :node node :when :both)
53   "open code"
54   (multiple-value-bind (min max)
55       (function-type-nargs (continuation-type fun))
56     (cond
57      ((and min (eql min max))
58       (let ((dums (loop repeat min collect (gensym))))
59         `#'(lambda ,dums (not (funcall fun ,@dums)))))
60      ((let* ((cont (node-cont node))
61              (dest (continuation-dest cont)))
62         (and (combination-p dest)
63              (eq (combination-fun dest) cont)))
64       '#'(lambda (&rest args)
65            (not (apply fun args))))
66      (t
67       (give-up-ir1-transform
68        "The function doesn't have a fixed argument count.")))))
69 \f
70 ;;;; list hackery
71
72 ;;; Translate CxxR into CAR/CDR combos.
73
74 (defun source-transform-cxr (form)
75   (if (or (byte-compiling) (/= (length form) 2))
76       (values nil t)
77       (let ((name (symbol-name (car form))))
78         (do ((i (- (length name) 2) (1- i))
79              (res (cadr form)
80                   `(,(ecase (char name i)
81                        (#\A 'car)
82                        (#\D 'cdr))
83                     ,res)))
84             ((zerop i) res)))))
85
86 (do ((i 2 (1+ i))
87      (b '(1 0) (cons i b)))
88     ((= i 5))
89   (dotimes (j (ash 1 i))
90     (setf (info :function :source-transform
91                 (intern (format nil "C~{~:[A~;D~]~}R"
92                                 (mapcar #'(lambda (x) (logbitp x j)) b))))
93           #'source-transform-cxr)))
94
95 ;;; Turn FIRST..FOURTH and REST into the obvious synonym, assuming
96 ;;; whatever is right for them is right for us. FIFTH..TENTH turn into
97 ;;; Nth, which can be expanded into a CAR/CDR later on if policy
98 ;;; favors it.
99 (def-source-transform first (x) `(car ,x))
100 (def-source-transform rest (x) `(cdr ,x))
101 (def-source-transform second (x) `(cadr ,x))
102 (def-source-transform third (x) `(caddr ,x))
103 (def-source-transform fourth (x) `(cadddr ,x))
104 (def-source-transform fifth (x) `(nth 4 ,x))
105 (def-source-transform sixth (x) `(nth 5 ,x))
106 (def-source-transform seventh (x) `(nth 6 ,x))
107 (def-source-transform eighth (x) `(nth 7 ,x))
108 (def-source-transform ninth (x) `(nth 8 ,x))
109 (def-source-transform tenth (x) `(nth 9 ,x))
110
111 ;;; Translate RPLACx to LET and SETF.
112 (def-source-transform rplaca (x y)
113   (once-only ((n-x x))
114     `(progn
115        (setf (car ,n-x) ,y)
116        ,n-x)))
117 (def-source-transform rplacd (x y)
118   (once-only ((n-x x))
119     `(progn
120        (setf (cdr ,n-x) ,y)
121        ,n-x)))
122
123 (def-source-transform nth (n l) `(car (nthcdr ,n ,l)))
124
125 (defvar *default-nthcdr-open-code-limit* 6)
126 (defvar *extreme-nthcdr-open-code-limit* 20)
127
128 (deftransform nthcdr ((n l) (unsigned-byte t) * :node node)
129   "convert NTHCDR to CAxxR"
130   (unless (constant-continuation-p n)
131     (give-up-ir1-transform))
132   (let ((n (continuation-value n)))
133     (when (> n
134              (if (policy node (= speed 3) (= space 0))
135                  *extreme-nthcdr-open-code-limit*
136                  *default-nthcdr-open-code-limit*))
137       (give-up-ir1-transform))
138
139     (labels ((frob (n)
140                (if (zerop n)
141                    'l
142                    `(cdr ,(frob (1- n))))))
143       (frob n))))
144 \f
145 ;;;; arithmetic and numerology
146
147 (def-source-transform plusp (x) `(> ,x 0))
148 (def-source-transform minusp (x) `(< ,x 0))
149 (def-source-transform zerop (x) `(= ,x 0))
150
151 (def-source-transform 1+ (x) `(+ ,x 1))
152 (def-source-transform 1- (x) `(- ,x 1))
153
154 (def-source-transform oddp (x) `(not (zerop (logand ,x 1))))
155 (def-source-transform evenp (x) `(zerop (logand ,x 1)))
156
157 ;;; Note that all the integer division functions are available for
158 ;;; inline expansion.
159
160 ;;; FIXME: DEF-FROB instead of FROB
161 (macrolet ((frob (fun)
162              `(def-source-transform ,fun (x &optional (y nil y-p))
163                 (declare (ignore y))
164                 (if y-p
165                     (values nil t)
166                     `(,',fun ,x 1)))))
167   (frob truncate)
168   (frob round)
169   #!+propagate-float-type
170   (frob floor)
171   #!+propagate-float-type
172   (frob ceiling))
173
174 (def-source-transform lognand (x y) `(lognot (logand ,x ,y)))
175 (def-source-transform lognor (x y) `(lognot (logior ,x ,y)))
176 (def-source-transform logandc1 (x y) `(logand (lognot ,x) ,y))
177 (def-source-transform logandc2 (x y) `(logand ,x (lognot ,y)))
178 (def-source-transform logorc1 (x y) `(logior (lognot ,x) ,y))
179 (def-source-transform logorc2 (x y) `(logior ,x (lognot ,y)))
180 (def-source-transform logtest (x y) `(not (zerop (logand ,x ,y))))
181 (def-source-transform logbitp (index integer)
182   `(not (zerop (logand (ash 1 ,index) ,integer))))
183 (def-source-transform byte (size position) `(cons ,size ,position))
184 (def-source-transform byte-size (spec) `(car ,spec))
185 (def-source-transform byte-position (spec) `(cdr ,spec))
186 (def-source-transform ldb-test (bytespec integer)
187   `(not (zerop (mask-field ,bytespec ,integer))))
188
189 ;;; With the ratio and complex accessors, we pick off the "identity"
190 ;;; case, and use a primitive to handle the cell access case.
191 (def-source-transform numerator (num)
192   (once-only ((n-num `(the rational ,num)))
193     `(if (ratiop ,n-num)
194          (%numerator ,n-num)
195          ,n-num)))
196 (def-source-transform denominator (num)
197   (once-only ((n-num `(the rational ,num)))
198     `(if (ratiop ,n-num)
199          (%denominator ,n-num)
200          1)))
201 \f
202 ;;;; Interval arithmetic for computing bounds
203 ;;;; (toy@rtp.ericsson.se)
204 ;;;;
205 ;;;; This is a set of routines for operating on intervals. It
206 ;;;; implements a simple interval arithmetic package. Although SBCL
207 ;;;; has an interval type in numeric-type, we choose to use our own
208 ;;;; for two reasons:
209 ;;;;
210 ;;;;   1. This package is simpler than numeric-type
211 ;;;;
212 ;;;;   2. It makes debugging much easier because you can just strip
213 ;;;;   out these routines and test them independently of SBCL. (a
214 ;;;;   big win!)
215 ;;;;
216 ;;;; One disadvantage is a probable increase in consing because we
217 ;;;; have to create these new interval structures even though
218 ;;;; numeric-type has everything we want to know. Reason 2 wins for
219 ;;;; now.
220
221 #-sb-xc-host ;(CROSS-FLOAT-INFINITY-KLUDGE, see base-target-features.lisp-expr)
222 (progn
223 #!+propagate-float-type
224 (progn
225
226 ;;; The basic interval type. It can handle open and closed intervals.
227 ;;; A bound is open if it is a list containing a number, just like
228 ;;; Lisp says. NIL means unbounded.
229 (defstruct (interval
230              (:constructor %make-interval))
231   low high)
232
233 (defun make-interval (&key low high)
234   (labels ((normalize-bound (val)
235              (cond ((and (floatp val)
236                          (float-infinity-p val))
237                     ;; Handle infinities
238                     nil)
239                    ((or (numberp val)
240                         (eq val nil))
241                     ;; Handle any closed bounds
242                     val)
243                    ((listp val)
244                     ;; We have an open bound. Normalize the numeric
245                     ;; bound. If the normalized bound is still a number
246                     ;; (not nil), keep the bound open. Otherwise, the
247                     ;; bound is really unbounded, so drop the openness.
248                     (let ((new-val (normalize-bound (first val))))
249                       (when new-val
250                         ;; Bound exists, so keep it open still
251                         (list new-val))))
252                    (t
253                     (error "Unknown bound type in make-interval!")))))
254     (%make-interval :low (normalize-bound low)
255                     :high (normalize-bound high))))
256
257 #!-sb-fluid (declaim (inline bound-value set-bound))
258
259 ;;; Extract the numeric value of a bound. Return NIL, if X is NIL.
260 (defun bound-value (x)
261   (if (consp x) (car x) x))
262
263 ;;; Given a number X, create a form suitable as a bound for an
264 ;;; interval. Make the bound open if OPEN-P is T. NIL remains NIL.
265 (defun set-bound (x open-p)
266   (if (and x open-p) (list x) x))
267
268 ;;; Apply the function F to a bound X. If X is an open bound, then
269 ;;; the result will be open. IF X is NIL, the result is NIL.
270 (defun bound-func (f x)
271   (and x
272        (with-float-traps-masked (:underflow :overflow :inexact :divide-by-zero)
273          ;; With these traps masked, we might get things like infinity
274          ;; or negative infinity returned. Check for this and return
275          ;; NIL to indicate unbounded.
276          (let ((y (funcall f (bound-value x))))
277            (if (and (floatp y)
278                     (float-infinity-p y))
279                nil
280                (set-bound (funcall f (bound-value x)) (consp x)))))))
281
282 ;;; Apply a binary operator OP to two bounds X and Y. The result is
283 ;;; NIL if either is NIL. Otherwise bound is computed and the result
284 ;;; is open if either X or Y is open.
285 ;;;
286 ;;; FIXME: only used in this file, not needed in target runtime
287 (defmacro bound-binop (op x y)
288   `(and ,x ,y
289        (with-float-traps-masked (:underflow :overflow :inexact :divide-by-zero)
290          (set-bound (,op (bound-value ,x)
291                          (bound-value ,y))
292                     (or (consp ,x) (consp ,y))))))
293
294 ;;; NUMERIC-TYPE->INTERVAL
295 ;;;
296 ;;; Convert a numeric-type object to an interval object.
297
298 (defun numeric-type->interval (x)
299   (declare (type numeric-type x))
300   (make-interval :low (numeric-type-low x)
301                  :high (numeric-type-high x)))
302
303 (defun copy-interval-limit (limit)
304   (if (numberp limit)
305       limit
306       (copy-list limit)))
307
308 (defun copy-interval (x)
309   (declare (type interval x))
310   (make-interval :low (copy-interval-limit (interval-low x))
311                  :high (copy-interval-limit (interval-high x))))
312
313 ;;; INTERVAL-SPLIT
314 ;;;
315 ;;; Given a point P contained in the interval X, split X into two
316 ;;; interval at the point P. If CLOSE-LOWER is T, then the left
317 ;;; interval contains P. If CLOSE-UPPER is T, the right interval
318 ;;; contains P. You can specify both to be T or NIL.
319 (defun interval-split (p x &optional close-lower close-upper)
320   (declare (type number p)
321            (type interval x))
322   (list (make-interval :low (copy-interval-limit (interval-low x))
323                        :high (if close-lower p (list p)))
324         (make-interval :low (if close-upper (list p) p)
325                        :high (copy-interval-limit (interval-high x)))))
326
327 ;;; INTERVAL-CLOSURE
328 ;;;
329 ;;; Return the closure of the interval. That is, convert open bounds
330 ;;; to closed bounds.
331 (defun interval-closure (x)
332   (declare (type interval x))
333   (make-interval :low (bound-value (interval-low x))
334                  :high (bound-value (interval-high x))))
335
336 (defun signed-zero->= (x y)
337   (declare (real x y))
338   (or (> x y)
339       (and (= x y)
340            (>= (float-sign (float x))
341                (float-sign (float y))))))
342
343 ;;; INTERVAL-RANGE-INFO
344 ;;;
345 ;;; For an interval X, if X >= POINT, return '+. If X <= POINT, return
346 ;;; '-. Otherwise return NIL.
347 #+nil
348 (defun interval-range-info (x &optional (point 0))
349   (declare (type interval x))
350   (let ((lo (interval-low x))
351         (hi (interval-high x)))
352     (cond ((and lo (signed-zero->= (bound-value lo) point))
353            '+)
354           ((and hi (signed-zero->= point (bound-value hi)))
355            '-)
356           (t
357            nil))))
358 (defun interval-range-info (x &optional (point 0))
359   (declare (type interval x))
360   (labels ((signed->= (x y)
361              (if (and (zerop x) (zerop y) (floatp x) (floatp y))
362                  (>= (float-sign x) (float-sign y))
363                  (>= x y))))
364     (let ((lo (interval-low x))
365           (hi (interval-high x)))
366       (cond ((and lo (signed->= (bound-value lo) point))
367              '+)
368             ((and hi (signed->= point (bound-value hi)))
369              '-)
370             (t
371              nil)))))
372
373 ;;; INTERVAL-BOUNDED-P
374 ;;;
375 ;;; Test to see whether the interval X is bounded. HOW determines the
376 ;;; test, and should be either ABOVE, BELOW, or BOTH.
377 (defun interval-bounded-p (x how)
378   (declare (type interval x))
379   (ecase how
380     ('above
381      (interval-high x))
382     ('below
383      (interval-low x))
384     ('both
385      (and (interval-low x) (interval-high x)))))
386
387 ;;; Signed zero comparison functions. Use these functions if we need
388 ;;; to distinguish between signed zeroes.
389
390 (defun signed-zero-< (x y)
391   (declare (real x y))
392   (or (< x y)
393       (and (= x y)
394            (< (float-sign (float x))
395               (float-sign (float y))))))
396 (defun signed-zero-> (x y)
397   (declare (real x y))
398   (or (> x y)
399       (and (= x y)
400            (> (float-sign (float x))
401               (float-sign (float y))))))
402
403 (defun signed-zero-= (x y)
404   (declare (real x y))
405   (and (= x y)
406        (= (float-sign (float x))
407           (float-sign (float y)))))
408
409 (defun signed-zero-<= (x y)
410   (declare (real x y))
411   (or (< x y)
412       (and (= x y)
413            (<= (float-sign (float x))
414                (float-sign (float y))))))
415
416 ;;; INTERVAL-CONTAINS-P
417 ;;;
418 ;;; See whether the interval X contains the number P, taking into account
419 ;;; that the interval might not be closed.
420 (defun interval-contains-p (p x)
421   (declare (type number p)
422            (type interval x))
423   ;; Does the interval X contain the number P?  This would be a lot
424   ;; easier if all intervals were closed!
425   (let ((lo (interval-low x))
426         (hi (interval-high x)))
427     (cond ((and lo hi)
428            ;; The interval is bounded
429            (if (and (signed-zero-<= (bound-value lo) p)
430                     (signed-zero-<= p (bound-value hi)))
431                ;; P is definitely in the closure of the interval.
432                ;; We just need to check the end points now.
433                (cond ((signed-zero-= p (bound-value lo))
434                       (numberp lo))
435                      ((signed-zero-= p (bound-value hi))
436                       (numberp hi))
437                      (t t))
438                nil))
439           (hi
440            ;; Interval with upper bound
441            (if (signed-zero-< p (bound-value hi))
442                t
443                (and (numberp hi) (signed-zero-= p hi))))
444           (lo
445            ;; Interval with lower bound
446            (if (signed-zero-> p (bound-value lo))
447                t
448                (and (numberp lo) (signed-zero-= p lo))))
449           (t
450            ;; Interval with no bounds
451            t))))
452
453 ;;; INTERVAL-INTERSECT-P
454 ;;;
455 ;;; Determine if two intervals X and Y intersect. Return T if so. If
456 ;;; CLOSED-INTERVALS-P is T, the treat the intervals as if they were
457 ;;; closed. Otherwise the intervals are treated as they are.
458 ;;;
459 ;;; Thus if X = [0, 1) and Y = (1, 2), then they do not intersect
460 ;;; because no element in X is in Y. However, if CLOSED-INTERVALS-P
461 ;;; is T, then they do intersect because we use the closure of X = [0,
462 ;;; 1] and Y = [1, 2] to determine intersection.
463 (defun interval-intersect-p (x y &optional closed-intervals-p)
464   (declare (type interval x y))
465   (multiple-value-bind (intersect diff)
466       (interval-intersection/difference (if closed-intervals-p
467                                             (interval-closure x)
468                                             x)
469                                         (if closed-intervals-p
470                                             (interval-closure y)
471                                             y))
472     (declare (ignore diff))
473     intersect))
474
475 ;;; Are the two intervals adjacent?  That is, is there a number
476 ;;; between the two intervals that is not an element of either
477 ;;; interval?  If so, they are not adjacent. For example [0, 1) and
478 ;;; [1, 2] are adjacent but [0, 1) and (1, 2] are not because 1 lies
479 ;;; between both intervals.
480 (defun interval-adjacent-p (x y)
481   (declare (type interval x y))
482   (flet ((adjacent (lo hi)
483            ;; Check to see whether lo and hi are adjacent. If either is
484            ;; nil, they can't be adjacent.
485            (when (and lo hi (= (bound-value lo) (bound-value hi)))
486              ;; The bounds are equal. They are adjacent if one of
487              ;; them is closed (a number). If both are open (consp),
488              ;; then there is a number that lies between them.
489              (or (numberp lo) (numberp hi)))))
490     (or (adjacent (interval-low y) (interval-high x))
491         (adjacent (interval-low x) (interval-high y)))))
492
493 ;;; INTERVAL-INTERSECTION/DIFFERENCE
494 ;;;
495 ;;; Compute the intersection and difference between two intervals.
496 ;;; Two values are returned: the intersection and the difference.
497 ;;;
498 ;;; Let the two intervals be X and Y, and let I and D be the two
499 ;;; values returned by this function. Then I = X intersect Y. If I
500 ;;; is NIL (the empty set), then D is X union Y, represented as the
501 ;;; list of X and Y. If I is not the empty set, then D is (X union Y)
502 ;;; - I, which is a list of two intervals.
503 ;;;
504 ;;; For example, let X = [1,5] and Y = [-1,3). Then I = [1,3) and D =
505 ;;; [-1,1) union [3,5], which is returned as a list of two intervals.
506 (defun interval-intersection/difference (x y)
507   (declare (type interval x y))
508   (let ((x-lo (interval-low x))
509         (x-hi (interval-high x))
510         (y-lo (interval-low y))
511         (y-hi (interval-high y)))
512     (labels
513         ((opposite-bound (p)
514            ;; If p is an open bound, make it closed. If p is a closed
515            ;; bound, make it open.
516            (if (listp p)
517                (first p)
518                (list p)))
519          (test-number (p int)
520            ;; Test whether P is in the interval.
521            (when (interval-contains-p (bound-value p)
522                                       (interval-closure int))
523              (let ((lo (interval-low int))
524                    (hi (interval-high int)))
525                ;; Check for endpoints
526                (cond ((and lo (= (bound-value p) (bound-value lo)))
527                       (not (and (consp p) (numberp lo))))
528                      ((and hi (= (bound-value p) (bound-value hi)))
529                       (not (and (numberp p) (consp hi))))
530                      (t t)))))
531          (test-lower-bound (p int)
532            ;; P is a lower bound of an interval.
533            (if p
534                (test-number p int)
535                (not (interval-bounded-p int 'below))))
536          (test-upper-bound (p int)
537            ;; P is an upper bound of an interval
538            (if p
539                (test-number p int)
540                (not (interval-bounded-p int 'above)))))
541       (let ((x-lo-in-y (test-lower-bound x-lo y))
542             (x-hi-in-y (test-upper-bound x-hi y))
543             (y-lo-in-x (test-lower-bound y-lo x))
544             (y-hi-in-x (test-upper-bound y-hi x)))
545         (cond ((or x-lo-in-y x-hi-in-y y-lo-in-x y-hi-in-x)
546                ;; Intervals intersect. Let's compute the intersection
547                ;; and the difference.
548                (multiple-value-bind (lo left-lo left-hi)
549                    (cond (x-lo-in-y (values x-lo y-lo (opposite-bound x-lo)))
550                          (y-lo-in-x (values y-lo x-lo (opposite-bound y-lo))))
551                  (multiple-value-bind (hi right-lo right-hi)
552                      (cond (x-hi-in-y
553                             (values x-hi (opposite-bound x-hi) y-hi))
554                            (y-hi-in-x
555                             (values y-hi (opposite-bound y-hi) x-hi)))
556                    (values (make-interval :low lo :high hi)
557                            (list (make-interval :low left-lo :high left-hi)
558                                  (make-interval :low right-lo :high right-hi))))))
559               (t
560                (values nil (list x y))))))))
561
562 ;;; INTERVAL-MERGE-PAIR
563 ;;;
564 ;;; If intervals X and Y intersect, return a new interval that is the
565 ;;; union of the two. If they do not intersect, return NIL.
566 (defun interval-merge-pair (x y)
567   (declare (type interval x y))
568   ;; If x and y intersect or are adjacent, create the union.
569   ;; Otherwise return nil
570   (when (or (interval-intersect-p x y)
571             (interval-adjacent-p x y))
572     (flet ((select-bound (x1 x2 min-op max-op)
573              (let ((x1-val (bound-value x1))
574                    (x2-val (bound-value x2)))
575                (cond ((and x1 x2)
576                       ;; Both bounds are finite. Select the right one.
577                       (cond ((funcall min-op x1-val x2-val)
578                              ;; x1 definitely better
579                              x1)
580                             ((funcall max-op x1-val x2-val)
581                              ;; x2 definitely better
582                              x2)
583                             (t
584                              ;; Bounds are equal. Select either
585                              ;; value and make it open only if
586                              ;; both were open.
587                              (set-bound x1-val (and (consp x1) (consp x2))))))
588                      (t
589                       ;; At least one bound is not finite. The
590                       ;; non-finite bound always wins.
591                       nil)))))
592       (let* ((x-lo (copy-interval-limit (interval-low x)))
593              (x-hi (copy-interval-limit (interval-high x)))
594              (y-lo (copy-interval-limit (interval-low y)))
595              (y-hi (copy-interval-limit (interval-high y))))
596         (make-interval :low (select-bound x-lo y-lo #'< #'>)
597                        :high (select-bound x-hi y-hi #'> #'<))))))
598
599 ;;; Basic arithmetic operations on intervals. We probably should do
600 ;;; true interval arithmetic here, but it's complicated because we
601 ;;; have float and integer types and bounds can be open or closed.
602
603 ;;; INTERVAL-NEG
604 ;;;
605 ;;; The negative of an interval
606 (defun interval-neg (x)
607   (declare (type interval x))
608   (make-interval :low (bound-func #'- (interval-high x))
609                  :high (bound-func #'- (interval-low x))))
610
611 ;;; INTERVAL-ADD
612 ;;;
613 ;;; Add two intervals
614 (defun interval-add (x y)
615   (declare (type interval x y))
616   (make-interval :low (bound-binop + (interval-low x) (interval-low y))
617                  :high (bound-binop + (interval-high x) (interval-high y))))
618
619 ;;; INTERVAL-SUB
620 ;;;
621 ;;; Subtract two intervals
622 (defun interval-sub (x y)
623   (declare (type interval x y))
624   (make-interval :low (bound-binop - (interval-low x) (interval-high y))
625                  :high (bound-binop - (interval-high x) (interval-low y))))
626
627 ;;; INTERVAL-MUL
628 ;;;
629 ;;; Multiply two intervals
630 (defun interval-mul (x y)
631   (declare (type interval x y))
632   (flet ((bound-mul (x y)
633            (cond ((or (null x) (null y))
634                   ;; Multiply by infinity is infinity
635                   nil)
636                  ((or (and (numberp x) (zerop x))
637                       (and (numberp y) (zerop y)))
638                   ;; Multiply by closed zero is special. The result
639                   ;; is always a closed bound. But don't replace this
640                   ;; with zero; we want the multiplication to produce
641                   ;; the correct signed zero, if needed.
642                   (* (bound-value x) (bound-value y)))
643                  ((or (and (floatp x) (float-infinity-p x))
644                       (and (floatp y) (float-infinity-p y)))
645                   ;; Infinity times anything is infinity
646                   nil)
647                  (t
648                   ;; General multiply. The result is open if either is open.
649                   (bound-binop * x y)))))
650     (let ((x-range (interval-range-info x))
651           (y-range (interval-range-info y)))
652       (cond ((null x-range)
653              ;; Split x into two and multiply each separately
654              (destructuring-bind (x- x+) (interval-split 0 x t t)
655                (interval-merge-pair (interval-mul x- y)
656                                     (interval-mul x+ y))))
657             ((null y-range)
658              ;; Split y into two and multiply each separately
659              (destructuring-bind (y- y+) (interval-split 0 y t t)
660                (interval-merge-pair (interval-mul x y-)
661                                     (interval-mul x y+))))
662             ((eq x-range '-)
663              (interval-neg (interval-mul (interval-neg x) y)))
664             ((eq y-range '-)
665              (interval-neg (interval-mul x (interval-neg y))))
666             ((and (eq x-range '+) (eq y-range '+))
667              ;; If we are here, X and Y are both positive
668              (make-interval :low (bound-mul (interval-low x) (interval-low y))
669                             :high (bound-mul (interval-high x) (interval-high y))))
670             (t
671              (error "This shouldn't happen!"))))))
672
673 ;;; INTERVAL-DIV
674 ;;;
675 ;;; Divide two intervals.
676 (defun interval-div (top bot)
677   (declare (type interval top bot))
678   (flet ((bound-div (x y y-low-p)
679            ;; Compute x/y
680            (cond ((null y)
681                   ;; Divide by infinity means result is 0. However,
682                   ;; we need to watch out for the sign of the result,
683                   ;; to correctly handle signed zeros. We also need
684                   ;; to watch out for positive or negative infinity.
685                   (if (floatp (bound-value x))
686                       (if y-low-p
687                           (- (float-sign (bound-value x) 0.0))
688                           (float-sign (bound-value x) 0.0))
689                       0))
690                  ((zerop (bound-value y))
691                   ;; Divide by zero means result is infinity
692                   nil)
693                  ((and (numberp x) (zerop x))
694                   ;; Zero divided by anything is zero.
695                   x)
696                  (t
697                   (bound-binop / x y)))))
698     (let ((top-range (interval-range-info top))
699           (bot-range (interval-range-info bot)))
700       (cond ((null bot-range)
701              ;; The denominator contains zero, so anything goes!
702              (make-interval :low nil :high nil))
703             ((eq bot-range '-)
704              ;; Denominator is negative so flip the sign, compute the
705              ;; result, and flip it back.
706              (interval-neg (interval-div top (interval-neg bot))))
707             ((null top-range)
708              ;; Split top into two positive and negative parts, and
709              ;; divide each separately
710              (destructuring-bind (top- top+) (interval-split 0 top t t)
711                (interval-merge-pair (interval-div top- bot)
712                                     (interval-div top+ bot))))
713             ((eq top-range '-)
714              ;; Top is negative so flip the sign, divide, and flip the
715              ;; sign of the result.
716              (interval-neg (interval-div (interval-neg top) bot)))
717             ((and (eq top-range '+) (eq bot-range '+))
718              ;; The easy case
719              (make-interval :low (bound-div (interval-low top) (interval-high bot) t)
720                             :high (bound-div (interval-high top) (interval-low bot) nil)))
721             (t
722              (error "This shouldn't happen!"))))))
723
724 ;;; INTERVAL-FUNC
725 ;;;
726 ;;; Apply the function F to the interval X. If X = [a, b], then the
727 ;;; result is [f(a), f(b)]. It is up to the user to make sure the
728 ;;; result makes sense. It will if F is monotonic increasing (or
729 ;;; non-decreasing).
730 (defun interval-func (f x)
731   (declare (type interval x))
732   (let ((lo (bound-func f (interval-low x)))
733         (hi (bound-func f (interval-high x))))
734     (make-interval :low lo :high hi)))
735
736 ;;; INTERVAL-<
737 ;;;
738 ;;; Return T if X < Y. That is every number in the interval X is
739 ;;; always less than any number in the interval Y.
740 (defun interval-< (x y)
741   (declare (type interval x y))
742   ;; X < Y only if X is bounded above, Y is bounded below, and they
743   ;; don't overlap.
744   (when (and (interval-bounded-p x 'above)
745              (interval-bounded-p y 'below))
746     ;; Intervals are bounded in the appropriate way. Make sure they
747     ;; don't overlap.
748     (let ((left (interval-high x))
749           (right (interval-low y)))
750       (cond ((> (bound-value left)
751                 (bound-value right))
752              ;; Definitely overlap so result is NIL
753              nil)
754             ((< (bound-value left)
755                 (bound-value right))
756              ;; Definitely don't touch, so result is T
757              t)
758             (t
759              ;; Limits are equal. Check for open or closed bounds.
760              ;; Don't overlap if one or the other are open.
761              (or (consp left) (consp right)))))))
762
763 ;;; INVTERVAL->=
764 ;;;
765 ;;; Return T if X >= Y. That is, every number in the interval X is
766 ;;; always greater than any number in the interval Y.
767 (defun interval->= (x y)
768   (declare (type interval x y))
769   ;; X >= Y if lower bound of X >= upper bound of Y
770   (when (and (interval-bounded-p x 'below)
771              (interval-bounded-p y 'above))
772     (>= (bound-value (interval-low x)) (bound-value (interval-high y)))))
773
774 ;;; INTERVAL-ABS
775 ;;;
776 ;;; Return an interval that is the absolute value of X. Thus, if X =
777 ;;; [-1 10], the result is [0, 10].
778 (defun interval-abs (x)
779   (declare (type interval x))
780   (case (interval-range-info x)
781     ('+
782      (copy-interval x))
783     ('-
784      (interval-neg x))
785     (t
786      (destructuring-bind (x- x+) (interval-split 0 x t t)
787        (interval-merge-pair (interval-neg x-) x+)))))
788
789 ;;; INTERVAL-SQR
790 ;;;
791 ;;; Compute the square of an interval.
792 (defun interval-sqr (x)
793   (declare (type interval x))
794   (interval-func #'(lambda (x) (* x x))
795                  (interval-abs x)))
796 )) ; end PROGN's
797 \f
798 ;;;; numeric derive-type methods
799
800 ;;; Utility for defining derive-type methods of integer operations. If the
801 ;;; types of both X and Y are integer types, then we compute a new integer type
802 ;;; with bounds determined Fun when applied to X and Y. Otherwise, we use
803 ;;; Numeric-Contagion.
804 (defun derive-integer-type (x y fun)
805   (declare (type continuation x y) (type function fun))
806   (let ((x (continuation-type x))
807         (y (continuation-type y)))
808     (if (and (numeric-type-p x) (numeric-type-p y)
809              (eq (numeric-type-class x) 'integer)
810              (eq (numeric-type-class y) 'integer)
811              (eq (numeric-type-complexp x) :real)
812              (eq (numeric-type-complexp y) :real))
813         (multiple-value-bind (low high) (funcall fun x y)
814           (make-numeric-type :class 'integer
815                              :complexp :real
816                              :low low
817                              :high high))
818         (numeric-contagion x y))))
819
820 #!+(or propagate-float-type propagate-fun-type)
821 (progn
822
823 ;; Simple utility to flatten a list
824 (defun flatten-list (x)
825   (labels ((flatten-helper (x r);; 'r' is the stuff to the 'right'.
826              (cond ((null x) r)
827                    ((atom x)
828                     (cons x r))
829                    (t (flatten-helper (car x)
830                                       (flatten-helper (cdr x) r))))))
831     (flatten-helper x nil)))
832
833 ;;; Take some type of continuation and massage it so that we get a
834 ;;; list of the constituent types. If ARG is *EMPTY-TYPE*, return NIL
835 ;;; to indicate failure.
836 (defun prepare-arg-for-derive-type (arg)
837   (flet ((listify (arg)
838            (typecase arg
839              (numeric-type
840               (list arg))
841              (union-type
842               (union-type-types arg))
843              (t
844               (list arg)))))
845     (unless (eq arg *empty-type*)
846       ;; Make sure all args are some type of numeric-type. For member
847       ;; types, convert the list of members into a union of equivalent
848       ;; single-element member-type's.
849       (let ((new-args nil))
850         (dolist (arg (listify arg))
851           (if (member-type-p arg)
852               ;; Run down the list of members and convert to a list of
853               ;; member types.
854               (dolist (member (member-type-members arg))
855                 (push (if (numberp member)
856                           (make-member-type :members (list member))
857                           *empty-type*)
858                       new-args))
859               (push arg new-args)))
860         (unless (member *empty-type* new-args)
861           new-args)))))
862
863 ;;; Convert from the standard type convention for which -0.0 and 0.0
864 ;;; and equal to an intermediate convention for which they are
865 ;;; considered different which is more natural for some of the
866 ;;; optimisers.
867 #!-negative-zero-is-not-zero
868 (defun convert-numeric-type (type)
869   (declare (type numeric-type type))
870   ;;; Only convert real float interval delimiters types.
871   (if (eq (numeric-type-complexp type) :real)
872       (let* ((lo (numeric-type-low type))
873              (lo-val (bound-value lo))
874              (lo-float-zero-p (and lo (floatp lo-val) (= lo-val 0.0)))
875              (hi (numeric-type-high type))
876              (hi-val (bound-value hi))
877              (hi-float-zero-p (and hi (floatp hi-val) (= hi-val 0.0))))
878         (if (or lo-float-zero-p hi-float-zero-p)
879             (make-numeric-type
880              :class (numeric-type-class type)
881              :format (numeric-type-format type)
882              :complexp :real
883              :low (if lo-float-zero-p
884                       (if (consp lo)
885                           (list (float 0.0 lo-val))
886                           (float -0.0 lo-val))
887                       lo)
888              :high (if hi-float-zero-p
889                        (if (consp hi)
890                            (list (float -0.0 hi-val))
891                            (float 0.0 hi-val))
892                        hi))
893             type))
894       ;; Not real float.
895       type))
896
897 ;;; Convert back from the intermediate convention for which -0.0 and
898 ;;; 0.0 are considered different to the standard type convention for
899 ;;; which and equal.
900 #!-negative-zero-is-not-zero
901 (defun convert-back-numeric-type (type)
902   (declare (type numeric-type type))
903   ;;; Only convert real float interval delimiters types.
904   (if (eq (numeric-type-complexp type) :real)
905       (let* ((lo (numeric-type-low type))
906              (lo-val (bound-value lo))
907              (lo-float-zero-p
908               (and lo (floatp lo-val) (= lo-val 0.0)
909                    (float-sign lo-val)))
910              (hi (numeric-type-high type))
911              (hi-val (bound-value hi))
912              (hi-float-zero-p
913               (and hi (floatp hi-val) (= hi-val 0.0)
914                    (float-sign hi-val))))
915         (cond
916           ;; (float +0.0 +0.0) => (member 0.0)
917           ;; (float -0.0 -0.0) => (member -0.0)
918           ((and lo-float-zero-p hi-float-zero-p)
919            ;; Shouldn't have exclusive bounds here.
920            (assert (and (not (consp lo)) (not (consp hi))))
921            (if (= lo-float-zero-p hi-float-zero-p)
922                ;; (float +0.0 +0.0) => (member 0.0)
923                ;; (float -0.0 -0.0) => (member -0.0)
924                (specifier-type `(member ,lo-val))
925                ;; (float -0.0 +0.0) => (float 0.0 0.0)
926                ;; (float +0.0 -0.0) => (float 0.0 0.0)
927                (make-numeric-type :class (numeric-type-class type)
928                                   :format (numeric-type-format type)
929                                   :complexp :real
930                                   :low hi-val
931                                   :high hi-val)))
932           (lo-float-zero-p
933            (cond
934              ;; (float -0.0 x) => (float 0.0 x)
935              ((and (not (consp lo)) (minusp lo-float-zero-p))
936               (make-numeric-type :class (numeric-type-class type)
937                                  :format (numeric-type-format type)
938                                  :complexp :real
939                                  :low (float 0.0 lo-val)
940                                  :high hi))
941              ;; (float (+0.0) x) => (float (0.0) x)
942              ((and (consp lo) (plusp lo-float-zero-p))
943               (make-numeric-type :class (numeric-type-class type)
944                                  :format (numeric-type-format type)
945                                  :complexp :real
946                                  :low (list (float 0.0 lo-val))
947                                  :high hi))
948              (t
949               ;; (float +0.0 x) => (or (member 0.0) (float (0.0) x))
950               ;; (float (-0.0) x) => (or (member 0.0) (float (0.0) x))
951               (list (make-member-type :members (list (float 0.0 lo-val)))
952                     (make-numeric-type :class (numeric-type-class type)
953                                        :format (numeric-type-format type)
954                                        :complexp :real
955                                        :low (list (float 0.0 lo-val))
956                                        :high hi)))))
957           (hi-float-zero-p
958            (cond
959              ;; (float x +0.0) => (float x 0.0)
960              ((and (not (consp hi)) (plusp hi-float-zero-p))
961               (make-numeric-type :class (numeric-type-class type)
962                                  :format (numeric-type-format type)
963                                  :complexp :real
964                                  :low lo
965                                  :high (float 0.0 hi-val)))
966              ;; (float x (-0.0)) => (float x (0.0))
967              ((and (consp hi) (minusp hi-float-zero-p))
968               (make-numeric-type :class (numeric-type-class type)
969                                  :format (numeric-type-format type)
970                                  :complexp :real
971                                  :low lo
972                                  :high (list (float 0.0 hi-val))))
973              (t
974               ;; (float x (+0.0)) => (or (member -0.0) (float x (0.0)))
975               ;; (float x -0.0) => (or (member -0.0) (float x (0.0)))
976               (list (make-member-type :members (list (float -0.0 hi-val)))
977                     (make-numeric-type :class (numeric-type-class type)
978                                        :format (numeric-type-format type)
979                                        :complexp :real
980                                        :low lo
981                                        :high (list (float 0.0 hi-val)))))))
982           (t
983            type)))
984       ;; Not real float.
985       type))
986
987 ;;; Convert back a possible list of numeric types.
988 #!-negative-zero-is-not-zero
989 (defun convert-back-numeric-type-list (type-list)
990   (typecase type-list
991     (list
992      (let ((results '()))
993        (dolist (type type-list)
994          (if (numeric-type-p type)
995              (let ((result (convert-back-numeric-type type)))
996                (if (listp result)
997                    (setf results (append results result))
998                    (push result results)))
999              (push type results)))
1000        results))
1001     (numeric-type
1002      (convert-back-numeric-type type-list))
1003     (union-type
1004      (convert-back-numeric-type-list (union-type-types type-list)))
1005     (t
1006      type-list)))
1007
1008 ;;; Make-Canonical-Union-Type
1009 ;;;
1010 ;;; Take a list of types and return a canonical type specifier,
1011 ;;; combining any members types together. If both positive and
1012 ;;; negative members types are present they are converted to a float
1013 ;;; type. X This would be far simpler if the type-union methods could
1014 ;;; handle member/number unions.
1015 (defun make-canonical-union-type (type-list)
1016   (let ((members '())
1017         (misc-types '()))
1018     (dolist (type type-list)
1019       (if (member-type-p type)
1020           (setf members (union members (member-type-members type)))
1021           (push type misc-types)))
1022     #!+long-float
1023     (when (null (set-difference '(-0l0 0l0) members))
1024       #!-negative-zero-is-not-zero
1025       (push (specifier-type '(long-float 0l0 0l0)) misc-types)
1026       #!+negative-zero-is-not-zero
1027       (push (specifier-type '(long-float -0l0 0l0)) misc-types)
1028       (setf members (set-difference members '(-0l0 0l0))))
1029     (when (null (set-difference '(-0d0 0d0) members))
1030       #!-negative-zero-is-not-zero
1031       (push (specifier-type '(double-float 0d0 0d0)) misc-types)
1032       #!+negative-zero-is-not-zero
1033       (push (specifier-type '(double-float -0d0 0d0)) misc-types)
1034       (setf members (set-difference members '(-0d0 0d0))))
1035     (when (null (set-difference '(-0f0 0f0) members))
1036       #!-negative-zero-is-not-zero
1037       (push (specifier-type '(single-float 0f0 0f0)) misc-types)
1038       #!+negative-zero-is-not-zero
1039       (push (specifier-type '(single-float -0f0 0f0)) misc-types)
1040       (setf members (set-difference members '(-0f0 0f0))))
1041     (cond ((null members)
1042            (let ((res (first misc-types)))
1043              (dolist (type (rest misc-types))
1044                (setq res (type-union res type)))
1045              res))
1046           ((null misc-types)
1047            (make-member-type :members members))
1048           (t
1049            (let ((res (first misc-types)))
1050              (dolist (type (rest misc-types))
1051                (setq res (type-union res type)))
1052              (dolist (type members)
1053                (setq res (type-union
1054                           res (make-member-type :members (list type)))))
1055              res)))))
1056
1057 ;;; Convert-Member-Type
1058 ;;;
1059 ;;; Convert a member type with a single member to a numeric type.
1060 (defun convert-member-type (arg)
1061   (let* ((members (member-type-members arg))
1062          (member (first members))
1063          (member-type (type-of member)))
1064     (assert (not (rest members)))
1065     (specifier-type `(,(if (subtypep member-type 'integer)
1066                            'integer
1067                            member-type)
1068                       ,member ,member))))
1069
1070 ;;; ONE-ARG-DERIVE-TYPE
1071 ;;;
1072 ;;; This is used in defoptimizers for computing the resulting type of
1073 ;;; a function.
1074 ;;;
1075 ;;; Given the continuation ARG, derive the resulting type using the
1076 ;;; DERIVE-FCN. DERIVE-FCN takes exactly one argument which is some
1077 ;;; "atomic" continuation type like numeric-type or member-type
1078 ;;; (containing just one element). It should return the resulting
1079 ;;; type, which can be a list of types.
1080 ;;;
1081 ;;; For the case of member types, if a member-fcn is given it is
1082 ;;; called to compute the result otherwise the member type is first
1083 ;;; converted to a numeric type and the derive-fcn is call.
1084 (defun one-arg-derive-type (arg derive-fcn member-fcn
1085                                 &optional (convert-type t))
1086   (declare (type function derive-fcn)
1087            (type (or null function) member-fcn)
1088            #!+negative-zero-is-not-zero (ignore convert-type))
1089   (let ((arg-list (prepare-arg-for-derive-type (continuation-type arg))))
1090     (when arg-list
1091       (flet ((deriver (x)
1092                (typecase x
1093                  (member-type
1094                   (if member-fcn
1095                       (with-float-traps-masked
1096                           (:underflow :overflow :divide-by-zero)
1097                         (make-member-type
1098                          :members (list
1099                                    (funcall member-fcn
1100                                             (first (member-type-members x))))))
1101                       ;; Otherwise convert to a numeric type.
1102                       (let ((result-type-list
1103                              (funcall derive-fcn (convert-member-type x))))
1104                         #!-negative-zero-is-not-zero
1105                         (if convert-type
1106                             (convert-back-numeric-type-list result-type-list)
1107                             result-type-list)
1108                         #!+negative-zero-is-not-zero
1109                         result-type-list)))
1110                  (numeric-type
1111                   #!-negative-zero-is-not-zero
1112                   (if convert-type
1113                       (convert-back-numeric-type-list
1114                        (funcall derive-fcn (convert-numeric-type x)))
1115                       (funcall derive-fcn x))
1116                   #!+negative-zero-is-not-zero
1117                   (funcall derive-fcn x))
1118                  (t
1119                   *universal-type*))))
1120         ;; Run down the list of args and derive the type of each one,
1121         ;; saving all of the results in a list.
1122         (let ((results nil))
1123           (dolist (arg arg-list)
1124             (let ((result (deriver arg)))
1125               (if (listp result)
1126                   (setf results (append results result))
1127                   (push result results))))
1128           (if (rest results)
1129               (make-canonical-union-type results)
1130               (first results)))))))
1131
1132 ;;; TWO-ARG-DERIVE-TYPE
1133 ;;;
1134 ;;; Same as ONE-ARG-DERIVE-TYPE, except we assume the function takes
1135 ;;; two arguments. DERIVE-FCN takes 3 args in this case: the two
1136 ;;; original args and a third which is T to indicate if the two args
1137 ;;; really represent the same continuation. This is useful for
1138 ;;; deriving the type of things like (* x x), which should always be
1139 ;;; positive. If we didn't do this, we wouldn't be able to tell.
1140 (defun two-arg-derive-type (arg1 arg2 derive-fcn fcn
1141                                  &optional (convert-type t))
1142   #!+negative-zero-is-not-zero
1143   (declare (ignore convert-type))
1144   (flet (#!-negative-zero-is-not-zero
1145          (deriver (x y same-arg)
1146            (cond ((and (member-type-p x) (member-type-p y))
1147                   (let* ((x (first (member-type-members x)))
1148                          (y (first (member-type-members y)))
1149                          (result (with-float-traps-masked
1150                                      (:underflow :overflow :divide-by-zero
1151                                       :invalid)
1152                                    (funcall fcn x y))))
1153                     (cond ((null result))
1154                           ((and (floatp result) (float-nan-p result))
1155                            (make-numeric-type
1156                             :class 'float
1157                             :format (type-of result)
1158                             :complexp :real))
1159                           (t
1160                            (make-member-type :members (list result))))))
1161                  ((and (member-type-p x) (numeric-type-p y))
1162                   (let* ((x (convert-member-type x))
1163                          (y (if convert-type (convert-numeric-type y) y))
1164                          (result (funcall derive-fcn x y same-arg)))
1165                     (if convert-type
1166                         (convert-back-numeric-type-list result)
1167                         result)))
1168                  ((and (numeric-type-p x) (member-type-p y))
1169                   (let* ((x (if convert-type (convert-numeric-type x) x))
1170                          (y (convert-member-type y))
1171                          (result (funcall derive-fcn x y same-arg)))
1172                     (if convert-type
1173                         (convert-back-numeric-type-list result)
1174                         result)))
1175                  ((and (numeric-type-p x) (numeric-type-p y))
1176                   (let* ((x (if convert-type (convert-numeric-type x) x))
1177                          (y (if convert-type (convert-numeric-type y) y))
1178                          (result (funcall derive-fcn x y same-arg)))
1179                     (if convert-type
1180                         (convert-back-numeric-type-list result)
1181                         result)))
1182                  (t
1183                   *universal-type*)))
1184          #!+negative-zero-is-not-zero
1185          (deriver (x y same-arg)
1186            (cond ((and (member-type-p x) (member-type-p y))
1187                   (let* ((x (first (member-type-members x)))
1188                          (y (first (member-type-members y)))
1189                          (result (with-float-traps-masked
1190                                      (:underflow :overflow :divide-by-zero)
1191                                    (funcall fcn x y))))
1192                     (if result
1193                         (make-member-type :members (list result)))))
1194                  ((and (member-type-p x) (numeric-type-p y))
1195                   (let ((x (convert-member-type x)))
1196                     (funcall derive-fcn x y same-arg)))
1197                  ((and (numeric-type-p x) (member-type-p y))
1198                   (let ((y (convert-member-type y)))
1199                     (funcall derive-fcn x y same-arg)))
1200                  ((and (numeric-type-p x) (numeric-type-p y))
1201                   (funcall derive-fcn x y same-arg))
1202                  (t
1203                   *universal-type*))))
1204     (let ((same-arg (same-leaf-ref-p arg1 arg2))
1205           (a1 (prepare-arg-for-derive-type (continuation-type arg1)))
1206           (a2 (prepare-arg-for-derive-type (continuation-type arg2))))
1207       (when (and a1 a2)
1208         (let ((results nil))
1209           (if same-arg
1210               ;; Since the args are the same continuation, just run
1211               ;; down the lists.
1212               (dolist (x a1)
1213                 (let ((result (deriver x x same-arg)))
1214                   (if (listp result)
1215                       (setf results (append results result))
1216                       (push result results))))
1217               ;; Try all pairwise combinations.
1218               (dolist (x a1)
1219                 (dolist (y a2)
1220                   (let ((result (or (deriver x y same-arg)
1221                                     (numeric-contagion x y))))
1222                     (if (listp result)
1223                         (setf results (append results result))
1224                         (push result results))))))
1225           (if (rest results)
1226               (make-canonical-union-type results)
1227               (first results)))))))
1228
1229 ) ; PROGN
1230 \f
1231 #!-propagate-float-type
1232 (progn
1233 (defoptimizer (+ derive-type) ((x y))
1234   (derive-integer-type
1235    x y
1236    #'(lambda (x y)
1237        (flet ((frob (x y)
1238                 (if (and x y)
1239                     (+ x y)
1240                     nil)))
1241          (values (frob (numeric-type-low x) (numeric-type-low y))
1242                  (frob (numeric-type-high x) (numeric-type-high y)))))))
1243
1244 (defoptimizer (- derive-type) ((x y))
1245   (derive-integer-type
1246    x y
1247    #'(lambda (x y)
1248        (flet ((frob (x y)
1249                 (if (and x y)
1250                     (- x y)
1251                     nil)))
1252          (values (frob (numeric-type-low x) (numeric-type-high y))
1253                  (frob (numeric-type-high x) (numeric-type-low y)))))))
1254
1255 (defoptimizer (* derive-type) ((x y))
1256   (derive-integer-type
1257    x y
1258    #'(lambda (x y)
1259        (let ((x-low (numeric-type-low x))
1260              (x-high (numeric-type-high x))
1261              (y-low (numeric-type-low y))
1262              (y-high (numeric-type-high y)))
1263          (cond ((not (and x-low y-low))
1264                 (values nil nil))
1265                ((or (minusp x-low) (minusp y-low))
1266                 (if (and x-high y-high)
1267                     (let ((max (* (max (abs x-low) (abs x-high))
1268                                   (max (abs y-low) (abs y-high)))))
1269                       (values (- max) max))
1270                     (values nil nil)))
1271                (t
1272                 (values (* x-low y-low)
1273                         (if (and x-high y-high)
1274                             (* x-high y-high)
1275                             nil))))))))
1276
1277 (defoptimizer (/ derive-type) ((x y))
1278   (numeric-contagion (continuation-type x) (continuation-type y)))
1279
1280 ) ; PROGN
1281
1282 #!+propagate-float-type
1283 (progn
1284 (defun +-derive-type-aux (x y same-arg)
1285   (if (and (numeric-type-real-p x)
1286            (numeric-type-real-p y))
1287       (let ((result
1288              (if same-arg
1289                  (let ((x-int (numeric-type->interval x)))
1290                    (interval-add x-int x-int))
1291                  (interval-add (numeric-type->interval x)
1292                                (numeric-type->interval y))))
1293             (result-type (numeric-contagion x y)))
1294         ;; If the result type is a float, we need to be sure to coerce
1295         ;; the bounds into the correct type.
1296         (when (eq (numeric-type-class result-type) 'float)
1297           (setf result (interval-func
1298                         #'(lambda (x)
1299                             (coerce x (or (numeric-type-format result-type)
1300                                           'float)))
1301                         result)))
1302         (make-numeric-type
1303          :class (if (and (eq (numeric-type-class x) 'integer)
1304                          (eq (numeric-type-class y) 'integer))
1305                     ;; The sum of integers is always an integer
1306                     'integer
1307                     (numeric-type-class result-type))
1308          :format (numeric-type-format result-type)
1309          :low (interval-low result)
1310          :high (interval-high result)))
1311       ;; General contagion
1312       (numeric-contagion x y)))
1313
1314 (defoptimizer (+ derive-type) ((x y))
1315   (two-arg-derive-type x y #'+-derive-type-aux #'+))
1316
1317 (defun --derive-type-aux (x y same-arg)
1318   (if (and (numeric-type-real-p x)
1319            (numeric-type-real-p y))
1320       (let ((result
1321              ;; (- x x) is always 0.
1322              (if same-arg
1323                  (make-interval :low 0 :high 0)
1324                  (interval-sub (numeric-type->interval x)
1325                                (numeric-type->interval y))))
1326             (result-type (numeric-contagion x y)))
1327         ;; If the result type is a float, we need to be sure to coerce
1328         ;; the bounds into the correct type.
1329         (when (eq (numeric-type-class result-type) 'float)
1330           (setf result (interval-func
1331                         #'(lambda (x)
1332                             (coerce x (or (numeric-type-format result-type)
1333                                           'float)))
1334                         result)))
1335         (make-numeric-type
1336          :class (if (and (eq (numeric-type-class x) 'integer)
1337                          (eq (numeric-type-class y) 'integer))
1338                     ;; The difference of integers is always an integer
1339                     'integer
1340                     (numeric-type-class result-type))
1341          :format (numeric-type-format result-type)
1342          :low (interval-low result)
1343          :high (interval-high result)))
1344       ;; General contagion
1345       (numeric-contagion x y)))
1346
1347 (defoptimizer (- derive-type) ((x y))
1348   (two-arg-derive-type x y #'--derive-type-aux #'-))
1349
1350 (defun *-derive-type-aux (x y same-arg)
1351   (if (and (numeric-type-real-p x)
1352            (numeric-type-real-p y))
1353       (let ((result
1354              ;; (* x x) is always positive, so take care to do it
1355              ;; right.
1356              (if same-arg
1357                  (interval-sqr (numeric-type->interval x))
1358                  (interval-mul (numeric-type->interval x)
1359                                (numeric-type->interval y))))
1360             (result-type (numeric-contagion x y)))
1361         ;; If the result type is a float, we need to be sure to coerce
1362         ;; the bounds into the correct type.
1363         (when (eq (numeric-type-class result-type) 'float)
1364           (setf result (interval-func
1365                         #'(lambda (x)
1366                             (coerce x (or (numeric-type-format result-type)
1367                                           'float)))
1368                         result)))
1369         (make-numeric-type
1370          :class (if (and (eq (numeric-type-class x) 'integer)
1371                          (eq (numeric-type-class y) 'integer))
1372                     ;; The product of integers is always an integer
1373                     'integer
1374                     (numeric-type-class result-type))
1375          :format (numeric-type-format result-type)
1376          :low (interval-low result)
1377          :high (interval-high result)))
1378       (numeric-contagion x y)))
1379
1380 (defoptimizer (* derive-type) ((x y))
1381   (two-arg-derive-type x y #'*-derive-type-aux #'*))
1382
1383 (defun /-derive-type-aux (x y same-arg)
1384   (if (and (numeric-type-real-p x)
1385            (numeric-type-real-p y))
1386       (let ((result
1387              ;; (/ x x) is always 1, except if x can contain 0. In
1388              ;; that case, we shouldn't optimize the division away
1389              ;; because we want 0/0 to signal an error.
1390              (if (and same-arg
1391                       (not (interval-contains-p
1392                             0 (interval-closure (numeric-type->interval y)))))
1393                  (make-interval :low 1 :high 1)
1394                  (interval-div (numeric-type->interval x)
1395                                (numeric-type->interval y))))
1396             (result-type (numeric-contagion x y)))
1397         ;; If the result type is a float, we need to be sure to coerce
1398         ;; the bounds into the correct type.
1399         (when (eq (numeric-type-class result-type) 'float)
1400           (setf result (interval-func
1401                         #'(lambda (x)
1402                             (coerce x (or (numeric-type-format result-type)
1403                                           'float)))
1404                         result)))
1405         (make-numeric-type :class (numeric-type-class result-type)
1406                            :format (numeric-type-format result-type)
1407                            :low (interval-low result)
1408                            :high (interval-high result)))
1409       (numeric-contagion x y)))
1410
1411 (defoptimizer (/ derive-type) ((x y))
1412   (two-arg-derive-type x y #'/-derive-type-aux #'/))
1413
1414 ) ; PROGN
1415
1416 ;;; KLUDGE: All this ASH optimization is suppressed under CMU CL
1417 ;;; because as of version 2.4.6 for Debian, CMU CL blows up on (ASH
1418 ;;; 1000000000 -100000000000) (i.e. ASH of two bignums yielding zero)
1419 ;;; and it's hard to avoid that calculation in here.
1420 #-(and cmu sb-xc-host)
1421 (progn
1422 #!-propagate-fun-type
1423 (defoptimizer (ash derive-type) ((n shift))
1424   (or (let ((n-type (continuation-type n)))
1425         (when (numeric-type-p n-type)
1426           (let ((n-low (numeric-type-low n-type))
1427                 (n-high (numeric-type-high n-type)))
1428             (if (constant-continuation-p shift)
1429                 (let ((shift (continuation-value shift)))
1430                   (make-numeric-type :class 'integer
1431                                      :complexp :real
1432                                      :low (when n-low (ash n-low shift))
1433                                      :high (when n-high (ash n-high shift))))
1434                 (let ((s-type (continuation-type shift)))
1435                   (when (numeric-type-p s-type)
1436                     (let ((s-low (numeric-type-low s-type))
1437                           (s-high (numeric-type-high s-type)))
1438                       (if (and s-low s-high (<= s-low 64) (<= s-high 64))
1439                           (make-numeric-type :class 'integer
1440                                              :complexp :real
1441                                              :low (when n-low
1442                                                     (min (ash n-low s-high)
1443                                                          (ash n-low s-low)))
1444                                              :high (when n-high
1445                                                      (max (ash n-high s-high)
1446                                                           (ash n-high s-low))))
1447                           (make-numeric-type :class 'integer
1448                                              :complexp :real)))))))))
1449       *universal-type*))
1450 #!+propagate-fun-type
1451 (defun ash-derive-type-aux (n-type shift same-arg)
1452   (declare (ignore same-arg))
1453   (or (and (csubtypep n-type (specifier-type 'integer))
1454            (csubtypep shift (specifier-type 'integer))
1455            (let ((n-low (numeric-type-low n-type))
1456                  (n-high (numeric-type-high n-type))
1457                  (s-low (numeric-type-low shift))
1458                  (s-high (numeric-type-high shift)))
1459              ;; KLUDGE: The bare 64's here should be related to
1460              ;; symbolic machine word size values somehow.
1461              (if (and s-low s-high (<= s-low 64) (<= s-high 64))
1462                  (make-numeric-type :class 'integer :complexp :real
1463                                     :low (when n-low
1464                                            (min (ash n-low s-high)
1465                                                 (ash n-low s-low)))
1466                                     :high (when n-high
1467                                             (max (ash n-high s-high)
1468                                                  (ash n-high s-low))))
1469                  (make-numeric-type :class 'integer
1470                                     :complexp :real))))
1471       *universal-type*))
1472 #!+propagate-fun-type
1473 (defoptimizer (ash derive-type) ((n shift))
1474   (two-arg-derive-type n shift #'ash-derive-type-aux #'ash))
1475 ) ; PROGN
1476
1477 #!-propagate-float-type
1478 (macrolet ((frob (fun)
1479              `#'(lambda (type type2)
1480                   (declare (ignore type2))
1481                   (let ((lo (numeric-type-low type))
1482                         (hi (numeric-type-high type)))
1483                     (values (if hi (,fun hi) nil) (if lo (,fun lo) nil))))))
1484
1485   (defoptimizer (%negate derive-type) ((num))
1486     (derive-integer-type num num (frob -)))
1487
1488   (defoptimizer (lognot derive-type) ((int))
1489     (derive-integer-type int int (frob lognot))))
1490
1491 #!+propagate-float-type
1492 (defoptimizer (lognot derive-type) ((int))
1493   (derive-integer-type int int
1494                        #'(lambda (type type2)
1495                            (declare (ignore type2))
1496                            (let ((lo (numeric-type-low type))
1497                                  (hi (numeric-type-high type)))
1498                              (values (if hi (lognot hi) nil)
1499                                      (if lo (lognot lo) nil)
1500                                      (numeric-type-class type)
1501                                      (numeric-type-format type))))))
1502
1503 #!+propagate-float-type
1504 (defoptimizer (%negate derive-type) ((num))
1505   (flet ((negate-bound (b)
1506            (set-bound (- (bound-value b)) (consp b))))
1507     (one-arg-derive-type num
1508                          #'(lambda (type)
1509                              (let ((lo (numeric-type-low type))
1510                                    (hi (numeric-type-high type))
1511                                    (result (copy-numeric-type type)))
1512                                (setf (numeric-type-low result)
1513                                       (if hi (negate-bound hi) nil))
1514                                (setf (numeric-type-high result)
1515                                      (if lo (negate-bound lo) nil))
1516                                result))
1517                          #'-)))
1518
1519 #!-propagate-float-type
1520 (defoptimizer (abs derive-type) ((num))
1521   (let ((type (continuation-type num)))
1522     (if (and (numeric-type-p type)
1523              (eq (numeric-type-class type) 'integer)
1524              (eq (numeric-type-complexp type) :real))
1525         (let ((lo (numeric-type-low type))
1526               (hi (numeric-type-high type)))
1527           (make-numeric-type :class 'integer :complexp :real
1528                              :low (cond ((and hi (minusp hi))
1529                                          (abs hi))
1530                                         (lo
1531                                          (max 0 lo))
1532                                         (t
1533                                          0))
1534                              :high (if (and hi lo)
1535                                        (max (abs hi) (abs lo))
1536                                        nil)))
1537         (numeric-contagion type type))))
1538
1539 #!+propagate-float-type
1540 (defun abs-derive-type-aux (type)
1541   (cond ((eq (numeric-type-complexp type) :complex)
1542          ;; The absolute value of a complex number is always a
1543          ;; non-negative float.
1544          (let* ((format (case (numeric-type-class type)
1545                           ((integer rational) 'single-float)
1546                           (t (numeric-type-format type))))
1547                 (bound-format (or format 'float)))
1548            (make-numeric-type :class 'float
1549                               :format format
1550                               :complexp :real
1551                               :low (coerce 0 bound-format)
1552                               :high nil)))
1553         (t
1554          ;; The absolute value of a real number is a non-negative real
1555          ;; of the same type.
1556          (let* ((abs-bnd (interval-abs (numeric-type->interval type)))
1557                 (class (numeric-type-class type))
1558                 (format (numeric-type-format type))
1559                 (bound-type (or format class 'real)))
1560            (make-numeric-type
1561             :class class
1562             :format format
1563             :complexp :real
1564             :low (coerce-numeric-bound (interval-low abs-bnd) bound-type)
1565             :high (coerce-numeric-bound
1566                    (interval-high abs-bnd) bound-type))))))
1567
1568 #!+propagate-float-type
1569 (defoptimizer (abs derive-type) ((num))
1570   (one-arg-derive-type num #'abs-derive-type-aux #'abs))
1571
1572 #!-propagate-float-type
1573 (defoptimizer (truncate derive-type) ((number divisor))
1574   (let ((number-type (continuation-type number))
1575         (divisor-type (continuation-type divisor))
1576         (integer-type (specifier-type 'integer)))
1577     (if (and (numeric-type-p number-type)
1578              (csubtypep number-type integer-type)
1579              (numeric-type-p divisor-type)
1580              (csubtypep divisor-type integer-type))
1581         (let ((number-low (numeric-type-low number-type))
1582               (number-high (numeric-type-high number-type))
1583               (divisor-low (numeric-type-low divisor-type))
1584               (divisor-high (numeric-type-high divisor-type)))
1585           (values-specifier-type
1586            `(values ,(integer-truncate-derive-type number-low number-high
1587                                                    divisor-low divisor-high)
1588                     ,(integer-rem-derive-type number-low number-high
1589                                               divisor-low divisor-high))))
1590         *universal-type*)))
1591
1592 #-sb-xc-host ;(CROSS-FLOAT-INFINITY-KLUDGE, see base-target-features.lisp-expr)
1593 (progn
1594 #!+propagate-float-type
1595 (progn
1596
1597 (defun rem-result-type (number-type divisor-type)
1598   ;; Figure out what the remainder type is. The remainder is an
1599   ;; integer if both args are integers; a rational if both args are
1600   ;; rational; and a float otherwise.
1601   (cond ((and (csubtypep number-type (specifier-type 'integer))
1602               (csubtypep divisor-type (specifier-type 'integer)))
1603          'integer)
1604         ((and (csubtypep number-type (specifier-type 'rational))
1605               (csubtypep divisor-type (specifier-type 'rational)))
1606          'rational)
1607         ((and (csubtypep number-type (specifier-type 'float))
1608               (csubtypep divisor-type (specifier-type 'float)))
1609          ;; Both are floats so the result is also a float, of
1610          ;; the largest type.
1611          (or (float-format-max (numeric-type-format number-type)
1612                                (numeric-type-format divisor-type))
1613              'float))
1614         ((and (csubtypep number-type (specifier-type 'float))
1615               (csubtypep divisor-type (specifier-type 'rational)))
1616          ;; One of the arguments is a float and the other is a
1617          ;; rational. The remainder is a float of the same
1618          ;; type.
1619          (or (numeric-type-format number-type) 'float))
1620         ((and (csubtypep divisor-type (specifier-type 'float))
1621               (csubtypep number-type (specifier-type 'rational)))
1622          ;; One of the arguments is a float and the other is a
1623          ;; rational. The remainder is a float of the same
1624          ;; type.
1625          (or (numeric-type-format divisor-type) 'float))
1626         (t
1627          ;; Some unhandled combination. This usually means both args
1628          ;; are REAL so the result is a REAL.
1629          'real)))
1630
1631 (defun truncate-derive-type-quot (number-type divisor-type)
1632   (let* ((rem-type (rem-result-type number-type divisor-type))
1633          (number-interval (numeric-type->interval number-type))
1634          (divisor-interval (numeric-type->interval divisor-type)))
1635     ;;(declare (type (member '(integer rational float)) rem-type))
1636     ;; We have real numbers now.
1637     (cond ((eq rem-type 'integer)
1638            ;; Since the remainder type is INTEGER, both args are
1639            ;; INTEGERs.
1640            (let* ((res (integer-truncate-derive-type
1641                         (interval-low number-interval)
1642                         (interval-high number-interval)
1643                         (interval-low divisor-interval)
1644                         (interval-high divisor-interval))))
1645              (specifier-type (if (listp res) res 'integer))))
1646           (t
1647            (let ((quot (truncate-quotient-bound
1648                         (interval-div number-interval
1649                                       divisor-interval))))
1650              (specifier-type `(integer ,(or (interval-low quot) '*)
1651                                        ,(or (interval-high quot) '*))))))))
1652
1653 (defun truncate-derive-type-rem (number-type divisor-type)
1654   (let* ((rem-type (rem-result-type number-type divisor-type))
1655          (number-interval (numeric-type->interval number-type))
1656          (divisor-interval (numeric-type->interval divisor-type))
1657          (rem (truncate-rem-bound number-interval divisor-interval)))
1658     ;;(declare (type (member '(integer rational float)) rem-type))
1659     ;; We have real numbers now.
1660     (cond ((eq rem-type 'integer)
1661            ;; Since the remainder type is INTEGER, both args are
1662            ;; INTEGERs.
1663            (specifier-type `(,rem-type ,(or (interval-low rem) '*)
1664                                        ,(or (interval-high rem) '*))))
1665           (t
1666            (multiple-value-bind (class format)
1667                (ecase rem-type
1668                  (integer
1669                   (values 'integer nil))
1670                  (rational
1671                   (values 'rational nil))
1672                  ((or single-float double-float #!+long-float long-float)
1673                   (values 'float rem-type))
1674                  (float
1675                   (values 'float nil))
1676                  (real
1677                   (values nil nil)))
1678              (when (member rem-type '(float single-float double-float
1679                                             #!+long-float long-float))
1680                (setf rem (interval-func #'(lambda (x)
1681                                             (coerce x rem-type))
1682                                         rem)))
1683              (make-numeric-type :class class
1684                                 :format format
1685                                 :low (interval-low rem)
1686                                 :high (interval-high rem)))))))
1687
1688 (defun truncate-derive-type-quot-aux (num div same-arg)
1689   (declare (ignore same-arg))
1690   (if (and (numeric-type-real-p num)
1691            (numeric-type-real-p div))
1692       (truncate-derive-type-quot num div)
1693       *empty-type*))
1694
1695 (defun truncate-derive-type-rem-aux (num div same-arg)
1696   (declare (ignore same-arg))
1697   (if (and (numeric-type-real-p num)
1698            (numeric-type-real-p div))
1699       (truncate-derive-type-rem num div)
1700       *empty-type*))
1701
1702 (defoptimizer (truncate derive-type) ((number divisor))
1703   (let ((quot (two-arg-derive-type number divisor
1704                                    #'truncate-derive-type-quot-aux #'truncate))
1705         (rem (two-arg-derive-type number divisor
1706                                   #'truncate-derive-type-rem-aux #'rem)))
1707     (when (and quot rem)
1708       (make-values-type :required (list quot rem)))))
1709
1710 (defun ftruncate-derive-type-quot (number-type divisor-type)
1711   ;; The bounds are the same as for truncate. However, the first
1712   ;; result is a float of some type. We need to determine what that
1713   ;; type is. Basically it's the more contagious of the two types.
1714   (let ((q-type (truncate-derive-type-quot number-type divisor-type))
1715         (res-type (numeric-contagion number-type divisor-type)))
1716     (make-numeric-type :class 'float
1717                        :format (numeric-type-format res-type)
1718                        :low (numeric-type-low q-type)
1719                        :high (numeric-type-high q-type))))
1720
1721 (defun ftruncate-derive-type-quot-aux (n d same-arg)
1722   (declare (ignore same-arg))
1723   (if (and (numeric-type-real-p n)
1724            (numeric-type-real-p d))
1725       (ftruncate-derive-type-quot n d)
1726       *empty-type*))
1727
1728 (defoptimizer (ftruncate derive-type) ((number divisor))
1729   (let ((quot
1730          (two-arg-derive-type number divisor
1731                               #'ftruncate-derive-type-quot-aux #'ftruncate))
1732         (rem (two-arg-derive-type number divisor
1733                                   #'truncate-derive-type-rem-aux #'rem)))
1734     (when (and quot rem)
1735       (make-values-type :required (list quot rem)))))
1736
1737 (defun %unary-truncate-derive-type-aux (number)
1738   (truncate-derive-type-quot number (specifier-type '(integer 1 1))))
1739
1740 (defoptimizer (%unary-truncate derive-type) ((number))
1741   (one-arg-derive-type number
1742                        #'%unary-truncate-derive-type-aux
1743                        #'%unary-truncate))
1744
1745 ;;; Define optimizers for FLOOR and CEILING.
1746 (macrolet
1747     ((frob-opt (name q-name r-name)
1748        (let ((q-aux (symbolicate q-name "-AUX"))
1749              (r-aux (symbolicate r-name "-AUX")))
1750          `(progn
1751            ;; Compute type of quotient (first) result
1752            (defun ,q-aux (number-type divisor-type)
1753              (let* ((number-interval
1754                      (numeric-type->interval number-type))
1755                     (divisor-interval
1756                      (numeric-type->interval divisor-type))
1757                     (quot (,q-name (interval-div number-interval
1758                                                  divisor-interval))))
1759                (specifier-type `(integer ,(or (interval-low quot) '*)
1760                                          ,(or (interval-high quot) '*)))))
1761            ;; Compute type of remainder
1762            (defun ,r-aux (number-type divisor-type)
1763              (let* ((divisor-interval
1764                      (numeric-type->interval divisor-type))
1765                     (rem (,r-name divisor-interval))
1766                     (result-type (rem-result-type number-type divisor-type)))
1767                (multiple-value-bind (class format)
1768                    (ecase result-type
1769                      (integer
1770                       (values 'integer nil))
1771                      (rational
1772                       (values 'rational nil))
1773                      ((or single-float double-float #!+long-float long-float)
1774                       (values 'float result-type))
1775                      (float
1776                       (values 'float nil))
1777                      (real
1778                       (values nil nil)))
1779                  (when (member result-type '(float single-float double-float
1780                                              #!+long-float long-float))
1781                    ;; Make sure the limits on the interval have
1782                    ;; the right type.
1783                    (setf rem (interval-func #'(lambda (x)
1784                                                 (coerce x result-type))
1785                                             rem)))
1786                  (make-numeric-type :class class
1787                                     :format format
1788                                     :low (interval-low rem)
1789                                     :high (interval-high rem)))))
1790            ;; The optimizer itself
1791            (defoptimizer (,name derive-type) ((number divisor))
1792              (flet ((derive-q (n d same-arg)
1793                       (declare (ignore same-arg))
1794                       (if (and (numeric-type-real-p n)
1795                                (numeric-type-real-p d))
1796                           (,q-aux n d)
1797                           *empty-type*))
1798                     (derive-r (n d same-arg)
1799                       (declare (ignore same-arg))
1800                       (if (and (numeric-type-real-p n)
1801                                (numeric-type-real-p d))
1802                           (,r-aux n d)
1803                           *empty-type*)))
1804                (let ((quot (two-arg-derive-type
1805                             number divisor #'derive-q #',name))
1806                      (rem (two-arg-derive-type
1807                            number divisor #'derive-r #'mod)))
1808                  (when (and quot rem)
1809                    (make-values-type :required (list quot rem))))))
1810            ))))
1811
1812   ;; FIXME: DEF-FROB-OPT, not just FROB-OPT
1813   (frob-opt floor floor-quotient-bound floor-rem-bound)
1814   (frob-opt ceiling ceiling-quotient-bound ceiling-rem-bound))
1815
1816 ;;; Define optimizers for FFLOOR and FCEILING
1817 (macrolet
1818     ((frob-opt (name q-name r-name)
1819        (let ((q-aux (symbolicate "F" q-name "-AUX"))
1820              (r-aux (symbolicate r-name "-AUX")))
1821          `(progn
1822            ;; Compute type of quotient (first) result
1823            (defun ,q-aux (number-type divisor-type)
1824              (let* ((number-interval
1825                      (numeric-type->interval number-type))
1826                     (divisor-interval
1827                      (numeric-type->interval divisor-type))
1828                     (quot (,q-name (interval-div number-interval
1829                                                  divisor-interval)))
1830                     (res-type (numeric-contagion number-type divisor-type)))
1831                (make-numeric-type
1832                 :class (numeric-type-class res-type)
1833                 :format (numeric-type-format res-type)
1834                 :low  (interval-low quot)
1835                 :high (interval-high quot))))
1836
1837            (defoptimizer (,name derive-type) ((number divisor))
1838              (flet ((derive-q (n d same-arg)
1839                       (declare (ignore same-arg))
1840                       (if (and (numeric-type-real-p n)
1841                                (numeric-type-real-p d))
1842                           (,q-aux n d)
1843                           *empty-type*))
1844                     (derive-r (n d same-arg)
1845                       (declare (ignore same-arg))
1846                       (if (and (numeric-type-real-p n)
1847                                (numeric-type-real-p d))
1848                           (,r-aux n d)
1849                           *empty-type*)))
1850                (let ((quot (two-arg-derive-type
1851                             number divisor #'derive-q #',name))
1852                      (rem (two-arg-derive-type
1853                            number divisor #'derive-r #'mod)))
1854                  (when (and quot rem)
1855                    (make-values-type :required (list quot rem))))))))))
1856
1857   ;; FIXME: DEF-FROB-OPT, not just FROB-OPT
1858   (frob-opt ffloor floor-quotient-bound floor-rem-bound)
1859   (frob-opt fceiling ceiling-quotient-bound ceiling-rem-bound))
1860
1861 ;;; Functions to compute the bounds on the quotient and remainder for
1862 ;;; the FLOOR function.
1863 (defun floor-quotient-bound (quot)
1864   ;; Take the floor of the quotient and then massage it into what we
1865   ;; need.
1866   (let ((lo (interval-low quot))
1867         (hi (interval-high quot)))
1868     ;; Take the floor of the lower bound. The result is always a
1869     ;; closed lower bound.
1870     (setf lo (if lo
1871                  (floor (bound-value lo))
1872                  nil))
1873     ;; For the upper bound, we need to be careful
1874     (setf hi
1875           (cond ((consp hi)
1876                  ;; An open bound. We need to be careful here because
1877                  ;; the floor of '(10.0) is 9, but the floor of
1878                  ;; 10.0 is 10.
1879                  (multiple-value-bind (q r) (floor (first hi))
1880                    (if (zerop r)
1881                        (1- q)
1882                        q)))
1883                 (hi
1884                  ;; A closed bound, so the answer is obvious.
1885                  (floor hi))
1886                 (t
1887                  hi)))
1888     (make-interval :low lo :high hi)))
1889 (defun floor-rem-bound (div)
1890   ;; The remainder depends only on the divisor. Try to get the
1891   ;; correct sign for the remainder if we can.
1892   (case (interval-range-info div)
1893     (+
1894      ;; Divisor is always positive.
1895      (let ((rem (interval-abs div)))
1896        (setf (interval-low rem) 0)
1897        (when (and (numberp (interval-high rem))
1898                   (not (zerop (interval-high rem))))
1899          ;; The remainder never contains the upper bound. However,
1900          ;; watch out for the case where the high limit is zero!
1901          (setf (interval-high rem) (list (interval-high rem))))
1902        rem))
1903     (-
1904      ;; Divisor is always negative
1905      (let ((rem (interval-neg (interval-abs div))))
1906        (setf (interval-high rem) 0)
1907        (when (numberp (interval-low rem))
1908          ;; The remainder never contains the lower bound.
1909          (setf (interval-low rem) (list (interval-low rem))))
1910        rem))
1911     (otherwise
1912      ;; The divisor can be positive or negative. All bets off.
1913      ;; The magnitude of remainder is the maximum value of the
1914      ;; divisor.
1915      (let ((limit (bound-value (interval-high (interval-abs div)))))
1916        ;; The bound never reaches the limit, so make the interval open
1917        (make-interval :low (if limit
1918                                (list (- limit))
1919                                limit)
1920                       :high (list limit))))))
1921 #| Test cases
1922 (floor-quotient-bound (make-interval :low 0.3 :high 10.3))
1923 => #S(INTERVAL :LOW 0 :HIGH 10)
1924 (floor-quotient-bound (make-interval :low 0.3 :high '(10.3)))
1925 => #S(INTERVAL :LOW 0 :HIGH 10)
1926 (floor-quotient-bound (make-interval :low 0.3 :high 10))
1927 => #S(INTERVAL :LOW 0 :HIGH 10)
1928 (floor-quotient-bound (make-interval :low 0.3 :high '(10)))
1929 => #S(INTERVAL :LOW 0 :HIGH 9)
1930 (floor-quotient-bound (make-interval :low '(0.3) :high 10.3))
1931 => #S(INTERVAL :LOW 0 :HIGH 10)
1932 (floor-quotient-bound (make-interval :low '(0.0) :high 10.3))
1933 => #S(INTERVAL :LOW 0 :HIGH 10)
1934 (floor-quotient-bound (make-interval :low '(-1.3) :high 10.3))
1935 => #S(INTERVAL :LOW -2 :HIGH 10)
1936 (floor-quotient-bound (make-interval :low '(-1.0) :high 10.3))
1937 => #S(INTERVAL :LOW -1 :HIGH 10)
1938 (floor-quotient-bound (make-interval :low -1.0 :high 10.3))
1939 => #S(INTERVAL :LOW -1 :HIGH 10)
1940
1941 (floor-rem-bound (make-interval :low 0.3 :high 10.3))
1942 => #S(INTERVAL :LOW 0 :HIGH '(10.3))
1943 (floor-rem-bound (make-interval :low 0.3 :high '(10.3)))
1944 => #S(INTERVAL :LOW 0 :HIGH '(10.3))
1945 (floor-rem-bound (make-interval :low -10 :high -2.3))
1946 #S(INTERVAL :LOW (-10) :HIGH 0)
1947 (floor-rem-bound (make-interval :low 0.3 :high 10))
1948 => #S(INTERVAL :LOW 0 :HIGH '(10))
1949 (floor-rem-bound (make-interval :low '(-1.3) :high 10.3))
1950 => #S(INTERVAL :LOW '(-10.3) :HIGH '(10.3))
1951 (floor-rem-bound (make-interval :low '(-20.3) :high 10.3))
1952 => #S(INTERVAL :LOW (-20.3) :HIGH (20.3))
1953 |#
1954 \f
1955 ;;; same functions for CEILING
1956 (defun ceiling-quotient-bound (quot)
1957   ;; Take the ceiling of the quotient and then massage it into what we
1958   ;; need.
1959   (let ((lo (interval-low quot))
1960         (hi (interval-high quot)))
1961     ;; Take the ceiling of the upper bound. The result is always a
1962     ;; closed upper bound.
1963     (setf hi (if hi
1964                  (ceiling (bound-value hi))
1965                  nil))
1966     ;; For the lower bound, we need to be careful
1967     (setf lo
1968           (cond ((consp lo)
1969                  ;; An open bound. We need to be careful here because
1970                  ;; the ceiling of '(10.0) is 11, but the ceiling of
1971                  ;; 10.0 is 10.
1972                  (multiple-value-bind (q r) (ceiling (first lo))
1973                    (if (zerop r)
1974                        (1+ q)
1975                        q)))
1976                 (lo
1977                  ;; A closed bound, so the answer is obvious.
1978                  (ceiling lo))
1979                 (t
1980                  lo)))
1981     (make-interval :low lo :high hi)))
1982 (defun ceiling-rem-bound (div)
1983   ;; The remainder depends only on the divisor. Try to get the
1984   ;; correct sign for the remainder if we can.
1985
1986   (case (interval-range-info div)
1987     (+
1988      ;; Divisor is always positive. The remainder is negative.
1989      (let ((rem (interval-neg (interval-abs div))))
1990        (setf (interval-high rem) 0)
1991        (when (and (numberp (interval-low rem))
1992                   (not (zerop (interval-low rem))))
1993          ;; The remainder never contains the upper bound. However,
1994          ;; watch out for the case when the upper bound is zero!
1995          (setf (interval-low rem) (list (interval-low rem))))
1996        rem))
1997     (-
1998      ;; Divisor is always negative. The remainder is positive
1999      (let ((rem (interval-abs div)))
2000        (setf (interval-low rem) 0)
2001        (when (numberp (interval-high rem))
2002          ;; The remainder never contains the lower bound.
2003          (setf (interval-high rem) (list (interval-high rem))))
2004        rem))
2005     (otherwise
2006      ;; The divisor can be positive or negative. All bets off.
2007      ;; The magnitude of remainder is the maximum value of the
2008      ;; divisor.
2009      (let ((limit (bound-value (interval-high (interval-abs div)))))
2010        ;; The bound never reaches the limit, so make the interval open
2011        (make-interval :low (if limit
2012                                (list (- limit))
2013                                limit)
2014                       :high (list limit))))))
2015
2016 #| Test cases
2017 (ceiling-quotient-bound (make-interval :low 0.3 :high 10.3))
2018 => #S(INTERVAL :LOW 1 :HIGH 11)
2019 (ceiling-quotient-bound (make-interval :low 0.3 :high '(10.3)))
2020 => #S(INTERVAL :LOW 1 :HIGH 11)
2021 (ceiling-quotient-bound (make-interval :low 0.3 :high 10))
2022 => #S(INTERVAL :LOW 1 :HIGH 10)
2023 (ceiling-quotient-bound (make-interval :low 0.3 :high '(10)))
2024 => #S(INTERVAL :LOW 1 :HIGH 10)
2025 (ceiling-quotient-bound (make-interval :low '(0.3) :high 10.3))
2026 => #S(INTERVAL :LOW 1 :HIGH 11)
2027 (ceiling-quotient-bound (make-interval :low '(0.0) :high 10.3))
2028 => #S(INTERVAL :LOW 1 :HIGH 11)
2029 (ceiling-quotient-bound (make-interval :low '(-1.3) :high 10.3))
2030 => #S(INTERVAL :LOW -1 :HIGH 11)
2031 (ceiling-quotient-bound (make-interval :low '(-1.0) :high 10.3))
2032 => #S(INTERVAL :LOW 0 :HIGH 11)
2033 (ceiling-quotient-bound (make-interval :low -1.0 :high 10.3))
2034 => #S(INTERVAL :LOW -1 :HIGH 11)
2035
2036 (ceiling-rem-bound (make-interval :low 0.3 :high 10.3))
2037 => #S(INTERVAL :LOW (-10.3) :HIGH 0)
2038 (ceiling-rem-bound (make-interval :low 0.3 :high '(10.3)))
2039 => #S(INTERVAL :LOW 0 :HIGH '(10.3))
2040 (ceiling-rem-bound (make-interval :low -10 :high -2.3))
2041 => #S(INTERVAL :LOW 0 :HIGH (10))
2042 (ceiling-rem-bound (make-interval :low 0.3 :high 10))
2043 => #S(INTERVAL :LOW (-10) :HIGH 0)
2044 (ceiling-rem-bound (make-interval :low '(-1.3) :high 10.3))
2045 => #S(INTERVAL :LOW (-10.3) :HIGH (10.3))
2046 (ceiling-rem-bound (make-interval :low '(-20.3) :high 10.3))
2047 => #S(INTERVAL :LOW (-20.3) :HIGH (20.3))
2048 |#
2049 \f
2050 (defun truncate-quotient-bound (quot)
2051   ;; For positive quotients, truncate is exactly like floor. For
2052   ;; negative quotients, truncate is exactly like ceiling. Otherwise,
2053   ;; it's the union of the two pieces.
2054   (case (interval-range-info quot)
2055     (+
2056      ;; Just like floor
2057      (floor-quotient-bound quot))
2058     (-
2059      ;; Just like ceiling
2060      (ceiling-quotient-bound quot))
2061     (otherwise
2062      ;; Split the interval into positive and negative pieces, compute
2063      ;; the result for each piece and put them back together.
2064      (destructuring-bind (neg pos) (interval-split 0 quot t t)
2065        (interval-merge-pair (ceiling-quotient-bound neg)
2066                             (floor-quotient-bound pos))))))
2067
2068 (defun truncate-rem-bound (num div)
2069   ;; This is significantly more complicated than floor or ceiling. We
2070   ;; need both the number and the divisor to determine the range. The
2071   ;; basic idea is to split the ranges of num and den into positive
2072   ;; and negative pieces and deal with each of the four possibilities
2073   ;; in turn.
2074   (case (interval-range-info num)
2075     (+
2076      (case (interval-range-info div)
2077        (+
2078         (floor-rem-bound div))
2079        (-
2080         (ceiling-rem-bound div))
2081        (otherwise
2082         (destructuring-bind (neg pos) (interval-split 0 div t t)
2083           (interval-merge-pair (truncate-rem-bound num neg)
2084                                (truncate-rem-bound num pos))))))
2085     (-
2086      (case (interval-range-info div)
2087        (+
2088         (ceiling-rem-bound div))
2089        (-
2090         (floor-rem-bound div))
2091        (otherwise
2092         (destructuring-bind (neg pos) (interval-split 0 div t t)
2093           (interval-merge-pair (truncate-rem-bound num neg)
2094                                (truncate-rem-bound num pos))))))
2095     (otherwise
2096      (destructuring-bind (neg pos) (interval-split 0 num t t)
2097        (interval-merge-pair (truncate-rem-bound neg div)
2098                             (truncate-rem-bound pos div))))))
2099 )) ; end PROGN's
2100
2101 ;;; Derive useful information about the range. Returns three values:
2102 ;;; - '+ if its positive, '- negative, or nil if it overlaps 0.
2103 ;;; - The abs of the minimal value (i.e. closest to 0) in the range.
2104 ;;; - The abs of the maximal value if there is one, or nil if it is
2105 ;;;   unbounded.
2106 (defun numeric-range-info (low high)
2107   (cond ((and low (not (minusp low)))
2108          (values '+ low high))
2109         ((and high (not (plusp high)))
2110          (values '- (- high) (if low (- low) nil)))
2111         (t
2112          (values nil 0 (and low high (max (- low) high))))))
2113
2114 (defun integer-truncate-derive-type
2115        (number-low number-high divisor-low divisor-high)
2116   ;; The result cannot be larger in magnitude than the number, but the sign
2117   ;; might change. If we can determine the sign of either the number or
2118   ;; the divisor, we can eliminate some of the cases.
2119   (multiple-value-bind (number-sign number-min number-max)
2120       (numeric-range-info number-low number-high)
2121     (multiple-value-bind (divisor-sign divisor-min divisor-max)
2122         (numeric-range-info divisor-low divisor-high)
2123       (when (and divisor-max (zerop divisor-max))
2124         ;; We've got a problem: guaranteed division by zero.
2125         (return-from integer-truncate-derive-type t))
2126       (when (zerop divisor-min)
2127         ;; We'll assume that they aren't going to divide by zero.
2128         (incf divisor-min))
2129       (cond ((and number-sign divisor-sign)
2130              ;; We know the sign of both.
2131              (if (eq number-sign divisor-sign)
2132                  ;; Same sign, so the result will be positive.
2133                  `(integer ,(if divisor-max
2134                                 (truncate number-min divisor-max)
2135                                 0)
2136                            ,(if number-max
2137                                 (truncate number-max divisor-min)
2138                                 '*))
2139                  ;; Different signs, the result will be negative.
2140                  `(integer ,(if number-max
2141                                 (- (truncate number-max divisor-min))
2142                                 '*)
2143                            ,(if divisor-max
2144                                 (- (truncate number-min divisor-max))
2145                                 0))))
2146             ((eq divisor-sign '+)
2147              ;; The divisor is positive. Therefore, the number will just
2148              ;; become closer to zero.
2149              `(integer ,(if number-low
2150                             (truncate number-low divisor-min)
2151                             '*)
2152                        ,(if number-high
2153                             (truncate number-high divisor-min)
2154                             '*)))
2155             ((eq divisor-sign '-)
2156              ;; The divisor is negative. Therefore, the absolute value of
2157              ;; the number will become closer to zero, but the sign will also
2158              ;; change.
2159              `(integer ,(if number-high
2160                             (- (truncate number-high divisor-min))
2161                             '*)
2162                        ,(if number-low
2163                             (- (truncate number-low divisor-min))
2164                             '*)))
2165             ;; The divisor could be either positive or negative.
2166             (number-max
2167              ;; The number we are dividing has a bound. Divide that by the
2168              ;; smallest posible divisor.
2169              (let ((bound (truncate number-max divisor-min)))
2170                `(integer ,(- bound) ,bound)))
2171             (t
2172              ;; The number we are dividing is unbounded, so we can't tell
2173              ;; anything about the result.
2174              `integer)))))
2175
2176 #!-propagate-float-type
2177 (defun integer-rem-derive-type
2178        (number-low number-high divisor-low divisor-high)
2179   (if (and divisor-low divisor-high)
2180       ;; We know the range of the divisor, and the remainder must be smaller
2181       ;; than the divisor. We can tell the sign of the remainer if we know
2182       ;; the sign of the number.
2183       (let ((divisor-max (1- (max (abs divisor-low) (abs divisor-high)))))
2184         `(integer ,(if (or (null number-low)
2185                            (minusp number-low))
2186                        (- divisor-max)
2187                        0)
2188                   ,(if (or (null number-high)
2189                            (plusp number-high))
2190                        divisor-max
2191                        0)))
2192       ;; The divisor is potentially either very positive or very negative.
2193       ;; Therefore, the remainer is unbounded, but we might be able to tell
2194       ;; something about the sign from the number.
2195       `(integer ,(if (and number-low (not (minusp number-low)))
2196                      ;; The number we are dividing is positive. Therefore,
2197                      ;; the remainder must be positive.
2198                      0
2199                      '*)
2200                 ,(if (and number-high (not (plusp number-high)))
2201                      ;; The number we are dividing is negative. Therefore,
2202                      ;; the remainder must be negative.
2203                      0
2204                      '*))))
2205
2206 #!-propagate-float-type
2207 (defoptimizer (random derive-type) ((bound &optional state))
2208   (let ((type (continuation-type bound)))
2209     (when (numeric-type-p type)
2210       (let ((class (numeric-type-class type))
2211             (high (numeric-type-high type))
2212             (format (numeric-type-format type)))
2213         (make-numeric-type
2214          :class class
2215          :format format
2216          :low (coerce 0 (or format class 'real))
2217          :high (cond ((not high) nil)
2218                      ((eq class 'integer) (max (1- high) 0))
2219                      ((or (consp high) (zerop high)) high)
2220                      (t `(,high))))))))
2221
2222 #!+propagate-float-type
2223 (defun random-derive-type-aux (type)
2224   (let ((class (numeric-type-class type))
2225         (high (numeric-type-high type))
2226         (format (numeric-type-format type)))
2227     (make-numeric-type
2228          :class class
2229          :format format
2230          :low (coerce 0 (or format class 'real))
2231          :high (cond ((not high) nil)
2232                      ((eq class 'integer) (max (1- high) 0))
2233                      ((or (consp high) (zerop high)) high)
2234                      (t `(,high))))))
2235
2236 #!+propagate-float-type
2237 (defoptimizer (random derive-type) ((bound &optional state))
2238   (one-arg-derive-type bound #'random-derive-type-aux nil))
2239 \f
2240 ;;;; logical derive-type methods
2241
2242 ;;; Return the maximum number of bits an integer of the supplied type can take
2243 ;;; up, or NIL if it is unbounded. The second (third) value is T if the
2244 ;;; integer can be positive (negative) and NIL if not. Zero counts as
2245 ;;; positive.
2246 (defun integer-type-length (type)
2247   (if (numeric-type-p type)
2248       (let ((min (numeric-type-low type))
2249             (max (numeric-type-high type)))
2250         (values (and min max (max (integer-length min) (integer-length max)))
2251                 (or (null max) (not (minusp max)))
2252                 (or (null min) (minusp min))))
2253       (values nil t t)))
2254
2255 #!-propagate-fun-type
2256 (progn
2257 (defoptimizer (logand derive-type) ((x y))
2258   (multiple-value-bind (x-len x-pos x-neg)
2259       (integer-type-length (continuation-type x))
2260     (declare (ignore x-pos))
2261     (multiple-value-bind (y-len y-pos y-neg)
2262         (integer-type-length (continuation-type y))
2263       (declare (ignore y-pos))
2264       (if (not x-neg)
2265           ;; X must be positive.
2266           (if (not y-neg)
2267               ;; The must both be positive.
2268               (cond ((or (null x-len) (null y-len))
2269                      (specifier-type 'unsigned-byte))
2270                     ((or (zerop x-len) (zerop y-len))
2271                      (specifier-type '(integer 0 0)))
2272                     (t
2273                      (specifier-type `(unsigned-byte ,(min x-len y-len)))))
2274               ;; X is positive, but Y might be negative.
2275               (cond ((null x-len)
2276                      (specifier-type 'unsigned-byte))
2277                     ((zerop x-len)
2278                      (specifier-type '(integer 0 0)))
2279                     (t
2280                      (specifier-type `(unsigned-byte ,x-len)))))
2281           ;; X might be negative.
2282           (if (not y-neg)
2283               ;; Y must be positive.
2284               (cond ((null y-len)
2285                      (specifier-type 'unsigned-byte))
2286                     ((zerop y-len)
2287                      (specifier-type '(integer 0 0)))
2288                     (t
2289                      (specifier-type
2290                       `(unsigned-byte ,y-len))))
2291               ;; Either might be negative.
2292               (if (and x-len y-len)
2293                   ;; The result is bounded.
2294                   (specifier-type `(signed-byte ,(1+ (max x-len y-len))))
2295                   ;; We can't tell squat about the result.
2296                   (specifier-type 'integer)))))))
2297
2298 (defoptimizer (logior derive-type) ((x y))
2299   (multiple-value-bind (x-len x-pos x-neg)
2300       (integer-type-length (continuation-type x))
2301     (multiple-value-bind (y-len y-pos y-neg)
2302         (integer-type-length (continuation-type y))
2303       (cond
2304        ((and (not x-neg) (not y-neg))
2305         ;; Both are positive.
2306         (specifier-type `(unsigned-byte ,(if (and x-len y-len)
2307                                              (max x-len y-len)
2308                                              '*))))
2309        ((not x-pos)
2310         ;; X must be negative.
2311         (if (not y-pos)
2312             ;; Both are negative. The result is going to be negative and be
2313             ;; the same length or shorter than the smaller.
2314             (if (and x-len y-len)
2315                 ;; It's bounded.
2316                 (specifier-type `(integer ,(ash -1 (min x-len y-len)) -1))
2317                 ;; It's unbounded.
2318                 (specifier-type '(integer * -1)))
2319             ;; X is negative, but we don't know about Y. The result will be
2320             ;; negative, but no more negative than X.
2321             (specifier-type
2322              `(integer ,(or (numeric-type-low (continuation-type x)) '*)
2323                        -1))))
2324        (t
2325         ;; X might be either positive or negative.
2326         (if (not y-pos)
2327             ;; But Y is negative. The result will be negative.
2328             (specifier-type
2329              `(integer ,(or (numeric-type-low (continuation-type y)) '*)
2330                        -1))
2331             ;; We don't know squat about either. It won't get any bigger.
2332             (if (and x-len y-len)
2333                 ;; Bounded.
2334                 (specifier-type `(signed-byte ,(1+ (max x-len y-len))))
2335                 ;; Unbounded.
2336                 (specifier-type 'integer))))))))
2337
2338 (defoptimizer (logxor derive-type) ((x y))
2339   (multiple-value-bind (x-len x-pos x-neg)
2340       (integer-type-length (continuation-type x))
2341     (multiple-value-bind (y-len y-pos y-neg)
2342         (integer-type-length (continuation-type y))
2343       (cond
2344        ((or (and (not x-neg) (not y-neg))
2345             (and (not x-pos) (not y-pos)))
2346         ;; Either both are negative or both are positive. The result will be
2347         ;; positive, and as long as the longer.
2348         (specifier-type `(unsigned-byte ,(if (and x-len y-len)
2349                                              (max x-len y-len)
2350                                              '*))))
2351        ((or (and (not x-pos) (not y-neg))
2352             (and (not y-neg) (not y-pos)))
2353         ;; Either X is negative and Y is positive of vice-verca. The result
2354         ;; will be negative.
2355         (specifier-type `(integer ,(if (and x-len y-len)
2356                                        (ash -1 (max x-len y-len))
2357                                        '*)
2358                                   -1)))
2359        ;; We can't tell what the sign of the result is going to be. All we
2360        ;; know is that we don't create new bits.
2361        ((and x-len y-len)
2362         (specifier-type `(signed-byte ,(1+ (max x-len y-len)))))
2363        (t
2364         (specifier-type 'integer))))))
2365
2366 ) ; PROGN
2367
2368 #!+propagate-fun-type
2369 (progn
2370 (defun logand-derive-type-aux (x y &optional same-leaf)
2371   (declare (ignore same-leaf))
2372   (multiple-value-bind (x-len x-pos x-neg) (integer-type-length x)
2373     (declare (ignore x-pos))
2374     (multiple-value-bind (y-len y-pos y-neg) (integer-type-length  y)
2375       (declare (ignore y-pos))
2376       (if (not x-neg)
2377           ;; X must be positive.
2378           (if (not y-neg)
2379               ;; The must both be positive.
2380               (cond ((or (null x-len) (null y-len))
2381                      (specifier-type 'unsigned-byte))
2382                     ((or (zerop x-len) (zerop y-len))
2383                      (specifier-type '(integer 0 0)))
2384                     (t
2385                      (specifier-type `(unsigned-byte ,(min x-len y-len)))))
2386               ;; X is positive, but Y might be negative.
2387               (cond ((null x-len)
2388                      (specifier-type 'unsigned-byte))
2389                     ((zerop x-len)
2390                      (specifier-type '(integer 0 0)))
2391                     (t
2392                      (specifier-type `(unsigned-byte ,x-len)))))
2393           ;; X might be negative.
2394           (if (not y-neg)
2395               ;; Y must be positive.
2396               (cond ((null y-len)
2397                      (specifier-type 'unsigned-byte))
2398                     ((zerop y-len)
2399                      (specifier-type '(integer 0 0)))
2400                     (t
2401                      (specifier-type
2402                       `(unsigned-byte ,y-len))))
2403               ;; Either might be negative.
2404               (if (and x-len y-len)
2405                   ;; The result is bounded.
2406                   (specifier-type `(signed-byte ,(1+ (max x-len y-len))))
2407                   ;; We can't tell squat about the result.
2408                   (specifier-type 'integer)))))))
2409
2410 (defun logior-derive-type-aux (x y &optional same-leaf)
2411   (declare (ignore same-leaf))
2412   (multiple-value-bind (x-len x-pos x-neg) (integer-type-length x)
2413     (multiple-value-bind (y-len y-pos y-neg) (integer-type-length y)
2414       (cond
2415        ((and (not x-neg) (not y-neg))
2416         ;; Both are positive.
2417         (if (and x-len y-len (zerop x-len) (zerop y-len))
2418             (specifier-type '(integer 0 0))
2419             (specifier-type `(unsigned-byte ,(if (and x-len y-len)
2420                                              (max x-len y-len)
2421                                              '*)))))
2422        ((not x-pos)
2423         ;; X must be negative.
2424         (if (not y-pos)
2425             ;; Both are negative. The result is going to be negative and be
2426             ;; the same length or shorter than the smaller.
2427             (if (and x-len y-len)
2428                 ;; It's bounded.
2429                 (specifier-type `(integer ,(ash -1 (min x-len y-len)) -1))
2430                 ;; It's unbounded.
2431                 (specifier-type '(integer * -1)))
2432             ;; X is negative, but we don't know about Y. The result will be
2433             ;; negative, but no more negative than X.
2434             (specifier-type
2435              `(integer ,(or (numeric-type-low x) '*)
2436                        -1))))
2437        (t
2438         ;; X might be either positive or negative.
2439         (if (not y-pos)
2440             ;; But Y is negative. The result will be negative.
2441             (specifier-type
2442              `(integer ,(or (numeric-type-low y) '*)
2443                        -1))
2444             ;; We don't know squat about either. It won't get any bigger.
2445             (if (and x-len y-len)
2446                 ;; Bounded.
2447                 (specifier-type `(signed-byte ,(1+ (max x-len y-len))))
2448                 ;; Unbounded.
2449                 (specifier-type 'integer))))))))
2450
2451 (defun logxor-derive-type-aux (x y &optional same-leaf)
2452   (declare (ignore same-leaf))
2453   (multiple-value-bind (x-len x-pos x-neg) (integer-type-length x)
2454     (multiple-value-bind (y-len y-pos y-neg) (integer-type-length y)
2455       (cond
2456        ((or (and (not x-neg) (not y-neg))
2457             (and (not x-pos) (not y-pos)))
2458         ;; Either both are negative or both are positive. The result will be
2459         ;; positive, and as long as the longer.
2460         (if (and x-len y-len (zerop x-len) (zerop y-len))
2461             (specifier-type '(integer 0 0))
2462             (specifier-type `(unsigned-byte ,(if (and x-len y-len)
2463                                              (max x-len y-len)
2464                                              '*)))))
2465        ((or (and (not x-pos) (not y-neg))
2466             (and (not y-neg) (not y-pos)))
2467         ;; Either X is negative and Y is positive of vice-verca. The result
2468         ;; will be negative.
2469         (specifier-type `(integer ,(if (and x-len y-len)
2470                                        (ash -1 (max x-len y-len))
2471                                        '*)
2472                                   -1)))
2473        ;; We can't tell what the sign of the result is going to be. All we
2474        ;; know is that we don't create new bits.
2475        ((and x-len y-len)
2476         (specifier-type `(signed-byte ,(1+ (max x-len y-len)))))
2477        (t
2478         (specifier-type 'integer))))))
2479
2480 (macrolet ((frob (logfcn)
2481              (let ((fcn-aux (symbolicate logfcn "-DERIVE-TYPE-AUX")))
2482              `(defoptimizer (,logfcn derive-type) ((x y))
2483                 (two-arg-derive-type x y #',fcn-aux #',logfcn)))))
2484   ;; FIXME: DEF-FROB, not just FROB
2485   (frob logand)
2486   (frob logior)
2487   (frob logxor))
2488
2489 ) ; PROGN
2490 \f
2491 ;;;; miscellaneous derive-type methods
2492
2493 (defoptimizer (code-char derive-type) ((code))
2494   (specifier-type 'base-char))
2495
2496 (defoptimizer (values derive-type) ((&rest values))
2497   (values-specifier-type
2498    `(values ,@(mapcar #'(lambda (x)
2499                           (type-specifier (continuation-type x)))
2500                       values))))
2501 \f
2502 ;;;; byte operations
2503 ;;;;
2504 ;;;; We try to turn byte operations into simple logical operations. First, we
2505 ;;;; convert byte specifiers into separate size and position arguments passed
2506 ;;;; to internal %FOO functions. We then attempt to transform the %FOO
2507 ;;;; functions into boolean operations when the size and position are constant
2508 ;;;; and the operands are fixnums.
2509
2510 (macrolet (;; Evaluate body with Size-Var and Pos-Var bound to expressions that
2511            ;; evaluate to the Size and Position of the byte-specifier form
2512            ;; Spec. We may wrap a let around the result of the body to bind
2513            ;; some variables.
2514            ;;
2515            ;; If the spec is a Byte form, then bind the vars to the subforms.
2516            ;; otherwise, evaluate Spec and use the Byte-Size and Byte-Position.
2517            ;; The goal of this transformation is to avoid consing up byte
2518            ;; specifiers and then immediately throwing them away.
2519            (with-byte-specifier ((size-var pos-var spec) &body body)
2520              (once-only ((spec `(macroexpand ,spec))
2521                          (temp '(gensym)))
2522                         `(if (and (consp ,spec)
2523                                   (eq (car ,spec) 'byte)
2524                                   (= (length ,spec) 3))
2525                         (let ((,size-var (second ,spec))
2526                               (,pos-var (third ,spec)))
2527                           ,@body)
2528                         (let ((,size-var `(byte-size ,,temp))
2529                               (,pos-var `(byte-position ,,temp)))
2530                           `(let ((,,temp ,,spec))
2531                              ,,@body))))))
2532
2533   (def-source-transform ldb (spec int)
2534     (with-byte-specifier (size pos spec)
2535       `(%ldb ,size ,pos ,int)))
2536
2537   (def-source-transform dpb (newbyte spec int)
2538     (with-byte-specifier (size pos spec)
2539       `(%dpb ,newbyte ,size ,pos ,int)))
2540
2541   (def-source-transform mask-field (spec int)
2542     (with-byte-specifier (size pos spec)
2543       `(%mask-field ,size ,pos ,int)))
2544
2545   (def-source-transform deposit-field (newbyte spec int)
2546     (with-byte-specifier (size pos spec)
2547       `(%deposit-field ,newbyte ,size ,pos ,int))))
2548
2549 (defoptimizer (%ldb derive-type) ((size posn num))
2550   (let ((size (continuation-type size)))
2551     (if (and (numeric-type-p size)
2552              (csubtypep size (specifier-type 'integer)))
2553         (let ((size-high (numeric-type-high size)))
2554           (if (and size-high (<= size-high sb!vm:word-bits))
2555               (specifier-type `(unsigned-byte ,size-high))
2556               (specifier-type 'unsigned-byte)))
2557         *universal-type*)))
2558
2559 (defoptimizer (%mask-field derive-type) ((size posn num))
2560   (let ((size (continuation-type size))
2561         (posn (continuation-type posn)))
2562     (if (and (numeric-type-p size)
2563              (csubtypep size (specifier-type 'integer))
2564              (numeric-type-p posn)
2565              (csubtypep posn (specifier-type 'integer)))
2566         (let ((size-high (numeric-type-high size))
2567               (posn-high (numeric-type-high posn)))
2568           (if (and size-high posn-high
2569                    (<= (+ size-high posn-high) sb!vm:word-bits))
2570               (specifier-type `(unsigned-byte ,(+ size-high posn-high)))
2571               (specifier-type 'unsigned-byte)))
2572         *universal-type*)))
2573
2574 (defoptimizer (%dpb derive-type) ((newbyte size posn int))
2575   (let ((size (continuation-type size))
2576         (posn (continuation-type posn))
2577         (int (continuation-type int)))
2578     (if (and (numeric-type-p size)
2579              (csubtypep size (specifier-type 'integer))
2580              (numeric-type-p posn)
2581              (csubtypep posn (specifier-type 'integer))
2582              (numeric-type-p int)
2583              (csubtypep int (specifier-type 'integer)))
2584         (let ((size-high (numeric-type-high size))
2585               (posn-high (numeric-type-high posn))
2586               (high (numeric-type-high int))
2587               (low (numeric-type-low int)))
2588           (if (and size-high posn-high high low
2589                    (<= (+ size-high posn-high) sb!vm:word-bits))
2590               (specifier-type
2591                (list (if (minusp low) 'signed-byte 'unsigned-byte)
2592                      (max (integer-length high)
2593                           (integer-length low)
2594                           (+ size-high posn-high))))
2595               *universal-type*))
2596         *universal-type*)))
2597
2598 (defoptimizer (%deposit-field derive-type) ((newbyte size posn int))
2599   (let ((size (continuation-type size))
2600         (posn (continuation-type posn))
2601         (int (continuation-type int)))
2602     (if (and (numeric-type-p size)
2603              (csubtypep size (specifier-type 'integer))
2604              (numeric-type-p posn)
2605              (csubtypep posn (specifier-type 'integer))
2606              (numeric-type-p int)
2607              (csubtypep int (specifier-type 'integer)))
2608         (let ((size-high (numeric-type-high size))
2609               (posn-high (numeric-type-high posn))
2610               (high (numeric-type-high int))
2611               (low (numeric-type-low int)))
2612           (if (and size-high posn-high high low
2613                    (<= (+ size-high posn-high) sb!vm:word-bits))
2614               (specifier-type
2615                (list (if (minusp low) 'signed-byte 'unsigned-byte)
2616                      (max (integer-length high)
2617                           (integer-length low)
2618                           (+ size-high posn-high))))
2619               *universal-type*))
2620         *universal-type*)))
2621
2622 (deftransform %ldb ((size posn int)
2623                     (fixnum fixnum integer)
2624                     (unsigned-byte #.sb!vm:word-bits))
2625   "convert to inline logical ops"
2626   `(logand (ash int (- posn))
2627            (ash ,(1- (ash 1 sb!vm:word-bits))
2628                 (- size ,sb!vm:word-bits))))
2629
2630 (deftransform %mask-field ((size posn int)
2631                            (fixnum fixnum integer)
2632                            (unsigned-byte #.sb!vm:word-bits))
2633   "convert to inline logical ops"
2634   `(logand int
2635            (ash (ash ,(1- (ash 1 sb!vm:word-bits))
2636                      (- size ,sb!vm:word-bits))
2637                 posn)))
2638
2639 ;;; Note: for %DPB and %DEPOSIT-FIELD, we can't use
2640 ;;;   (OR (SIGNED-BYTE N) (UNSIGNED-BYTE N))
2641 ;;; as the result type, as that would allow result types
2642 ;;; that cover the range -2^(n-1) .. 1-2^n, instead of allowing result types
2643 ;;; of (UNSIGNED-BYTE N) and result types of (SIGNED-BYTE N).
2644
2645 (deftransform %dpb ((new size posn int)
2646                     *
2647                     (unsigned-byte #.sb!vm:word-bits))
2648   "convert to inline logical ops"
2649   `(let ((mask (ldb (byte size 0) -1)))
2650      (logior (ash (logand new mask) posn)
2651              (logand int (lognot (ash mask posn))))))
2652
2653 (deftransform %dpb ((new size posn int)
2654                     *
2655                     (signed-byte #.sb!vm:word-bits))
2656   "convert to inline logical ops"
2657   `(let ((mask (ldb (byte size 0) -1)))
2658      (logior (ash (logand new mask) posn)
2659              (logand int (lognot (ash mask posn))))))
2660
2661 (deftransform %deposit-field ((new size posn int)
2662                               *
2663                               (unsigned-byte #.sb!vm:word-bits))
2664   "convert to inline logical ops"
2665   `(let ((mask (ash (ldb (byte size 0) -1) posn)))
2666      (logior (logand new mask)
2667              (logand int (lognot mask)))))
2668
2669 (deftransform %deposit-field ((new size posn int)
2670                               *
2671                               (signed-byte #.sb!vm:word-bits))
2672   "convert to inline logical ops"
2673   `(let ((mask (ash (ldb (byte size 0) -1) posn)))
2674      (logior (logand new mask)
2675              (logand int (lognot mask)))))
2676 \f
2677 ;;; miscellanous numeric transforms
2678
2679 ;;; If a constant appears as the first arg, swap the args.
2680 (deftransform commutative-arg-swap ((x y) * * :defun-only t :node node)
2681   (if (and (constant-continuation-p x)
2682            (not (constant-continuation-p y)))
2683       `(,(continuation-function-name (basic-combination-fun node))
2684         y
2685         ,(continuation-value x))
2686       (give-up-ir1-transform)))
2687
2688 (dolist (x '(= char= + * logior logand logxor))
2689   (%deftransform x '(function * *) #'commutative-arg-swap
2690                  "place constant arg last."))
2691
2692 ;;; Handle the case of a constant BOOLE-CODE.
2693 (deftransform boole ((op x y) * * :when :both)
2694   "convert to inline logical ops"
2695   (unless (constant-continuation-p op)
2696     (give-up-ir1-transform "BOOLE code is not a constant."))
2697   (let ((control (continuation-value op)))
2698     (case control
2699       (#.boole-clr 0)
2700       (#.boole-set -1)
2701       (#.boole-1 'x)
2702       (#.boole-2 'y)
2703       (#.boole-c1 '(lognot x))
2704       (#.boole-c2 '(lognot y))
2705       (#.boole-and '(logand x y))
2706       (#.boole-ior '(logior x y))
2707       (#.boole-xor '(logxor x y))
2708       (#.boole-eqv '(logeqv x y))
2709       (#.boole-nand '(lognand x y))
2710       (#.boole-nor '(lognor x y))
2711       (#.boole-andc1 '(logandc1 x y))
2712       (#.boole-andc2 '(logandc2 x y))
2713       (#.boole-orc1 '(logorc1 x y))
2714       (#.boole-orc2 '(logorc2 x y))
2715       (t
2716        (abort-ir1-transform "~S is an illegal control arg to BOOLE."
2717                             control)))))
2718 \f
2719 ;;;; converting special case multiply/divide to shifts
2720
2721 ;;; If arg is a constant power of two, turn * into a shift.
2722 (deftransform * ((x y) (integer integer) * :when :both)
2723   "convert x*2^k to shift"
2724   (unless (constant-continuation-p y)
2725     (give-up-ir1-transform))
2726   (let* ((y (continuation-value y))
2727          (y-abs (abs y))
2728          (len (1- (integer-length y-abs))))
2729     (unless (= y-abs (ash 1 len))
2730       (give-up-ir1-transform))
2731     (if (minusp y)
2732         `(- (ash x ,len))
2733         `(ash x ,len))))
2734
2735 ;;; If both arguments and the result are (unsigned-byte 32), try to come up
2736 ;;; with a ``better'' multiplication using multiplier recoding. There are two
2737 ;;; different ways the multiplier can be recoded. The more obvious is to shift
2738 ;;; X by the correct amount for each bit set in Y and to sum the results. But
2739 ;;; if there is a string of bits that are all set, you can add X shifted by
2740 ;;; one more then the bit position of the first set bit and subtract X shifted
2741 ;;; by the bit position of the last set bit. We can't use this second method
2742 ;;; when the high order bit is bit 31 because shifting by 32 doesn't work
2743 ;;; too well.
2744 (deftransform * ((x y)
2745                  ((unsigned-byte 32) (unsigned-byte 32))
2746                  (unsigned-byte 32))
2747   "recode as shift and add"
2748   (unless (constant-continuation-p y)
2749     (give-up-ir1-transform))
2750   (let ((y (continuation-value y))
2751         (result nil)
2752         (first-one nil))
2753     (labels ((tub32 (x) `(truly-the (unsigned-byte 32) ,x))
2754              (add (next-factor)
2755                (setf result
2756                      (tub32
2757                       (if result
2758                           `(+ ,result ,(tub32 next-factor))
2759                           next-factor)))))
2760       (declare (inline add))
2761       (dotimes (bitpos 32)
2762         (if first-one
2763             (when (not (logbitp bitpos y))
2764               (add (if (= (1+ first-one) bitpos)
2765                        ;; There is only a single bit in the string.
2766                        `(ash x ,first-one)
2767                        ;; There are at least two.
2768                        `(- ,(tub32 `(ash x ,bitpos))
2769                            ,(tub32 `(ash x ,first-one)))))
2770               (setf first-one nil))
2771             (when (logbitp bitpos y)
2772               (setf first-one bitpos))))
2773       (when first-one
2774         (cond ((= first-one 31))
2775               ((= first-one 30)
2776                (add '(ash x 30)))
2777               (t
2778                (add `(- ,(tub32 '(ash x 31)) ,(tub32 `(ash x ,first-one))))))
2779         (add '(ash x 31))))
2780     (or result 0)))
2781
2782 ;;; If arg is a constant power of two, turn FLOOR into a shift and mask.
2783 ;;; If CEILING, add in (1- (ABS Y)) and then do FLOOR.
2784 (flet ((frob (y ceil-p)
2785          (unless (constant-continuation-p y)
2786            (give-up-ir1-transform))
2787          (let* ((y (continuation-value y))
2788                 (y-abs (abs y))
2789                 (len (1- (integer-length y-abs))))
2790            (unless (= y-abs (ash 1 len))
2791              (give-up-ir1-transform))
2792            (let ((shift (- len))
2793                  (mask (1- y-abs)))
2794              `(let ,(when ceil-p `((x (+ x ,(1- y-abs)))))
2795                 ,(if (minusp y)
2796                      `(values (ash (- x) ,shift)
2797                               (- (logand (- x) ,mask)))
2798                      `(values (ash x ,shift)
2799                               (logand x ,mask))))))))
2800   (deftransform floor ((x y) (integer integer) *)
2801     "convert division by 2^k to shift"
2802     (frob y nil))
2803   (deftransform ceiling ((x y) (integer integer) *)
2804     "convert division by 2^k to shift"
2805     (frob y t)))
2806
2807 ;;; Do the same for MOD.
2808 (deftransform mod ((x y) (integer integer) * :when :both)
2809   "convert remainder mod 2^k to LOGAND"
2810   (unless (constant-continuation-p y)
2811     (give-up-ir1-transform))
2812   (let* ((y (continuation-value y))
2813          (y-abs (abs y))
2814          (len (1- (integer-length y-abs))))
2815     (unless (= y-abs (ash 1 len))
2816       (give-up-ir1-transform))
2817     (let ((mask (1- y-abs)))
2818       (if (minusp y)
2819           `(- (logand (- x) ,mask))
2820           `(logand x ,mask)))))
2821
2822 ;;; If arg is a constant power of two, turn TRUNCATE into a shift and mask.
2823 (deftransform truncate ((x y) (integer integer))
2824   "convert division by 2^k to shift"
2825   (unless (constant-continuation-p y)
2826     (give-up-ir1-transform))
2827   (let* ((y (continuation-value y))
2828          (y-abs (abs y))
2829          (len (1- (integer-length y-abs))))
2830     (unless (= y-abs (ash 1 len))
2831       (give-up-ir1-transform))
2832     (let* ((shift (- len))
2833            (mask (1- y-abs)))
2834       `(if (minusp x)
2835            (values ,(if (minusp y)
2836                         `(ash (- x) ,shift)
2837                         `(- (ash (- x) ,shift)))
2838                    (- (logand (- x) ,mask)))
2839            (values ,(if (minusp y)
2840                         `(- (ash (- x) ,shift))
2841                         `(ash x ,shift))
2842                    (logand x ,mask))))))
2843
2844 ;;; And the same for REM.
2845 (deftransform rem ((x y) (integer integer) * :when :both)
2846   "convert remainder mod 2^k to LOGAND"
2847   (unless (constant-continuation-p y)
2848     (give-up-ir1-transform))
2849   (let* ((y (continuation-value y))
2850          (y-abs (abs y))
2851          (len (1- (integer-length y-abs))))
2852     (unless (= y-abs (ash 1 len))
2853       (give-up-ir1-transform))
2854     (let ((mask (1- y-abs)))
2855       `(if (minusp x)
2856            (- (logand (- x) ,mask))
2857            (logand x ,mask)))))
2858 \f
2859 ;;;; arithmetic and logical identity operation elimination
2860 ;;;;
2861 ;;;; Flush calls to various arith functions that convert to the identity
2862 ;;;; function or a constant.
2863
2864 (dolist (stuff '((ash 0 x)
2865                  (logand -1 x)
2866                  (logand 0 0)
2867                  (logior 0 x)
2868                  (logior -1 -1)
2869                  (logxor -1 (lognot x))
2870                  (logxor 0 x)))
2871   (destructuring-bind (name identity result) stuff
2872     (deftransform name ((x y) `(* (constant-argument (member ,identity))) '*
2873                         :eval-name t :when :both)
2874       "fold identity operations"
2875       result)))
2876
2877 ;;; These are restricted to rationals, because (- 0 0.0) is 0.0, not -0.0, and
2878 ;;; (* 0 -4.0) is -0.0.
2879 (deftransform - ((x y) ((constant-argument (member 0)) rational) *
2880                  :when :both)
2881   "convert (- 0 x) to negate"
2882   '(%negate y))
2883 (deftransform * ((x y) (rational (constant-argument (member 0))) *
2884                  :when :both)
2885   "convert (* x 0) to 0."
2886   0)
2887
2888 ;;; Return T if in an arithmetic op including continuations X and Y, the
2889 ;;; result type is not affected by the type of X. That is, Y is at least as
2890 ;;; contagious as X.
2891 #+nil
2892 (defun not-more-contagious (x y)
2893   (declare (type continuation x y))
2894   (let ((x (continuation-type x))
2895         (y (continuation-type y)))
2896     (values (type= (numeric-contagion x y)
2897                    (numeric-contagion y y)))))
2898 ;;; Patched version by Raymond Toy. dtc: Should be safer although it
2899 ;;; needs more work as valid transforms are missed; some cases are
2900 ;;; specific to particular transform functions so the use of this
2901 ;;; function may need a re-think.
2902 (defun not-more-contagious (x y)
2903   (declare (type continuation x y))
2904   (flet ((simple-numeric-type (num)
2905            (and (numeric-type-p num)
2906                 ;; Return non-NIL if NUM is integer, rational, or a float
2907                 ;; of some type (but not FLOAT)
2908                 (case (numeric-type-class num)
2909                   ((integer rational)
2910                    t)
2911                   (float
2912                    (numeric-type-format num))
2913                   (t
2914                    nil)))))
2915     (let ((x (continuation-type x))
2916           (y (continuation-type y)))
2917       (if (and (simple-numeric-type x)
2918                (simple-numeric-type y))
2919           (values (type= (numeric-contagion x y)
2920                          (numeric-contagion y y)))))))
2921
2922 ;;; Fold (+ x 0).
2923 ;;;
2924 ;;;    If y is not constant, not zerop, or is contagious, or a
2925 ;;; positive float +0.0 then give up.
2926 (deftransform + ((x y) (t (constant-argument t)) * :when :both)
2927   "fold zero arg"
2928   (let ((val (continuation-value y)))
2929     (unless (and (zerop val)
2930                  (not (and (floatp val) (plusp (float-sign val))))
2931                  (not-more-contagious y x))
2932       (give-up-ir1-transform)))
2933   'x)
2934
2935 ;;; Fold (- x 0).
2936 ;;;
2937 ;;;    If y is not constant, not zerop, or is contagious, or a
2938 ;;; negative float -0.0 then give up.
2939 (deftransform - ((x y) (t (constant-argument t)) * :when :both)
2940   "fold zero arg"
2941   (let ((val (continuation-value y)))
2942     (unless (and (zerop val)
2943                  (not (and (floatp val) (minusp (float-sign val))))
2944                  (not-more-contagious y x))
2945       (give-up-ir1-transform)))
2946   'x)
2947
2948 ;;; Fold (OP x +/-1)
2949 (dolist (stuff '((* x (%negate x))
2950                  (/ x (%negate x))
2951                  (expt x (/ 1 x))))
2952   (destructuring-bind (name result minus-result) stuff
2953     (deftransform name ((x y) '(t (constant-argument real)) '* :eval-name t
2954                         :when :both)
2955       "fold identity operations"
2956       (let ((val (continuation-value y)))
2957         (unless (and (= (abs val) 1)
2958                      (not-more-contagious y x))
2959           (give-up-ir1-transform))
2960         (if (minusp val) minus-result result)))))
2961
2962 ;;; Fold (expt x n) into multiplications for small integral values of
2963 ;;; N; convert (expt x 1/2) to sqrt.
2964 (deftransform expt ((x y) (t (constant-argument real)) *)
2965   "recode as multiplication or sqrt"
2966   (let ((val (continuation-value y)))
2967     ;; If Y would cause the result to be promoted to the same type as
2968     ;; Y, we give up. If not, then the result will be the same type
2969     ;; as X, so we can replace the exponentiation with simple
2970     ;; multiplication and division for small integral powers.
2971     (unless (not-more-contagious y x)
2972       (give-up-ir1-transform))
2973     (cond ((zerop val) '(float 1 x))
2974           ((= val 2) '(* x x))
2975           ((= val -2) '(/ (* x x)))
2976           ((= val 3) '(* x x x))
2977           ((= val -3) '(/ (* x x x)))
2978           ((= val 1/2) '(sqrt x))
2979           ((= val -1/2) '(/ (sqrt x)))
2980           (t (give-up-ir1-transform)))))
2981
2982 ;;; KLUDGE: Shouldn't (/ 0.0 0.0), etc. cause exceptions in these
2983 ;;; transformations?
2984 ;;; Perhaps we should have to prove that the denominator is nonzero before
2985 ;;; doing them? (Also the DOLIST over macro calls is weird. Perhaps
2986 ;;; just FROB?) -- WHN 19990917
2987 (dolist (name '(ash /))
2988   (deftransform name ((x y) '((constant-argument (integer 0 0)) integer) '*
2989                       :eval-name t :when :both)
2990     "fold zero arg"
2991     0))
2992 (dolist (name '(truncate round floor ceiling))
2993   (deftransform name ((x y) '((constant-argument (integer 0 0)) integer) '*
2994                       :eval-name t :when :both)
2995     "fold zero arg"
2996     '(values 0 0)))
2997 \f
2998 ;;;; character operations
2999
3000 (deftransform char-equal ((a b) (base-char base-char))
3001   "open code"
3002   '(let* ((ac (char-code a))
3003           (bc (char-code b))
3004           (sum (logxor ac bc)))
3005      (or (zerop sum)
3006          (when (eql sum #x20)
3007            (let ((sum (+ ac bc)))
3008              (and (> sum 161) (< sum 213)))))))
3009
3010 (deftransform char-upcase ((x) (base-char))
3011   "open code"
3012   '(let ((n-code (char-code x)))
3013      (if (and (> n-code #o140)  ; Octal 141 is #\a.
3014               (< n-code #o173)) ; Octal 172 is #\z.
3015          (code-char (logxor #x20 n-code))
3016          x)))
3017
3018 (deftransform char-downcase ((x) (base-char))
3019   "open code"
3020   '(let ((n-code (char-code x)))
3021      (if (and (> n-code 64)     ; 65 is #\A.
3022               (< n-code 91))    ; 90 is #\Z.
3023          (code-char (logxor #x20 n-code))
3024          x)))
3025 \f
3026 ;;;; equality predicate transforms
3027
3028 ;;; Return true if X and Y are continuations whose only use is a reference
3029 ;;; to the same leaf, and the value of the leaf cannot change.
3030 (defun same-leaf-ref-p (x y)
3031   (declare (type continuation x y))
3032   (let ((x-use (continuation-use x))
3033         (y-use (continuation-use y)))
3034     (and (ref-p x-use)
3035          (ref-p y-use)
3036          (eq (ref-leaf x-use) (ref-leaf y-use))
3037          (constant-reference-p x-use))))
3038
3039 ;;; If X and Y are the same leaf, then the result is true. Otherwise, if
3040 ;;; there is no intersection between the types of the arguments, then the
3041 ;;; result is definitely false.
3042 (deftransform simple-equality-transform ((x y) * * :defun-only t
3043                                          :when :both)
3044   (cond ((same-leaf-ref-p x y)
3045          't)
3046         ((not (types-intersect (continuation-type x) (continuation-type y)))
3047          'nil)
3048         (t
3049          (give-up-ir1-transform))))
3050
3051 (dolist (x '(eq char= equal))
3052   (%deftransform x '(function * *) #'simple-equality-transform))
3053
3054 ;;; Similar to SIMPLE-EQUALITY-PREDICATE, except that we also try to convert
3055 ;;; to a type-specific predicate or EQ:
3056 ;;; -- If both args are characters, convert to CHAR=. This is better than just
3057 ;;;    converting to EQ, since CHAR= may have special compilation strategies
3058 ;;;    for non-standard representations, etc.
3059 ;;; -- If either arg is definitely not a number, then we can compare with EQ.
3060 ;;; -- Otherwise, we try to put the arg we know more about second. If X is
3061 ;;;    constant then we put it second. If X is a subtype of Y, we put it
3062 ;;;    second. These rules make it easier for the back end to match these
3063 ;;;    interesting cases.
3064 ;;; -- If Y is a fixnum, then we quietly pass because the back end can handle
3065 ;;;    that case, otherwise give an efficency note.
3066 (deftransform eql ((x y) * * :when :both)
3067   "convert to simpler equality predicate"
3068   (let ((x-type (continuation-type x))
3069         (y-type (continuation-type y))
3070         (char-type (specifier-type 'character))
3071         (number-type (specifier-type 'number)))
3072     (cond ((same-leaf-ref-p x y)
3073            't)
3074           ((not (types-intersect x-type y-type))
3075            'nil)
3076           ((and (csubtypep x-type char-type)
3077                 (csubtypep y-type char-type))
3078            '(char= x y))
3079           ((or (not (types-intersect x-type number-type))
3080                (not (types-intersect y-type number-type)))
3081            '(eq x y))
3082           ((and (not (constant-continuation-p y))
3083                 (or (constant-continuation-p x)
3084                     (and (csubtypep x-type y-type)
3085                          (not (csubtypep y-type x-type)))))
3086            '(eql y x))
3087           (t
3088            (give-up-ir1-transform)))))
3089
3090 ;;; Convert to EQL if both args are rational and complexp is specified
3091 ;;; and the same for both.
3092 (deftransform = ((x y) * * :when :both)
3093   "open code"
3094   (let ((x-type (continuation-type x))
3095         (y-type (continuation-type y)))
3096     (if (and (csubtypep x-type (specifier-type 'number))
3097              (csubtypep y-type (specifier-type 'number)))
3098         (cond ((or (and (csubtypep x-type (specifier-type 'float))
3099                         (csubtypep y-type (specifier-type 'float)))
3100                    (and (csubtypep x-type (specifier-type '(complex float)))
3101                         (csubtypep y-type (specifier-type '(complex float)))))
3102                ;; They are both floats. Leave as = so that -0.0 is
3103                ;; handled correctly.
3104                (give-up-ir1-transform))
3105               ((or (and (csubtypep x-type (specifier-type 'rational))
3106                         (csubtypep y-type (specifier-type 'rational)))
3107                    (and (csubtypep x-type (specifier-type '(complex rational)))
3108                         (csubtypep y-type (specifier-type '(complex rational)))))
3109                ;; They are both rationals and complexp is the same. Convert
3110                ;; to EQL.
3111                '(eql x y))
3112               (t
3113                (give-up-ir1-transform
3114                 "The operands might not be the same type.")))
3115         (give-up-ir1-transform
3116          "The operands might not be the same type."))))
3117
3118 ;;; If Cont's type is a numeric type, then return the type, otherwise
3119 ;;; GIVE-UP-IR1-TRANSFORM.
3120 (defun numeric-type-or-lose (cont)
3121   (declare (type continuation cont))
3122   (let ((res (continuation-type cont)))
3123     (unless (numeric-type-p res) (give-up-ir1-transform))
3124     res))
3125
3126 ;;; See whether we can statically determine (< X Y) using type information.
3127 ;;; If X's high bound is < Y's low, then X < Y. Similarly, if X's low is >=
3128 ;;; to Y's high, the X >= Y (so return NIL). If not, at least make sure any
3129 ;;; constant arg is second.
3130 ;;;
3131 ;;; KLUDGE: Why should constant argument be second? It would be nice to find
3132 ;;; out and explain. -- WHN 19990917
3133 #!-propagate-float-type
3134 (defun ir1-transform-< (x y first second inverse)
3135   (if (same-leaf-ref-p x y)
3136       'nil
3137       (let* ((x-type (numeric-type-or-lose x))
3138              (x-lo (numeric-type-low x-type))
3139              (x-hi (numeric-type-high x-type))
3140              (y-type (numeric-type-or-lose y))
3141              (y-lo (numeric-type-low y-type))
3142              (y-hi (numeric-type-high y-type)))
3143         (cond ((and x-hi y-lo (< x-hi y-lo))
3144                't)
3145               ((and y-hi x-lo (>= x-lo y-hi))
3146                'nil)
3147               ((and (constant-continuation-p first)
3148                     (not (constant-continuation-p second)))
3149                `(,inverse y x))
3150               (t
3151                (give-up-ir1-transform))))))
3152 #!+propagate-float-type
3153 (defun ir1-transform-< (x y first second inverse)
3154   (if (same-leaf-ref-p x y)
3155       'nil
3156       (let ((xi (numeric-type->interval (numeric-type-or-lose x)))
3157             (yi (numeric-type->interval (numeric-type-or-lose y))))
3158         (cond ((interval-< xi yi)
3159                't)
3160               ((interval->= xi yi)
3161                'nil)
3162               ((and (constant-continuation-p first)
3163                     (not (constant-continuation-p second)))
3164                `(,inverse y x))
3165               (t
3166                (give-up-ir1-transform))))))
3167
3168 (deftransform < ((x y) (integer integer) * :when :both)
3169   (ir1-transform-< x y x y '>))
3170
3171 (deftransform > ((x y) (integer integer) * :when :both)
3172   (ir1-transform-< y x x y '<))
3173
3174 #!+propagate-float-type
3175 (deftransform < ((x y) (float float) * :when :both)
3176   (ir1-transform-< x y x y '>))
3177
3178 #!+propagate-float-type
3179 (deftransform > ((x y) (float float) * :when :both)
3180   (ir1-transform-< y x x y '<))
3181 \f
3182 ;;;; converting N-arg comparisons
3183 ;;;;
3184 ;;;; We convert calls to N-arg comparison functions such as < into
3185 ;;;; two-arg calls. This transformation is enabled for all such
3186 ;;;; comparisons in this file. If any of these predicates are not
3187 ;;;; open-coded, then the transformation should be removed at some
3188 ;;;; point to avoid pessimization.
3189
3190 ;;; This function is used for source transformation of N-arg
3191 ;;; comparison functions other than inequality. We deal both with
3192 ;;; converting to two-arg calls and inverting the sense of the test,
3193 ;;; if necessary. If the call has two args, then we pass or return a
3194 ;;; negated test as appropriate. If it is a degenerate one-arg call,
3195 ;;; then we transform to code that returns true. Otherwise, we bind
3196 ;;; all the arguments and expand into a bunch of IFs.
3197 (declaim (ftype (function (symbol list boolean) *) multi-compare))
3198 (defun multi-compare (predicate args not-p)
3199   (let ((nargs (length args)))
3200     (cond ((< nargs 1) (values nil t))
3201           ((= nargs 1) `(progn ,@args t))
3202           ((= nargs 2)
3203            (if not-p
3204                `(if (,predicate ,(first args) ,(second args)) nil t)
3205                (values nil t)))
3206           (t
3207            (do* ((i (1- nargs) (1- i))
3208                  (last nil current)
3209                  (current (gensym) (gensym))
3210                  (vars (list current) (cons current vars))
3211                  (result 't (if not-p
3212                                 `(if (,predicate ,current ,last)
3213                                      nil ,result)
3214                                 `(if (,predicate ,current ,last)
3215                                      ,result nil))))
3216                ((zerop i)
3217                 `((lambda ,vars ,result) . ,args)))))))
3218
3219 (def-source-transform = (&rest args) (multi-compare '= args nil))
3220 (def-source-transform < (&rest args) (multi-compare '< args nil))
3221 (def-source-transform > (&rest args) (multi-compare '> args nil))
3222 (def-source-transform <= (&rest args) (multi-compare '> args t))
3223 (def-source-transform >= (&rest args) (multi-compare '< args t))
3224
3225 (def-source-transform char= (&rest args) (multi-compare 'char= args nil))
3226 (def-source-transform char< (&rest args) (multi-compare 'char< args nil))
3227 (def-source-transform char> (&rest args) (multi-compare 'char> args nil))
3228 (def-source-transform char<= (&rest args) (multi-compare 'char> args t))
3229 (def-source-transform char>= (&rest args) (multi-compare 'char< args t))
3230
3231 (def-source-transform char-equal (&rest args) (multi-compare 'char-equal args nil))
3232 (def-source-transform char-lessp (&rest args) (multi-compare 'char-lessp args nil))
3233 (def-source-transform char-greaterp (&rest args) (multi-compare 'char-greaterp args nil))
3234 (def-source-transform char-not-greaterp (&rest args) (multi-compare 'char-greaterp args t))
3235 (def-source-transform char-not-lessp (&rest args) (multi-compare 'char-lessp args t))
3236
3237 ;;; This function does source transformation of N-arg inequality
3238 ;;; functions such as /=. This is similar to Multi-Compare in the <3
3239 ;;; arg cases. If there are more than two args, then we expand into
3240 ;;; the appropriate n^2 comparisons only when speed is important.
3241 (declaim (ftype (function (symbol list) *) multi-not-equal))
3242 (defun multi-not-equal (predicate args)
3243   (let ((nargs (length args)))
3244     (cond ((< nargs 1) (values nil t))
3245           ((= nargs 1) `(progn ,@args t))
3246           ((= nargs 2)
3247            `(if (,predicate ,(first args) ,(second args)) nil t))
3248           ((not (policy nil (>= speed space) (>= speed cspeed)))
3249            (values nil t))
3250           (t
3251            (collect ((vars))
3252              (dotimes (i nargs) (vars (gensym)))
3253              (do ((var (vars) next)
3254                   (next (cdr (vars)) (cdr next))
3255                   (result 't))
3256                  ((null next)
3257                   `((lambda ,(vars) ,result) . ,args))
3258                (let ((v1 (first var)))
3259                  (dolist (v2 next)
3260                    (setq result `(if (,predicate ,v1 ,v2) nil ,result))))))))))
3261
3262 (def-source-transform /= (&rest args) (multi-not-equal '= args))
3263 (def-source-transform char/= (&rest args) (multi-not-equal 'char= args))
3264 (def-source-transform char-not-equal (&rest args) (multi-not-equal 'char-equal args))
3265
3266 ;;; Expand MAX and MIN into the obvious comparisons.
3267 (def-source-transform max (arg &rest more-args)
3268   (if (null more-args)
3269       `(values ,arg)
3270       (once-only ((arg1 arg)
3271                   (arg2 `(max ,@more-args)))
3272         `(if (> ,arg1 ,arg2)
3273              ,arg1 ,arg2))))
3274 (def-source-transform min (arg &rest more-args)
3275   (if (null more-args)
3276       `(values ,arg)
3277       (once-only ((arg1 arg)
3278                   (arg2 `(min ,@more-args)))
3279         `(if (< ,arg1 ,arg2)
3280              ,arg1 ,arg2))))
3281 \f
3282 ;;;; converting N-arg arithmetic functions
3283 ;;;;
3284 ;;;; N-arg arithmetic and logic functions are associated into two-arg
3285 ;;;; versions, and degenerate cases are flushed.
3286
3287 ;;; Left-associate First-Arg and More-Args using Function.
3288 (declaim (ftype (function (symbol t list) list) associate-arguments))
3289 (defun associate-arguments (function first-arg more-args)
3290   (let ((next (rest more-args))
3291         (arg (first more-args)))
3292     (if (null next)
3293         `(,function ,first-arg ,arg)
3294         (associate-arguments function `(,function ,first-arg ,arg) next))))
3295
3296 ;;; Do source transformations for transitive functions such as +.
3297 ;;; One-arg cases are replaced with the arg and zero arg cases with
3298 ;;; the identity. If Leaf-Fun is true, then replace two-arg calls with
3299 ;;; a call to that function.
3300 (defun source-transform-transitive (fun args identity &optional leaf-fun)
3301   (declare (symbol fun leaf-fun) (list args))
3302   (case (length args)
3303     (0 identity)
3304     (1 `(values ,(first args)))
3305     (2 (if leaf-fun
3306            `(,leaf-fun ,(first args) ,(second args))
3307            (values nil t)))
3308     (t
3309      (associate-arguments fun (first args) (rest args)))))
3310
3311 (def-source-transform + (&rest args) (source-transform-transitive '+ args 0))
3312 (def-source-transform * (&rest args) (source-transform-transitive '* args 1))
3313 (def-source-transform logior (&rest args) (source-transform-transitive 'logior args 0))
3314 (def-source-transform logxor (&rest args) (source-transform-transitive 'logxor args 0))
3315 (def-source-transform logand (&rest args) (source-transform-transitive 'logand args -1))
3316
3317 (def-source-transform logeqv (&rest args)
3318   (if (evenp (length args))
3319       `(lognot (logxor ,@args))
3320       `(logxor ,@args)))
3321
3322 ;;; Note: we can't use SOURCE-TRANSFORM-TRANSITIVE for GCD and LCM
3323 ;;; because when they are given one argument, they return its absolute
3324 ;;; value.
3325
3326 (def-source-transform gcd (&rest args)
3327   (case (length args)
3328     (0 0)
3329     (1 `(abs (the integer ,(first args))))
3330     (2 (values nil t))
3331     (t (associate-arguments 'gcd (first args) (rest args)))))
3332
3333 (def-source-transform lcm (&rest args)
3334   (case (length args)
3335     (0 1)
3336     (1 `(abs (the integer ,(first args))))
3337     (2 (values nil t))
3338     (t (associate-arguments 'lcm (first args) (rest args)))))
3339
3340 ;;; Do source transformations for intransitive n-arg functions such as
3341 ;;; /. With one arg, we form the inverse. With two args we pass.
3342 ;;; Otherwise we associate into two-arg calls.
3343 (declaim (ftype (function (symbol list t) list) source-transform-intransitive))
3344 (defun source-transform-intransitive (function args inverse)
3345   (case (length args)
3346     ((0 2) (values nil t))
3347     (1 `(,@inverse ,(first args)))
3348     (t (associate-arguments function (first args) (rest args)))))
3349
3350 (def-source-transform - (&rest args)
3351   (source-transform-intransitive '- args '(%negate)))
3352 (def-source-transform / (&rest args)
3353   (source-transform-intransitive '/ args '(/ 1)))
3354 \f
3355 ;;;; APPLY
3356
3357 ;;; We convert APPLY into MULTIPLE-VALUE-CALL so that the compiler
3358 ;;; only needs to understand one kind of variable-argument call. It is
3359 ;;; more efficient to convert APPLY to MV-CALL than MV-CALL to APPLY.
3360 (def-source-transform apply (fun arg &rest more-args)
3361   (let ((args (cons arg more-args)))
3362     `(multiple-value-call ,fun
3363        ,@(mapcar #'(lambda (x)
3364                      `(values ,x))
3365                  (butlast args))
3366        (values-list ,(car (last args))))))
3367 \f
3368 ;;;; FORMAT
3369 ;;;;
3370 ;;;; If the control string is a compile-time constant, then replace it
3371 ;;;; with a use of the FORMATTER macro so that the control string is
3372 ;;;; ``compiled.'' Furthermore, if the destination is either a stream
3373 ;;;; or T and the control string is a function (i.e. formatter), then
3374 ;;;; convert the call to format to just a funcall of that function.
3375
3376 (deftransform format ((dest control &rest args) (t simple-string &rest t) *
3377                       :policy (> speed space))
3378   (unless (constant-continuation-p control)
3379     (give-up-ir1-transform "The control string is not a constant."))
3380   (let ((arg-names (mapcar #'(lambda (x) (declare (ignore x)) (gensym)) args)))
3381     `(lambda (dest control ,@arg-names)
3382        (declare (ignore control))
3383        (format dest (formatter ,(continuation-value control)) ,@arg-names))))
3384
3385 (deftransform format ((stream control &rest args) (stream function &rest t) *
3386                       :policy (> speed space))
3387   (let ((arg-names (mapcar #'(lambda (x) (declare (ignore x)) (gensym)) args)))
3388     `(lambda (stream control ,@arg-names)
3389        (funcall control stream ,@arg-names)
3390        nil)))
3391
3392 (deftransform format ((tee control &rest args) ((member t) function &rest t) *
3393                       :policy (> speed space))
3394   (let ((arg-names (mapcar #'(lambda (x) (declare (ignore x)) (gensym)) args)))
3395     `(lambda (tee control ,@arg-names)
3396        (declare (ignore tee))
3397        (funcall control *standard-output* ,@arg-names)
3398        nil)))