1 ;;;; This file contains macro-like source transformations which
2 ;;;; convert uses of certain functions into the canonical form desired
3 ;;;; within the compiler. FIXME: and other IR1 transforms and stuff.
5 ;;;; This software is part of the SBCL system. See the README file for
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.
16 ;;; We turn IDENTITY into PROG1 so that it is obvious that it just
17 ;;; returns the first value of its argument. Ditto for VALUES with one
19 (define-source-transform identity
(x) `(prog1 ,x
))
20 (define-source-transform values
(x) `(prog1 ,x
))
22 ;;; CONSTANTLY is pretty much never worth transforming, but it's good to get the type.
23 (defoptimizer (constantly derive-type
) ((value))
25 `(function (&rest t
) (values ,(type-specifier (lvar-type value
)) &optional
))))
27 ;;; If the function has a known number of arguments, then return a
28 ;;; lambda with the appropriate fixed number of args. If the
29 ;;; destination is a FUNCALL, then do the &REST APPLY thing, and let
30 ;;; MV optimization figure things out.
31 (deftransform complement
((fun) * * :node node
)
33 (multiple-value-bind (min max
)
34 (fun-type-nargs (lvar-type fun
))
36 ((and min
(eql min max
))
37 (let ((dums (make-gensym-list min
)))
38 `#'(lambda ,dums
(not (funcall fun
,@dums
)))))
39 ((awhen (node-lvar node
)
40 (let ((dest (lvar-dest it
)))
41 (and (combination-p dest
)
42 (eq (combination-fun dest
) it
))))
43 '#'(lambda (&rest args
)
44 (not (apply fun args
))))
46 (give-up-ir1-transform
47 "The function doesn't have a fixed argument count.")))))
50 (defun derive-symbol-value-type (lvar node
)
51 (if (constant-lvar-p lvar
)
52 (let* ((sym (lvar-value lvar
))
53 (var (maybe-find-free-var sym
))
55 (let ((*lexenv
* (node-lexenv node
)))
56 (lexenv-find var type-restrictions
))))
57 (global-type (info :variable
:type sym
)))
59 (type-intersection local-type global-type
)
63 (defoptimizer (symbol-value derive-type
) ((symbol) node
)
64 (derive-symbol-value-type symbol node
))
66 (defoptimizer (symbol-global-value derive-type
) ((symbol) node
)
67 (derive-symbol-value-type symbol node
))
71 ;;; Translate CxR into CAR/CDR combos.
72 (defun source-transform-cxr (form)
73 (if (/= (length form
) 2)
75 (let* ((name (car form
))
79 (leaf (leaf-source-name name
))))))
80 (do ((i (- (length string
) 2) (1- i
))
82 `(,(ecase (char string i
)
88 ;;; Make source transforms to turn CxR forms into combinations of CAR
89 ;;; and CDR. ANSI specifies that everything up to 4 A/D operations is
91 ;;; Don't transform CAD*R, they are treated specially for &more args
94 (/show0
"about to set CxR source transforms")
95 (loop for i of-type index from
2 upto
4 do
96 ;; Iterate over BUF = all names CxR where x = an I-element
97 ;; string of #\A or #\D characters.
98 (let ((buf (make-string (+ 2 i
))))
99 (setf (aref buf
0) #\C
100 (aref buf
(1+ i
)) #\R
)
101 (dotimes (j (ash 2 i
))
102 (declare (type index j
))
104 (declare (type index k
))
105 (setf (aref buf
(1+ k
))
106 (if (logbitp k j
) #\A
#\D
)))
107 (unless (member buf
'("CADR" "CADDR" "CADDDR")
109 (setf (info :function
:source-transform
(intern buf
))
110 #'source-transform-cxr
)))))
111 (/show0
"done setting CxR source transforms")
113 ;;; Turn FIRST..FOURTH and REST into the obvious synonym, assuming
114 ;;; whatever is right for them is right for us. FIFTH..TENTH turn into
115 ;;; Nth, which can be expanded into a CAR/CDR later on if policy
117 (define-source-transform rest
(x) `(cdr ,x
))
118 (define-source-transform first
(x) `(car ,x
))
119 (define-source-transform second
(x) `(cadr ,x
))
120 (define-source-transform third
(x) `(caddr ,x
))
121 (define-source-transform fourth
(x) `(cadddr ,x
))
122 (define-source-transform fifth
(x) `(nth 4 ,x
))
123 (define-source-transform sixth
(x) `(nth 5 ,x
))
124 (define-source-transform seventh
(x) `(nth 6 ,x
))
125 (define-source-transform eighth
(x) `(nth 7 ,x
))
126 (define-source-transform ninth
(x) `(nth 8 ,x
))
127 (define-source-transform tenth
(x) `(nth 9 ,x
))
129 ;;; LIST with one arg is an extremely common operation (at least inside
130 ;;; SBCL itself); translate it to CONS to take advantage of common
131 ;;; allocation routines.
132 (define-source-transform list
(&rest args
)
134 (1 `(cons ,(first args
) nil
))
137 (defoptimizer (list derive-type
) ((&rest args
) node
)
139 (specifier-type 'cons
)
140 (specifier-type 'null
)))
142 ;;; And similarly for LIST*.
143 (define-source-transform list
* (arg &rest others
)
144 (cond ((not others
) arg
)
145 ((not (cdr others
)) `(cons ,arg
,(car others
)))
148 (defoptimizer (list* derive-type
) ((arg &rest args
))
150 (specifier-type 'cons
)
155 (define-source-transform nconc
(&rest args
)
161 ;;; (append nil nil nil fixnum) => fixnum
162 ;;; (append x x cons x x) => cons
163 ;;; (append x x x x list) => list
164 ;;; (append x x x x sequence) => sequence
165 ;;; (append fixnum x ...) => nil
166 (defun derive-append-type (args)
168 (return-from derive-append-type
(specifier-type 'null
)))
169 (let* ((cons-type (specifier-type 'cons
))
170 (null-type (specifier-type 'null
))
171 (list-type (specifier-type 'list
))
172 (last (lvar-type (car (last args
)))))
173 ;; Derive the actual return type, assuming that all but the last
174 ;; arguments are LISTs (otherwise, APPEND/NCONC doesn't return).
175 (loop with all-nil
= t
; all but the last args are NIL?
176 with some-cons
= nil
; some args are conses?
177 for
(arg next
) on args
178 for lvar-type
= (type-approx-intersection2 (lvar-type arg
)
181 do
(multiple-value-bind (typep definitely
)
182 (ctypep nil lvar-type
)
183 (cond ((type= lvar-type
*empty-type
*)
184 ;; type mismatch! insert an inline check that'll cause
185 ;; compile-time warnings.
186 (assert-lvar-type arg list-type
187 (lexenv-policy *lexenv
*)))
188 (some-cons) ; we know result's a cons -- nothing to do
189 ((and (not typep
) definitely
) ; can't be NIL
190 (setf some-cons t
)) ; must be a CONS
192 (setf all-nil
(csubtypep lvar-type null-type
)))))
194 ;; if some of the previous arguments are CONSes so is the result;
195 ;; if all the previous values are NIL, we're a fancy identity;
196 ;; otherwise, could be either
197 (return (cond (some-cons cons-type
)
199 (t (type-union last cons-type
)))))))
201 (defoptimizer (append derive-type
) ((&rest args
))
202 (derive-append-type args
))
204 (defoptimizer (sb!impl
::append2 derive-type
) ((&rest args
))
205 (derive-append-type args
))
207 (defoptimizer (nconc derive-type
) ((&rest args
))
208 (derive-append-type args
))
210 ;;; Translate RPLACx to LET and SETF.
211 (define-source-transform rplaca
(x y
)
216 (define-source-transform rplacd
(x y
)
222 (deftransform last
((list &optional n
) (t &optional t
))
223 (let ((c (constant-lvar-p n
)))
225 (and c
(eql 1 (lvar-value n
))))
227 ((and c
(eql 0 (lvar-value n
)))
230 (let ((type (lvar-type n
)))
231 (cond ((csubtypep type
(specifier-type 'fixnum
))
232 '(%lastn
/fixnum list n
))
233 ((csubtypep type
(specifier-type 'bignum
))
234 '(%lastn
/bignum list n
))
236 (give-up-ir1-transform "second argument type too vague"))))))))
238 (define-source-transform gethash
(&rest args
)
240 (2 `(sb!impl
::gethash3
,@args nil
))
241 (3 `(sb!impl
::gethash3
,@args
))
243 (define-source-transform get
(&rest args
)
245 (2 `(sb!impl
::get3
,@args nil
))
246 (3 `(sb!impl
::get3
,@args
))
249 (defvar *default-nthcdr-open-code-limit
* 6)
250 (defvar *extreme-nthcdr-open-code-limit
* 20)
252 (deftransform nthcdr
((n l
) (unsigned-byte t
) * :node node
)
253 "convert NTHCDR to CAxxR"
254 (unless (constant-lvar-p n
)
255 (give-up-ir1-transform))
256 (let ((n (lvar-value n
)))
258 (if (policy node
(and (= speed
3) (= space
0)))
259 *extreme-nthcdr-open-code-limit
*
260 *default-nthcdr-open-code-limit
*))
261 (give-up-ir1-transform))
266 `(cdr ,(frob (1- n
))))))
269 ;;;; arithmetic and numerology
271 (define-source-transform plusp
(x) `(> ,x
0))
272 (define-source-transform minusp
(x) `(< ,x
0))
273 (define-source-transform zerop
(x) `(= ,x
0))
275 (define-source-transform 1+ (x) `(+ ,x
1))
276 (define-source-transform 1-
(x) `(- ,x
1))
278 (define-source-transform oddp
(x) `(logtest ,x
1))
279 (define-source-transform evenp
(x) `(not (logtest ,x
1)))
281 ;;; Note that all the integer division functions are available for
282 ;;; inline expansion.
284 (macrolet ((deffrob (fun)
285 `(define-source-transform ,fun
(x &optional
(y nil y-p
))
292 #-sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
294 #-sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
297 ;;; This used to be a source transform (hence the lack of restrictions
298 ;;; on the argument types), but we make it a regular transform so that
299 ;;; the VM has a chance to see the bare LOGTEST and potentiall choose
300 ;;; to implement it differently. --njf, 06-02-2006
302 ;;; Other transforms may be useful even with direct LOGTEST VOPs; let
303 ;;; them fire (including the type-directed constant folding below), but
304 ;;; disable the inlining rewrite in such cases. -- PK, 2013-05-20
305 (deftransform logtest
((x y
) * * :node node
)
306 (let ((type (two-arg-derive-type x y
307 #'logand-derive-type-aux
309 (multiple-value-bind (typep definitely
)
311 (cond ((and (not typep
) definitely
)
313 ((type= type
(specifier-type '(eql 0)))
315 ((neq :default
(combination-implementation-style node
))
316 (give-up-ir1-transform))
318 `(not (zerop (logand x y
))))))))
320 (deftransform logbitp
321 ((index integer
) (unsigned-byte (or (signed-byte #.sb
!vm
:n-word-bits
)
322 (unsigned-byte #.sb
!vm
:n-word-bits
))))
323 (flet ((general-case ()
324 `(if (>= index
#.sb
!vm
:n-word-bits
)
326 (not (zerop (logand integer
(ash 1 index
)))))))
327 (if (constant-lvar-p integer
)
328 (let ((val (lvar-value integer
)))
329 (cond ((eql val
0) nil
)
334 (define-source-transform byte
(size position
)
335 `(cons ,size
,position
))
336 (define-source-transform byte-size
(spec) `(car ,spec
))
337 (define-source-transform byte-position
(spec) `(cdr ,spec
))
338 (define-source-transform ldb-test
(bytespec integer
)
339 `(not (zerop (mask-field ,bytespec
,integer
))))
341 ;;; With the ratio and complex accessors, we pick off the "identity"
342 ;;; case, and use a primitive to handle the cell access case.
343 (define-source-transform numerator
(num)
344 (once-only ((n-num `(the rational
,num
)))
348 (define-source-transform denominator
(num)
349 (once-only ((n-num `(the rational
,num
)))
351 (%denominator
,n-num
)
354 ;;;; interval arithmetic for computing bounds
356 ;;;; This is a set of routines for operating on intervals. It
357 ;;;; implements a simple interval arithmetic package. Although SBCL
358 ;;;; has an interval type in NUMERIC-TYPE, we choose to use our own
359 ;;;; for two reasons:
361 ;;;; 1. This package is simpler than NUMERIC-TYPE.
363 ;;;; 2. It makes debugging much easier because you can just strip
364 ;;;; out these routines and test them independently of SBCL. (This is a
367 ;;;; One disadvantage is a probable increase in consing because we
368 ;;;; have to create these new interval structures even though
369 ;;;; numeric-type has everything we want to know. Reason 2 wins for
372 ;;; Support operations that mimic real arithmetic comparison
373 ;;; operators, but imposing a total order on the floating points such
374 ;;; that negative zeros are strictly less than positive zeros.
375 (macrolet ((def (name op
)
378 (if (and (floatp x
) (floatp y
) (zerop x
) (zerop y
))
379 (,op
(float-sign x
) (float-sign y
))
381 (def signed-zero-
>= >=)
382 (def signed-zero-
> >)
383 (def signed-zero-
= =)
384 (def signed-zero-
< <)
385 (def signed-zero-
<= <=))
387 ;;; The basic interval type. It can handle open and closed intervals.
388 ;;; A bound is open if it is a list containing a number, just like
389 ;;; Lisp says. NIL means unbounded.
390 (defstruct (interval (:constructor %make-interval
)
394 (defun make-interval (&key low high
)
395 (labels ((normalize-bound (val)
398 (float-infinity-p val
))
399 ;; Handle infinities.
403 ;; Handle any closed bounds.
406 ;; We have an open bound. Normalize the numeric
407 ;; bound. If the normalized bound is still a number
408 ;; (not nil), keep the bound open. Otherwise, the
409 ;; bound is really unbounded, so drop the openness.
410 (let ((new-val (normalize-bound (first val
))))
412 ;; The bound exists, so keep it open still.
415 (error "unknown bound type in MAKE-INTERVAL")))))
416 (%make-interval
:low
(normalize-bound low
)
417 :high
(normalize-bound high
))))
419 ;;; Given a number X, create a form suitable as a bound for an
420 ;;; interval. Make the bound open if OPEN-P is T. NIL remains NIL.
421 #!-sb-fluid
(declaim (inline set-bound
))
422 (defun set-bound (x open-p
)
423 (if (and x open-p
) (list x
) x
))
425 ;;; Apply the function F to a bound X. If X is an open bound and the
426 ;;; function is declared strictly monotonic, then the result will be
427 ;;; open. IF X is NIL, the result is NIL.
428 (defun bound-func (f x strict
)
429 (declare (type function f
))
432 (with-float-traps-masked (:underflow
:overflow
:inexact
:divide-by-zero
)
433 ;; With these traps masked, we might get things like infinity
434 ;; or negative infinity returned. Check for this and return
435 ;; NIL to indicate unbounded.
436 (let ((y (funcall f
(type-bound-number x
))))
438 (float-infinity-p y
))
440 (set-bound y
(and strict
(consp x
))))))
441 ;; Some numerical operations will signal SIMPLE-TYPE-ERROR, e.g.
442 ;; in the course of converting a bignum to a float. Default to
444 (simple-type-error ()))))
446 (defun safe-double-coercion-p (x)
447 (or (typep x
'double-float
)
448 (<= most-negative-double-float x most-positive-double-float
)))
450 (defun safe-single-coercion-p (x)
451 (or (typep x
'single-float
)
453 ;; Fix for bug 420, and related issues: during type derivation we often
454 ;; end up deriving types for both
456 ;; (some-op <int> <single>)
458 ;; (some-op (coerce <int> 'single-float) <single>)
460 ;; or other equivalent transformed forms. The problem with this
461 ;; is that on x86 (+ <int> <single>) is on the machine level
464 ;; (coerce (+ (coerce <int> 'double-float)
465 ;; (coerce <single> 'double-float))
468 ;; so if the result of (coerce <int> 'single-float) is not exact, the
469 ;; derived types for the transformed forms will have an empty
470 ;; intersection -- which in turn means that the compiler will conclude
471 ;; that the call never returns, and all hell breaks lose when it *does*
472 ;; return at runtime. (This affects not just +, but other operators are
475 ;; See also: SAFE-CTYPE-FOR-SINGLE-COERCION-P
477 ;; FIXME: If we ever add SSE-support for x86, this conditional needs to
480 (not (typep x
`(or (integer * (,most-negative-exactly-single-float-fixnum
))
481 (integer (,most-positive-exactly-single-float-fixnum
) *))))
482 (<= most-negative-single-float x most-positive-single-float
))))
484 ;;; Apply a binary operator OP to two bounds X and Y. The result is
485 ;;; NIL if either is NIL. Otherwise bound is computed and the result
486 ;;; is open if either X or Y is open.
488 ;;; FIXME: only used in this file, not needed in target runtime
490 ;;; ANSI contaigon specifies coercion to floating point if one of the
491 ;;; arguments is floating point. Here we should check to be sure that
492 ;;; the other argument is within the bounds of that floating point
495 (defmacro safely-binop
(op x y
)
497 ((typep ,x
'double-float
)
498 (when (safe-double-coercion-p ,y
)
500 ((typep ,y
'double-float
)
501 (when (safe-double-coercion-p ,x
)
503 ((typep ,x
'single-float
)
504 (when (safe-single-coercion-p ,y
)
506 ((typep ,y
'single-float
)
507 (when (safe-single-coercion-p ,x
)
511 (defmacro bound-binop
(op x y
)
512 (with-unique-names (xb yb res
)
514 (with-float-traps-masked (:underflow
:overflow
:inexact
:divide-by-zero
)
515 (let* ((,xb
(type-bound-number ,x
))
516 (,yb
(type-bound-number ,y
))
517 (,res
(safely-binop ,op
,xb
,yb
)))
519 (and (or (consp ,x
) (consp ,y
))
520 ;; Open bounds can very easily be messed up
521 ;; by FP rounding, so take care here.
524 ;; Multiplying a greater-than-zero with
525 ;; less than one can round to zero.
526 `(or (not (fp-zero-p ,res
))
527 (cond ((and (consp ,x
) (fp-zero-p ,xb
))
529 ((and (consp ,y
) (fp-zero-p ,yb
))
532 ;; Dividing a greater-than-zero with
533 ;; greater than one can round to zero.
534 `(or (not (fp-zero-p ,res
))
535 (cond ((and (consp ,x
) (fp-zero-p ,xb
))
537 ((and (consp ,y
) (fp-zero-p ,yb
))
540 ;; Adding or subtracting greater-than-zero
541 ;; can end up with identity.
542 `(and (not (fp-zero-p ,xb
))
543 (not (fp-zero-p ,yb
))))))))))))
545 (defun coercion-loses-precision-p (val type
)
548 (double-float (subtypep type
'single-float
))
549 (rational (subtypep type
'float
))
550 (t (bug "Unexpected arguments to bounds coercion: ~S ~S" val type
))))
552 (defun coerce-for-bound (val type
)
554 (let ((xbound (coerce-for-bound (car val
) type
)))
555 (if (coercion-loses-precision-p (car val
) type
)
559 ((subtypep type
'double-float
)
560 (if (<= most-negative-double-float val most-positive-double-float
)
562 ((or (subtypep type
'single-float
) (subtypep type
'float
))
563 ;; coerce to float returns a single-float
564 (if (<= most-negative-single-float val most-positive-single-float
)
566 (t (coerce val type
)))))
568 (defun coerce-and-truncate-floats (val type
)
571 (let ((xbound (coerce-for-bound (car val
) type
)))
572 (if (coercion-loses-precision-p (car val
) type
)
576 ((subtypep type
'double-float
)
577 (if (<= most-negative-double-float val most-positive-double-float
)
579 (if (< val most-negative-double-float
)
580 most-negative-double-float most-positive-double-float
)))
581 ((or (subtypep type
'single-float
) (subtypep type
'float
))
582 ;; coerce to float returns a single-float
583 (if (<= most-negative-single-float val most-positive-single-float
)
585 (if (< val most-negative-single-float
)
586 most-negative-single-float most-positive-single-float
)))
587 (t (coerce val type
))))))
589 ;;; Convert a numeric-type object to an interval object.
590 (defun numeric-type->interval
(x)
591 (declare (type numeric-type x
))
592 (make-interval :low
(numeric-type-low x
)
593 :high
(numeric-type-high x
)))
595 (defun type-approximate-interval (type)
596 (declare (type ctype type
))
597 (let ((types (prepare-arg-for-derive-type type
))
600 (let ((type (if (member-type-p type
)
601 (convert-member-type type
)
603 (unless (numeric-type-p type
)
604 (return-from type-approximate-interval nil
))
605 (let ((interval (numeric-type->interval type
)))
608 (interval-approximate-union result interval
)
612 (defun copy-interval-limit (limit)
617 (defun copy-interval (x)
618 (declare (type interval x
))
619 (make-interval :low
(copy-interval-limit (interval-low x
))
620 :high
(copy-interval-limit (interval-high x
))))
622 ;;; Given a point P contained in the interval X, split X into two
623 ;;; intervals at the point P. If CLOSE-LOWER is T, then the left
624 ;;; interval contains P. If CLOSE-UPPER is T, the right interval
625 ;;; contains P. You can specify both to be T or NIL.
626 (defun interval-split (p x
&optional close-lower close-upper
)
627 (declare (type number p
)
629 (list (make-interval :low
(copy-interval-limit (interval-low x
))
630 :high
(if close-lower p
(list p
)))
631 (make-interval :low
(if close-upper
(list p
) p
)
632 :high
(copy-interval-limit (interval-high x
)))))
634 ;;; Return the closure of the interval. That is, convert open bounds
635 ;;; to closed bounds.
636 (defun interval-closure (x)
637 (declare (type interval x
))
638 (make-interval :low
(type-bound-number (interval-low x
))
639 :high
(type-bound-number (interval-high x
))))
641 ;;; For an interval X, if X >= POINT, return '+. If X <= POINT, return
642 ;;; '-. Otherwise return NIL.
643 (defun interval-range-info (x &optional
(point 0))
644 (declare (type interval x
))
645 (let ((lo (interval-low x
))
646 (hi (interval-high x
)))
647 (cond ((and lo
(signed-zero->= (type-bound-number lo
) point
))
649 ((and hi
(signed-zero->= point
(type-bound-number hi
)))
654 ;;; Test to see whether the interval X is bounded. HOW determines the
655 ;;; test, and should be either ABOVE, BELOW, or BOTH.
656 (defun interval-bounded-p (x how
)
657 (declare (type interval x
))
664 (and (interval-low x
) (interval-high x
)))))
666 ;;; See whether the interval X contains the number P, taking into
667 ;;; account that the interval might not be closed.
668 (defun interval-contains-p (p x
)
669 (declare (type number p
)
671 ;; Does the interval X contain the number P? This would be a lot
672 ;; easier if all intervals were closed!
673 (let ((lo (interval-low x
))
674 (hi (interval-high x
)))
676 ;; The interval is bounded
677 (if (and (signed-zero-<= (type-bound-number lo
) p
)
678 (signed-zero-<= p
(type-bound-number hi
)))
679 ;; P is definitely in the closure of the interval.
680 ;; We just need to check the end points now.
681 (cond ((signed-zero-= p
(type-bound-number lo
))
683 ((signed-zero-= p
(type-bound-number hi
))
688 ;; Interval with upper bound
689 (if (signed-zero-< p
(type-bound-number hi
))
691 (and (numberp hi
) (signed-zero-= p hi
))))
693 ;; Interval with lower bound
694 (if (signed-zero-> p
(type-bound-number lo
))
696 (and (numberp lo
) (signed-zero-= p lo
))))
698 ;; Interval with no bounds
701 ;;; Determine whether two intervals X and Y intersect. Return T if so.
702 ;;; If CLOSED-INTERVALS-P is T, the treat the intervals as if they
703 ;;; were closed. Otherwise the intervals are treated as they are.
705 ;;; Thus if X = [0, 1) and Y = (1, 2), then they do not intersect
706 ;;; because no element in X is in Y. However, if CLOSED-INTERVALS-P
707 ;;; is T, then they do intersect because we use the closure of X = [0,
708 ;;; 1] and Y = [1, 2] to determine intersection.
709 (defun interval-intersect-p (x y
&optional closed-intervals-p
)
710 (declare (type interval x y
))
711 (and (interval-intersection/difference
(if closed-intervals-p
714 (if closed-intervals-p
719 ;;; Are the two intervals adjacent? That is, is there a number
720 ;;; between the two intervals that is not an element of either
721 ;;; interval? If so, they are not adjacent. For example [0, 1) and
722 ;;; [1, 2] are adjacent but [0, 1) and (1, 2] are not because 1 lies
723 ;;; between both intervals.
724 (defun interval-adjacent-p (x y
)
725 (declare (type interval x y
))
726 (flet ((adjacent (lo hi
)
727 ;; Check to see whether lo and hi are adjacent. If either is
728 ;; nil, they can't be adjacent.
729 (when (and lo hi
(= (type-bound-number lo
) (type-bound-number hi
)))
730 ;; The bounds are equal. They are adjacent if one of
731 ;; them is closed (a number). If both are open (consp),
732 ;; then there is a number that lies between them.
733 (or (numberp lo
) (numberp hi
)))))
734 (or (adjacent (interval-low y
) (interval-high x
))
735 (adjacent (interval-low x
) (interval-high y
)))))
737 ;;; Compute the intersection and difference between two intervals.
738 ;;; Two values are returned: the intersection and the difference.
740 ;;; Let the two intervals be X and Y, and let I and D be the two
741 ;;; values returned by this function. Then I = X intersect Y. If I
742 ;;; is NIL (the empty set), then D is X union Y, represented as the
743 ;;; list of X and Y. If I is not the empty set, then D is (X union Y)
744 ;;; - I, which is a list of two intervals.
746 ;;; For example, let X = [1,5] and Y = [-1,3). Then I = [1,3) and D =
747 ;;; [-1,1) union [3,5], which is returned as a list of two intervals.
748 (defun interval-intersection/difference
(x y
)
749 (declare (type interval x y
))
750 (let ((x-lo (interval-low x
))
751 (x-hi (interval-high x
))
752 (y-lo (interval-low y
))
753 (y-hi (interval-high y
)))
756 ;; If p is an open bound, make it closed. If p is a closed
757 ;; bound, make it open.
761 (test-number (p int bound
)
762 ;; Test whether P is in the interval.
763 (let ((pn (type-bound-number p
)))
764 (when (interval-contains-p pn
(interval-closure int
))
765 ;; Check for endpoints.
766 (let* ((lo (interval-low int
))
767 (hi (interval-high int
))
768 (lon (type-bound-number lo
))
769 (hin (type-bound-number hi
)))
771 ;; Interval may be a point.
772 ((and lon hin
(= lon hin pn
))
773 (and (numberp p
) (numberp lo
) (numberp hi
)))
774 ;; Point matches the low end.
775 ;; [P] [P,?} => TRUE [P] (P,?} => FALSE
776 ;; (P [P,?} => TRUE P) [P,?} => FALSE
777 ;; (P (P,?} => TRUE P) (P,?} => FALSE
778 ((and lon
(= pn lon
))
779 (or (and (numberp p
) (numberp lo
))
780 (and (consp p
) (eq :low bound
))))
781 ;; [P] {?,P] => TRUE [P] {?,P) => FALSE
782 ;; P) {?,P] => TRUE (P {?,P] => FALSE
783 ;; P) {?,P) => TRUE (P {?,P) => FALSE
784 ((and hin
(= pn hin
))
785 (or (and (numberp p
) (numberp hi
))
786 (and (consp p
) (eq :high bound
))))
787 ;; Not an endpoint, all is well.
790 (test-lower-bound (p int
)
791 ;; P is a lower bound of an interval.
793 (test-number p int
:low
)
794 (not (interval-bounded-p int
'below
))))
795 (test-upper-bound (p int
)
796 ;; P is an upper bound of an interval.
798 (test-number p int
:high
)
799 (not (interval-bounded-p int
'above
)))))
800 (let ((x-lo-in-y (test-lower-bound x-lo y
))
801 (x-hi-in-y (test-upper-bound x-hi y
))
802 (y-lo-in-x (test-lower-bound y-lo x
))
803 (y-hi-in-x (test-upper-bound y-hi x
)))
804 (cond ((or x-lo-in-y x-hi-in-y y-lo-in-x y-hi-in-x
)
805 ;; Intervals intersect. Let's compute the intersection
806 ;; and the difference.
807 (multiple-value-bind (lo left-lo left-hi
)
808 (cond (x-lo-in-y (values x-lo y-lo
(opposite-bound x-lo
)))
809 (y-lo-in-x (values y-lo x-lo
(opposite-bound y-lo
))))
810 (multiple-value-bind (hi right-lo right-hi
)
812 (values x-hi
(opposite-bound x-hi
) y-hi
))
814 (values y-hi
(opposite-bound y-hi
) x-hi
)))
815 (values (make-interval :low lo
:high hi
)
816 (list (make-interval :low left-lo
818 (make-interval :low right-lo
821 (values nil
(list x y
))))))))
823 ;;; If intervals X and Y intersect, return a new interval that is the
824 ;;; union of the two. If they do not intersect, return NIL.
825 (defun interval-merge-pair (x y
)
826 (declare (type interval x y
))
827 ;; If x and y intersect or are adjacent, create the union.
828 ;; Otherwise return nil
829 (when (or (interval-intersect-p x y
)
830 (interval-adjacent-p x y
))
831 (flet ((select-bound (x1 x2 min-op max-op
)
832 (let ((x1-val (type-bound-number x1
))
833 (x2-val (type-bound-number x2
)))
835 ;; Both bounds are finite. Select the right one.
836 (cond ((funcall min-op x1-val x2-val
)
837 ;; x1 is definitely better.
839 ((funcall max-op x1-val x2-val
)
840 ;; x2 is definitely better.
843 ;; Bounds are equal. Select either
844 ;; value and make it open only if
846 (set-bound x1-val
(and (consp x1
) (consp x2
))))))
848 ;; At least one bound is not finite. The
849 ;; non-finite bound always wins.
851 (let* ((x-lo (copy-interval-limit (interval-low x
)))
852 (x-hi (copy-interval-limit (interval-high x
)))
853 (y-lo (copy-interval-limit (interval-low y
)))
854 (y-hi (copy-interval-limit (interval-high y
))))
855 (make-interval :low
(select-bound x-lo y-lo
#'< #'>)
856 :high
(select-bound x-hi y-hi
#'> #'<))))))
858 ;;; return the minimal interval, containing X and Y
859 (defun interval-approximate-union (x y
)
860 (cond ((interval-merge-pair x y
))
862 (make-interval :low
(copy-interval-limit (interval-low x
))
863 :high
(copy-interval-limit (interval-high y
))))
865 (make-interval :low
(copy-interval-limit (interval-low y
))
866 :high
(copy-interval-limit (interval-high x
))))))
868 ;;; basic arithmetic operations on intervals. We probably should do
869 ;;; true interval arithmetic here, but it's complicated because we
870 ;;; have float and integer types and bounds can be open or closed.
872 ;;; the negative of an interval
873 (defun interval-neg (x)
874 (declare (type interval x
))
875 (make-interval :low
(bound-func #'-
(interval-high x
) t
)
876 :high
(bound-func #'-
(interval-low x
) t
)))
878 ;;; Add two intervals.
879 (defun interval-add (x y
)
880 (declare (type interval x y
))
881 (make-interval :low
(bound-binop + (interval-low x
) (interval-low y
))
882 :high
(bound-binop + (interval-high x
) (interval-high y
))))
884 ;;; Subtract two intervals.
885 (defun interval-sub (x y
)
886 (declare (type interval x y
))
887 (make-interval :low
(bound-binop -
(interval-low x
) (interval-high y
))
888 :high
(bound-binop -
(interval-high x
) (interval-low y
))))
890 ;;; Multiply two intervals.
891 (defun interval-mul (x y
)
892 (declare (type interval x y
))
893 (flet ((bound-mul (x y
)
894 (cond ((or (null x
) (null y
))
895 ;; Multiply by infinity is infinity
897 ((or (and (numberp x
) (zerop x
))
898 (and (numberp y
) (zerop y
)))
899 ;; Multiply by closed zero is special. The result
900 ;; is always a closed bound. But don't replace this
901 ;; with zero; we want the multiplication to produce
902 ;; the correct signed zero, if needed. Use SIGNUM
903 ;; to avoid trying to multiply huge bignums with 0.0.
904 (* (signum (type-bound-number x
)) (signum (type-bound-number y
))))
905 ((or (and (floatp x
) (float-infinity-p x
))
906 (and (floatp y
) (float-infinity-p y
)))
907 ;; Infinity times anything is infinity
910 ;; General multiply. The result is open if either is open.
911 (bound-binop * x y
)))))
912 (let ((x-range (interval-range-info x
))
913 (y-range (interval-range-info y
)))
914 (cond ((null x-range
)
915 ;; Split x into two and multiply each separately
916 (destructuring-bind (x- x
+) (interval-split 0 x t t
)
917 (interval-merge-pair (interval-mul x- y
)
918 (interval-mul x
+ y
))))
920 ;; Split y into two and multiply each separately
921 (destructuring-bind (y- y
+) (interval-split 0 y t t
)
922 (interval-merge-pair (interval-mul x y-
)
923 (interval-mul x y
+))))
925 (interval-neg (interval-mul (interval-neg x
) y
)))
927 (interval-neg (interval-mul x
(interval-neg y
))))
928 ((and (eq x-range
'+) (eq y-range
'+))
929 ;; If we are here, X and Y are both positive.
931 :low
(bound-mul (interval-low x
) (interval-low y
))
932 :high
(bound-mul (interval-high x
) (interval-high y
))))
934 (bug "excluded case in INTERVAL-MUL"))))))
936 ;;; Divide two intervals.
937 (defun interval-div (top bot
)
938 (declare (type interval top bot
))
939 (flet ((bound-div (x y y-low-p
)
942 ;; Divide by infinity means result is 0. However,
943 ;; we need to watch out for the sign of the result,
944 ;; to correctly handle signed zeros. We also need
945 ;; to watch out for positive or negative infinity.
946 (if (floatp (type-bound-number x
))
948 (- (float-sign (type-bound-number x
) 0.0))
949 (float-sign (type-bound-number x
) 0.0))
951 ((zerop (type-bound-number y
))
952 ;; Divide by zero means result is infinity
955 (bound-binop / x y
)))))
956 (let ((top-range (interval-range-info top
))
957 (bot-range (interval-range-info bot
)))
958 (cond ((null bot-range
)
959 ;; The denominator contains zero, so anything goes!
960 (make-interval :low nil
:high nil
))
962 ;; Denominator is negative so flip the sign, compute the
963 ;; result, and flip it back.
964 (interval-neg (interval-div top
(interval-neg bot
))))
966 ;; Split top into two positive and negative parts, and
967 ;; divide each separately
968 (destructuring-bind (top- top
+) (interval-split 0 top t t
)
969 (interval-merge-pair (interval-div top- bot
)
970 (interval-div top
+ bot
))))
972 ;; Top is negative so flip the sign, divide, and flip the
973 ;; sign of the result.
974 (interval-neg (interval-div (interval-neg top
) bot
)))
975 ((and (eq top-range
'+) (eq bot-range
'+))
978 :low
(bound-div (interval-low top
) (interval-high bot
) t
)
979 :high
(bound-div (interval-high top
) (interval-low bot
) nil
)))
981 (bug "excluded case in INTERVAL-DIV"))))))
983 ;;; Apply the function F to the interval X. If X = [a, b], then the
984 ;;; result is [f(a), f(b)]. It is up to the user to make sure the
985 ;;; result makes sense. It will if F is monotonic increasing (or, if
986 ;;; the interval is closed, non-decreasing).
988 ;;; (Actually most uses of INTERVAL-FUNC are coercions to float types,
989 ;;; which are not monotonic increasing, so default to calling
990 ;;; BOUND-FUNC with a non-strict argument).
991 (defun interval-func (f x
&optional increasing
)
992 (declare (type function f
)
994 (let ((lo (bound-func f
(interval-low x
) increasing
))
995 (hi (bound-func f
(interval-high x
) increasing
)))
996 (make-interval :low lo
:high hi
)))
998 ;;; Return T if X < Y. That is every number in the interval X is
999 ;;; always less than any number in the interval Y.
1000 (defun interval-< (x y
)
1001 (declare (type interval x y
))
1002 ;; X < Y only if X is bounded above, Y is bounded below, and they
1004 (when (and (interval-bounded-p x
'above
)
1005 (interval-bounded-p y
'below
))
1006 ;; Intervals are bounded in the appropriate way. Make sure they
1008 (let ((left (interval-high x
))
1009 (right (interval-low y
)))
1010 (cond ((> (type-bound-number left
)
1011 (type-bound-number right
))
1012 ;; The intervals definitely overlap, so result is NIL.
1014 ((< (type-bound-number left
)
1015 (type-bound-number right
))
1016 ;; The intervals definitely don't touch, so result is T.
1019 ;; Limits are equal. Check for open or closed bounds.
1020 ;; Don't overlap if one or the other are open.
1021 (or (consp left
) (consp right
)))))))
1023 ;;; Return T if X >= Y. That is, every number in the interval X is
1024 ;;; always greater than any number in the interval Y.
1025 (defun interval->= (x y
)
1026 (declare (type interval x y
))
1027 ;; X >= Y if lower bound of X >= upper bound of Y
1028 (when (and (interval-bounded-p x
'below
)
1029 (interval-bounded-p y
'above
))
1030 (>= (type-bound-number (interval-low x
))
1031 (type-bound-number (interval-high y
)))))
1033 ;;; Return T if X = Y.
1034 (defun interval-= (x y
)
1035 (declare (type interval x y
))
1036 (and (interval-bounded-p x
'both
)
1037 (interval-bounded-p y
'both
)
1041 ;; Open intervals cannot be =
1042 (return-from interval-
= nil
))))
1043 ;; Both intervals refer to the same point
1044 (= (bound (interval-high x
)) (bound (interval-low x
))
1045 (bound (interval-high y
)) (bound (interval-low y
))))))
1047 ;;; Return T if X /= Y
1048 (defun interval-/= (x y
)
1049 (not (interval-intersect-p x y
)))
1051 ;;; Return an interval that is the absolute value of X. Thus, if
1052 ;;; X = [-1 10], the result is [0, 10].
1053 (defun interval-abs (x)
1054 (declare (type interval x
))
1055 (case (interval-range-info x
)
1061 (destructuring-bind (x- x
+) (interval-split 0 x t t
)
1062 (interval-merge-pair (interval-neg x-
) x
+)))))
1064 ;;; Compute the square of an interval.
1065 (defun interval-sqr (x)
1066 (declare (type interval x
))
1067 (interval-func (lambda (x) (* x x
)) (interval-abs x
)))
1069 ;;;; numeric DERIVE-TYPE methods
1071 ;;; a utility for defining derive-type methods of integer operations. If
1072 ;;; the types of both X and Y are integer types, then we compute a new
1073 ;;; integer type with bounds determined by FUN when applied to X and Y.
1074 ;;; Otherwise, we use NUMERIC-CONTAGION.
1075 (defun derive-integer-type-aux (x y fun
)
1076 (declare (type function fun
))
1077 (if (and (numeric-type-p x
) (numeric-type-p y
)
1078 (eq (numeric-type-class x
) 'integer
)
1079 (eq (numeric-type-class y
) 'integer
)
1080 (eq (numeric-type-complexp x
) :real
)
1081 (eq (numeric-type-complexp y
) :real
))
1082 (multiple-value-bind (low high
) (funcall fun x y
)
1083 (make-numeric-type :class
'integer
1087 (numeric-contagion x y
)))
1089 (defun derive-integer-type (x y fun
)
1090 (declare (type lvar x y
) (type function fun
))
1091 (let ((x (lvar-type x
))
1093 (derive-integer-type-aux x y fun
)))
1095 ;;; simple utility to flatten a list
1096 (defun flatten-list (x)
1097 (labels ((flatten-and-append (tree list
)
1098 (cond ((null tree
) list
)
1099 ((atom tree
) (cons tree list
))
1100 (t (flatten-and-append
1101 (car tree
) (flatten-and-append (cdr tree
) list
))))))
1102 (flatten-and-append x nil
)))
1104 ;;; Take some type of lvar and massage it so that we get a list of the
1105 ;;; constituent types. If ARG is *EMPTY-TYPE*, return NIL to indicate
1107 (defun prepare-arg-for-derive-type (arg)
1108 (flet ((listify (arg)
1113 (union-type-types arg
))
1116 (unless (eq arg
*empty-type
*)
1117 ;; Make sure all args are some type of numeric-type. For member
1118 ;; types, convert the list of members into a union of equivalent
1119 ;; single-element member-type's.
1120 (let ((new-args nil
))
1121 (dolist (arg (listify arg
))
1122 (if (member-type-p arg
)
1123 ;; Run down the list of members and convert to a list of
1125 (mapc-member-type-members
1127 (push (if (numberp member
)
1128 (make-member-type :members
(list member
))
1132 (push arg new-args
)))
1133 (unless (member *empty-type
* new-args
)
1136 ;;; Convert from the standard type convention for which -0.0 and 0.0
1137 ;;; are equal to an intermediate convention for which they are
1138 ;;; considered different which is more natural for some of the
1140 (defun convert-numeric-type (type)
1141 (declare (type numeric-type type
))
1142 ;;; Only convert real float interval delimiters types.
1143 (if (eq (numeric-type-complexp type
) :real
)
1144 (let* ((lo (numeric-type-low type
))
1145 (lo-val (type-bound-number lo
))
1146 (lo-float-zero-p (and lo
(floatp lo-val
) (= lo-val
0.0)))
1147 (hi (numeric-type-high type
))
1148 (hi-val (type-bound-number hi
))
1149 (hi-float-zero-p (and hi
(floatp hi-val
) (= hi-val
0.0))))
1150 (if (or lo-float-zero-p hi-float-zero-p
)
1152 :class
(numeric-type-class type
)
1153 :format
(numeric-type-format type
)
1155 :low
(if lo-float-zero-p
1157 (list (float 0.0 lo-val
))
1158 (float (load-time-value (make-unportable-float :single-float-negative-zero
)) lo-val
))
1160 :high
(if hi-float-zero-p
1162 (list (float (load-time-value (make-unportable-float :single-float-negative-zero
)) hi-val
))
1169 ;;; Convert back from the intermediate convention for which -0.0 and
1170 ;;; 0.0 are considered different to the standard type convention for
1171 ;;; which and equal.
1172 (defun convert-back-numeric-type (type)
1173 (declare (type numeric-type type
))
1174 ;;; Only convert real float interval delimiters types.
1175 (if (eq (numeric-type-complexp type
) :real
)
1176 (let* ((lo (numeric-type-low type
))
1177 (lo-val (type-bound-number lo
))
1179 (and lo
(floatp lo-val
) (= lo-val
0.0)
1180 (float-sign lo-val
)))
1181 (hi (numeric-type-high type
))
1182 (hi-val (type-bound-number hi
))
1184 (and hi
(floatp hi-val
) (= hi-val
0.0)
1185 (float-sign hi-val
))))
1187 ;; (float +0.0 +0.0) => (member 0.0)
1188 ;; (float -0.0 -0.0) => (member -0.0)
1189 ((and lo-float-zero-p hi-float-zero-p
)
1190 ;; shouldn't have exclusive bounds here..
1191 (aver (and (not (consp lo
)) (not (consp hi
))))
1192 (if (= lo-float-zero-p hi-float-zero-p
)
1193 ;; (float +0.0 +0.0) => (member 0.0)
1194 ;; (float -0.0 -0.0) => (member -0.0)
1195 (specifier-type `(member ,lo-val
))
1196 ;; (float -0.0 +0.0) => (float 0.0 0.0)
1197 ;; (float +0.0 -0.0) => (float 0.0 0.0)
1198 (make-numeric-type :class
(numeric-type-class type
)
1199 :format
(numeric-type-format type
)
1205 ;; (float -0.0 x) => (float 0.0 x)
1206 ((and (not (consp lo
)) (minusp lo-float-zero-p
))
1207 (make-numeric-type :class
(numeric-type-class type
)
1208 :format
(numeric-type-format type
)
1210 :low
(float 0.0 lo-val
)
1212 ;; (float (+0.0) x) => (float (0.0) x)
1213 ((and (consp lo
) (plusp lo-float-zero-p
))
1214 (make-numeric-type :class
(numeric-type-class type
)
1215 :format
(numeric-type-format type
)
1217 :low
(list (float 0.0 lo-val
))
1220 ;; (float +0.0 x) => (or (member 0.0) (float (0.0) x))
1221 ;; (float (-0.0) x) => (or (member 0.0) (float (0.0) x))
1222 (list (make-member-type :members
(list (float 0.0 lo-val
)))
1223 (make-numeric-type :class
(numeric-type-class type
)
1224 :format
(numeric-type-format type
)
1226 :low
(list (float 0.0 lo-val
))
1230 ;; (float x +0.0) => (float x 0.0)
1231 ((and (not (consp hi
)) (plusp hi-float-zero-p
))
1232 (make-numeric-type :class
(numeric-type-class type
)
1233 :format
(numeric-type-format type
)
1236 :high
(float 0.0 hi-val
)))
1237 ;; (float x (-0.0)) => (float x (0.0))
1238 ((and (consp hi
) (minusp hi-float-zero-p
))
1239 (make-numeric-type :class
(numeric-type-class type
)
1240 :format
(numeric-type-format type
)
1243 :high
(list (float 0.0 hi-val
))))
1245 ;; (float x (+0.0)) => (or (member -0.0) (float x (0.0)))
1246 ;; (float x -0.0) => (or (member -0.0) (float x (0.0)))
1247 (list (make-member-type :members
(list (float (load-time-value (make-unportable-float :single-float-negative-zero
)) hi-val
)))
1248 (make-numeric-type :class
(numeric-type-class type
)
1249 :format
(numeric-type-format type
)
1252 :high
(list (float 0.0 hi-val
)))))))
1258 ;;; Convert back a possible list of numeric types.
1259 (defun convert-back-numeric-type-list (type-list)
1262 (let ((results '()))
1263 (dolist (type type-list
)
1264 (if (numeric-type-p type
)
1265 (let ((result (convert-back-numeric-type type
)))
1267 (setf results
(append results result
))
1268 (push result results
)))
1269 (push type results
)))
1272 (convert-back-numeric-type type-list
))
1274 (convert-back-numeric-type-list (union-type-types type-list
)))
1278 ;;; Take a list of types and return a canonical type specifier,
1279 ;;; combining any MEMBER types together. If both positive and negative
1280 ;;; MEMBER types are present they are converted to a float type.
1281 ;;; XXX This would be far simpler if the type-union methods could handle
1282 ;;; member/number unions.
1284 ;;; If we're about to generate an overly complex union of numeric types, start
1285 ;;; collapse the ranges together.
1287 ;;; FIXME: The MEMBER canonicalization parts of MAKE-DERIVED-UNION-TYPE and
1288 ;;; entire CONVERT-MEMBER-TYPE probably belong in the kernel's type logic,
1289 ;;; invoked always, instead of in the compiler, invoked only during some type
1291 (defvar *derived-numeric-union-complexity-limit
* 6)
1293 (defun make-derived-union-type (type-list)
1294 (let ((xset (alloc-xset))
1297 (numeric-type *empty-type
*))
1298 (dolist (type type-list
)
1299 (cond ((member-type-p type
)
1300 (mapc-member-type-members
1302 (if (fp-zero-p member
)
1303 (unless (member member fp-zeroes
)
1304 (pushnew member fp-zeroes
))
1305 (add-to-xset member xset
)))
1307 ((numeric-type-p type
)
1308 (let ((*approximate-numeric-unions
*
1309 (when (and (union-type-p numeric-type
)
1310 (nthcdr *derived-numeric-union-complexity-limit
*
1311 (union-type-types numeric-type
)))
1313 (setf numeric-type
(type-union type numeric-type
))))
1315 (push type misc-types
))))
1316 (if (and (xset-empty-p xset
) (not fp-zeroes
))
1317 (apply #'type-union numeric-type misc-types
)
1318 (apply #'type-union
(make-member-type :xset xset
:fp-zeroes fp-zeroes
)
1319 numeric-type misc-types
))))
1321 ;;; Convert a member type with a single member to a numeric type.
1322 (defun convert-member-type (arg)
1323 (let* ((members (member-type-members arg
))
1324 (member (first members
))
1325 (member-type (type-of member
)))
1326 (aver (not (rest members
)))
1327 (specifier-type (cond ((typep member
'integer
)
1328 `(integer ,member
,member
))
1329 ((memq member-type
'(short-float single-float
1330 double-float long-float
))
1331 `(,member-type
,member
,member
))
1335 ;;; This is used in defoptimizers for computing the resulting type of
1338 ;;; Given the lvar ARG, derive the resulting type using the
1339 ;;; DERIVE-FUN. DERIVE-FUN takes exactly one argument which is some
1340 ;;; "atomic" lvar type like numeric-type or member-type (containing
1341 ;;; just one element). It should return the resulting type, which can
1342 ;;; be a list of types.
1344 ;;; For the case of member types, if a MEMBER-FUN is given it is
1345 ;;; called to compute the result otherwise the member type is first
1346 ;;; converted to a numeric type and the DERIVE-FUN is called.
1347 (defun one-arg-derive-type (arg derive-fun member-fun
1348 &optional
(convert-type t
))
1349 (declare (type function derive-fun
)
1350 (type (or null function
) member-fun
))
1351 (let ((arg-list (prepare-arg-for-derive-type (lvar-type arg
))))
1357 (with-float-traps-masked
1358 (:underflow
:overflow
:divide-by-zero
)
1360 `(eql ,(funcall member-fun
1361 (first (member-type-members x
))))))
1362 ;; Otherwise convert to a numeric type.
1363 (let ((result-type-list
1364 (funcall derive-fun
(convert-member-type x
))))
1366 (convert-back-numeric-type-list result-type-list
)
1367 result-type-list
))))
1370 (convert-back-numeric-type-list
1371 (funcall derive-fun
(convert-numeric-type x
)))
1372 (funcall derive-fun x
)))
1374 *universal-type
*))))
1375 ;; Run down the list of args and derive the type of each one,
1376 ;; saving all of the results in a list.
1377 (let ((results nil
))
1378 (dolist (arg arg-list
)
1379 (let ((result (deriver arg
)))
1381 (setf results
(append results result
))
1382 (push result results
))))
1384 (make-derived-union-type results
)
1385 (first results
)))))))
1387 ;;; Same as ONE-ARG-DERIVE-TYPE, except we assume the function takes
1388 ;;; two arguments. DERIVE-FUN takes 3 args in this case: the two
1389 ;;; original args and a third which is T to indicate if the two args
1390 ;;; really represent the same lvar. This is useful for deriving the
1391 ;;; type of things like (* x x), which should always be positive. If
1392 ;;; we didn't do this, we wouldn't be able to tell.
1393 (defun two-arg-derive-type (arg1 arg2 derive-fun fun
1394 &optional
(convert-type t
))
1395 (declare (type function derive-fun fun
))
1396 (flet ((deriver (x y same-arg
)
1397 (cond ((and (member-type-p x
) (member-type-p y
))
1398 (let* ((x (first (member-type-members x
)))
1399 (y (first (member-type-members y
)))
1400 (result (ignore-errors
1401 (with-float-traps-masked
1402 (:underflow
:overflow
:divide-by-zero
1404 (funcall fun x y
)))))
1405 (cond ((null result
) *empty-type
*)
1406 ((and (floatp result
) (float-nan-p result
))
1407 (make-numeric-type :class
'float
1408 :format
(type-of result
)
1411 (specifier-type `(eql ,result
))))))
1412 ((and (member-type-p x
) (numeric-type-p y
))
1413 (let* ((x (convert-member-type x
))
1414 (y (if convert-type
(convert-numeric-type y
) y
))
1415 (result (funcall derive-fun x y same-arg
)))
1417 (convert-back-numeric-type-list result
)
1419 ((and (numeric-type-p x
) (member-type-p y
))
1420 (let* ((x (if convert-type
(convert-numeric-type x
) x
))
1421 (y (convert-member-type y
))
1422 (result (funcall derive-fun x y same-arg
)))
1424 (convert-back-numeric-type-list result
)
1426 ((and (numeric-type-p x
) (numeric-type-p y
))
1427 (let* ((x (if convert-type
(convert-numeric-type x
) x
))
1428 (y (if convert-type
(convert-numeric-type y
) y
))
1429 (result (funcall derive-fun x y same-arg
)))
1431 (convert-back-numeric-type-list result
)
1434 *universal-type
*))))
1435 (let ((same-arg (same-leaf-ref-p arg1 arg2
))
1436 (a1 (prepare-arg-for-derive-type (lvar-type arg1
)))
1437 (a2 (prepare-arg-for-derive-type (lvar-type arg2
))))
1439 (let ((results nil
))
1441 ;; Since the args are the same LVARs, just run down the
1444 (let ((result (deriver x x same-arg
)))
1446 (setf results
(append results result
))
1447 (push result results
))))
1448 ;; Try all pairwise combinations.
1451 (let ((result (or (deriver x y same-arg
)
1452 (numeric-contagion x y
))))
1454 (setf results
(append results result
))
1455 (push result results
))))))
1457 (make-derived-union-type results
)
1458 (first results
)))))))
1460 #+sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1462 (defoptimizer (+ derive-type
) ((x y
))
1463 (derive-integer-type
1470 (values (frob (numeric-type-low x
) (numeric-type-low y
))
1471 (frob (numeric-type-high x
) (numeric-type-high y
)))))))
1473 (defoptimizer (- derive-type
) ((x y
))
1474 (derive-integer-type
1481 (values (frob (numeric-type-low x
) (numeric-type-high y
))
1482 (frob (numeric-type-high x
) (numeric-type-low y
)))))))
1484 (defoptimizer (* derive-type
) ((x y
))
1485 (derive-integer-type
1488 (let ((x-low (numeric-type-low x
))
1489 (x-high (numeric-type-high x
))
1490 (y-low (numeric-type-low y
))
1491 (y-high (numeric-type-high y
)))
1492 (cond ((not (and x-low y-low
))
1494 ((or (minusp x-low
) (minusp y-low
))
1495 (if (and x-high y-high
)
1496 (let ((max (* (max (abs x-low
) (abs x-high
))
1497 (max (abs y-low
) (abs y-high
)))))
1498 (values (- max
) max
))
1501 (values (* x-low y-low
)
1502 (if (and x-high y-high
)
1506 (defoptimizer (/ derive-type
) ((x y
))
1507 (numeric-contagion (lvar-type x
) (lvar-type y
)))
1511 #-sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1513 (defun +-derive-type-aux
(x y same-arg
)
1514 (if (and (numeric-type-real-p x
)
1515 (numeric-type-real-p y
))
1518 (let ((x-int (numeric-type->interval x
)))
1519 (interval-add x-int x-int
))
1520 (interval-add (numeric-type->interval x
)
1521 (numeric-type->interval y
))))
1522 (result-type (numeric-contagion x y
)))
1523 ;; If the result type is a float, we need to be sure to coerce
1524 ;; the bounds into the correct type.
1525 (when (eq (numeric-type-class result-type
) 'float
)
1526 (setf result
(interval-func
1528 (coerce-for-bound x
(or (numeric-type-format result-type
)
1532 :class
(if (and (eq (numeric-type-class x
) 'integer
)
1533 (eq (numeric-type-class y
) 'integer
))
1534 ;; The sum of integers is always an integer.
1536 (numeric-type-class result-type
))
1537 :format
(numeric-type-format result-type
)
1538 :low
(interval-low result
)
1539 :high
(interval-high result
)))
1540 ;; general contagion
1541 (numeric-contagion x y
)))
1543 (defoptimizer (+ derive-type
) ((x y
))
1544 (two-arg-derive-type x y
#'+-derive-type-aux
#'+))
1546 (defun --derive-type-aux (x y same-arg
)
1547 (if (and (numeric-type-real-p x
)
1548 (numeric-type-real-p y
))
1550 ;; (- X X) is always 0.
1552 (make-interval :low
0 :high
0)
1553 (interval-sub (numeric-type->interval x
)
1554 (numeric-type->interval y
))))
1555 (result-type (numeric-contagion x y
)))
1556 ;; If the result type is a float, we need to be sure to coerce
1557 ;; the bounds into the correct type.
1558 (when (eq (numeric-type-class result-type
) 'float
)
1559 (setf result
(interval-func
1561 (coerce-for-bound x
(or (numeric-type-format result-type
)
1565 :class
(if (and (eq (numeric-type-class x
) 'integer
)
1566 (eq (numeric-type-class y
) 'integer
))
1567 ;; The difference of integers is always an integer.
1569 (numeric-type-class result-type
))
1570 :format
(numeric-type-format result-type
)
1571 :low
(interval-low result
)
1572 :high
(interval-high result
)))
1573 ;; general contagion
1574 (numeric-contagion x y
)))
1576 (defoptimizer (- derive-type
) ((x y
))
1577 (two-arg-derive-type x y
#'--derive-type-aux
#'-
))
1579 (defun *-derive-type-aux
(x y same-arg
)
1580 (if (and (numeric-type-real-p x
)
1581 (numeric-type-real-p y
))
1583 ;; (* X X) is always positive, so take care to do it right.
1585 (interval-sqr (numeric-type->interval x
))
1586 (interval-mul (numeric-type->interval x
)
1587 (numeric-type->interval y
))))
1588 (result-type (numeric-contagion x y
)))
1589 ;; If the result type is a float, we need to be sure to coerce
1590 ;; the bounds into the correct type.
1591 (when (eq (numeric-type-class result-type
) 'float
)
1592 (setf result
(interval-func
1594 (coerce-for-bound x
(or (numeric-type-format result-type
)
1598 :class
(if (and (eq (numeric-type-class x
) 'integer
)
1599 (eq (numeric-type-class y
) 'integer
))
1600 ;; The product of integers is always an integer.
1602 (numeric-type-class result-type
))
1603 :format
(numeric-type-format result-type
)
1604 :low
(interval-low result
)
1605 :high
(interval-high result
)))
1606 (numeric-contagion x y
)))
1608 (defoptimizer (* derive-type
) ((x y
))
1609 (two-arg-derive-type x y
#'*-derive-type-aux
#'*))
1611 (defun /-derive-type-aux
(x y same-arg
)
1612 (if (and (numeric-type-real-p x
)
1613 (numeric-type-real-p y
))
1615 ;; (/ X X) is always 1, except if X can contain 0. In
1616 ;; that case, we shouldn't optimize the division away
1617 ;; because we want 0/0 to signal an error.
1619 (not (interval-contains-p
1620 0 (interval-closure (numeric-type->interval y
)))))
1621 (make-interval :low
1 :high
1)
1622 (interval-div (numeric-type->interval x
)
1623 (numeric-type->interval y
))))
1624 (result-type (numeric-contagion x y
)))
1625 ;; If the result type is a float, we need to be sure to coerce
1626 ;; the bounds into the correct type.
1627 (when (eq (numeric-type-class result-type
) 'float
)
1628 (setf result
(interval-func
1630 (coerce-for-bound x
(or (numeric-type-format result-type
)
1633 (make-numeric-type :class
(numeric-type-class result-type
)
1634 :format
(numeric-type-format result-type
)
1635 :low
(interval-low result
)
1636 :high
(interval-high result
)))
1637 (numeric-contagion x y
)))
1639 (defoptimizer (/ derive-type
) ((x y
))
1640 (two-arg-derive-type x y
#'/-derive-type-aux
#'/))
1644 (defun ash-derive-type-aux (n-type shift same-arg
)
1645 (declare (ignore same-arg
))
1646 ;; KLUDGE: All this ASH optimization is suppressed under CMU CL for
1647 ;; some bignum cases because as of version 2.4.6 for Debian and 18d,
1648 ;; CMU CL blows up on (ASH 1000000000 -100000000000) (i.e. ASH of
1649 ;; two bignums yielding zero) and it's hard to avoid that
1650 ;; calculation in here.
1651 #+(and cmu sb-xc-host
)
1652 (when (and (or (typep (numeric-type-low n-type
) 'bignum
)
1653 (typep (numeric-type-high n-type
) 'bignum
))
1654 (or (typep (numeric-type-low shift
) 'bignum
)
1655 (typep (numeric-type-high shift
) 'bignum
)))
1656 (return-from ash-derive-type-aux
*universal-type
*))
1657 (flet ((ash-outer (n s
)
1658 (when (and (fixnump s
)
1660 (> s sb
!xc
:most-negative-fixnum
))
1662 ;; KLUDGE: The bare 64's here should be related to
1663 ;; symbolic machine word size values somehow.
1666 (if (and (fixnump s
)
1667 (> s sb
!xc
:most-negative-fixnum
))
1669 (if (minusp n
) -
1 0))))
1670 (or (and (csubtypep n-type
(specifier-type 'integer
))
1671 (csubtypep shift
(specifier-type 'integer
))
1672 (let ((n-low (numeric-type-low n-type
))
1673 (n-high (numeric-type-high n-type
))
1674 (s-low (numeric-type-low shift
))
1675 (s-high (numeric-type-high shift
)))
1676 (make-numeric-type :class
'integer
:complexp
:real
1679 (ash-outer n-low s-high
)
1680 (ash-inner n-low s-low
)))
1683 (ash-inner n-high s-low
)
1684 (ash-outer n-high s-high
))))))
1687 (defoptimizer (ash derive-type
) ((n shift
))
1688 (two-arg-derive-type n shift
#'ash-derive-type-aux
#'ash
))
1690 #+sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1691 (macrolet ((frob (fun)
1692 `#'(lambda (type type2
)
1693 (declare (ignore type2
))
1694 (let ((lo (numeric-type-low type
))
1695 (hi (numeric-type-high type
)))
1696 (values (if hi
(,fun hi
) nil
) (if lo
(,fun lo
) nil
))))))
1698 (defoptimizer (%negate derive-type
) ((num))
1699 (derive-integer-type num num
(frob -
))))
1701 (defun lognot-derive-type-aux (int)
1702 (derive-integer-type-aux int int
1703 (lambda (type type2
)
1704 (declare (ignore type2
))
1705 (let ((lo (numeric-type-low type
))
1706 (hi (numeric-type-high type
)))
1707 (values (if hi
(lognot hi
) nil
)
1708 (if lo
(lognot lo
) nil
)
1709 (numeric-type-class type
)
1710 (numeric-type-format type
))))))
1712 (defoptimizer (lognot derive-type
) ((int))
1713 (lognot-derive-type-aux (lvar-type int
)))
1715 #-sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1716 (defoptimizer (%negate derive-type
) ((num))
1717 (flet ((negate-bound (b)
1719 (set-bound (- (type-bound-number b
))
1721 (one-arg-derive-type num
1723 (modified-numeric-type
1725 :low
(negate-bound (numeric-type-high type
))
1726 :high
(negate-bound (numeric-type-low type
))))
1729 #+sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1730 (defoptimizer (abs derive-type
) ((num))
1731 (let ((type (lvar-type num
)))
1732 (if (and (numeric-type-p type
)
1733 (eq (numeric-type-class type
) 'integer
)
1734 (eq (numeric-type-complexp type
) :real
))
1735 (let ((lo (numeric-type-low type
))
1736 (hi (numeric-type-high type
)))
1737 (make-numeric-type :class
'integer
:complexp
:real
1738 :low
(cond ((and hi
(minusp hi
))
1744 :high
(if (and hi lo
)
1745 (max (abs hi
) (abs lo
))
1747 (numeric-contagion type type
))))
1749 #-sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1750 (defun abs-derive-type-aux (type)
1751 (cond ((eq (numeric-type-complexp type
) :complex
)
1752 ;; The absolute value of a complex number is always a
1753 ;; non-negative float.
1754 (let* ((format (case (numeric-type-class type
)
1755 ((integer rational
) 'single-float
)
1756 (t (numeric-type-format type
))))
1757 (bound-format (or format
'float
)))
1758 (make-numeric-type :class
'float
1761 :low
(coerce 0 bound-format
)
1764 ;; The absolute value of a real number is a non-negative real
1765 ;; of the same type.
1766 (let* ((abs-bnd (interval-abs (numeric-type->interval type
)))
1767 (class (numeric-type-class type
))
1768 (format (numeric-type-format type
))
1769 (bound-type (or format class
'real
)))
1774 :low
(coerce-and-truncate-floats (interval-low abs-bnd
) bound-type
)
1775 :high
(coerce-and-truncate-floats
1776 (interval-high abs-bnd
) bound-type
))))))
1778 #-sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1779 (defoptimizer (abs derive-type
) ((num))
1780 (one-arg-derive-type num
#'abs-derive-type-aux
#'abs
))
1782 #+sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1783 (defoptimizer (truncate derive-type
) ((number divisor
))
1784 (let ((number-type (lvar-type number
))
1785 (divisor-type (lvar-type divisor
))
1786 (integer-type (specifier-type 'integer
)))
1787 (if (and (numeric-type-p number-type
)
1788 (csubtypep number-type integer-type
)
1789 (numeric-type-p divisor-type
)
1790 (csubtypep divisor-type integer-type
))
1791 (let ((number-low (numeric-type-low number-type
))
1792 (number-high (numeric-type-high number-type
))
1793 (divisor-low (numeric-type-low divisor-type
))
1794 (divisor-high (numeric-type-high divisor-type
)))
1795 (values-specifier-type
1796 `(values ,(integer-truncate-derive-type number-low number-high
1797 divisor-low divisor-high
)
1798 ,(integer-rem-derive-type number-low number-high
1799 divisor-low divisor-high
))))
1802 #-sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
1805 (defun rem-result-type (number-type divisor-type
)
1806 ;; Figure out what the remainder type is. The remainder is an
1807 ;; integer if both args are integers; a rational if both args are
1808 ;; rational; and a float otherwise.
1809 (cond ((and (csubtypep number-type
(specifier-type 'integer
))
1810 (csubtypep divisor-type
(specifier-type 'integer
)))
1812 ((and (csubtypep number-type
(specifier-type 'rational
))
1813 (csubtypep divisor-type
(specifier-type 'rational
)))
1815 ((and (csubtypep number-type
(specifier-type 'float
))
1816 (csubtypep divisor-type
(specifier-type 'float
)))
1817 ;; Both are floats so the result is also a float, of
1818 ;; the largest type.
1819 (or (float-format-max (numeric-type-format number-type
)
1820 (numeric-type-format divisor-type
))
1822 ((and (csubtypep number-type
(specifier-type 'float
))
1823 (csubtypep divisor-type
(specifier-type 'rational
)))
1824 ;; One of the arguments is a float and the other is a
1825 ;; rational. The remainder is a float of the same
1827 (or (numeric-type-format number-type
) 'float
))
1828 ((and (csubtypep divisor-type
(specifier-type 'float
))
1829 (csubtypep number-type
(specifier-type 'rational
)))
1830 ;; One of the arguments is a float and the other is a
1831 ;; rational. The remainder is a float of the same
1833 (or (numeric-type-format divisor-type
) 'float
))
1835 ;; Some unhandled combination. This usually means both args
1836 ;; are REAL so the result is a REAL.
1839 (defun truncate-derive-type-quot (number-type divisor-type
)
1840 (let* ((rem-type (rem-result-type number-type divisor-type
))
1841 (number-interval (numeric-type->interval number-type
))
1842 (divisor-interval (numeric-type->interval divisor-type
)))
1843 ;;(declare (type (member '(integer rational float)) rem-type))
1844 ;; We have real numbers now.
1845 (cond ((eq rem-type
'integer
)
1846 ;; Since the remainder type is INTEGER, both args are
1848 (let* ((res (integer-truncate-derive-type
1849 (interval-low number-interval
)
1850 (interval-high number-interval
)
1851 (interval-low divisor-interval
)
1852 (interval-high divisor-interval
))))
1853 (specifier-type (if (listp res
) res
'integer
))))
1855 (let ((quot (truncate-quotient-bound
1856 (interval-div number-interval
1857 divisor-interval
))))
1858 (specifier-type `(integer ,(or (interval-low quot
) '*)
1859 ,(or (interval-high quot
) '*))))))))
1861 (defun truncate-derive-type-rem (number-type divisor-type
)
1862 (let* ((rem-type (rem-result-type number-type divisor-type
))
1863 (number-interval (numeric-type->interval number-type
))
1864 (divisor-interval (numeric-type->interval divisor-type
))
1865 (rem (truncate-rem-bound number-interval divisor-interval
)))
1866 ;;(declare (type (member '(integer rational float)) rem-type))
1867 ;; We have real numbers now.
1868 (cond ((eq rem-type
'integer
)
1869 ;; Since the remainder type is INTEGER, both args are
1871 (specifier-type `(,rem-type
,(or (interval-low rem
) '*)
1872 ,(or (interval-high rem
) '*))))
1874 (multiple-value-bind (class format
)
1877 (values 'integer nil
))
1879 (values 'rational nil
))
1880 ((or single-float double-float
#!+long-float long-float
)
1881 (values 'float rem-type
))
1883 (values 'float nil
))
1886 (when (member rem-type
'(float single-float double-float
1887 #!+long-float long-float
))
1888 (setf rem
(interval-func #'(lambda (x)
1889 (coerce-for-bound x rem-type
))
1891 (make-numeric-type :class class
1893 :low
(interval-low rem
)
1894 :high
(interval-high rem
)))))))
1896 (defun truncate-derive-type-quot-aux (num div same-arg
)
1897 (declare (ignore same-arg
))
1898 (if (and (numeric-type-real-p num
)
1899 (numeric-type-real-p div
))
1900 (truncate-derive-type-quot num div
)
1903 (defun truncate-derive-type-rem-aux (num div same-arg
)
1904 (declare (ignore same-arg
))
1905 (if (and (numeric-type-real-p num
)
1906 (numeric-type-real-p div
))
1907 (truncate-derive-type-rem num div
)
1910 (defoptimizer (truncate derive-type
) ((number divisor
))
1911 (let ((quot (two-arg-derive-type number divisor
1912 #'truncate-derive-type-quot-aux
#'truncate
))
1913 (rem (two-arg-derive-type number divisor
1914 #'truncate-derive-type-rem-aux
#'rem
)))
1915 (when (and quot rem
)
1916 (make-values-type :required
(list quot rem
)))))
1918 (defun ftruncate-derive-type-quot (number-type divisor-type
)
1919 ;; The bounds are the same as for truncate. However, the first
1920 ;; result is a float of some type. We need to determine what that
1921 ;; type is. Basically it's the more contagious of the two types.
1922 (let ((q-type (truncate-derive-type-quot number-type divisor-type
))
1923 (res-type (numeric-contagion number-type divisor-type
)))
1924 (make-numeric-type :class
'float
1925 :format
(numeric-type-format res-type
)
1926 :low
(numeric-type-low q-type
)
1927 :high
(numeric-type-high q-type
))))
1929 (defun ftruncate-derive-type-quot-aux (n d same-arg
)
1930 (declare (ignore same-arg
))
1931 (if (and (numeric-type-real-p n
)
1932 (numeric-type-real-p d
))
1933 (ftruncate-derive-type-quot n d
)
1936 (defoptimizer (ftruncate derive-type
) ((number divisor
))
1938 (two-arg-derive-type number divisor
1939 #'ftruncate-derive-type-quot-aux
#'ftruncate
))
1940 (rem (two-arg-derive-type number divisor
1941 #'truncate-derive-type-rem-aux
#'rem
)))
1942 (when (and quot rem
)
1943 (make-values-type :required
(list quot rem
)))))
1945 (defun %unary-truncate-derive-type-aux
(number)
1946 (truncate-derive-type-quot number
(specifier-type '(integer 1 1))))
1948 (defoptimizer (%unary-truncate derive-type
) ((number))
1949 (one-arg-derive-type number
1950 #'%unary-truncate-derive-type-aux
1953 (defoptimizer (%unary-truncate
/single-float derive-type
) ((number))
1954 (one-arg-derive-type number
1955 #'%unary-truncate-derive-type-aux
1958 (defoptimizer (%unary-truncate
/double-float derive-type
) ((number))
1959 (one-arg-derive-type number
1960 #'%unary-truncate-derive-type-aux
1963 (defoptimizer (%unary-ftruncate derive-type
) ((number))
1964 (let ((divisor (specifier-type '(integer 1 1))))
1965 (one-arg-derive-type number
1967 (ftruncate-derive-type-quot-aux n divisor nil
))
1968 #'%unary-ftruncate
)))
1970 (defoptimizer (%unary-round derive-type
) ((number))
1971 (one-arg-derive-type number
1974 (unless (numeric-type-real-p n
)
1975 (return *empty-type
*))
1976 (let* ((interval (numeric-type->interval n
))
1977 (low (interval-low interval
))
1978 (high (interval-high interval
)))
1980 (setf low
(car low
)))
1982 (setf high
(car high
)))
1992 ;;; Define optimizers for FLOOR and CEILING.
1994 ((def (name q-name r-name
)
1995 (let ((q-aux (symbolicate q-name
"-AUX"))
1996 (r-aux (symbolicate r-name
"-AUX")))
1998 ;; Compute type of quotient (first) result.
1999 (defun ,q-aux
(number-type divisor-type
)
2000 (let* ((number-interval
2001 (numeric-type->interval number-type
))
2003 (numeric-type->interval divisor-type
))
2004 (quot (,q-name
(interval-div number-interval
2005 divisor-interval
))))
2006 (specifier-type `(integer ,(or (interval-low quot
) '*)
2007 ,(or (interval-high quot
) '*)))))
2008 ;; Compute type of remainder.
2009 (defun ,r-aux
(number-type divisor-type
)
2010 (let* ((divisor-interval
2011 (numeric-type->interval divisor-type
))
2012 (rem (,r-name divisor-interval
))
2013 (result-type (rem-result-type number-type divisor-type
)))
2014 (multiple-value-bind (class format
)
2017 (values 'integer nil
))
2019 (values 'rational nil
))
2020 ((or single-float double-float
#!+long-float long-float
)
2021 (values 'float result-type
))
2023 (values 'float nil
))
2026 (when (member result-type
'(float single-float double-float
2027 #!+long-float long-float
))
2028 ;; Make sure that the limits on the interval have
2030 (setf rem
(interval-func (lambda (x)
2031 (coerce-for-bound x result-type
))
2033 (make-numeric-type :class class
2035 :low
(interval-low rem
)
2036 :high
(interval-high rem
)))))
2037 ;; the optimizer itself
2038 (defoptimizer (,name derive-type
) ((number divisor
))
2039 (flet ((derive-q (n d same-arg
)
2040 (declare (ignore same-arg
))
2041 (if (and (numeric-type-real-p n
)
2042 (numeric-type-real-p d
))
2045 (derive-r (n d same-arg
)
2046 (declare (ignore same-arg
))
2047 (if (and (numeric-type-real-p n
)
2048 (numeric-type-real-p d
))
2051 (let ((quot (two-arg-derive-type
2052 number divisor
#'derive-q
#',name
))
2053 (rem (two-arg-derive-type
2054 number divisor
#'derive-r
#'mod
)))
2055 (when (and quot rem
)
2056 (make-values-type :required
(list quot rem
))))))))))
2058 (def floor floor-quotient-bound floor-rem-bound
)
2059 (def ceiling ceiling-quotient-bound ceiling-rem-bound
))
2061 ;;; Define optimizers for FFLOOR and FCEILING
2062 (macrolet ((def (name q-name r-name
)
2063 (let ((q-aux (symbolicate "F" q-name
"-AUX"))
2064 (r-aux (symbolicate r-name
"-AUX")))
2066 ;; Compute type of quotient (first) result.
2067 (defun ,q-aux
(number-type divisor-type
)
2068 (let* ((number-interval
2069 (numeric-type->interval number-type
))
2071 (numeric-type->interval divisor-type
))
2072 (quot (,q-name
(interval-div number-interval
2074 (res-type (numeric-contagion number-type
2077 :class
(numeric-type-class res-type
)
2078 :format
(numeric-type-format res-type
)
2079 :low
(interval-low quot
)
2080 :high
(interval-high quot
))))
2082 (defoptimizer (,name derive-type
) ((number divisor
))
2083 (flet ((derive-q (n d same-arg
)
2084 (declare (ignore same-arg
))
2085 (if (and (numeric-type-real-p n
)
2086 (numeric-type-real-p d
))
2089 (derive-r (n d same-arg
)
2090 (declare (ignore same-arg
))
2091 (if (and (numeric-type-real-p n
)
2092 (numeric-type-real-p d
))
2095 (let ((quot (two-arg-derive-type
2096 number divisor
#'derive-q
#',name
))
2097 (rem (two-arg-derive-type
2098 number divisor
#'derive-r
#'mod
)))
2099 (when (and quot rem
)
2100 (make-values-type :required
(list quot rem
))))))))))
2102 (def ffloor floor-quotient-bound floor-rem-bound
)
2103 (def fceiling ceiling-quotient-bound ceiling-rem-bound
))
2105 ;;; functions to compute the bounds on the quotient and remainder for
2106 ;;; the FLOOR function
2107 (defun floor-quotient-bound (quot)
2108 ;; Take the floor of the quotient and then massage it into what we
2110 (let ((lo (interval-low quot
))
2111 (hi (interval-high quot
)))
2112 ;; Take the floor of the lower bound. The result is always a
2113 ;; closed lower bound.
2115 (floor (type-bound-number lo
))
2117 ;; For the upper bound, we need to be careful.
2120 ;; An open bound. We need to be careful here because
2121 ;; the floor of '(10.0) is 9, but the floor of
2123 (multiple-value-bind (q r
) (floor (first hi
))
2128 ;; A closed bound, so the answer is obvious.
2132 (make-interval :low lo
:high hi
)))
2133 (defun floor-rem-bound (div)
2134 ;; The remainder depends only on the divisor. Try to get the
2135 ;; correct sign for the remainder if we can.
2136 (case (interval-range-info div
)
2138 ;; The divisor is always positive.
2139 (let ((rem (interval-abs div
)))
2140 (setf (interval-low rem
) 0)
2141 (when (and (numberp (interval-high rem
))
2142 (not (zerop (interval-high rem
))))
2143 ;; The remainder never contains the upper bound. However,
2144 ;; watch out for the case where the high limit is zero!
2145 (setf (interval-high rem
) (list (interval-high rem
))))
2148 ;; The divisor is always negative.
2149 (let ((rem (interval-neg (interval-abs div
))))
2150 (setf (interval-high rem
) 0)
2151 (when (numberp (interval-low rem
))
2152 ;; The remainder never contains the lower bound.
2153 (setf (interval-low rem
) (list (interval-low rem
))))
2156 ;; The divisor can be positive or negative. All bets off. The
2157 ;; magnitude of remainder is the maximum value of the divisor.
2158 (let ((limit (type-bound-number (interval-high (interval-abs div
)))))
2159 ;; The bound never reaches the limit, so make the interval open.
2160 (make-interval :low
(if limit
2163 :high
(list limit
))))))
2165 (floor-quotient-bound (make-interval :low
0.3 :high
10.3))
2166 => #S
(INTERVAL :LOW
0 :HIGH
10)
2167 (floor-quotient-bound (make-interval :low
0.3 :high
'(10.3
)))
2168 => #S
(INTERVAL :LOW
0 :HIGH
10)
2169 (floor-quotient-bound (make-interval :low
0.3 :high
10))
2170 => #S
(INTERVAL :LOW
0 :HIGH
10)
2171 (floor-quotient-bound (make-interval :low
0.3 :high
'(10)))
2172 => #S
(INTERVAL :LOW
0 :HIGH
9)
2173 (floor-quotient-bound (make-interval :low
'(0.3
) :high
10.3))
2174 => #S
(INTERVAL :LOW
0 :HIGH
10)
2175 (floor-quotient-bound (make-interval :low
'(0.0
) :high
10.3))
2176 => #S
(INTERVAL :LOW
0 :HIGH
10)
2177 (floor-quotient-bound (make-interval :low
'(-1.3
) :high
10.3))
2178 => #S
(INTERVAL :LOW -
2 :HIGH
10)
2179 (floor-quotient-bound (make-interval :low
'(-1.0
) :high
10.3))
2180 => #S
(INTERVAL :LOW -
1 :HIGH
10)
2181 (floor-quotient-bound (make-interval :low -
1.0 :high
10.3))
2182 => #S
(INTERVAL :LOW -
1 :HIGH
10)
2184 (floor-rem-bound (make-interval :low
0.3 :high
10.3))
2185 => #S
(INTERVAL :LOW
0 :HIGH
'(10.3
))
2186 (floor-rem-bound (make-interval :low
0.3 :high
'(10.3
)))
2187 => #S
(INTERVAL :LOW
0 :HIGH
'(10.3
))
2188 (floor-rem-bound (make-interval :low -
10 :high -
2.3))
2189 #S
(INTERVAL :LOW
(-10) :HIGH
0)
2190 (floor-rem-bound (make-interval :low
0.3 :high
10))
2191 => #S
(INTERVAL :LOW
0 :HIGH
'(10))
2192 (floor-rem-bound (make-interval :low
'(-1.3
) :high
10.3))
2193 => #S
(INTERVAL :LOW
'(-10.3
) :HIGH
'(10.3
))
2194 (floor-rem-bound (make-interval :low
'(-20.3
) :high
10.3))
2195 => #S
(INTERVAL :LOW
(-20.3
) :HIGH
(20.3
))
2198 ;;; same functions for CEILING
2199 (defun ceiling-quotient-bound (quot)
2200 ;; Take the ceiling of the quotient and then massage it into what we
2202 (let ((lo (interval-low quot
))
2203 (hi (interval-high quot
)))
2204 ;; Take the ceiling of the upper bound. The result is always a
2205 ;; closed upper bound.
2207 (ceiling (type-bound-number hi
))
2209 ;; For the lower bound, we need to be careful.
2212 ;; An open bound. We need to be careful here because
2213 ;; the ceiling of '(10.0) is 11, but the ceiling of
2215 (multiple-value-bind (q r
) (ceiling (first lo
))
2220 ;; A closed bound, so the answer is obvious.
2224 (make-interval :low lo
:high hi
)))
2225 (defun ceiling-rem-bound (div)
2226 ;; The remainder depends only on the divisor. Try to get the
2227 ;; correct sign for the remainder if we can.
2228 (case (interval-range-info div
)
2230 ;; Divisor is always positive. The remainder is negative.
2231 (let ((rem (interval-neg (interval-abs div
))))
2232 (setf (interval-high rem
) 0)
2233 (when (and (numberp (interval-low rem
))
2234 (not (zerop (interval-low rem
))))
2235 ;; The remainder never contains the upper bound. However,
2236 ;; watch out for the case when the upper bound is zero!
2237 (setf (interval-low rem
) (list (interval-low rem
))))
2240 ;; Divisor is always negative. The remainder is positive
2241 (let ((rem (interval-abs div
)))
2242 (setf (interval-low rem
) 0)
2243 (when (numberp (interval-high rem
))
2244 ;; The remainder never contains the lower bound.
2245 (setf (interval-high rem
) (list (interval-high rem
))))
2248 ;; The divisor can be positive or negative. All bets off. The
2249 ;; magnitude of remainder is the maximum value of the divisor.
2250 (let ((limit (type-bound-number (interval-high (interval-abs div
)))))
2251 ;; The bound never reaches the limit, so make the interval open.
2252 (make-interval :low
(if limit
2255 :high
(list limit
))))))
2258 (ceiling-quotient-bound (make-interval :low
0.3 :high
10.3))
2259 => #S
(INTERVAL :LOW
1 :HIGH
11)
2260 (ceiling-quotient-bound (make-interval :low
0.3 :high
'(10.3
)))
2261 => #S
(INTERVAL :LOW
1 :HIGH
11)
2262 (ceiling-quotient-bound (make-interval :low
0.3 :high
10))
2263 => #S
(INTERVAL :LOW
1 :HIGH
10)
2264 (ceiling-quotient-bound (make-interval :low
0.3 :high
'(10)))
2265 => #S
(INTERVAL :LOW
1 :HIGH
10)
2266 (ceiling-quotient-bound (make-interval :low
'(0.3
) :high
10.3))
2267 => #S
(INTERVAL :LOW
1 :HIGH
11)
2268 (ceiling-quotient-bound (make-interval :low
'(0.0
) :high
10.3))
2269 => #S
(INTERVAL :LOW
1 :HIGH
11)
2270 (ceiling-quotient-bound (make-interval :low
'(-1.3
) :high
10.3))
2271 => #S
(INTERVAL :LOW -
1 :HIGH
11)
2272 (ceiling-quotient-bound (make-interval :low
'(-1.0
) :high
10.3))
2273 => #S
(INTERVAL :LOW
0 :HIGH
11)
2274 (ceiling-quotient-bound (make-interval :low -
1.0 :high
10.3))
2275 => #S
(INTERVAL :LOW -
1 :HIGH
11)
2277 (ceiling-rem-bound (make-interval :low
0.3 :high
10.3))
2278 => #S
(INTERVAL :LOW
(-10.3
) :HIGH
0)
2279 (ceiling-rem-bound (make-interval :low
0.3 :high
'(10.3
)))
2280 => #S
(INTERVAL :LOW
0 :HIGH
'(10.3
))
2281 (ceiling-rem-bound (make-interval :low -
10 :high -
2.3))
2282 => #S
(INTERVAL :LOW
0 :HIGH
(10))
2283 (ceiling-rem-bound (make-interval :low
0.3 :high
10))
2284 => #S
(INTERVAL :LOW
(-10) :HIGH
0)
2285 (ceiling-rem-bound (make-interval :low
'(-1.3
) :high
10.3))
2286 => #S
(INTERVAL :LOW
(-10.3
) :HIGH
(10.3
))
2287 (ceiling-rem-bound (make-interval :low
'(-20.3
) :high
10.3))
2288 => #S
(INTERVAL :LOW
(-20.3
) :HIGH
(20.3
))
2291 (defun truncate-quotient-bound (quot)
2292 ;; For positive quotients, truncate is exactly like floor. For
2293 ;; negative quotients, truncate is exactly like ceiling. Otherwise,
2294 ;; it's the union of the two pieces.
2295 (case (interval-range-info quot
)
2298 (floor-quotient-bound quot
))
2300 ;; just like CEILING
2301 (ceiling-quotient-bound quot
))
2303 ;; Split the interval into positive and negative pieces, compute
2304 ;; the result for each piece and put them back together.
2305 (destructuring-bind (neg pos
) (interval-split 0 quot t t
)
2306 (interval-merge-pair (ceiling-quotient-bound neg
)
2307 (floor-quotient-bound pos
))))))
2309 (defun truncate-rem-bound (num div
)
2310 ;; This is significantly more complicated than FLOOR or CEILING. We
2311 ;; need both the number and the divisor to determine the range. The
2312 ;; basic idea is to split the ranges of NUM and DEN into positive
2313 ;; and negative pieces and deal with each of the four possibilities
2315 (case (interval-range-info num
)
2317 (case (interval-range-info div
)
2319 (floor-rem-bound div
))
2321 (ceiling-rem-bound div
))
2323 (destructuring-bind (neg pos
) (interval-split 0 div t t
)
2324 (interval-merge-pair (truncate-rem-bound num neg
)
2325 (truncate-rem-bound num pos
))))))
2327 (case (interval-range-info div
)
2329 (ceiling-rem-bound div
))
2331 (floor-rem-bound div
))
2333 (destructuring-bind (neg pos
) (interval-split 0 div t t
)
2334 (interval-merge-pair (truncate-rem-bound num neg
)
2335 (truncate-rem-bound num pos
))))))
2337 (destructuring-bind (neg pos
) (interval-split 0 num t t
)
2338 (interval-merge-pair (truncate-rem-bound neg div
)
2339 (truncate-rem-bound pos div
))))))
2342 ;;; Derive useful information about the range. Returns three values:
2343 ;;; - '+ if its positive, '- negative, or nil if it overlaps 0.
2344 ;;; - The abs of the minimal value (i.e. closest to 0) in the range.
2345 ;;; - The abs of the maximal value if there is one, or nil if it is
2347 (defun numeric-range-info (low high
)
2348 (cond ((and low
(not (minusp low
)))
2349 (values '+ low high
))
2350 ((and high
(not (plusp high
)))
2351 (values '-
(- high
) (if low
(- low
) nil
)))
2353 (values nil
0 (and low high
(max (- low
) high
))))))
2355 (defun integer-truncate-derive-type
2356 (number-low number-high divisor-low divisor-high
)
2357 ;; The result cannot be larger in magnitude than the number, but the
2358 ;; sign might change. If we can determine the sign of either the
2359 ;; number or the divisor, we can eliminate some of the cases.
2360 (multiple-value-bind (number-sign number-min number-max
)
2361 (numeric-range-info number-low number-high
)
2362 (multiple-value-bind (divisor-sign divisor-min divisor-max
)
2363 (numeric-range-info divisor-low divisor-high
)
2364 (when (and divisor-max
(zerop divisor-max
))
2365 ;; We've got a problem: guaranteed division by zero.
2366 (return-from integer-truncate-derive-type t
))
2367 (when (zerop divisor-min
)
2368 ;; We'll assume that they aren't going to divide by zero.
2370 (cond ((and number-sign divisor-sign
)
2371 ;; We know the sign of both.
2372 (if (eq number-sign divisor-sign
)
2373 ;; Same sign, so the result will be positive.
2374 `(integer ,(if divisor-max
2375 (truncate number-min divisor-max
)
2378 (truncate number-max divisor-min
)
2380 ;; Different signs, the result will be negative.
2381 `(integer ,(if number-max
2382 (- (truncate number-max divisor-min
))
2385 (- (truncate number-min divisor-max
))
2387 ((eq divisor-sign
'+)
2388 ;; The divisor is positive. Therefore, the number will just
2389 ;; become closer to zero.
2390 `(integer ,(if number-low
2391 (truncate number-low divisor-min
)
2394 (truncate number-high divisor-min
)
2396 ((eq divisor-sign
'-
)
2397 ;; The divisor is negative. Therefore, the absolute value of
2398 ;; the number will become closer to zero, but the sign will also
2400 `(integer ,(if number-high
2401 (- (truncate number-high divisor-min
))
2404 (- (truncate number-low divisor-min
))
2406 ;; The divisor could be either positive or negative.
2408 ;; The number we are dividing has a bound. Divide that by the
2409 ;; smallest posible divisor.
2410 (let ((bound (truncate number-max divisor-min
)))
2411 `(integer ,(- bound
) ,bound
)))
2413 ;; The number we are dividing is unbounded, so we can't tell
2414 ;; anything about the result.
2417 #+sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
2418 (defun integer-rem-derive-type
2419 (number-low number-high divisor-low divisor-high
)
2420 (if (and divisor-low divisor-high
)
2421 ;; We know the range of the divisor, and the remainder must be
2422 ;; smaller than the divisor. We can tell the sign of the
2423 ;; remainder if we know the sign of the number.
2424 (let ((divisor-max (1- (max (abs divisor-low
) (abs divisor-high
)))))
2425 `(integer ,(if (or (null number-low
)
2426 (minusp number-low
))
2429 ,(if (or (null number-high
)
2430 (plusp number-high
))
2433 ;; The divisor is potentially either very positive or very
2434 ;; negative. Therefore, the remainder is unbounded, but we might
2435 ;; be able to tell something about the sign from the number.
2436 `(integer ,(if (and number-low
(not (minusp number-low
)))
2437 ;; The number we are dividing is positive.
2438 ;; Therefore, the remainder must be positive.
2441 ,(if (and number-high
(not (plusp number-high
)))
2442 ;; The number we are dividing is negative.
2443 ;; Therefore, the remainder must be negative.
2447 #+sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
2448 (defoptimizer (random derive-type
) ((bound &optional state
))
2449 (let ((type (lvar-type bound
)))
2450 (when (numeric-type-p type
)
2451 (let ((class (numeric-type-class type
))
2452 (high (numeric-type-high type
))
2453 (format (numeric-type-format type
)))
2457 :low
(coerce 0 (or format class
'real
))
2458 :high
(cond ((not high
) nil
)
2459 ((eq class
'integer
) (max (1- high
) 0))
2460 ((or (consp high
) (zerop high
)) high
)
2463 #-sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
2464 (defun random-derive-type-aux (type)
2465 (let ((class (numeric-type-class type
))
2466 (high (numeric-type-high type
))
2467 (format (numeric-type-format type
)))
2471 :low
(coerce 0 (or format class
'real
))
2472 :high
(cond ((not high
) nil
)
2473 ((eq class
'integer
) (max (1- high
) 0))
2474 ((or (consp high
) (zerop high
)) high
)
2477 #-sb-xc-host
; (See CROSS-FLOAT-INFINITY-KLUDGE.)
2478 (defoptimizer (random derive-type
) ((bound &optional state
))
2479 (one-arg-derive-type bound
#'random-derive-type-aux nil
))
2481 ;;;; miscellaneous derive-type methods
2483 (defoptimizer (integer-length derive-type
) ((x))
2484 (let ((x-type (lvar-type x
)))
2485 (when (numeric-type-p x-type
)
2486 ;; If the X is of type (INTEGER LO HI), then the INTEGER-LENGTH
2487 ;; of X is (INTEGER (MIN lo hi) (MAX lo hi), basically. Be
2488 ;; careful about LO or HI being NIL, though. Also, if 0 is
2489 ;; contained in X, the lower bound is obviously 0.
2490 (flet ((null-or-min (a b
)
2491 (and a b
(min (integer-length a
)
2492 (integer-length b
))))
2494 (and a b
(max (integer-length a
)
2495 (integer-length b
)))))
2496 (let* ((min (numeric-type-low x-type
))
2497 (max (numeric-type-high x-type
))
2498 (min-len (null-or-min min max
))
2499 (max-len (null-or-max min max
)))
2500 (when (ctypep 0 x-type
)
2502 (specifier-type `(integer ,(or min-len
'*) ,(or max-len
'*))))))))
2504 (defoptimizer (isqrt derive-type
) ((x))
2505 (let ((x-type (lvar-type x
)))
2506 (when (numeric-type-p x-type
)
2507 (let* ((lo (numeric-type-low x-type
))
2508 (hi (numeric-type-high x-type
))
2509 (lo-res (if lo
(isqrt lo
) '*))
2510 (hi-res (if hi
(isqrt hi
) '*)))
2511 (specifier-type `(integer ,lo-res
,hi-res
))))))
2513 (defoptimizer (char-code derive-type
) ((char))
2514 (let ((type (type-intersection (lvar-type char
) (specifier-type 'character
))))
2515 (cond ((member-type-p type
)
2518 ,@(loop for member in
(member-type-members type
)
2519 when
(characterp member
)
2520 collect
(char-code member
)))))
2521 ((sb!kernel
::character-set-type-p type
)
2524 ,@(loop for
(low . high
)
2525 in
(character-set-type-pairs type
)
2526 collect
`(integer ,low
,high
)))))
2527 ((csubtypep type
(specifier-type 'base-char
))
2529 `(mod ,base-char-code-limit
)))
2532 `(mod ,sb
!xc
:char-code-limit
))))))
2534 (defoptimizer (code-char derive-type
) ((code))
2535 (let ((type (lvar-type code
)))
2536 ;; FIXME: unions of integral ranges? It ought to be easier to do
2537 ;; this, given that CHARACTER-SET is basically an integral range
2538 ;; type. -- CSR, 2004-10-04
2539 (when (numeric-type-p type
)
2540 (let* ((lo (numeric-type-low type
))
2541 (hi (numeric-type-high type
))
2542 (type (specifier-type `(character-set ((,lo .
,hi
))))))
2544 ;; KLUDGE: when running on the host, we lose a slight amount
2545 ;; of precision so that we don't have to "unparse" types
2546 ;; that formally we can't, such as (CHARACTER-SET ((0
2547 ;; . 0))). -- CSR, 2004-10-06
2549 ((csubtypep type
(specifier-type 'standard-char
)) type
)
2551 ((csubtypep type
(specifier-type 'base-char
))
2552 (specifier-type 'base-char
))
2554 ((csubtypep type
(specifier-type 'extended-char
))
2555 (specifier-type 'extended-char
))
2556 (t #+sb-xc-host
(specifier-type 'character
)
2557 #-sb-xc-host type
))))))
2559 (defoptimizer (values derive-type
) ((&rest values
))
2560 (make-values-type :required
(mapcar #'lvar-type values
)))
2562 (defun signum-derive-type-aux (type)
2563 (if (eq (numeric-type-complexp type
) :complex
)
2564 (let* ((format (case (numeric-type-class type
)
2565 ((integer rational
) 'single-float
)
2566 (t (numeric-type-format type
))))
2567 (bound-format (or format
'float
)))
2568 (make-numeric-type :class
'float
2571 :low
(coerce -
1 bound-format
)
2572 :high
(coerce 1 bound-format
)))
2573 (let* ((interval (numeric-type->interval type
))
2574 (range-info (interval-range-info interval
))
2575 (contains-0-p (interval-contains-p 0 interval
))
2576 (class (numeric-type-class type
))
2577 (format (numeric-type-format type
))
2578 (one (coerce 1 (or format class
'real
)))
2579 (zero (coerce 0 (or format class
'real
)))
2580 (minus-one (coerce -
1 (or format class
'real
)))
2581 (plus (make-numeric-type :class class
:format format
2582 :low one
:high one
))
2583 (minus (make-numeric-type :class class
:format format
2584 :low minus-one
:high minus-one
))
2585 ;; KLUDGE: here we have a fairly horrible hack to deal
2586 ;; with the schizophrenia in the type derivation engine.
2587 ;; The problem is that the type derivers reinterpret
2588 ;; numeric types as being exact; so (DOUBLE-FLOAT 0d0
2589 ;; 0d0) within the derivation mechanism doesn't include
2590 ;; -0d0. Ugh. So force it in here, instead.
2591 (zero (make-numeric-type :class class
:format format
2592 :low
(- zero
) :high zero
)))
2594 (+ (if contains-0-p
(type-union plus zero
) plus
))
2595 (- (if contains-0-p
(type-union minus zero
) minus
))
2596 (t (type-union minus zero plus
))))))
2598 (defoptimizer (signum derive-type
) ((num))
2599 (one-arg-derive-type num
#'signum-derive-type-aux nil
))
2601 ;;;; byte operations
2603 ;;;; We try to turn byte operations into simple logical operations.
2604 ;;;; First, we convert byte specifiers into separate size and position
2605 ;;;; arguments passed to internal %FOO functions. We then attempt to
2606 ;;;; transform the %FOO functions into boolean operations when the
2607 ;;;; size and position are constant and the operands are fixnums.
2609 (macrolet (;; Evaluate body with SIZE-VAR and POS-VAR bound to
2610 ;; expressions that evaluate to the SIZE and POSITION of
2611 ;; the byte-specifier form SPEC. We may wrap a let around
2612 ;; the result of the body to bind some variables.
2614 ;; If the spec is a BYTE form, then bind the vars to the
2615 ;; subforms. otherwise, evaluate SPEC and use the BYTE-SIZE
2616 ;; and BYTE-POSITION. The goal of this transformation is to
2617 ;; avoid consing up byte specifiers and then immediately
2618 ;; throwing them away.
2619 (with-byte-specifier ((size-var pos-var spec
) &body body
)
2620 (once-only ((spec `(macroexpand ,spec
))
2622 `(if (and (consp ,spec
)
2623 (eq (car ,spec
) 'byte
)
2624 (= (length ,spec
) 3))
2625 (let ((,size-var
(second ,spec
))
2626 (,pos-var
(third ,spec
)))
2628 (let ((,size-var
`(byte-size ,,temp
))
2629 (,pos-var
`(byte-position ,,temp
)))
2630 `(let ((,,temp
,,spec
))
2633 (define-source-transform ldb
(spec int
)
2634 (with-byte-specifier (size pos spec
)
2635 `(%ldb
,size
,pos
,int
)))
2637 (define-source-transform dpb
(newbyte spec int
)
2638 (with-byte-specifier (size pos spec
)
2639 `(%dpb
,newbyte
,size
,pos
,int
)))
2641 (define-source-transform mask-field
(spec int
)
2642 (with-byte-specifier (size pos spec
)
2643 `(%mask-field
,size
,pos
,int
)))
2645 (define-source-transform deposit-field
(newbyte spec int
)
2646 (with-byte-specifier (size pos spec
)
2647 `(%deposit-field
,newbyte
,size
,pos
,int
))))
2649 (defoptimizer (%ldb derive-type
) ((size posn num
))
2650 (let ((size (lvar-type size
)))
2651 (if (and (numeric-type-p size
)
2652 (csubtypep size
(specifier-type 'integer
)))
2653 (let ((size-high (numeric-type-high size
)))
2654 (if (and size-high
(<= size-high sb
!vm
:n-word-bits
))
2655 (specifier-type `(unsigned-byte* ,size-high
))
2656 (specifier-type 'unsigned-byte
)))
2659 (defoptimizer (%mask-field derive-type
) ((size posn num
))
2660 (let ((size (lvar-type size
))
2661 (posn (lvar-type posn
)))
2662 (if (and (numeric-type-p size
)
2663 (csubtypep size
(specifier-type 'integer
))
2664 (numeric-type-p posn
)
2665 (csubtypep posn
(specifier-type 'integer
)))
2666 (let ((size-high (numeric-type-high size
))
2667 (posn-high (numeric-type-high posn
)))
2668 (if (and size-high posn-high
2669 (<= (+ size-high posn-high
) sb
!vm
:n-word-bits
))
2670 (specifier-type `(unsigned-byte* ,(+ size-high posn-high
)))
2671 (specifier-type 'unsigned-byte
)))
2674 (defun %deposit-field-derive-type-aux
(size posn int
)
2675 (let ((size (lvar-type size
))
2676 (posn (lvar-type posn
))
2677 (int (lvar-type int
)))
2678 (when (and (numeric-type-p size
)
2679 (numeric-type-p posn
)
2680 (numeric-type-p int
))
2681 (let ((size-high (numeric-type-high size
))
2682 (posn-high (numeric-type-high posn
))
2683 (high (numeric-type-high int
))
2684 (low (numeric-type-low int
)))
2685 (when (and size-high posn-high high low
2686 ;; KLUDGE: we need this cutoff here, otherwise we
2687 ;; will merrily derive the type of %DPB as
2688 ;; (UNSIGNED-BYTE 1073741822), and then attempt to
2689 ;; canonicalize this type to (INTEGER 0 (1- (ASH 1
2690 ;; 1073741822))), with hilarious consequences. We
2691 ;; cutoff at 4*SB!VM:N-WORD-BITS to allow inference
2692 ;; over a reasonable amount of shifting, even on
2693 ;; the alpha/32 port, where N-WORD-BITS is 32 but
2694 ;; machine integers are 64-bits. -- CSR,
2696 (<= (+ size-high posn-high
) (* 4 sb
!vm
:n-word-bits
)))
2697 (let ((raw-bit-count (max (integer-length high
)
2698 (integer-length low
)
2699 (+ size-high posn-high
))))
2702 `(signed-byte ,(1+ raw-bit-count
))
2703 `(unsigned-byte* ,raw-bit-count
)))))))))
2705 (defoptimizer (%dpb derive-type
) ((newbyte size posn int
))
2706 (%deposit-field-derive-type-aux size posn int
))
2708 (defoptimizer (%deposit-field derive-type
) ((newbyte size posn int
))
2709 (%deposit-field-derive-type-aux size posn int
))
2711 (deftransform %ldb
((size posn int
)
2712 (fixnum fixnum integer
)
2713 (unsigned-byte #.sb
!vm
:n-word-bits
))
2714 "convert to inline logical operations"
2715 `(logand (ash int
(- posn
))
2716 (ash ,(1- (ash 1 sb
!vm
:n-word-bits
))
2717 (- size
,sb
!vm
:n-word-bits
))))
2719 (deftransform %mask-field
((size posn int
)
2720 (fixnum fixnum integer
)
2721 (unsigned-byte #.sb
!vm
:n-word-bits
))
2722 "convert to inline logical operations"
2724 (ash (ash ,(1- (ash 1 sb
!vm
:n-word-bits
))
2725 (- size
,sb
!vm
:n-word-bits
))
2728 ;;; Note: for %DPB and %DEPOSIT-FIELD, we can't use
2729 ;;; (OR (SIGNED-BYTE N) (UNSIGNED-BYTE N))
2730 ;;; as the result type, as that would allow result types that cover
2731 ;;; the range -2^(n-1) .. 1-2^n, instead of allowing result types of
2732 ;;; (UNSIGNED-BYTE N) and result types of (SIGNED-BYTE N).
2734 (deftransform %dpb
((new size posn int
)
2736 (unsigned-byte #.sb
!vm
:n-word-bits
))
2737 "convert to inline logical operations"
2738 `(let ((mask (ldb (byte size
0) -
1)))
2739 (logior (ash (logand new mask
) posn
)
2740 (logand int
(lognot (ash mask posn
))))))
2742 (deftransform %dpb
((new size posn int
)
2744 (signed-byte #.sb
!vm
:n-word-bits
))
2745 "convert to inline logical operations"
2746 `(let ((mask (ldb (byte size
0) -
1)))
2747 (logior (ash (logand new mask
) posn
)
2748 (logand int
(lognot (ash mask posn
))))))
2750 (deftransform %deposit-field
((new size posn int
)
2752 (unsigned-byte #.sb
!vm
:n-word-bits
))
2753 "convert to inline logical operations"
2754 `(let ((mask (ash (ldb (byte size
0) -
1) posn
)))
2755 (logior (logand new mask
)
2756 (logand int
(lognot mask
)))))
2758 (deftransform %deposit-field
((new size posn int
)
2760 (signed-byte #.sb
!vm
:n-word-bits
))
2761 "convert to inline logical operations"
2762 `(let ((mask (ash (ldb (byte size
0) -
1) posn
)))
2763 (logior (logand new mask
)
2764 (logand int
(lognot mask
)))))
2766 (defoptimizer (mask-signed-field derive-type
) ((size x
))
2767 (let ((size (lvar-type size
)))
2768 (if (numeric-type-p size
)
2769 (let ((size-high (numeric-type-high size
)))
2770 (if (and size-high
(<= 1 size-high sb
!vm
:n-word-bits
))
2771 (specifier-type `(signed-byte ,size-high
))
2778 (defun %ash
/right
(integer amount
)
2779 (ash integer
(- amount
)))
2781 (deftransform ash
((integer amount
))
2782 "Convert ASH of signed word to %ASH/RIGHT"
2783 (unless (and (csubtypep (lvar-type integer
) ; do that ourselves to avoid
2784 (specifier-type 'sb
!vm
:signed-word
)) ; optimization
2785 (csubtypep (lvar-type amount
) ; notes.
2786 (specifier-type '(integer * 0))))
2787 (give-up-ir1-transform))
2788 (when (constant-lvar-p amount
)
2789 (give-up-ir1-transform))
2790 (let ((use (lvar-uses amount
)))
2791 (cond ((and (combination-p use
)
2792 (eql '%negate
(lvar-fun-name (combination-fun use
))))
2793 (splice-fun-args amount
'%negate
1)
2794 `(lambda (integer amount
)
2795 (declare (type unsigned-byte amount
))
2796 (%ash
/right integer
(if (>= amount
,sb
!vm
:n-word-bits
)
2797 ,(1- sb
!vm
:n-word-bits
)
2800 `(%ash
/right integer
(if (<= amount
,(- sb
!vm
:n-word-bits
))
2801 ,(1- sb
!vm
:n-word-bits
)
2804 (deftransform ash
((integer amount
))
2805 "Convert ASH of word to %ASH/RIGHT"
2806 (unless (and (csubtypep (lvar-type integer
)
2807 (specifier-type 'sb
!vm
:word
))
2808 (csubtypep (lvar-type amount
)
2809 (specifier-type '(integer * 0))))
2810 (give-up-ir1-transform))
2811 (when (constant-lvar-p amount
)
2812 (give-up-ir1-transform))
2813 (let ((use (lvar-uses amount
)))
2814 (cond ((and (combination-p use
)
2815 (eql '%negate
(lvar-fun-name (combination-fun use
))))
2816 (splice-fun-args amount
'%negate
1)
2817 `(lambda (integer amount
)
2818 (declare (type unsigned-byte amount
))
2819 (if (>= amount
,sb
!vm
:n-word-bits
)
2821 (%ash
/right integer amount
))))
2823 `(if (<= amount
,(- sb
!vm
:n-word-bits
))
2825 (%ash
/right integer
(- amount
)))))))
2827 (deftransform %ash
/right
((integer amount
) (integer (constant-arg unsigned-byte
)))
2828 "Convert %ASH/RIGHT by constant back to ASH"
2829 `(ash integer
,(- (lvar-value amount
))))
2831 (deftransform %ash
/right
((integer amount
) * * :node node
)
2832 "strength reduce large variable right shift"
2833 (let ((return-type (single-value-type (node-derived-type node
))))
2834 (cond ((type= return-type
(specifier-type '(eql 0)))
2836 ((type= return-type
(specifier-type '(eql -
1)))
2838 ((csubtypep return-type
(specifier-type '(member -
1 0)))
2839 `(ash integer
,(- sb
!vm
:n-word-bits
)))
2841 (give-up-ir1-transform)))))
2843 (defun %ash
/right-derive-type-aux
(n-type shift same-arg
)
2844 (declare (ignore same-arg
))
2845 (or (and (or (csubtypep n-type
(specifier-type 'sb
!vm
:signed-word
))
2846 (csubtypep n-type
(specifier-type 'word
)))
2847 (csubtypep shift
(specifier-type `(mod ,sb
!vm
:n-word-bits
)))
2848 (let ((n-low (numeric-type-low n-type
))
2849 (n-high (numeric-type-high n-type
))
2850 (s-low (numeric-type-low shift
))
2851 (s-high (numeric-type-high shift
)))
2852 (make-numeric-type :class
'integer
:complexp
:real
2855 (ash n-low
(- s-low
))
2856 (ash n-low
(- s-high
))))
2859 (ash n-high
(- s-high
))
2860 (ash n-high
(- s-low
)))))))
2863 (defoptimizer (%ash
/right derive-type
) ((n shift
))
2864 (two-arg-derive-type n shift
#'%ash
/right-derive-type-aux
#'%ash
/right
))
2867 ;;; Modular functions
2869 ;;; (ldb (byte s 0) (foo x y ...)) =
2870 ;;; (ldb (byte s 0) (foo (ldb (byte s 0) x) y ...))
2872 ;;; and similar for other arguments.
2874 (defun make-modular-fun-type-deriver (prototype kind width signedp
)
2875 (declare (ignore kind
))
2877 (binding* ((info (info :function
:info prototype
) :exit-if-null
)
2878 (fun (fun-info-derive-type info
) :exit-if-null
)
2879 (mask-type (specifier-type
2881 ((nil) (let ((mask (1- (ash 1 width
))))
2882 `(integer ,mask
,mask
)))
2883 ((t) `(signed-byte ,width
))))))
2885 (let ((res (funcall fun call
)))
2887 (if (eq signedp nil
)
2888 (logand-derive-type-aux res mask-type
))))))
2891 (binding* ((info (info :function
:info prototype
) :exit-if-null
)
2892 (fun (fun-info-derive-type info
) :exit-if-null
)
2893 (res (funcall fun call
) :exit-if-null
)
2894 (mask-type (specifier-type
2896 ((nil) (let ((mask (1- (ash 1 width
))))
2897 `(integer ,mask
,mask
)))
2898 ((t) `(signed-byte ,width
))))))
2899 (if (eq signedp nil
)
2900 (logand-derive-type-aux res mask-type
)))))
2902 ;;; Try to recursively cut all uses of LVAR to WIDTH bits.
2904 ;;; For good functions, we just recursively cut arguments; their
2905 ;;; "goodness" means that the result will not increase (in the
2906 ;;; (unsigned-byte +infinity) sense). An ordinary modular function is
2907 ;;; replaced with the version, cutting its result to WIDTH or more
2908 ;;; bits. For most functions (e.g. for +) we cut all arguments; for
2909 ;;; others (e.g. for ASH) we have "optimizers", cutting only necessary
2910 ;;; arguments (maybe to a different width) and returning the name of a
2911 ;;; modular version, if it exists, or NIL. If we have changed
2912 ;;; anything, we need to flush old derived types, because they have
2913 ;;; nothing in common with the new code.
2914 (defun cut-to-width (lvar kind width signedp
)
2915 (declare (type lvar lvar
) (type (integer 0) width
))
2916 (let ((type (specifier-type (if (zerop width
)
2919 ((nil) 'unsigned-byte
)
2922 (labels ((reoptimize-node (node name
)
2923 (setf (node-derived-type node
)
2925 (info :function
:type name
)))
2926 (setf (lvar-%derived-type
(node-lvar node
)) nil
)
2927 (setf (node-reoptimize node
) t
)
2928 (setf (block-reoptimize (node-block node
)) t
)
2929 (reoptimize-component (node-component node
) :maybe
))
2930 (insert-lvar-cut (lvar)
2931 "Insert a LOGAND/MASK-SIGNED-FIELD to cut the value of LVAR
2932 to the required bit width. Returns T if any change was made.
2934 When the destination of LVAR will definitely cut LVAR's value
2935 to width (i.e. it's a logand or mask-signed-field with constant
2936 other argument), do nothing. Otherwise, splice LOGAND/M-S-F in."
2937 (binding* ((dest (lvar-dest lvar
) :exit-if-null
)
2938 (nil (combination-p dest
) :exit-if-null
)
2939 (name (lvar-fun-name (combination-fun dest
) t
))
2940 (args (combination-args dest
)))
2943 (when (= 2 (length args
))
2944 (let ((other (if (eql (first args
) lvar
)
2947 (when (and (constant-lvar-p other
)
2948 (ctypep (lvar-value other
) type
)
2950 (return-from insert-lvar-cut
)))))
2953 (eql lvar
(second args
))
2954 (constant-lvar-p (first args
))
2955 (<= (lvar-value (first args
)) width
))
2956 (return-from insert-lvar-cut
)))))
2959 `(mask-signed-field ,width
'dummy
)
2960 `(logand 'dummy
,(ldb (byte width
0) -
1))))
2961 (do-uses (node lvar
)
2962 (setf (block-reoptimize (node-block node
)) t
)
2963 (reoptimize-component (node-component node
) :maybe
))
2966 "Try to cut a node to width. The primary return value is
2967 whether we managed to cut (cleverly), and the second whether
2968 anything was changed. The third return value tells whether
2969 the cut value might be wider than expected."
2970 (when (block-delete-p (node-block node
))
2971 (return-from cut-node
(values t nil
)))
2974 (typecase (ref-leaf node
)
2976 (let* ((constant-value (constant-value (ref-leaf node
)))
2978 (cond ((not (integerp constant-value
))
2979 (return-from cut-node
(values t nil
)))
2981 (mask-signed-field width constant-value
))
2983 (ldb (byte width
0) constant-value
)))))
2984 (cond ((= constant-value new-value
)
2985 (values t nil
)) ; we knew what to do and did nothing
2987 (change-ref-leaf node
(make-constant new-value
)
2989 (let ((lvar (node-lvar node
)))
2990 (setf (lvar-%derived-type lvar
)
2991 (and (lvar-has-single-use-p lvar
)
2992 (make-values-type :required
(list (ctype-of new-value
))))))
2993 (setf (block-reoptimize (node-block node
)) t
)
2994 (reoptimize-component (node-component node
) :maybe
)
2997 (when (eq (basic-combination-kind node
) :known
)
2998 (let* ((fun-ref (lvar-use (combination-fun node
)))
2999 (fun-name (lvar-fun-name (combination-fun node
)))
3000 (modular-fun (find-modular-version fun-name kind
3002 (cond ((not modular-fun
)
3003 ;; don't know what to do here
3005 ((let ((dtype (single-value-type
3006 (node-derived-type node
))))
3011 (specifier-type 'unsigned-byte
)))
3014 (specifier-type '(integer * 0))))
3018 (csubtypep dtype type
)))
3022 (binding* ((name (etypecase modular-fun
3023 ((eql :good
) fun-name
)
3025 (modular-fun-info-name modular-fun
))
3027 (funcall modular-fun node width
)))
3031 (unless (eql modular-fun
:good
)
3032 (setq did-something t
3036 (find-free-fun name
"in a strange place"))
3037 (setf (combination-kind node
) :full
))
3038 (unless (functionp modular-fun
)
3039 (dolist (arg (basic-combination-args node
))
3040 (multiple-value-bind (change wide
)
3042 (setf did-something
(or did-something change
)
3043 over-wide
(or over-wide wide
)))))
3045 (reoptimize-node node name
))
3046 (values t did-something over-wide
)))))))))
3047 (cut-lvar (lvar &key head
3048 &aux did-something must-insert over-wide
)
3049 "Cut all the LVAR's use nodes. If any of them wasn't handled
3050 and its type is too wide for the operation we wish to perform
3051 insert an explicit bit-width narrowing operation (LOGAND or
3052 MASK-SIGNED-FIELD) between the LVAR (*) and its destination.
3053 The narrowing operation might not be inserted if the LVAR's
3054 destination is already such an operation, to avoid endless
3057 If we're at the head, forcibly insert a cut operation if the
3058 result might be too wide.
3060 (*) We can't easily do that for each node, and doing so might
3061 result in code bloat, anyway. (I'm also not sure it would be
3062 correct for complicated C/D FG)"
3063 (do-uses (node lvar
)
3064 (multiple-value-bind (handled any-change wide
)
3066 (setf did-something
(or did-something any-change
)
3067 must-insert
(or must-insert
3069 (csubtypep (single-value-type
3070 (node-derived-type node
))
3072 over-wide
(or over-wide wide
))))
3073 (when (or must-insert
3074 (and head over-wide
))
3075 (setf did-something
(or (insert-lvar-cut lvar
) did-something
)
3076 ;; we're just the right width after an explicit cut.
3078 (values did-something over-wide
)))
3079 (cut-lvar lvar
:head t
))))
3081 (defun best-modular-version (width signedp
)
3082 ;; 1. exact width-matched :untagged
3083 ;; 2. >/>= width-matched :tagged
3084 ;; 3. >/>= width-matched :untagged
3085 (let* ((uuwidths (modular-class-widths *untagged-unsigned-modular-class
*))
3086 (uswidths (modular-class-widths *untagged-signed-modular-class
*))
3087 (uwidths (if (and uuwidths uswidths
)
3088 (merge 'list
(copy-list uuwidths
) (copy-list uswidths
)
3090 (or uuwidths uswidths
)))
3091 (twidths (modular-class-widths *tagged-modular-class
*)))
3092 (let ((exact (find (cons width signedp
) uwidths
:test
#'equal
)))
3094 (return-from best-modular-version
(values width
:untagged signedp
))))
3095 (flet ((inexact-match (w)
3097 ((eq signedp
(cdr w
)) (<= width
(car w
)))
3098 ((eq signedp nil
) (< width
(car w
))))))
3099 (let ((tgt (find-if #'inexact-match twidths
)))
3101 (return-from best-modular-version
3102 (values (car tgt
) :tagged
(cdr tgt
)))))
3103 (let ((ugt (find-if #'inexact-match uwidths
)))
3105 (return-from best-modular-version
3106 (values (car ugt
) :untagged
(cdr ugt
))))))))
3108 (defun integer-type-numeric-bounds (type)
3110 (numeric-type (values (numeric-type-low type
)
3111 (numeric-type-high type
)))
3115 (dolist (type (union-type-types type
) (values low high
))
3116 (unless (and (numeric-type-p type
)
3117 (eql (numeric-type-class type
) 'integer
))
3118 (return (values nil nil
)))
3119 (let ((this-low (numeric-type-low type
))
3120 (this-high (numeric-type-high type
)))
3121 (unless (and this-low this-high
)
3122 (return (values nil nil
)))
3123 (setf low
(min this-low
(or low this-low
))
3124 high
(max this-high
(or high this-high
)))))))))
3126 (defoptimizer (logand optimizer
) ((x y
) node
)
3127 (let ((result-type (single-value-type (node-derived-type node
))))
3128 (multiple-value-bind (low high
)
3129 (integer-type-numeric-bounds result-type
)
3130 (when (and (numberp low
)
3133 (let ((width (integer-length high
)))
3134 (multiple-value-bind (w kind signedp
)
3135 (best-modular-version width nil
)
3137 ;; FIXME: This should be (CUT-TO-WIDTH NODE KIND WIDTH SIGNEDP).
3139 ;; FIXME: I think the FIXME (which is from APD) above
3140 ;; implies that CUT-TO-WIDTH should do /everything/
3141 ;; that's required, including reoptimizing things
3142 ;; itself that it knows are necessary. At the moment,
3143 ;; CUT-TO-WIDTH sets up some new calls with
3144 ;; combination-type :FULL, which later get noticed as
3145 ;; known functions and properly converted.
3147 ;; We cut to W not WIDTH if SIGNEDP is true, because
3148 ;; signed constant replacement needs to know which bit
3149 ;; in the field is the signed bit.
3150 (let ((xact (cut-to-width x kind
(if signedp w width
) signedp
))
3151 (yact (cut-to-width y kind
(if signedp w width
) signedp
)))
3152 (declare (ignore xact yact
))
3153 nil
) ; After fixing above, replace with T, meaning
3154 ; "don't reoptimize this (LOGAND) node any more".
3157 (defoptimizer (mask-signed-field optimizer
) ((width x
) node
)
3158 (let ((result-type (single-value-type (node-derived-type node
))))
3159 (multiple-value-bind (low high
)
3160 (integer-type-numeric-bounds result-type
)
3161 (when (and (numberp low
) (numberp high
))
3162 (let ((width (max (integer-length high
) (integer-length low
))))
3163 (multiple-value-bind (w kind
)
3164 (best-modular-version (1+ width
) t
)
3166 ;; FIXME: This should be (CUT-TO-WIDTH NODE KIND W T).
3167 ;; [ see comment above in LOGAND optimizer ]
3168 (cut-to-width x kind w t
)
3169 nil
; After fixing above, replace with T.
3172 (defoptimizer (logior optimizer
) ((x y
) node
)
3173 (let ((result-type (single-value-type (node-derived-type node
))))
3174 (multiple-value-bind (low high
)
3175 (integer-type-numeric-bounds result-type
)
3176 (when (and (numberp low
)
3179 (let ((width (integer-length low
)))
3180 (multiple-value-bind (w kind
)
3181 (best-modular-version (1+ width
) t
)
3183 ;; FIXME: see comment in LOGAND optimizer
3184 (let ((xact (cut-to-width x kind w t
))
3185 (yact (cut-to-width y kind w t
)))
3186 (declare (ignore xact yact
))
3187 nil
) ; After fixing above, replace with T
3190 ;;; Handle the case of a constant BOOLE-CODE.
3191 (deftransform boole
((op x y
) * *)
3192 "convert to inline logical operations"
3193 (unless (constant-lvar-p op
)
3194 (give-up-ir1-transform "BOOLE code is not a constant."))
3195 (let ((control (lvar-value op
)))
3197 (#.sb
!xc
:boole-clr
0)
3198 (#.sb
!xc
:boole-set -
1)
3199 (#.sb
!xc
:boole-1
'x
)
3200 (#.sb
!xc
:boole-2
'y
)
3201 (#.sb
!xc
:boole-c1
'(lognot x
))
3202 (#.sb
!xc
:boole-c2
'(lognot y
))
3203 (#.sb
!xc
:boole-and
'(logand x y
))
3204 (#.sb
!xc
:boole-ior
'(logior x y
))
3205 (#.sb
!xc
:boole-xor
'(logxor x y
))
3206 (#.sb
!xc
:boole-eqv
'(logeqv x y
))
3207 (#.sb
!xc
:boole-nand
'(lognand x y
))
3208 (#.sb
!xc
:boole-nor
'(lognor x y
))
3209 (#.sb
!xc
:boole-andc1
'(logandc1 x y
))
3210 (#.sb
!xc
:boole-andc2
'(logandc2 x y
))
3211 (#.sb
!xc
:boole-orc1
'(logorc1 x y
))
3212 (#.sb
!xc
:boole-orc2
'(logorc2 x y
))
3214 (abort-ir1-transform "~S is an illegal control arg to BOOLE."
3217 ;;;; converting special case multiply/divide to shifts
3219 ;;; If arg is a constant power of two, turn * into a shift.
3220 (deftransform * ((x y
) (integer integer
) *)
3221 "convert x*2^k to shift"
3222 (unless (constant-lvar-p y
)
3223 (give-up-ir1-transform))
3224 (let* ((y (lvar-value y
))
3226 (len (1- (integer-length y-abs
))))
3227 (unless (and (> y-abs
0) (= y-abs
(ash 1 len
)))
3228 (give-up-ir1-transform))
3233 ;;; These must come before the ones below, so that they are tried
3234 ;;; first. Since %FLOOR and %CEILING are inlined, this allows
3235 ;;; the general case to be handled by TRUNCATE transforms.
3236 (deftransform floor
((x y
))
3239 (deftransform ceiling
((x y
))
3242 ;;; If arg is a constant power of two, turn FLOOR into a shift and
3243 ;;; mask. If CEILING, add in (1- (ABS Y)), do FLOOR and correct a
3245 (flet ((frob (y ceil-p
)
3246 (unless (constant-lvar-p y
)
3247 (give-up-ir1-transform))
3248 (let* ((y (lvar-value y
))
3250 (len (1- (integer-length y-abs
))))
3251 (unless (and (> y-abs
0) (= y-abs
(ash 1 len
)))
3252 (give-up-ir1-transform))
3253 (let ((shift (- len
))
3255 (delta (if ceil-p
(* (signum y
) (1- y-abs
)) 0)))
3256 `(let ((x (+ x
,delta
)))
3258 `(values (ash (- x
) ,shift
)
3259 (- (- (logand (- x
) ,mask
)) ,delta
))
3260 `(values (ash x
,shift
)
3261 (- (logand x
,mask
) ,delta
))))))))
3262 (deftransform floor
((x y
) (integer integer
) *)
3263 "convert division by 2^k to shift"
3265 (deftransform ceiling
((x y
) (integer integer
) *)
3266 "convert division by 2^k to shift"
3269 ;;; Do the same for MOD.
3270 (deftransform mod
((x y
) (integer integer
) *)
3271 "convert remainder mod 2^k to LOGAND"
3272 (unless (constant-lvar-p y
)
3273 (give-up-ir1-transform))
3274 (let* ((y (lvar-value y
))
3276 (len (1- (integer-length y-abs
))))
3277 (unless (and (> y-abs
0) (= y-abs
(ash 1 len
)))
3278 (give-up-ir1-transform))
3279 (let ((mask (1- y-abs
)))
3281 `(- (logand (- x
) ,mask
))
3282 `(logand x
,mask
)))))
3284 ;;; If arg is a constant power of two, turn TRUNCATE into a shift and mask.
3285 (deftransform truncate
((x y
) (integer integer
))
3286 "convert division by 2^k to shift"
3287 (unless (constant-lvar-p y
)
3288 (give-up-ir1-transform))
3289 (let* ((y (lvar-value y
))
3291 (len (1- (integer-length y-abs
))))
3292 (unless (and (> y-abs
0) (= y-abs
(ash 1 len
)))
3293 (give-up-ir1-transform))
3294 (let* ((shift (- len
))
3297 (values ,(if (minusp y
)
3299 `(- (ash (- x
) ,shift
)))
3300 (- (logand (- x
) ,mask
)))
3301 (values ,(if (minusp y
)
3302 `(ash (- ,mask x
) ,shift
)
3304 (logand x
,mask
))))))
3306 ;;; And the same for REM.
3307 (deftransform rem
((x y
) (integer integer
) *)
3308 "convert remainder mod 2^k to LOGAND"
3309 (unless (constant-lvar-p y
)
3310 (give-up-ir1-transform))
3311 (let* ((y (lvar-value y
))
3313 (len (1- (integer-length y-abs
))))
3314 (unless (and (> y-abs
0) (= y-abs
(ash 1 len
)))
3315 (give-up-ir1-transform))
3316 (let ((mask (1- y-abs
)))
3318 (- (logand (- x
) ,mask
))
3319 (logand x
,mask
)))))
3321 ;;; Return an expression to calculate the integer quotient of X and
3322 ;;; constant Y, using multiplication, shift and add/sub instead of
3323 ;;; division. Both arguments must be unsigned, fit in a machine word and
3324 ;;; Y must neither be zero nor a power of two. The quotient is rounded
3326 ;;; The algorithm is taken from the paper "Division by Invariant
3327 ;;; Integers using Multiplication", 1994 by Torbj\"{o}rn Granlund and
3328 ;;; Peter L. Montgomery, Figures 4.2 and 6.2, modified to exclude the
3329 ;;; case of division by powers of two.
3330 ;;; The algorithm includes an adaptive precision argument. Use it, since
3331 ;;; we often have sub-word value ranges. Careful, in this case, we need
3332 ;;; p s.t 2^p > n, not the ceiling of the binary log.
3333 ;;; Also, for some reason, the paper prefers shifting to masking. Mask
3334 ;;; instead. Masking is equivalent to shifting right, then left again;
3335 ;;; all the intermediate values are still words, so we just have to shift
3336 ;;; right a bit more to compensate, at the end.
3338 ;;; The following two examples show an average case and the worst case
3339 ;;; with respect to the complexity of the generated expression, under
3340 ;;; a word size of 64 bits:
3342 ;;; (UNSIGNED-DIV-TRANSFORMER 10 MOST-POSITIVE-WORD) ->
3343 ;;; (ASH (%MULTIPLY (LOGANDC2 X 0) 14757395258967641293) -3)
3345 ;;; (UNSIGNED-DIV-TRANSFORMER 7 MOST-POSITIVE-WORD) ->
3347 ;;; (T1 (%MULTIPLY NUM 2635249153387078803)))
3348 ;;; (ASH (LDB (BYTE 64 0)
3349 ;;; (+ T1 (ASH (LDB (BYTE 64 0)
3354 (defun gen-unsigned-div-by-constant-expr (y max-x
)
3355 (declare (type (integer 3 #.most-positive-word
) y
)
3357 (aver (not (zerop (logand y
(1- y
)))))
3359 ;; the floor of the binary logarithm of (positive) X
3360 (integer-length (1- x
)))
3361 (choose-multiplier (y precision
)
3363 (shift l
(1- shift
))
3364 (expt-2-n+l
(expt 2 (+ sb
!vm
:n-word-bits l
)))
3365 (m-low (truncate expt-2-n
+l y
) (ash m-low -
1))
3366 (m-high (truncate (+ expt-2-n
+l
3367 (ash expt-2-n
+l
(- precision
)))
3370 ((not (and (< (ash m-low -
1) (ash m-high -
1))
3372 (values m-high shift
)))))
3373 (let ((n (expt 2 sb
!vm
:n-word-bits
))
3374 (precision (integer-length max-x
))
3376 (multiple-value-bind (m shift2
)
3377 (choose-multiplier y precision
)
3378 (when (and (>= m n
) (evenp y
))
3379 (setq shift1
(ld (logand y
(- y
))))
3380 (multiple-value-setq (m shift2
)
3381 (choose-multiplier (/ y
(ash 1 shift1
))
3382 (- precision shift1
))))
3385 `(truly-the word
,x
)))
3387 (t1 (%multiply-high num
,(- m n
))))
3388 (ash ,(word `(+ t1
(ash ,(word `(- num t1
))
3391 ((and (zerop shift1
) (zerop shift2
))
3392 (let ((max (truncate max-x y
)))
3393 ;; Explicit TRULY-THE needed to get the FIXNUM=>FIXNUM
3395 `(truly-the (integer 0 ,max
)
3396 (%multiply-high x
,m
))))
3398 `(ash (%multiply-high
(logandc2 x
,(1- (ash 1 shift1
))) ,m
)
3399 ,(- (+ shift1 shift2
)))))))))
3401 ;;; If the divisor is constant and both args are positive and fit in a
3402 ;;; machine word, replace the division by a multiplication and possibly
3403 ;;; some shifts and an addition. Calculate the remainder by a second
3404 ;;; multiplication and a subtraction. Dead code elimination will
3405 ;;; suppress the latter part if only the quotient is needed. If the type
3406 ;;; of the dividend allows to derive that the quotient will always have
3407 ;;; the same value, emit much simpler code to handle that. (This case
3408 ;;; may be rare but it's easy to detect and the compiler doesn't find
3409 ;;; this optimization on its own.)
3410 (deftransform truncate
((x y
) (word (constant-arg word
))
3412 :policy
(and (> speed compilation-speed
)
3414 "convert integer division to multiplication"
3415 (let* ((y (lvar-value y
))
3416 (x-type (lvar-type x
))
3417 (max-x (or (and (numeric-type-p x-type
)
3418 (numeric-type-high x-type
))
3419 most-positive-word
)))
3420 ;; Division by zero, one or powers of two is handled elsewhere.
3421 (when (zerop (logand y
(1- y
)))
3422 (give-up-ir1-transform))
3423 `(let* ((quot ,(gen-unsigned-div-by-constant-expr y max-x
))
3424 (rem (ldb (byte #.sb
!vm
:n-word-bits
0)
3425 (- x
(* quot
,y
)))))
3426 (values quot rem
))))
3428 ;;;; arithmetic and logical identity operation elimination
3430 ;;; Flush calls to various arith functions that convert to the
3431 ;;; identity function or a constant.
3432 (macrolet ((def (name identity result
)
3433 `(deftransform ,name
((x y
) (* (constant-arg (member ,identity
))) *)
3434 "fold identity operations"
3441 (def logxor -
1 (lognot x
))
3444 (defun least-zero-bit (x)
3446 (1- (integer-length (logxor x
(1+ x
))))))
3448 (deftransform logand
((x y
) (* (constant-arg t
)) *)
3449 "fold identity operation"
3450 (let* ((y (lvar-value y
))
3451 (width (or (least-zero-bit y
) '*)))
3452 (unless (and (neq width
0) ; (logand x 0) handled elsewhere
3453 (csubtypep (lvar-type x
)
3454 (specifier-type `(unsigned-byte ,width
))))
3455 (give-up-ir1-transform))
3458 (deftransform mask-signed-field
((size x
) ((constant-arg t
) *) *)
3459 "fold identity operation"
3460 (let ((size (lvar-value size
)))
3461 (unless (csubtypep (lvar-type x
) (specifier-type `(signed-byte ,size
)))
3462 (give-up-ir1-transform))
3465 (deftransform logior
((x y
) (* (constant-arg t
)) *)
3466 "fold identity operation"
3467 (let* ((y (lvar-value y
))
3468 (width (or (least-zero-bit (lognot y
))
3469 (give-up-ir1-transform)))) ; (logior x 0) handled elsewhere
3470 (unless (csubtypep (lvar-type x
)
3471 (specifier-type `(integer ,(- (ash 1 width
)) -
1)))
3472 (give-up-ir1-transform))
3475 ;;; Pick off easy association opportunities for constant folding.
3476 ;;; More complicated stuff that also depends on commutativity
3477 ;;; (e.g. (f (f x k1) (f y k2)) => (f (f x y) (f k1 k2))) should
3478 ;;; probably be handled with a more general tree-rewriting pass.
3479 (macrolet ((def (operator &key
(type 'integer
) (folded operator
))
3480 `(deftransform ,operator
((x z
) (,type
(constant-arg ,type
)))
3481 ,(format nil
"associate ~A/~A of constants"
3483 (binding* ((node (if (lvar-has-single-use-p x
)
3485 (give-up-ir1-transform)))
3486 (nil (or (and (combination-p node
)
3488 (combination-fun node
))
3490 (give-up-ir1-transform)))
3491 (y (second (combination-args node
)))
3492 (nil (or (constant-lvar-p y
)
3493 (give-up-ir1-transform)))
3495 (unless (typep y
',type
)
3496 (give-up-ir1-transform))
3497 (splice-fun-args x
',folded
2)
3499 (declare (ignore y z
))
3500 ;; (operator (folded x y) z)
3501 ;; == (operator x (folded z y))
3502 (,',operator x
',(,folded
(lvar-value z
) y
)))))))
3506 (def logtest
:folded logand
)
3507 (def + :type rational
)
3508 (def + :type rational
:folded -
)
3509 (def * :type rational
)
3510 (def * :type rational
:folded
/))
3512 (deftransform mask-signed-field
((width x
) ((constant-arg unsigned-byte
) *))
3513 "Fold mask-signed-field/mask-signed-field of constant width"
3514 (binding* ((node (if (lvar-has-single-use-p x
)
3516 (give-up-ir1-transform)))
3517 (nil (or (combination-p node
)
3518 (give-up-ir1-transform)))
3519 (nil (or (eq (lvar-fun-name (combination-fun node
))
3521 (give-up-ir1-transform)))
3522 (x-width (first (combination-args node
)))
3523 (nil (or (constant-lvar-p x-width
)
3524 (give-up-ir1-transform)))
3525 (x-width (lvar-value x-width
)))
3526 (unless (typep x-width
'unsigned-byte
)
3527 (give-up-ir1-transform))
3528 (splice-fun-args x
'mask-signed-field
2)
3529 `(lambda (width x-width x
)
3530 (declare (ignore width x-width
))
3531 (mask-signed-field ,(min (lvar-value width
) x-width
) x
))))
3533 ;;; These are restricted to rationals, because (- 0 0.0) is 0.0, not -0.0, and
3534 ;;; (* 0 -4.0) is -0.0.
3535 (deftransform -
((x y
) ((constant-arg (member 0)) rational
) *)
3536 "convert (- 0 x) to negate"
3538 (deftransform * ((x y
) (rational (constant-arg (member 0))) *)
3539 "convert (* x 0) to 0"
3542 (deftransform %negate
((x) (rational))
3543 "Eliminate %negate/%negate of rationals"
3544 (splice-fun-args x
'%negate
1)
3547 (deftransform %negate
((x) (number))
3549 (let ((use (lvar-uses x
))
3551 (unless (and (combination-p use
)
3552 (eql '* (lvar-fun-name (combination-fun use
)))
3553 (constant-lvar-p (setf arg
(second (combination-args use
))))
3554 (numberp (setf arg
(lvar-value arg
))))
3555 (give-up-ir1-transform))
3556 (splice-fun-args x
'* 2)
3558 (declare (ignore y
))
3561 ;;; Return T if in an arithmetic op including lvars X and Y, the
3562 ;;; result type is not affected by the type of X. That is, Y is at
3563 ;;; least as contagious as X.
3565 (defun not-more-contagious (x y
)
3566 (declare (type continuation x y
))
3567 (let ((x (lvar-type x
))
3569 (values (type= (numeric-contagion x y
)
3570 (numeric-contagion y y
)))))
3571 ;;; Patched version by Raymond Toy. dtc: Should be safer although it
3572 ;;; XXX needs more work as valid transforms are missed; some cases are
3573 ;;; specific to particular transform functions so the use of this
3574 ;;; function may need a re-think.
3575 (defun not-more-contagious (x y
)
3576 (declare (type lvar x y
))
3577 (flet ((simple-numeric-type (num)
3578 (and (numeric-type-p num
)
3579 ;; Return non-NIL if NUM is integer, rational, or a float
3580 ;; of some type (but not FLOAT)
3581 (case (numeric-type-class num
)
3585 (numeric-type-format num
))
3588 (let ((x (lvar-type x
))
3590 (if (and (simple-numeric-type x
)
3591 (simple-numeric-type y
))
3592 (values (type= (numeric-contagion x y
)
3593 (numeric-contagion y y
)))))))
3595 (def!type exact-number
()
3596 '(or rational
(complex rational
)))
3600 ;;; Only safely applicable for exact numbers. For floating-point
3601 ;;; x, one would have to first show that neither x or y are signed
3602 ;;; 0s, and that x isn't an SNaN.
3603 (deftransform + ((x y
) (exact-number (constant-arg (eql 0))) *)
3608 (deftransform -
((x y
) (exact-number (constant-arg (eql 0))) *)
3612 ;;; Fold (OP x +/-1)
3614 ;;; %NEGATE might not always signal correctly.
3616 ((def (name result minus-result
)
3617 `(deftransform ,name
((x y
)
3618 (exact-number (constant-arg (member 1 -
1))))
3619 "fold identity operations"
3620 (if (minusp (lvar-value y
)) ',minus-result
',result
))))
3621 (def * x
(%negate x
))
3622 (def / x
(%negate x
))
3623 (def expt x
(/ 1 x
)))
3625 ;;; Fold (expt x n) into multiplications for small integral values of
3626 ;;; N; convert (expt x 1/2) to sqrt.
3627 (deftransform expt
((x y
) (t (constant-arg real
)) *)
3628 "recode as multiplication or sqrt"
3629 (let ((val (lvar-value y
)))
3630 ;; If Y would cause the result to be promoted to the same type as
3631 ;; Y, we give up. If not, then the result will be the same type
3632 ;; as X, so we can replace the exponentiation with simple
3633 ;; multiplication and division for small integral powers.
3634 (unless (not-more-contagious y x
)
3635 (give-up-ir1-transform))
3637 (let ((x-type (lvar-type x
)))
3638 (cond ((csubtypep x-type
(specifier-type '(or rational
3639 (complex rational
))))
3641 ((csubtypep x-type
(specifier-type 'real
))
3645 ((csubtypep x-type
(specifier-type 'complex
))
3646 ;; both parts are float
3648 (t (give-up-ir1-transform)))))
3649 ((= val
2) '(* x x
))
3650 ((= val -
2) '(/ (* x x
)))
3651 ((= val
3) '(* x x x
))
3652 ((= val -
3) '(/ (* x x x
)))
3653 ((= val
1/2) '(sqrt x
))
3654 ((= val -
1/2) '(/ (sqrt x
)))
3655 (t (give-up-ir1-transform)))))
3657 (deftransform expt
((x y
) ((constant-arg (member -
1 -
1.0 -
1.0d0
)) integer
) *)
3658 "recode as an ODDP check"
3659 (let ((val (lvar-value x
)))
3661 '(- 1 (* 2 (logand 1 y
)))
3666 ;;; KLUDGE: Shouldn't (/ 0.0 0.0), etc. cause exceptions in these
3667 ;;; transformations?
3668 ;;; Perhaps we should have to prove that the denominator is nonzero before
3669 ;;; doing them? -- WHN 19990917
3670 (macrolet ((def (name)
3671 `(deftransform ,name
((x y
) ((constant-arg (integer 0 0)) integer
)
3678 (macrolet ((def (name)
3679 `(deftransform ,name
((x y
) ((constant-arg (integer 0 0)) integer
)
3688 (macrolet ((def (name &optional float
)
3689 (let ((x (if float
'(float x
) 'x
)))
3690 `(deftransform ,name
((x y
) (integer (constant-arg (member 1 -
1)))
3692 "fold division by 1"
3693 `(values ,(if (minusp (lvar-value y
))
3706 ;;;; character operations
3708 (deftransform two-arg-char-equal
((a b
) (base-char base-char
) *
3709 :policy
(> speed space
))
3711 '(let* ((ac (char-code a
))
3713 (sum (logxor ac bc
)))
3715 (when (eql sum
#x20
)
3716 (let ((sum (+ ac bc
)))
3717 (or (and (> sum
161) (< sum
213))
3718 (and (> sum
415) (< sum
461))
3719 (and (> sum
463) (< sum
477))))))))
3721 (deftransform two-arg-char-equal
((a b
) (* (constant-arg character
)) *
3723 (let ((char (lvar-value b
)))
3724 (if (both-case-p char
)
3725 (let ((reverse (if (upper-case-p char
)
3726 (char-downcase char
)
3727 (char-upcase char
))))
3728 (if (policy node
(> speed space
))
3729 `(or (char= a
,char
)
3731 `(char-equal-constant a
,char
,reverse
)))
3734 (deftransform char-upcase
((x) (base-char))
3736 '(let ((n-code (char-code x
)))
3737 (if (or (and (> n-code
#o140
) ; Octal 141 is #\a.
3738 (< n-code
#o173
)) ; Octal 172 is #\z.
3739 (and (> n-code
#o337
)
3741 (and (> n-code
#o367
)
3743 (code-char (logxor #x20 n-code
))
3746 (deftransform char-downcase
((x) (base-char))
3748 '(let ((n-code (char-code x
)))
3749 (if (or (and (> n-code
64) ; 65 is #\A.
3750 (< n-code
91)) ; 90 is #\Z.
3755 (code-char (logxor #x20 n-code
))
3758 ;;;; equality predicate transforms
3760 ;;; Return true if X and Y are lvars whose only use is a
3761 ;;; reference to the same leaf, and the value of the leaf cannot
3763 (defun same-leaf-ref-p (x y
)
3764 (declare (type lvar x y
))
3765 (let ((x-use (principal-lvar-use x
))
3766 (y-use (principal-lvar-use y
)))
3769 (eq (ref-leaf x-use
) (ref-leaf y-use
))
3770 (constant-reference-p x-use
))))
3772 ;;; If X and Y are the same leaf, then the result is true. Otherwise,
3773 ;;; if there is no intersection between the types of the arguments,
3774 ;;; then the result is definitely false.
3775 (deftransform simple-equality-transform
((x y
) * *
3778 ((same-leaf-ref-p x y
) t
)
3779 ((not (types-equal-or-intersect (lvar-type x
) (lvar-type y
)))
3781 (t (give-up-ir1-transform))))
3784 `(%deftransform
',x
'(function * *) #'simple-equality-transform
)))
3787 (def two-arg-char-equal
))
3789 ;;; This is similar to SIMPLE-EQUALITY-TRANSFORM, except that we also
3790 ;;; try to convert to a type-specific predicate or EQ:
3791 ;;; -- If both args are characters, convert to CHAR=. This is better than
3792 ;;; just converting to EQ, since CHAR= may have special compilation
3793 ;;; strategies for non-standard representations, etc.
3794 ;;; -- If either arg is definitely a fixnum, we check to see if X is
3795 ;;; constant and if so, put X second. Doing this results in better
3796 ;;; code from the backend, since the backend assumes that any constant
3797 ;;; argument comes second.
3798 ;;; -- If either arg is definitely not a number or a fixnum, then we
3799 ;;; can compare with EQ.
3800 ;;; -- Otherwise, we try to put the arg we know more about second. If X
3801 ;;; is constant then we put it second. If X is a subtype of Y, we put
3802 ;;; it second. These rules make it easier for the back end to match
3803 ;;; these interesting cases.
3804 (deftransform eql
((x y
) * * :node node
)
3805 "convert to simpler equality predicate"
3806 (let ((x-type (lvar-type x
))
3807 (y-type (lvar-type y
))
3808 (char-type (specifier-type 'character
)))
3810 ((same-leaf-ref-p x y
) t
)
3811 ((not (types-equal-or-intersect x-type y-type
))
3813 ((and (csubtypep x-type char-type
)
3814 (csubtypep y-type char-type
))
3816 ((or (eq-comparable-type-p x-type
) (eq-comparable-type-p y-type
))
3819 (give-up-ir1-transform)))))
3821 ;;; similarly to the EQL transform above, we attempt to constant-fold
3822 ;;; or convert to a simpler predicate: mostly we have to be careful
3823 ;;; with strings and bit-vectors.
3824 (deftransform equal
((x y
) * *)
3825 "convert to simpler equality predicate"
3826 (let ((x-type (lvar-type x
))
3827 (y-type (lvar-type y
))
3828 (combination-type (specifier-type '(or bit-vector string
3830 (flet ((both-csubtypep (type)
3831 (let ((ctype (specifier-type type
)))
3832 (and (csubtypep x-type ctype
)
3833 (csubtypep y-type ctype
)))))
3835 ((same-leaf-ref-p x y
) t
)
3836 ((both-csubtypep 'string
)
3838 ((both-csubtypep 'bit-vector
)
3839 '(bit-vector-= x y
))
3840 ((both-csubtypep 'pathname
)
3842 ((or (not (types-equal-or-intersect x-type combination-type
))
3843 (not (types-equal-or-intersect y-type combination-type
)))
3844 (if (types-equal-or-intersect x-type y-type
)
3846 ;; Can't simply check for type intersection if both types are combination-type
3847 ;; since array specialization would mean types don't intersect, even when EQUAL
3848 ;; doesn't care for specialization.
3849 ;; Previously checking for intersection in the outer COND resulted in
3851 ;; (equal (the (cons (or simple-bit-vector
3852 ;; simple-base-string))
3854 ;; (the (cons (or (and bit-vector (not simple-array))
3855 ;; (simple-array character (*))))
3857 ;; being incorrectly folded to NIL
3859 (t (give-up-ir1-transform))))))
3861 (deftransform equalp
((x y
) * *)
3862 "convert to simpler equality predicate"
3863 (let ((x-type (lvar-type x
))
3864 (y-type (lvar-type y
))
3865 (combination-type (specifier-type '(or number array
3868 instance hash-table
))))
3869 (flet ((both-csubtypep (type)
3870 (let ((ctype (specifier-type type
)))
3871 (and (csubtypep x-type ctype
)
3872 (csubtypep y-type ctype
)))))
3874 ((same-leaf-ref-p x y
) t
)
3875 ((both-csubtypep 'string
)
3876 '(string-equal x y
))
3877 ((both-csubtypep 'bit-vector
)
3878 '(bit-vector-= x y
))
3879 ((both-csubtypep 'pathname
)
3881 ((both-csubtypep 'character
)
3883 ((both-csubtypep 'number
)
3885 ((both-csubtypep 'hash-table
)
3886 '(hash-table-equalp x y
))
3887 ((or (not (types-equal-or-intersect x-type combination-type
))
3888 (not (types-equal-or-intersect y-type combination-type
)))
3889 ;; See the comment about specialized types in the EQUAL transform above
3890 (if (types-equal-or-intersect y-type x-type
)
3893 (t (give-up-ir1-transform))))))
3895 ;;; Convert to EQL if both args are rational and complexp is specified
3896 ;;; and the same for both.
3897 (deftransform = ((x y
) (number number
) *)
3899 (let ((x-type (lvar-type x
))
3900 (y-type (lvar-type y
)))
3901 (cond ((or (and (csubtypep x-type
(specifier-type 'float
))
3902 (csubtypep y-type
(specifier-type 'float
)))
3903 (and (csubtypep x-type
(specifier-type '(complex float
)))
3904 (csubtypep y-type
(specifier-type '(complex float
))))
3905 #!+complex-float-vops
3906 (and (csubtypep x-type
(specifier-type '(or single-float
(complex single-float
))))
3907 (csubtypep y-type
(specifier-type '(or single-float
(complex single-float
)))))
3908 #!+complex-float-vops
3909 (and (csubtypep x-type
(specifier-type '(or double-float
(complex double-float
))))
3910 (csubtypep y-type
(specifier-type '(or double-float
(complex double-float
))))))
3911 ;; They are both floats. Leave as = so that -0.0 is
3912 ;; handled correctly.
3913 (give-up-ir1-transform))
3914 ((or (and (csubtypep x-type
(specifier-type 'rational
))
3915 (csubtypep y-type
(specifier-type 'rational
)))
3916 (and (csubtypep x-type
3917 (specifier-type '(complex rational
)))
3919 (specifier-type '(complex rational
)))))
3920 ;; They are both rationals and complexp is the same.
3924 (give-up-ir1-transform
3925 "The operands might not be the same type.")))))
3927 (defun maybe-float-lvar-p (lvar)
3928 (neq *empty-type
* (type-intersection (specifier-type 'float
)
3931 (flet ((maybe-invert (node op inverted x y
)
3932 ;; Don't invert if either argument can be a float (NaNs)
3934 ((or (maybe-float-lvar-p x
) (maybe-float-lvar-p y
))
3935 (delay-ir1-transform node
:constraint
)
3936 `(or (,op x y
) (= x y
)))
3938 `(if (,inverted x y
) nil t
)))))
3939 (deftransform >= ((x y
) (number number
) * :node node
)
3940 "invert or open code"
3941 (maybe-invert node
'> '< x y
))
3942 (deftransform <= ((x y
) (number number
) * :node node
)
3943 "invert or open code"
3944 (maybe-invert node
'< '> x y
)))
3946 ;;; See whether we can statically determine (< X Y) using type
3947 ;;; information. If X's high bound is < Y's low, then X < Y.
3948 ;;; Similarly, if X's low is >= to Y's high, the X >= Y (so return
3949 ;;; NIL). If not, at least make sure any constant arg is second.
3950 (macrolet ((def (name inverse reflexive-p surely-true surely-false
)
3951 `(deftransform ,name
((x y
))
3952 "optimize using intervals"
3953 (if (and (same-leaf-ref-p x y
)
3954 ;; For non-reflexive functions we don't need
3955 ;; to worry about NaNs: (non-ref-op NaN NaN) => false,
3956 ;; but with reflexive ones we don't know...
3958 '((and (not (maybe-float-lvar-p x
))
3959 (not (maybe-float-lvar-p y
))))))
3961 (let ((ix (or (type-approximate-interval (lvar-type x
))
3962 (give-up-ir1-transform)))
3963 (iy (or (type-approximate-interval (lvar-type y
))
3964 (give-up-ir1-transform))))
3969 ((and (constant-lvar-p x
)
3970 (not (constant-lvar-p y
)))
3973 (give-up-ir1-transform))))))))
3974 (def = = t
(interval-= ix iy
) (interval-/= ix iy
))
3975 (def /= /= nil
(interval-/= ix iy
) (interval-= ix iy
))
3976 (def < > nil
(interval-< ix iy
) (interval->= ix iy
))
3977 (def > < nil
(interval-< iy ix
) (interval->= iy ix
))
3978 (def <= >= t
(interval->= iy ix
) (interval-< iy ix
))
3979 (def >= <= t
(interval->= ix iy
) (interval-< ix iy
)))
3981 (defun ir1-transform-char< (x y first second inverse
)
3983 ((same-leaf-ref-p x y
) nil
)
3984 ;; If we had interval representation of character types, as we
3985 ;; might eventually have to to support 2^21 characters, then here
3986 ;; we could do some compile-time computation as in transforms for
3987 ;; < above. -- CSR, 2003-07-01
3988 ((and (constant-lvar-p first
)
3989 (not (constant-lvar-p second
)))
3991 (t (give-up-ir1-transform))))
3993 (deftransform char
< ((x y
) (character character
) *)
3994 (ir1-transform-char< x y x y
'char
>))
3996 (deftransform char
> ((x y
) (character character
) *)
3997 (ir1-transform-char< y x x y
'char
<))
3999 ;;;; converting N-arg comparisons
4001 ;;;; We convert calls to N-arg comparison functions such as < into
4002 ;;;; two-arg calls. This transformation is enabled for all such
4003 ;;;; comparisons in this file. If any of these predicates are not
4004 ;;;; open-coded, then the transformation should be removed at some
4005 ;;;; point to avoid pessimization.
4007 ;;; This function is used for source transformation of N-arg
4008 ;;; comparison functions other than inequality. We deal both with
4009 ;;; converting to two-arg calls and inverting the sense of the test,
4010 ;;; if necessary. If the call has two args, then we pass or return a
4011 ;;; negated test as appropriate. If it is a degenerate one-arg call,
4012 ;;; then we transform to code that returns true. Otherwise, we bind
4013 ;;; all the arguments and expand into a bunch of IFs.
4014 (defun multi-compare (predicate args not-p type
&optional force-two-arg-p
)
4015 (let ((nargs (length args
)))
4016 (cond ((< nargs
1) (values nil t
))
4017 ((= nargs
1) `(progn (the ,type
,@args
) t
))
4020 `(if (,predicate
,(first args
) ,(second args
)) nil t
)
4022 `(,predicate
,(first args
) ,(second args
))
4025 (do* ((i (1- nargs
) (1- i
))
4027 (current (gensym) (gensym))
4028 (vars (list current
) (cons current vars
))
4030 `(if (,predicate
,current
,last
)
4032 `(if (,predicate
,current
,last
)
4035 `((lambda ,vars
(declare (type ,type
,@vars
)) ,result
)
4038 (define-source-transform = (&rest args
) (multi-compare '= args nil
'number
))
4039 (define-source-transform < (&rest args
) (multi-compare '< args nil
'real
))
4040 (define-source-transform > (&rest args
) (multi-compare '> args nil
'real
))
4041 ;;; We cannot do the inversion for >= and <= here, since both
4042 ;;; (< NaN X) and (> NaN X)
4043 ;;; are false, and we don't have type-information available yet. The
4044 ;;; deftransforms for two-argument versions of >= and <= takes care of
4045 ;;; the inversion to > and < when possible.
4046 (define-source-transform <= (&rest args
) (multi-compare '<= args nil
'real
))
4047 (define-source-transform >= (&rest args
) (multi-compare '>= args nil
'real
))
4049 (define-source-transform char
= (&rest args
) (multi-compare 'char
= args nil
4051 (define-source-transform char
< (&rest args
) (multi-compare 'char
< args nil
4053 (define-source-transform char
> (&rest args
) (multi-compare 'char
> args nil
4055 (define-source-transform char
<= (&rest args
) (multi-compare 'char
> args t
4057 (define-source-transform char
>= (&rest args
) (multi-compare 'char
< args t
4060 (define-source-transform char-equal
(&rest args
)
4061 (multi-compare 'two-arg-char-equal args nil
'character t
))
4062 (define-source-transform char-lessp
(&rest args
)
4063 (multi-compare 'two-arg-char-lessp args nil
'character t
))
4064 (define-source-transform char-greaterp
(&rest args
)
4065 (multi-compare 'two-arg-char-greaterp args nil
'character t
))
4066 (define-source-transform char-not-greaterp
(&rest args
)
4067 (multi-compare 'two-arg-char-greaterp args t
'character t
))
4068 (define-source-transform char-not-lessp
(&rest args
)
4069 (multi-compare 'two-arg-char-lessp args t
'character t
))
4071 ;;; This function does source transformation of N-arg inequality
4072 ;;; functions such as /=. This is similar to MULTI-COMPARE in the <3
4073 ;;; arg cases. If there are more than two args, then we expand into
4074 ;;; the appropriate n^2 comparisons only when speed is important.
4075 (declaim (ftype (function (symbol list t
) *) multi-not-equal
))
4076 (defun multi-not-equal (predicate args type
)
4077 (let ((nargs (length args
)))
4078 (cond ((< nargs
1) (values nil t
))
4079 ((= nargs
1) `(progn (the ,type
,@args
) t
))
4081 `(if (,predicate
,(first args
) ,(second args
)) nil t
))
4082 ((not (policy *lexenv
*
4083 (and (>= speed space
)
4084 (>= speed compilation-speed
))))
4087 (let ((vars (make-gensym-list nargs
)))
4088 (do ((var vars next
)
4089 (next (cdr vars
) (cdr next
))
4092 `((lambda ,vars
(declare (type ,type
,@vars
)) ,result
)
4094 (let ((v1 (first var
)))
4096 (setq result
`(if (,predicate
,v1
,v2
) nil
,result
))))))))))
4098 (define-source-transform /= (&rest args
)
4099 (multi-not-equal '= args
'number
))
4100 (define-source-transform char
/= (&rest args
)
4101 (multi-not-equal 'char
= args
'character
))
4102 (define-source-transform char-not-equal
(&rest args
)
4103 (multi-not-equal 'char-equal args
'character
))
4105 ;;; Expand MAX and MIN into the obvious comparisons.
4106 (define-source-transform max
(arg0 &rest rest
)
4107 (once-only ((arg0 arg0
))
4109 `(values (the real
,arg0
))
4110 `(let ((maxrest (max ,@rest
)))
4111 (if (>= ,arg0 maxrest
) ,arg0 maxrest
)))))
4112 (define-source-transform min
(arg0 &rest rest
)
4113 (once-only ((arg0 arg0
))
4115 `(values (the real
,arg0
))
4116 `(let ((minrest (min ,@rest
)))
4117 (if (<= ,arg0 minrest
) ,arg0 minrest
)))))
4119 ;;; Simplify some cross-type comparisons
4120 (macrolet ((def (comparator round
)
4122 (deftransform ,comparator
4123 ((x y
) (rational (constant-arg float
)))
4124 "open-code RATIONAL to FLOAT comparison"
4125 (let ((y (lvar-value y
)))
4127 (when (or (float-nan-p y
)
4128 (float-infinity-p y
))
4129 (give-up-ir1-transform))
4130 (setf y
(rational y
))
4132 x
,(if (csubtypep (lvar-type x
)
4133 (specifier-type 'integer
))
4136 (deftransform ,comparator
4137 ((x y
) (integer (constant-arg ratio
)))
4138 "open-code INTEGER to RATIO comparison"
4139 `(,',comparator x
,(,round
(lvar-value y
)))))))
4143 (deftransform = ((x y
) (rational (constant-arg float
)))
4144 "open-code RATIONAL to FLOAT comparison"
4145 (let ((y (lvar-value y
)))
4147 (when (or (float-nan-p y
)
4148 (float-infinity-p y
))
4149 (give-up-ir1-transform))
4150 (setf y
(rational y
))
4151 (if (and (csubtypep (lvar-type x
)
4152 (specifier-type 'integer
))
4157 (deftransform = ((x y
) (integer (constant-arg ratio
)))
4158 "constant-fold INTEGER to RATIO comparison"
4161 ;;;; converting N-arg arithmetic functions
4163 ;;;; N-arg arithmetic and logic functions are associated into two-arg
4164 ;;;; versions, and degenerate cases are flushed.
4166 ;;; Left-associate FIRST-ARG and MORE-ARGS using FUNCTION.
4167 (declaim (ftype (sfunction (symbol t list t
) list
) associate-args
))
4168 (defun associate-args (fun first-arg more-args identity
)
4169 (let ((next (rest more-args
))
4170 (arg (first more-args
)))
4172 `(,fun
,first-arg
,(if arg arg identity
))
4173 (associate-args fun
`(,fun
,first-arg
,arg
) next identity
))))
4175 ;;; Reduce constants in ARGS list.
4176 (declaim (ftype (sfunction (symbol list t symbol
) list
) reduce-constants
))
4177 (defun reduce-constants (fun args identity one-arg-result-type
)
4178 (let ((one-arg-constant-p (ecase one-arg-result-type
4180 (integer #'integerp
)))
4181 (reduced-value identity
)
4183 (collect ((not-constants))
4185 (if (funcall one-arg-constant-p arg
)
4186 (setf reduced-value
(funcall fun reduced-value arg
)
4188 (not-constants arg
)))
4189 ;; It is tempting to drop constants reduced to identity here,
4190 ;; but if X is SNaN in (* X 1), we cannot drop the 1.
4193 `(,reduced-value
,@(not-constants))
4195 `(,reduced-value
)))))
4197 ;;; Do source transformations for transitive functions such as +.
4198 ;;; One-arg cases are replaced with the arg and zero arg cases with
4199 ;;; the identity. ONE-ARG-RESULT-TYPE is the type to ensure (with THE)
4200 ;;; that the argument in one-argument calls is.
4201 (declaim (ftype (function (symbol list t
&optional symbol list
)
4202 (values t
&optional
(member nil t
)))
4203 source-transform-transitive
))
4204 (defun source-transform-transitive (fun args identity
4205 &optional
(one-arg-result-type 'number
)
4206 (one-arg-prefixes '(values)))
4209 (1 `(,@one-arg-prefixes
(the ,one-arg-result-type
,(first args
))))
4211 (t (let ((reduced-args (reduce-constants fun args identity one-arg-result-type
)))
4212 (associate-args fun
(first reduced-args
) (rest reduced-args
) identity
)))))
4214 (define-source-transform + (&rest args
)
4215 (source-transform-transitive '+ args
0))
4216 (define-source-transform * (&rest args
)
4217 (source-transform-transitive '* args
1))
4218 (define-source-transform logior
(&rest args
)
4219 (source-transform-transitive 'logior args
0 'integer
))
4220 (define-source-transform logxor
(&rest args
)
4221 (source-transform-transitive 'logxor args
0 'integer
))
4222 (define-source-transform logand
(&rest args
)
4223 (source-transform-transitive 'logand args -
1 'integer
))
4224 (define-source-transform logeqv
(&rest args
)
4225 (source-transform-transitive 'logeqv args -
1 'integer
))
4226 (define-source-transform gcd
(&rest args
)
4227 (source-transform-transitive 'gcd args
0 'integer
'(abs)))
4228 (define-source-transform lcm
(&rest args
)
4229 (source-transform-transitive 'lcm args
1 'integer
'(abs)))
4231 ;;; Do source transformations for intransitive n-arg functions such as
4232 ;;; /. With one arg, we form the inverse. With two args we pass.
4233 ;;; Otherwise we associate into two-arg calls.
4234 (declaim (ftype (function (symbol symbol list t list
&optional symbol
)
4235 (values list
&optional
(member nil t
)))
4236 source-transform-intransitive
))
4237 (defun source-transform-intransitive (fun fun
* args identity one-arg-prefixes
4238 &optional
(one-arg-result-type 'number
))
4240 ((0 2) (values nil t
))
4241 (1 `(,@one-arg-prefixes
(the ,one-arg-result-type
,(first args
))))
4242 (t (let ((reduced-args
4243 (reduce-constants fun
* (rest args
) identity one-arg-result-type
)))
4244 (associate-args fun
(first args
) reduced-args identity
)))))
4246 (define-source-transform -
(&rest args
)
4247 (source-transform-intransitive '-
'+ args
0 '(%negate
)))
4248 (define-source-transform / (&rest args
)
4249 (source-transform-intransitive '/ '* args
1 '(/ 1)))
4251 ;;;; transforming APPLY
4253 ;;; We convert APPLY into MULTIPLE-VALUE-CALL so that the compiler
4254 ;;; only needs to understand one kind of variable-argument call. It is
4255 ;;; more efficient to convert APPLY to MV-CALL than MV-CALL to APPLY.
4256 (define-source-transform apply
(fun arg
&rest more-args
)
4257 (let ((args (cons arg more-args
)))
4258 `(multiple-value-call ,fun
4259 ,@(mapcar (lambda (x) `(values ,x
)) (butlast args
))
4260 (values-list ,(car (last args
))))))
4262 ;;;; transforming references to &REST argument
4264 ;;; We add magical &MORE arguments to all functions with &REST. If ARG names
4265 ;;; the &REST argument, this returns the lambda-vars for the context and
4267 (defun possible-rest-arg-context (arg)
4269 (let* ((var (lexenv-find arg vars
))
4270 (info (when (lambda-var-p var
)
4271 (lambda-var-arg-info var
))))
4273 (eq :rest
(arg-info-kind info
))
4274 (consp (arg-info-default info
)))
4275 (values-list (arg-info-default info
))))))
4277 (defun mark-more-context-used (rest-var)
4278 (let ((info (lambda-var-arg-info rest-var
)))
4279 (aver (eq :rest
(arg-info-kind info
)))
4280 (destructuring-bind (context count
&optional used
) (arg-info-default info
)
4282 (setf (arg-info-default info
) (list context count t
))))))
4284 (defun mark-more-context-invalid (rest-var)
4285 (let ((info (lambda-var-arg-info rest-var
)))
4286 (aver (eq :rest
(arg-info-kind info
)))
4287 (setf (arg-info-default info
) t
)))
4289 ;;; This determines of we the REF to a &REST variable is headed towards
4290 ;;; parts unknown, or if we can really use the context.
4291 (defun rest-var-more-context-ok (lvar)
4292 (let* ((use (lvar-use lvar
))
4293 (var (when (ref-p use
) (ref-leaf use
)))
4294 (home (when (lambda-var-p var
) (lambda-var-home var
)))
4295 (info (when (lambda-var-p var
) (lambda-var-arg-info var
)))
4296 (restp (when info
(eq :rest
(arg-info-kind info
)))))
4297 (flet ((ref-good-for-more-context-p (ref)
4298 (let ((dest (principal-lvar-end (node-lvar ref
))))
4299 (and (combination-p dest
)
4300 ;; If the destination is to anything but these, we're going to
4301 ;; actually need the rest list -- and since other operations
4302 ;; might modify the list destructively, the using the context
4303 ;; isn't good anywhere else either.
4304 (lvar-fun-is (combination-fun dest
)
4305 '(%rest-values %rest-ref %rest-length
4306 %rest-null %rest-true
))
4307 ;; If the home lambda is different and isn't DX, it might
4308 ;; escape -- in which case using the more context isn't safe.
4309 (let ((clambda (node-home-lambda dest
)))
4310 (or (eq home clambda
)
4311 (leaf-dynamic-extent clambda
)))))))
4312 (let ((ok (and restp
4313 (consp (arg-info-default info
))
4314 (not (lambda-var-specvar var
))
4315 (not (lambda-var-sets var
))
4316 (every #'ref-good-for-more-context-p
(lambda-var-refs var
)))))
4318 (mark-more-context-used var
)
4320 (mark-more-context-invalid var
)))
4323 ;;; VALUES-LIST -> %REST-VALUES
4324 (define-source-transform values-list
(list)
4325 (multiple-value-bind (context count
) (possible-rest-arg-context list
)
4327 `(%rest-values
,list
,context
,count
)
4330 ;;; NTH -> %REST-REF
4331 (define-source-transform nth
(n list
)
4332 (multiple-value-bind (context count
) (possible-rest-arg-context list
)
4334 `(%rest-ref
,n
,list
,context
,count
)
4335 `(car (nthcdr ,n
,list
)))))
4337 (define-source-transform elt
(seq n
)
4338 (if (policy *lexenv
* (= safety
3))
4340 (multiple-value-bind (context count
) (possible-rest-arg-context seq
)
4342 `(%rest-ref
,n
,seq
,context
,count
)
4345 ;;; CAxR -> %REST-REF
4346 (defun source-transform-car (list nth
)
4347 (multiple-value-bind (context count
) (possible-rest-arg-context list
)
4349 `(%rest-ref
,nth
,list
,context
,count
)
4352 (define-source-transform car
(list)
4353 (source-transform-car list
0))
4355 (define-source-transform cadr
(list)
4356 (or (source-transform-car list
1)
4357 `(car (cdr ,list
))))
4359 (define-source-transform caddr
(list)
4360 (or (source-transform-car list
2)
4361 `(car (cdr (cdr ,list
)))))
4363 (define-source-transform cadddr
(list)
4364 (or (source-transform-car list
3)
4365 `(car (cdr (cdr (cdr ,list
))))))
4367 ;;; LENGTH -> %REST-LENGTH
4368 (defun source-transform-length (list)
4369 (multiple-value-bind (context count
) (possible-rest-arg-context list
)
4371 `(%rest-length
,list
,context
,count
)
4373 (define-source-transform length
(list) (source-transform-length list
))
4374 (define-source-transform list-length
(list) (source-transform-length list
))
4376 ;;; ENDP, NULL and NOT -> %REST-NULL
4378 ;;; Outside &REST convert into an IF so that IF optimizations will eliminate
4379 ;;; redundant negations.
4380 (defun source-transform-null (x op
)
4381 (multiple-value-bind (context count
) (possible-rest-arg-context x
)
4383 `(%rest-null
',op
,x
,context
,count
))
4385 `(if (the list
,x
) nil t
))
4388 (define-source-transform not
(x) (source-transform-null x
'not
))
4389 (define-source-transform null
(x) (source-transform-null x
'null
))
4390 (define-source-transform endp
(x) (source-transform-null x
'endp
))
4392 (deftransform %rest-values
((list context count
))
4393 (if (rest-var-more-context-ok list
)
4394 `(%more-arg-values context
0 count
)
4395 `(values-list list
)))
4397 (deftransform %rest-ref
((n list context count
))
4398 (cond ((rest-var-more-context-ok list
)
4399 `(and (< (the index n
) count
)
4400 (%more-arg context n
)))
4401 ((and (constant-lvar-p n
) (zerop (lvar-value n
)))
4406 (deftransform %rest-length
((list context count
))
4407 (if (rest-var-more-context-ok list
)
4411 (deftransform %rest-null
((op list context count
))
4412 (aver (constant-lvar-p op
))
4413 (if (rest-var-more-context-ok list
)
4415 `(,(lvar-value op
) list
)))
4417 (deftransform %rest-true
((list context count
))
4418 (if (rest-var-more-context-ok list
)
4419 `(not (eql 0 count
))
4422 ;;;; transforming FORMAT
4424 ;;;; If the control string is a compile-time constant, then replace it
4425 ;;;; with a use of the FORMATTER macro so that the control string is
4426 ;;;; ``compiled.'' Furthermore, if the destination is either a stream
4427 ;;;; or T and the control string is a function (i.e. FORMATTER), then
4428 ;;;; convert the call to FORMAT to just a FUNCALL of that function.
4430 ;;; for compile-time argument count checking.
4432 ;;; FIXME II: In some cases, type information could be correlated; for
4433 ;;; instance, ~{ ... ~} requires a list argument, so if the lvar-type
4434 ;;; of a corresponding argument is known and does not intersect the
4435 ;;; list type, a warning could be signalled.
4436 (defun check-format-args (string args fun
)
4437 (declare (type string string
))
4438 (unless (typep string
'simple-string
)
4439 (setq string
(coerce string
'simple-string
)))
4440 (multiple-value-bind (min max
)
4441 (handler-case (sb!format
:%compiler-walk-format-string string args
)
4442 (sb!format
:format-error
(c)
4443 (compiler-warn "~A" c
)))
4445 (let ((nargs (length args
)))
4448 (warn 'format-too-few-args-warning
4450 "Too few arguments (~D) to ~S ~S: requires at least ~D."
4451 :format-arguments
(list nargs fun string min
)))
4453 (warn 'format-too-many-args-warning
4455 "Too many arguments (~D) to ~S ~S: uses at most ~D."
4456 :format-arguments
(list nargs fun string max
))))))))
4458 (defoptimizer (format optimizer
) ((dest control
&rest args
))
4459 (when (constant-lvar-p control
)
4460 (let ((x (lvar-value control
)))
4462 (check-format-args x args
'format
)))))
4464 ;;; We disable this transform in the cross-compiler to save memory in
4465 ;;; the target image; most of the uses of FORMAT in the compiler are for
4466 ;;; error messages, and those don't need to be particularly fast.
4468 (deftransform format
((dest control
&rest args
) (t simple-string
&rest t
) *
4469 :policy
(>= speed space
))
4470 (unless (constant-lvar-p control
)
4471 (give-up-ir1-transform "The control string is not a constant."))
4472 (let ((arg-names (make-gensym-list (length args
))))
4473 `(lambda (dest control
,@arg-names
)
4474 (declare (ignore control
))
4475 (format dest
(formatter ,(lvar-value control
)) ,@arg-names
))))
4477 (deftransform format
((stream control
&rest args
) (stream function
&rest t
))
4478 (let ((arg-names (make-gensym-list (length args
))))
4479 `(lambda (stream control
,@arg-names
)
4480 (funcall control stream
,@arg-names
)
4483 (deftransform format
((tee control
&rest args
) ((member t
) function
&rest t
))
4484 (let ((arg-names (make-gensym-list (length args
))))
4485 `(lambda (tee control
,@arg-names
)
4486 (declare (ignore tee
))
4487 (funcall control
*standard-output
* ,@arg-names
)
4490 (deftransform pathname
((pathspec) (pathname) *)
4493 (deftransform pathname
((pathspec) (string) *)
4494 '(values (parse-namestring pathspec
)))
4498 `(defoptimizer (,name optimizer
) ((control &rest args
))
4499 (when (constant-lvar-p control
)
4500 (let ((x (lvar-value control
)))
4502 (check-format-args x args
',name
)))))))
4505 #+sb-xc-host
; Only we should be using these
4508 (def compiler-error
)
4510 (def compiler-style-warn
)
4511 (def compiler-notify
)
4512 (def maybe-compiler-notify
)
4515 (defoptimizer (cerror optimizer
) ((report control
&rest args
))
4516 (when (and (constant-lvar-p control
)
4517 (constant-lvar-p report
))
4518 (let ((x (lvar-value control
))
4519 (y (lvar-value report
)))
4520 (when (and (stringp x
) (stringp y
))
4521 (multiple-value-bind (min1 max1
)
4523 (sb!format
:%compiler-walk-format-string x args
)
4524 (sb!format
:format-error
(c)
4525 (compiler-warn "~A" c
)))
4527 (multiple-value-bind (min2 max2
)
4529 (sb!format
:%compiler-walk-format-string y args
)
4530 (sb!format
:format-error
(c)
4531 (compiler-warn "~A" c
)))
4533 (let ((nargs (length args
)))
4535 ((< nargs
(min min1 min2
))
4536 (warn 'format-too-few-args-warning
4538 "Too few arguments (~D) to ~S ~S ~S: ~
4539 requires at least ~D."
4541 (list nargs
'cerror y x
(min min1 min2
))))
4542 ((> nargs
(max max1 max2
))
4543 (warn 'format-too-many-args-warning
4545 "Too many arguments (~D) to ~S ~S ~S: ~
4548 (list nargs
'cerror y x
(max max1 max2
))))))))))))))
4550 (defoptimizer (coerce derive-type
) ((value type
) node
)
4552 ((constant-lvar-p type
)
4553 ;; This branch is essentially (RESULT-TYPE-SPECIFIER-NTH-ARG 2),
4554 ;; but dealing with the niggle that complex canonicalization gets
4555 ;; in the way: (COERCE 1 'COMPLEX) returns 1, which is not of
4557 (let* ((specifier (lvar-value type
))
4558 (result-typeoid (careful-specifier-type specifier
)))
4560 ((null result-typeoid
) nil
)
4561 ((csubtypep result-typeoid
(specifier-type 'number
))
4562 ;; the difficult case: we have to cope with ANSI 12.1.5.3
4563 ;; Rule of Canonical Representation for Complex Rationals,
4564 ;; which is a truly nasty delivery to field.
4566 ((csubtypep result-typeoid
(specifier-type 'real
))
4567 ;; cleverness required here: it would be nice to deduce
4568 ;; that something of type (INTEGER 2 3) coerced to type
4569 ;; DOUBLE-FLOAT should return (DOUBLE-FLOAT 2.0d0 3.0d0).
4570 ;; FLOAT gets its own clause because it's implemented as
4571 ;; a UNION-TYPE, so we don't catch it in the NUMERIC-TYPE
4574 ((and (numeric-type-p result-typeoid
)
4575 (eq (numeric-type-complexp result-typeoid
) :real
))
4576 ;; FIXME: is this clause (a) necessary or (b) useful?
4578 ((or (csubtypep result-typeoid
4579 (specifier-type '(complex single-float
)))
4580 (csubtypep result-typeoid
4581 (specifier-type '(complex double-float
)))
4583 (csubtypep result-typeoid
4584 (specifier-type '(complex long-float
))))
4585 ;; float complex types are never canonicalized.
4588 ;; if it's not a REAL, or a COMPLEX FLOAToid, it's
4589 ;; probably just a COMPLEX or equivalent. So, in that
4590 ;; case, we will return a complex or an object of the
4591 ;; provided type if it's rational:
4592 (type-union result-typeoid
4593 (type-intersection (lvar-type value
)
4594 (specifier-type 'rational
))))))
4595 ((and (policy node
(zerop safety
))
4596 (csubtypep result-typeoid
(specifier-type '(array * (*)))))
4597 ;; At zero safety the deftransform for COERCE can elide dimension
4598 ;; checks for the things like (COERCE X '(SIMPLE-VECTOR 5)) -- so we
4599 ;; need to simplify the type to drop the dimension information.
4600 (let ((vtype (simplify-vector-type result-typeoid
)))
4602 (specifier-type vtype
)
4607 ;; OK, the result-type argument isn't constant. However, there
4608 ;; are common uses where we can still do better than just
4609 ;; *UNIVERSAL-TYPE*: e.g. (COERCE X (ARRAY-ELEMENT-TYPE Y)),
4610 ;; where Y is of a known type. See messages on cmucl-imp
4611 ;; 2001-02-14 and sbcl-devel 2002-12-12. We only worry here
4612 ;; about types that can be returned by (ARRAY-ELEMENT-TYPE Y), on
4613 ;; the basis that it's unlikely that other uses are both
4614 ;; time-critical and get to this branch of the COND (non-constant
4615 ;; second argument to COERCE). -- CSR, 2002-12-16
4616 (let ((value-type (lvar-type value
))
4617 (type-type (lvar-type type
)))
4619 ((good-cons-type-p (cons-type)
4620 ;; Make sure the cons-type we're looking at is something
4621 ;; we're prepared to handle which is basically something
4622 ;; that array-element-type can return.
4623 (or (and (member-type-p cons-type
)
4624 (eql 1 (member-type-size cons-type
))
4625 (null (first (member-type-members cons-type
))))
4626 (let ((car-type (cons-type-car-type cons-type
)))
4627 (and (member-type-p car-type
)
4628 (eql 1 (member-type-members car-type
))
4629 (let ((elt (first (member-type-members car-type
))))
4633 (numberp (first elt
)))))
4634 (good-cons-type-p (cons-type-cdr-type cons-type
))))))
4635 (unconsify-type (good-cons-type)
4636 ;; Convert the "printed" respresentation of a cons
4637 ;; specifier into a type specifier. That is, the
4638 ;; specifier (CONS (EQL SIGNED-BYTE) (CONS (EQL 16)
4639 ;; NULL)) is converted to (SIGNED-BYTE 16).
4640 (cond ((or (null good-cons-type
)
4641 (eq good-cons-type
'null
))
4643 ((and (eq (first good-cons-type
) 'cons
)
4644 (eq (first (second good-cons-type
)) 'member
))
4645 `(,(second (second good-cons-type
))
4646 ,@(unconsify-type (caddr good-cons-type
))))))
4647 (coerceable-p (part)
4648 ;; Can the value be coerced to the given type? Coerce is
4649 ;; complicated, so we don't handle every possible case
4650 ;; here---just the most common and easiest cases:
4652 ;; * Any REAL can be coerced to a FLOAT type.
4653 ;; * Any NUMBER can be coerced to a (COMPLEX
4654 ;; SINGLE/DOUBLE-FLOAT).
4656 ;; FIXME I: we should also be able to deal with characters
4659 ;; FIXME II: I'm not sure that anything is necessary
4660 ;; here, at least while COMPLEX is not a specialized
4661 ;; array element type in the system. Reasoning: if
4662 ;; something cannot be coerced to the requested type, an
4663 ;; error will be raised (and so any downstream compiled
4664 ;; code on the assumption of the returned type is
4665 ;; unreachable). If something can, then it will be of
4666 ;; the requested type, because (by assumption) COMPLEX
4667 ;; (and other difficult types like (COMPLEX INTEGER)
4668 ;; aren't specialized types.
4669 (let ((coerced-type (careful-specifier-type part
)))
4671 (or (and (csubtypep coerced-type
(specifier-type 'float
))
4672 (csubtypep value-type
(specifier-type 'real
)))
4673 (and (csubtypep coerced-type
4674 (specifier-type `(or (complex single-float
)
4675 (complex double-float
))))
4676 (csubtypep value-type
(specifier-type 'number
)))))))
4677 (process-types (type)
4678 ;; FIXME: This needs some work because we should be able
4679 ;; to derive the resulting type better than just the
4680 ;; type arg of coerce. That is, if X is (INTEGER 10
4681 ;; 20), then (COERCE X 'DOUBLE-FLOAT) should say
4682 ;; (DOUBLE-FLOAT 10d0 20d0) instead of just
4684 (cond ((member-type-p type
)
4687 (mapc-member-type-members
4689 (if (coerceable-p member
)
4690 (push member members
)
4691 (return-from punt
*universal-type
*)))
4693 (specifier-type `(or ,@members
)))))
4694 ((and (cons-type-p type
)
4695 (good-cons-type-p type
))
4696 (let ((c-type (unconsify-type (type-specifier type
))))
4697 (if (coerceable-p c-type
)
4698 (specifier-type c-type
)
4701 *universal-type
*))))
4702 (cond ((union-type-p type-type
)
4703 (apply #'type-union
(mapcar #'process-types
4704 (union-type-types type-type
))))
4705 ((or (member-type-p type-type
)
4706 (cons-type-p type-type
))
4707 (process-types type-type
))
4709 *universal-type
*)))))))
4711 (defoptimizer (compile derive-type
) ((nameoid function
))
4712 (when (csubtypep (lvar-type nameoid
)
4713 (specifier-type 'null
))
4714 (values-specifier-type '(values function boolean boolean
))))
4716 ;;; FIXME: Maybe also STREAM-ELEMENT-TYPE should be given some loving
4717 ;;; treatment along these lines? (See discussion in COERCE DERIVE-TYPE
4718 ;;; optimizer, above).
4719 (defoptimizer (array-element-type derive-type
) ((array))
4720 (let ((array-type (lvar-type array
)))
4721 (labels ((consify (list)
4724 `(cons (eql ,(car list
)) ,(consify (rest list
)))))
4725 (get-element-type (a)
4727 (type-specifier (array-type-specialized-element-type a
))))
4728 (cond ((eq element-type
'*)
4729 (specifier-type 'type-specifier
))
4730 ((symbolp element-type
)
4731 (make-member-type :members
(list element-type
)))
4732 ((consp element-type
)
4733 (specifier-type (consify element-type
)))
4735 (error "can't understand type ~S~%" element-type
))))))
4736 (labels ((recurse (type)
4737 (cond ((array-type-p type
)
4738 (get-element-type type
))
4739 ((union-type-p type
)
4741 (mapcar #'recurse
(union-type-types type
))))
4743 *universal-type
*))))
4744 (recurse array-type
)))))
4746 (define-source-transform sb
!impl
::sort-vector
(vector start end predicate key
)
4747 ;; Like CMU CL, we use HEAPSORT. However, other than that, this code
4748 ;; isn't really related to the CMU CL code, since instead of trying
4749 ;; to generalize the CMU CL code to allow START and END values, this
4750 ;; code has been written from scratch following Chapter 7 of
4751 ;; _Introduction to Algorithms_ by Corman, Rivest, and Shamir.
4752 `(macrolet ((%index
(x) `(truly-the index
,x
))
4753 (%parent
(i) `(ash ,i -
1))
4754 (%left
(i) `(%index
(ash ,i
1)))
4755 (%right
(i) `(%index
(1+ (ash ,i
1))))
4758 (left (%left i
) (%left i
)))
4759 ((> left current-heap-size
))
4760 (declare (type index i left
))
4761 (let* ((i-elt (%elt i
))
4762 (i-key (funcall keyfun i-elt
))
4763 (left-elt (%elt left
))
4764 (left-key (funcall keyfun left-elt
)))
4765 (multiple-value-bind (large large-elt large-key
)
4766 (if (funcall ,',predicate i-key left-key
)
4767 (values left left-elt left-key
)
4768 (values i i-elt i-key
))
4769 (let ((right (%right i
)))
4770 (multiple-value-bind (largest largest-elt
)
4771 (if (> right current-heap-size
)
4772 (values large large-elt
)
4773 (let* ((right-elt (%elt right
))
4774 (right-key (funcall keyfun right-elt
)))
4775 (if (funcall ,',predicate large-key right-key
)
4776 (values right right-elt
)
4777 (values large large-elt
))))
4778 (cond ((= largest i
)
4781 (setf (%elt i
) largest-elt
4782 (%elt largest
) i-elt
4784 (%sort-vector
(keyfun &optional
(vtype 'vector
))
4785 `(macrolet (;; KLUDGE: In SBCL ca. 0.6.10, I had
4786 ;; trouble getting type inference to
4787 ;; propagate all the way through this
4788 ;; tangled mess of inlining. The TRULY-THE
4789 ;; here works around that. -- WHN
4791 `(aref (truly-the ,',vtype
,',',vector
)
4792 (%index
(+ (%index
,i
) start-1
)))))
4793 (let (;; Heaps prefer 1-based addressing.
4794 (start-1 (1- ,',start
))
4795 (current-heap-size (- ,',end
,',start
))
4797 (declare (type (integer -
1 #.
(1- sb
!xc
:most-positive-fixnum
))
4799 (declare (type index current-heap-size
))
4800 (declare (type function keyfun
))
4801 (loop for i of-type index
4802 from
(ash current-heap-size -
1) downto
1 do
4805 (when (< current-heap-size
2)
4807 (rotatef (%elt
1) (%elt current-heap-size
))
4808 (decf current-heap-size
)
4810 (if (typep ,vector
'simple-vector
)
4811 ;; (VECTOR T) is worth optimizing for, and SIMPLE-VECTOR is
4812 ;; what we get from (VECTOR T) inside WITH-ARRAY-DATA.
4814 ;; Special-casing the KEY=NIL case lets us avoid some
4816 (%sort-vector
#'identity simple-vector
)
4817 (%sort-vector
,key simple-vector
))
4818 ;; It's hard to anticipate many speed-critical applications for
4819 ;; sorting vector types other than (VECTOR T), so we just lump
4820 ;; them all together in one slow dynamically typed mess.
4822 (declare (optimize (speed 2) (space 2) (inhibit-warnings 3)))
4823 (%sort-vector
(or ,key
#'identity
))))))
4825 (deftransform sort
((list predicate
&key key
)
4827 `(sb!impl
::stable-sort-list list
4828 (%coerce-callable-to-fun predicate
)
4829 (if key
(%coerce-callable-to-fun key
) #'identity
)))
4831 (deftransform stable-sort
((sequence predicate
&key key
)
4832 ((or vector list
) *))
4833 (let ((sequence-type (lvar-type sequence
)))
4834 (cond ((csubtypep sequence-type
(specifier-type 'list
))
4835 `(sb!impl
::stable-sort-list sequence
4836 (%coerce-callable-to-fun predicate
)
4837 (if key
(%coerce-callable-to-fun key
) #'identity
)))
4838 ((csubtypep sequence-type
(specifier-type 'simple-vector
))
4839 `(sb!impl
::stable-sort-simple-vector sequence
4840 (%coerce-callable-to-fun predicate
)
4841 (and key
(%coerce-callable-to-fun key
))))
4843 `(sb!impl
::stable-sort-vector sequence
4844 (%coerce-callable-to-fun predicate
)
4845 (and key
(%coerce-callable-to-fun key
)))))))
4847 ;;;; debuggers' little helpers
4849 ;;; for debugging when transforms are behaving mysteriously,
4850 ;;; e.g. when debugging a problem with an ASH transform
4851 ;;; (defun foo (&optional s)
4852 ;;; (sb-c::/report-lvar s "S outside WHEN")
4853 ;;; (when (and (integerp s) (> s 3))
4854 ;;; (sb-c::/report-lvar s "S inside WHEN")
4855 ;;; (let ((bound (ash 1 (1- s))))
4856 ;;; (sb-c::/report-lvar bound "BOUND")
4857 ;;; (let ((x (- bound))
4859 ;;; (sb-c::/report-lvar x "X")
4860 ;;; (sb-c::/report-lvar x "Y"))
4861 ;;; `(integer ,(- bound) ,(1- bound)))))
4862 ;;; (The DEFTRANSFORM doesn't do anything but report at compile time,
4863 ;;; and the function doesn't do anything at all.)
4866 (defknown /report-lvar
(t t
) null
)
4867 (deftransform /report-lvar
((x message
) (t t
))
4868 (format t
"~%/in /REPORT-LVAR~%")
4869 (format t
"/(LVAR-TYPE X)=~S~%" (lvar-type x
))
4870 (when (constant-lvar-p x
)
4871 (format t
"/(LVAR-VALUE X)=~S~%" (lvar-value x
)))
4872 (format t
"/MESSAGE=~S~%" (lvar-value message
))
4873 (give-up-ir1-transform "not a real transform"))
4874 (defun /report-lvar
(x message
)
4875 (declare (ignore x message
))))
4878 ;;;; Transforms for internal compiler utilities
4880 ;;; If QUALITY-NAME is constant and a valid name, don't bother
4881 ;;; checking that it's still valid at run-time.
4882 (deftransform policy-quality
((policy quality-name
)
4884 (unless (and (constant-lvar-p quality-name
)
4885 (policy-quality-name-p (lvar-value quality-name
)))
4886 (give-up-ir1-transform))
4887 '(%policy-quality policy quality-name
))
4889 (deftransform encode-universal-time
4890 ((second minute hour date month year
&optional time-zone
)
4891 ((constant-arg (mod 60)) (constant-arg (mod 60))
4892 (constant-arg (mod 24))
4893 (constant-arg (integer 1 31))
4894 (constant-arg (integer 1 12))
4895 (constant-arg (integer 1899))
4896 (constant-arg (rational -
24 24))))
4897 (let ((second (lvar-value second
))
4898 (minute (lvar-value minute
))
4899 (hour (lvar-value hour
))
4900 (date (lvar-value date
))
4901 (month (lvar-value month
))
4902 (year (lvar-value year
))
4903 (time-zone (lvar-value time-zone
)))
4904 (if (zerop (rem time-zone
1/3600))
4905 (encode-universal-time second minute hour date month year time-zone
)
4906 (give-up-ir1-transform))))
4908 #!-
(and win32
(not sb-thread
))
4909 (deftransform sleep
((seconds) ((integer 0 #.
(expt 10 8))))
4910 `(sb!unix
:nanosleep seconds
0))
4912 #!-
(and win32
(not sb-thread
))
4913 (deftransform sleep
((seconds) ((constant-arg (real 0))))
4914 (let ((seconds-value (lvar-value seconds
)))
4915 (multiple-value-bind (seconds nano
)
4916 (sb!impl
::split-seconds-for-sleep seconds-value
)
4917 (if (> seconds
(expt 10 8))
4918 (give-up-ir1-transform)
4919 `(sb!unix
:nanosleep
,seconds
,nano
)))))